diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java index a249869b1f..a31a3dcd50 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/AaptInvoker.java @@ -185,6 +185,10 @@ private void invokeAapt2(File apkFile, File manifest, File resDir, File rawDir, cmd.add("--enable-sparse-encoding"); } + if (mApkInfo.compactEntries) { + cmd.add("--enable-compact-entries"); + } + if (mApkInfo.isFrameworkApk) { cmd.add("-x"); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java index 38a036d583..3bdd7a2e4d 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/apk/ApkInfo.java @@ -51,6 +51,7 @@ public class ApkInfo implements YamlSerializable { public Map featureFlags = new LinkedHashMap<>(); public boolean sharedLibrary; public boolean sparseResources; + public boolean compactEntries; public List doNotCompress = new ArrayList<>(); public ApkInfo() { @@ -266,6 +267,10 @@ public void readItem(YamlReader reader) throws AndrolibException { sparseResources = line.getValueBool(); break; } + case "compactEntries": { + compactEntries = line.getValueBool(); + break; + } case "doNotCompress": { doNotCompress.clear(); reader.readStringList(doNotCompress); @@ -288,6 +293,7 @@ public void write(YamlWriter writer) { } writer.writeBool("sharedLibrary", sharedLibrary); writer.writeBool("sparseResources", sparseResources); + writer.writeBool("compactEntries", compactEntries); if (!doNotCompress.isEmpty()) { writer.writeList("doNotCompress", doNotCompress); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java index c058f61cfa..11a0208264 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java @@ -266,6 +266,13 @@ public void setSparseResources(boolean flag) { mApkInfo.sparseResources = flag; } + public void setCompactEntries(boolean flag) { + if (mApkInfo.compactEntries != flag) { + LOGGER.info("Compactly packed resource entries detected."); + } + mApkInfo.compactEntries = flag; + } + public void addSdkInfo(String key, String value) { mApkInfo.sdkInfo.put(key, value); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java index 3267edefbb..1a33c692d8 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java @@ -366,6 +366,12 @@ private EntryData readEntryData() throws IOException, AndrolibException { return null; } + // Be sure we don't poison mResTable by marking the application as compact + // Only flag the ResTable as compact if the main package is not loaded. + if (isCompact && !mResTable.isMainPkgLoaded()) { + mResTable.setCompactEntries(true); + } + // #3366 - In a compactly packed entry, the key index is the size & type is higher 8 bits on flags. // We assume a size of 8 bytes for compact entries and the specNamesId is the data itself encoded. ResValue value;