Determine minSdkVersion with baksmali for JARs + don't compress webp

We take advantage of the fact that baksmali can determine the minimum API version needed for a given collection of opcodes and extract it, then save to mMinSdkVersion, which is only used by smali via buildSourcesSmali.
This change, in addition to my previous change, allows to decompile and recompile JARs without worrying about specifying an API version via -api/--api-level.

As an extra, added webp file extension to NO_COMPRESS_PATTERN, according to AAPT2 standards, and since it's factually never compresses as it's an already compressed format.
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/tools/aapt2/cmd/Link.cpp;l=2328
This commit is contained in:
IgorEisberg 2021-07-04 02:14:56 +03:00
parent 1ed1076a84
commit 6cfa79e456
3 changed files with 29 additions and 10 deletions

View File

@ -50,16 +50,15 @@ public class Androlib {
public ApkOptions apkOptions;
private int mMinSdkVersion = 0;
public Androlib() {
this(new ApkOptions());
}
public Androlib(ApkOptions apkOptions) {
this.apkOptions = apkOptions;
mAndRes.apkOptions = apkOptions;
}
public Androlib() {
this.apkOptions = new ApkOptions();
mAndRes.apkOptions = this.apkOptions;
}
public ResTable getResTable(ExtFile apkFile)
throws AndrolibException {
return mAndRes.getResTable(apkFile, true);
@ -70,6 +69,10 @@ public class Androlib {
return mAndRes.getResTable(apkFile, loadMainPkg);
}
public int getMinSdkVersion() {
return mMinSdkVersion;
}
public void decodeSourcesRaw(ExtFile apkFile, File outDir, String filename)
throws AndrolibException {
try {
@ -92,7 +95,10 @@ public class Androlib {
OS.rmdir(smaliDir);
smaliDir.mkdirs();
LOGGER.info("Baksmaling " + filename + "...");
SmaliDecoder.decode(apkFile, smaliDir, filename, bakDeb, apiLevel);
apiLevel = SmaliDecoder.decode(apkFile, smaliDir, filename, bakDeb, apiLevel);
if (mMinSdkVersion == 0 || mMinSdkVersion > apiLevel) {
mMinSdkVersion = apiLevel;
}
} catch (BrutException ex) {
throw new AndrolibException(ex);
}
@ -809,5 +815,5 @@ public class Androlib {
"lib", "libs", "assets", "META-INF", "kotlin" };
private final static Pattern NO_COMPRESS_PATTERN = Pattern.compile("(" +
"jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|rtttl|imy|xmf|mp4|" +
"m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|mkv)$");
"m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|webp|mkv)$");
}

View File

@ -332,6 +332,8 @@ public class ApkDecoder {
putVersionInfo(meta);
putSharedLibraryInfo(meta);
putSparseResourcesInfo(meta);
} else {
putMinSdkInfo(meta);
}
putUnknownInfo(meta);
putFileCompressionInfo(meta);
@ -386,6 +388,15 @@ public class ApkDecoder {
}
}
private void putMinSdkInfo(MetaInfo meta) {
int minSdkVersion = mAndrolib.getMinSdkVersion();
if (minSdkVersion > 0) {
Map<String, String> sdkInfo = new LinkedHashMap<>();
sdkInfo.put("minSdkVersion", Integer.toString(minSdkVersion));
meta.sdkInfo = sdkInfo;
}
}
private void putPackageInfo(MetaInfo meta) throws AndrolibException {
String renamed = mResTable.getPackageRenamed();
String original = mResTable.getPackageOriginal();

View File

@ -31,9 +31,9 @@ import java.io.IOException;
public class SmaliDecoder {
public static void decode(File apkFile, File outDir, String dexName, boolean bakDeb, int apiLevel)
public static int decode(File apkFile, File outDir, String dexName, boolean bakDeb, int apiLevel)
throws AndrolibException {
new SmaliDecoder(apkFile, outDir, dexName, bakDeb, apiLevel).decode();
return new SmaliDecoder(apkFile, outDir, dexName, bakDeb, apiLevel).decode();
}
private SmaliDecoder(File apkFile, File outDir, String dexName, boolean bakDeb, int apiLevel) {
@ -44,7 +44,7 @@ public class SmaliDecoder {
mApiLevel = apiLevel;
}
private void decode() throws AndrolibException {
private int decode() throws AndrolibException {
try {
final BaksmaliOptions options = new BaksmaliOptions();
@ -96,6 +96,8 @@ public class SmaliDecoder {
}
Baksmali.disassembleDexFile(dexFile, mOutDir, jobs, options);
return dexFile.getOpcodes().api;
} catch (IOException ex) {
throw new AndrolibException(ex);
}