Sreamline decoding AndroidManifest.xml (#3171)

This commit is contained in:
sv99 2023-07-24 00:37:55 +03:00 committed by GitHub
parent d1a0c941ab
commit 3ba9838d08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -34,6 +34,7 @@ import org.xmlpull.v1.XmlSerializer;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.*; import java.util.*;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -102,16 +103,23 @@ public class ResourcesDecoder {
if (hasManifest()) { if (hasManifest()) {
if (mConfig.decodeResources == Config.DECODE_RESOURCES_FULL || if (mConfig.decodeResources == Config.DECODE_RESOURCES_FULL ||
mConfig.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) { mConfig.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) {
decodeManifest(getResTable(), mApkFile, outDir);
if (hasResources()) { if (hasResources()) {
decodeManifestWithResources(getResTable(), mApkFile, outDir);
if (!mConfig.analysisMode) { 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 // update apk info
mApkInfo.packageInfo.forcedPackageId = String.valueOf(mResTable.getPackageId()); 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 { else {
@ -128,60 +136,30 @@ public class ResourcesDecoder {
private void decodeManifest(ResTable resTable, ExtFile apkFile, File outDir) private void decodeManifest(ResTable resTable, ExtFile apkFile, File outDir)
throws AndrolibException { throws AndrolibException {
Duo<ResFileDecoder, AXmlResourceParser> duo = getManifestFileDecoder(false); AXmlResourceParser axmlParser = new AndroidManifestResourceParser();
ResFileDecoder fileDecoder = duo.m1; ResAttrDecoder attrDecoder = new ResAttrDecoder();
// Set ResAttrDecoder
duo.m2.setAttrDecoder(new ResAttrDecoder());
ResAttrDecoder attrDecoder = duo.m2.getAttrDecoder();
attrDecoder.setResTable(resTable); attrDecoder.setResTable(resTable);
axmlParser.setAttrDecoder(attrDecoder);
XmlPullStreamDecoder fileDecoder = new XmlPullStreamDecoder(axmlParser, getResXmlSerializer());
Directory inApk, out; Directory inApk, out;
try { try {
inApk = apkFile.getDirectory(); inApk = apkFile.getDirectory();
out = new FileDirectory(outDir); out = new FileDirectory(outDir);
if (hasResources())
LOGGER.info("Decoding AndroidManifest.xml framework resources...");
else
LOGGER.info("Decoding AndroidManifest.xml with only framework resources..."); LOGGER.info("Decoding AndroidManifest.xml with only framework resources...");
fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out, "AndroidManifest.xml"); InputStream inputStream = inApk.getFileInput("AndroidManifest.xml");
OutputStream outputStream = out.getFileOutput("AndroidManifest.xml");
fileDecoder.decodeManifest(inputStream, outputStream);
} catch (DirectoryException ex) { } catch (DirectoryException ex) {
throw new AndrolibException(ex); throw new AndrolibException(ex);
} }
} }
private void decodeManifestWithResources(ResTable resTable, ExtFile apkFile, File outDir)
throws AndrolibException {
Duo<ResFileDecoder, AXmlResourceParser> duo = getManifestFileDecoder(true);
ResFileDecoder fileDecoder = duo.m1;
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 resources...");
fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out, "AndroidManifest.xml");
// 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);
}
}
private void adjustPackageManifest(ResTable resTable, String filePath) private void adjustPackageManifest(ResTable resTable, String filePath)
throws AndrolibException { throws AndrolibException {
@ -206,18 +184,6 @@ public class ResourcesDecoder {
} }
} }
private Duo<ResFileDecoder, AXmlResourceParser> 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() { private ExtMXSerializer getResXmlSerializer() {
ExtMXSerializer serial = new ExtMXSerializer(); ExtMXSerializer serial = new ExtMXSerializer();
serial.setProperty(ExtXmlSerializer.PROPERTY_SERIALIZER_INDENTATION, " "); serial.setProperty(ExtXmlSerializer.PROPERTY_SERIALIZER_INDENTATION, " ");