From cdc66c1ac87b58cc8a481e6ebf61991d84b63301 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 26 Aug 2022 02:54:27 -0700 Subject: [PATCH] Move patching logic out of AXML --- .../topjohnwu/magisk/core/tasks/HideAPK.kt | 14 +++++++-- .../com/topjohnwu/magisk/core/utils/AXML.kt | 31 +++++++------------ 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/topjohnwu/magisk/core/tasks/HideAPK.kt b/app/src/main/java/com/topjohnwu/magisk/core/tasks/HideAPK.kt index 42ad4600a..7ae776487 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/tasks/HideAPK.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/tasks/HideAPK.kt @@ -71,14 +71,24 @@ object HideAPK { pkg: String, label: CharSequence ): Boolean { val info = context.packageManager.getPackageArchiveInfo(apk.path, 0) ?: return false - val name = info.applicationInfo.nonLocalizedLabel.toString() + val origLabel = info.applicationInfo.nonLocalizedLabel.toString() try { JarMap.open(apk, true).use { jar -> val je = jar.getJarEntry(ANDROID_MANIFEST) val xml = AXML(jar.getRawData(je)) - if (!xml.findAndPatch(APPLICATION_ID to pkg, name to label.toString())) + if (!xml.patchStrings { + for (i in it.indices) { + val s = it[i] + if (s.contains(APPLICATION_ID)) { + it[i] = s.replace(APPLICATION_ID, pkg) + } else if (s == origLabel) { + it[i] = label.toString() + } + } + }) { return false + } // Write apk changes jar.getOutputStream(je).use { it.write(xml.bytes) } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/utils/AXML.kt b/app/src/main/java/com/topjohnwu/magisk/core/utils/AXML.kt index a36c4ce24..1579b723b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/utils/AXML.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/utils/AXML.kt @@ -29,7 +29,7 @@ class AXML(b: ByteArray) { * Followed by an array of uint32_t with size = number of strings * Each entry points to an offset into the string data */ - fun findAndPatch(vararg patterns: Pair): Boolean { + fun patchStrings(patchFn: (Array) -> Unit): Boolean { val buffer = ByteBuffer.wrap(bytes).order(LITTLE_ENDIAN) fun findStringPool(): Int { @@ -42,7 +42,6 @@ class AXML(b: ByteArray) { return -1 } - var patch = false val start = findStringPool() if (start < 0) return false @@ -57,34 +56,26 @@ class AXML(b: ByteArray) { val dataOff = start + intBuf.get() intBuf.get() - val strings = ArrayList(count) - // Read and patch all strings - loop@ for (i in 0 until count) { + val strList = ArrayList(count) + // Collect all strings in the pool + for (i in 0 until count) { val off = dataOff + intBuf.get() val len = buffer.getShort(off) - val str = String(bytes, off + 2, len * 2, UTF_16LE) - for ((from, to) in patterns) { - if (str.contains(from)) { - strings.add(str.replace(from, to)) - patch = true - continue@loop - } - } - strings.add(str) + strList.add(String(bytes, off + 2, len * 2, UTF_16LE)) } - if (!patch) - return false + val strArr = strList.toTypedArray() + patchFn(strArr) // Write everything before string data, will patch values later val baos = RawByteStream() baos.write(bytes, 0, dataOff) // Write string data - val strList = IntArray(count) + val offList = IntArray(count) for (i in 0 until count) { - strList[i] = baos.size() - dataOff - val str = strings[i] + offList[i] = baos.size() - dataOff + val str = strArr[i] baos.write(str.length.toShortBytes()) baos.write(str.toByteArray(UTF_16LE)) // Null terminate @@ -103,7 +94,7 @@ class AXML(b: ByteArray) { // Patch index table newBuffer.position(start + STRING_INDICES_OFF) val newIntBuf = newBuffer.asIntBuffer() - strList.forEach { newIntBuf.put(it) } + offList.forEach { newIntBuf.put(it) } // Write the rest of the chunks val nextOff = start + size