From 3ba9838d08e292c3968aa70f3bf32d3e61437a59 Mon Sep 17 00:00:00 2001 From: sv99 Date: Mon, 24 Jul 2023 00:37:55 +0300 Subject: [PATCH] Sreamline decoding AndroidManifest.xml (#3171) --- .../brut/androlib/res/ResourcesDecoder.java | 82 ++++++------------- 1 file changed, 24 insertions(+), 58 deletions(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java index 3cd727044a..b8a4c843e3 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResourcesDecoder.java @@ -34,6 +34,7 @@ import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.util.*; import java.util.logging.Logger; @@ -102,16 +103,23 @@ public void decodeManifest(File outDir) throws AndrolibException { if (hasManifest()) { if (mConfig.decodeResources == Config.DECODE_RESOURCES_FULL || mConfig.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) { + decodeManifest(getResTable(), mApkFile, outDir); if (hasResources()) { - decodeManifestWithResources(getResTable(), mApkFile, outDir); if (!mConfig.analysisMode) { + // Remove versionName / versionCode (aapt API 16) + // + // check for a mismatch between resources.arsc package and the package listed in AndroidManifest + // also remove the android::versionCode / versionName from manifest for rebuild + // this is a required change to prevent aapt warning about conflicting versions + // it will be passed as a parameter to aapt like "--min-sdk-version" via apktool.yml + adjustPackageManifest(getResTable(), outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml"); + + ResXmlPatcher.removeManifestVersions(new File( + outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml")); + // update apk info mApkInfo.packageInfo.forcedPackageId = String.valueOf(mResTable.getPackageId()); } - } else { - // if there's no resources.arsc, decode the manifest without looking - // up attribute references - decodeManifest(getResTable(), mApkFile, outDir); } } else { @@ -128,55 +136,25 @@ public void decodeManifest(File outDir) throws AndrolibException { private void decodeManifest(ResTable resTable, ExtFile apkFile, File outDir) throws AndrolibException { - Duo duo = getManifestFileDecoder(false); - ResFileDecoder fileDecoder = duo.m1; - - // Set ResAttrDecoder - duo.m2.setAttrDecoder(new ResAttrDecoder()); - ResAttrDecoder attrDecoder = duo.m2.getAttrDecoder(); - attrDecoder.setResTable(resTable); - - Directory inApk, out; - try { - inApk = apkFile.getDirectory(); - out = new FileDirectory(outDir); - - LOGGER.info("Decoding AndroidManifest.xml with only framework resources..."); - fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out, "AndroidManifest.xml"); - - } catch (DirectoryException ex) { - throw new AndrolibException(ex); - } - } - - private void decodeManifestWithResources(ResTable resTable, ExtFile apkFile, File outDir) - throws AndrolibException { - - Duo duo = getManifestFileDecoder(true); - ResFileDecoder fileDecoder = duo.m1; - ResAttrDecoder attrDecoder = duo.m2.getAttrDecoder(); + AXmlResourceParser axmlParser = new AndroidManifestResourceParser(); + ResAttrDecoder attrDecoder = new ResAttrDecoder(); attrDecoder.setResTable(resTable); + axmlParser.setAttrDecoder(attrDecoder); + XmlPullStreamDecoder fileDecoder = new XmlPullStreamDecoder(axmlParser, getResXmlSerializer()); Directory inApk, out; try { inApk = apkFile.getDirectory(); out = new FileDirectory(outDir); - LOGGER.info("Decoding AndroidManifest.xml with resources..."); - fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out, "AndroidManifest.xml"); + if (hasResources()) + LOGGER.info("Decoding AndroidManifest.xml framework resources..."); + else + LOGGER.info("Decoding AndroidManifest.xml with only framework resources..."); + InputStream inputStream = inApk.getFileInput("AndroidManifest.xml"); + OutputStream outputStream = out.getFileOutput("AndroidManifest.xml"); + fileDecoder.decodeManifest(inputStream, outputStream); - // Remove versionName / versionCode (aapt API 16) - if (!mConfig.analysisMode) { - - // check for a mismatch between resources.arsc package and the package listed in AndroidManifest - // also remove the android::versionCode / versionName from manifest for rebuild - // this is a required change to prevent aapt warning about conflicting versions - // it will be passed as a parameter to aapt like "--min-sdk-version" via apktool.yml - adjustPackageManifest(resTable, outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml"); - - ResXmlPatcher.removeManifestVersions(new File( - outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml")); - } } catch (DirectoryException ex) { throw new AndrolibException(ex); } @@ -206,18 +184,6 @@ private void adjustPackageManifest(ResTable resTable, String filePath) } } - private Duo getManifestFileDecoder(boolean withResources) { - ResStreamDecoderContainer decoders = new ResStreamDecoderContainer(); - - AXmlResourceParser axmlParser = new AndroidManifestResourceParser(); - if (withResources) { - axmlParser.setAttrDecoder(new ResAttrDecoder()); - } - decoders.setDecoder("xml", new XmlPullStreamDecoder(axmlParser, getResXmlSerializer())); - - return new Duo<>(new ResFileDecoder(decoders), axmlParser); - } - private ExtMXSerializer getResXmlSerializer() { ExtMXSerializer serial = new ExtMXSerializer(); serial.setProperty(ExtXmlSerializer.PROPERTY_SERIALIZER_INDENTATION, " ");