Skip to content

Commit 85a710f

Browse files
authored
refactor class ApkDecoder (#3106)
1 parent 40d427e commit 85a710f

File tree

2 files changed

+129
-141
lines changed

2 files changed

+129
-141
lines changed

brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java

Lines changed: 36 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,17 @@
1919
import brut.androlib.exceptions.AndrolibException;
2020
import brut.androlib.exceptions.InFileNotFoundException;
2121
import brut.androlib.exceptions.OutDirExistsException;
22-
import brut.androlib.exceptions.UndefinedResObjectException;
2322
import brut.androlib.meta.MetaInfo;
24-
import brut.androlib.meta.PackageInfo;
25-
import brut.androlib.meta.UsesFramework;
26-
import brut.androlib.meta.VersionInfo;
2723
import brut.androlib.res.AndrolibResources;
28-
import brut.androlib.res.data.ResPackage;
2924
import brut.androlib.res.data.ResTable;
3025
import brut.androlib.res.data.ResUnknownFiles;
3126
import brut.androlib.src.SmaliDecoder;
3227
import brut.directory.Directory;
3328
import brut.directory.ExtFile;
34-
import brut.androlib.res.xml.ResXmlPatcher;
3529
import brut.common.BrutException;
3630
import brut.directory.DirectoryException;
3731
import brut.util.OS;
3832
import com.android.tools.smali.dexlib2.iface.DexFile;
39-
import com.google.common.base.Strings;
4033
import org.apache.commons.io.FilenameUtils;
4134

4235
import java.io.File;
@@ -111,7 +104,7 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
111104
if (hasResources()) {
112105
switch (config.decodeResources) {
113106
case Config.DECODE_RESOURCES_NONE:
114-
decodeResourcesRaw(mApkFile, outDir);
107+
copyResourcesRaw(mApkFile, outDir);
115108
if (config.forceDecodeManifest == Config.FORCE_DECODE_MANIFEST_FULL) {
116109
// done after raw decoding of resources because copyToDir overwrites dest files
117110
if (hasManifest()) {
@@ -135,15 +128,15 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
135128
decodeManifestFull(mApkFile, outDir, getResTable());
136129
}
137130
else {
138-
decodeManifestRaw(mApkFile, outDir);
131+
copyManifestRaw(mApkFile, outDir);
139132
}
140133
}
141134
}
142135

143136
if (hasSources()) {
144137
switch (config.decodeSources) {
145138
case Config.DECODE_SOURCES_NONE:
146-
decodeSourcesRaw(mApkFile, outDir, "classes.dex");
139+
copySourcesRaw(mApkFile, outDir, "classes.dex");
147140
break;
148141
case Config.DECODE_SOURCES_SMALI:
149142
case Config.DECODE_SOURCES_SMALI_ONLY_MAIN_CLASSES:
@@ -160,7 +153,7 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
160153
if (! file.equalsIgnoreCase("classes.dex")) {
161154
switch(config.decodeSources) {
162155
case Config.DECODE_SOURCES_NONE:
163-
decodeSourcesRaw(mApkFile, outDir, file);
156+
copySourcesRaw(mApkFile, outDir, file);
164157
break;
165158
case Config.DECODE_SOURCES_SMALI:
166159
decodeSourcesSmali(mApkFile, outDir, file);
@@ -169,7 +162,7 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
169162
if (file.startsWith("classes") && file.endsWith(".dex")) {
170163
decodeSourcesSmali(mApkFile, outDir, file);
171164
} else {
172-
decodeSourcesRaw(mApkFile, outDir, file);
165+
copySourcesRaw(mApkFile, outDir, file);
173166
}
174167
break;
175168
}
@@ -178,11 +171,11 @@ public void decode(File outDir) throws AndrolibException, IOException, Directory
178171
}
179172
}
180173

181-
decodeRawFiles(mApkFile, outDir);
182-
decodeUnknownFiles(mApkFile, outDir);
174+
copyRawFiles(mApkFile, outDir);
175+
copyUnknownFiles(mApkFile, outDir);
183176
mUncompressedFiles = new ArrayList<>();
184177
recordUncompressedFiles(mApkFile, mUncompressedFiles);
185-
writeOriginalFiles(mApkFile, outDir);
178+
copyOriginalFiles(mApkFile, outDir);
186179
writeMetaFile(outDir);
187180
} finally {
188181
try {
@@ -250,25 +243,25 @@ public void close() throws IOException {
250243
mAndRes.close();
251244
}
252245

253-
public void writeMetaFile(File outDir)
254-
throws AndrolibException {
246+
private void writeMetaFile(File outDir) throws AndrolibException {
255247
MetaInfo meta = new MetaInfo();
256248
meta.version = ApktoolProperties.getVersion();
257249
meta.apkFileName = mApkFile.getName();
258250

259251
if (mResTable != null) {
260-
meta.isFrameworkApk = mResTable.isFrameworkApk();
261-
putUsesFramework(meta);
262-
putSdkInfo(outDir, meta);
263-
putPackageInfo(meta);
264-
putVersionInfo(outDir, meta);
265-
putSharedLibraryInfo(meta);
266-
putSparseResourcesInfo(meta);
252+
mResTable.initMetaInfo(meta, outDir);
253+
if (config.frameworkTag != null) {
254+
meta.usesFramework.tag = config.frameworkTag;
255+
}
267256
} else {
268-
putMinSdkInfo(meta);
257+
if (mMinSdkVersion > 0) {
258+
meta.sdkInfo = getMinSdkInfo();
259+
}
260+
}
261+
meta.unknownFiles = mResUnknownFiles.getUnknownFiles();
262+
if (mUncompressedFiles != null && !mUncompressedFiles.isEmpty()) {
263+
meta.doNotCompress = mUncompressedFiles;
269264
}
270-
putUnknownInfo(meta);
271-
putFileCompressionInfo(meta);
272265

273266
try {
274267
meta.save(new File(outDir, "apktool.yml"));
@@ -277,111 +270,13 @@ public void writeMetaFile(File outDir)
277270
}
278271
}
279272

280-
private void putUsesFramework(MetaInfo meta) {
281-
Set<ResPackage> pkgs = mResTable.listFramePackages();
282-
if (pkgs.isEmpty()) {
283-
return;
284-
}
285-
286-
Integer[] ids = new Integer[pkgs.size()];
287-
int i = 0;
288-
for (ResPackage pkg : pkgs) {
289-
ids[i++] = pkg.getId();
290-
}
291-
Arrays.sort(ids);
292-
293-
meta.usesFramework = new UsesFramework();
294-
meta.usesFramework.ids = Arrays.asList(ids);
295-
296-
if (config.frameworkTag != null) {
297-
meta.usesFramework.tag = config.frameworkTag;
298-
}
299-
}
300-
301-
private void putSdkInfo(File outDir, MetaInfo meta) {
302-
Map<String, String> info = mResTable.getSdkInfo();
303-
if (info.size() > 0) {
304-
String refValue;
305-
if (info.get("minSdkVersion") != null) {
306-
refValue = ResXmlPatcher.pullValueFromIntegers(outDir, info.get("minSdkVersion"));
307-
if (refValue != null) {
308-
info.put("minSdkVersion", refValue);
309-
}
310-
}
311-
if (info.get("targetSdkVersion") != null) {
312-
refValue = ResXmlPatcher.pullValueFromIntegers(outDir, info.get("targetSdkVersion"));
313-
if (refValue != null) {
314-
info.put("targetSdkVersion", refValue);
315-
}
316-
}
317-
if (info.get("maxSdkVersion") != null) {
318-
refValue = ResXmlPatcher.pullValueFromIntegers(outDir, info.get("maxSdkVersion"));
319-
if (refValue != null) {
320-
info.put("maxSdkVersion", refValue);
321-
}
322-
}
323-
meta.sdkInfo = info;
324-
}
325-
}
326-
327-
private void putMinSdkInfo(MetaInfo meta) {
328-
if (mMinSdkVersion > 0) {
329-
Map<String, String> sdkInfo = new LinkedHashMap<>();
330-
sdkInfo.put("minSdkVersion", Integer.toString(mMinSdkVersion));
331-
meta.sdkInfo = sdkInfo;
332-
}
333-
}
334-
335-
private void putPackageInfo(MetaInfo meta) throws AndrolibException {
336-
String renamed = mResTable.getPackageRenamed();
337-
String original = mResTable.getPackageOriginal();
338-
339-
int id = mResTable.getPackageId();
340-
try {
341-
id = mResTable.getPackage(renamed).getId();
342-
} catch (UndefinedResObjectException ignored) {}
343-
344-
if (Strings.isNullOrEmpty(original)) {
345-
return;
346-
}
347-
348-
meta.packageInfo = new PackageInfo();
349-
350-
// only put rename-manifest-package into apktool.yml, if the change will be required
351-
if (!renamed.equalsIgnoreCase(original)) {
352-
meta.packageInfo.renameManifestPackage = renamed;
353-
}
354-
meta.packageInfo.forcedPackageId = String.valueOf(id);
355-
}
356-
357-
private void putVersionInfo(File outDir, MetaInfo meta) {
358-
VersionInfo info = mResTable.getVersionInfo();
359-
String refValue = ResXmlPatcher.pullValueFromStrings(outDir, info.versionName);
360-
if (refValue != null) {
361-
info.versionName = refValue;
362-
}
363-
meta.versionInfo = info;
364-
}
365-
366-
private void putSharedLibraryInfo(MetaInfo meta) {
367-
meta.sharedLibrary = mResTable.getSharedLibrary();
368-
}
369-
370-
private void putSparseResourcesInfo(MetaInfo meta) {
371-
meta.sparseResources = mResTable.getSparseResources();
372-
}
373-
374-
private void putUnknownInfo(MetaInfo meta) {
375-
meta.unknownFiles = mResUnknownFiles.getUnknownFiles();
376-
}
377-
378-
private void putFileCompressionInfo(MetaInfo meta) {
379-
if (mUncompressedFiles != null && !mUncompressedFiles.isEmpty()) {
380-
meta.doNotCompress = mUncompressedFiles;
381-
}
273+
private Map<String, String> getMinSdkInfo() {
274+
Map<String, String> sdkInfo = new LinkedHashMap<>();
275+
sdkInfo.put("minSdkVersion", Integer.toString(mMinSdkVersion));
276+
return sdkInfo;
382277
}
383278

384-
public void decodeSourcesRaw(ExtFile apkFile, File outDir, String filename)
279+
private void copySourcesRaw(ExtFile apkFile, File outDir, String filename)
385280
throws AndrolibException {
386281
try {
387282
LOGGER.info("Copying raw " + filename + " file...");
@@ -391,7 +286,7 @@ public void decodeSourcesRaw(ExtFile apkFile, File outDir, String filename)
391286
}
392287
}
393288

394-
public void decodeSourcesSmali(File apkFile, File outDir, String filename)
289+
private void decodeSourcesSmali(File apkFile, File outDir, String filename)
395290
throws AndrolibException {
396291
try {
397292
File smaliDir;
@@ -415,7 +310,7 @@ public void decodeSourcesSmali(File apkFile, File outDir, String filename)
415310
}
416311
}
417312

418-
public void decodeManifestRaw(ExtFile apkFile, File outDir)
313+
private void copyManifestRaw(ExtFile apkFile, File outDir)
419314
throws AndrolibException {
420315
try {
421316
LOGGER.info("Copying raw manifest...");
@@ -425,12 +320,12 @@ public void decodeManifestRaw(ExtFile apkFile, File outDir)
425320
}
426321
}
427322

428-
public void decodeManifestFull(ExtFile apkFile, File outDir, ResTable resTable)
323+
private void decodeManifestFull(ExtFile apkFile, File outDir, ResTable resTable)
429324
throws AndrolibException {
430325
mAndRes.decodeManifest(resTable, apkFile, outDir);
431326
}
432327

433-
public void decodeResourcesRaw(ExtFile apkFile, File outDir)
328+
private void copyResourcesRaw(ExtFile apkFile, File outDir)
434329
throws AndrolibException {
435330
try {
436331
LOGGER.info("Copying raw resources...");
@@ -440,17 +335,17 @@ public void decodeResourcesRaw(ExtFile apkFile, File outDir)
440335
}
441336
}
442337

443-
public void decodeResourcesFull(ExtFile apkFile, File outDir, ResTable resTable)
338+
private void decodeResourcesFull(ExtFile apkFile, File outDir, ResTable resTable)
444339
throws AndrolibException {
445340
mAndRes.decode(resTable, apkFile, outDir);
446341
}
447342

448-
public void decodeManifestWithResources(ExtFile apkFile, File outDir, ResTable resTable)
343+
private void decodeManifestWithResources(ExtFile apkFile, File outDir, ResTable resTable)
449344
throws AndrolibException {
450345
mAndRes.decodeManifestWithResources(resTable, apkFile, outDir);
451346
}
452347

453-
public void decodeRawFiles(ExtFile apkFile, File outDir)
348+
private void copyRawFiles(ExtFile apkFile, File outDir)
454349
throws AndrolibException {
455350
LOGGER.info("Copying assets and libs...");
456351
try {
@@ -484,7 +379,7 @@ private boolean isAPKFileNames(String file) {
484379
return false;
485380
}
486381

487-
public void decodeUnknownFiles(ExtFile apkFile, File outDir)
382+
private void copyUnknownFiles(ExtFile apkFile, File outDir)
488383
throws AndrolibException {
489384
LOGGER.info("Copying unknown files...");
490385
File unknownOut = new File(outDir, UNK_DIRNAME);
@@ -508,7 +403,7 @@ public void decodeUnknownFiles(ExtFile apkFile, File outDir)
508403
}
509404
}
510405

511-
public void writeOriginalFiles(ExtFile apkFile, File outDir)
406+
private void copyOriginalFiles(ExtFile apkFile, File outDir)
512407
throws AndrolibException {
513408
LOGGER.info("Copying original files...");
514409
File originalDir = new File(outDir, "original");
@@ -531,7 +426,7 @@ public void writeOriginalFiles(ExtFile apkFile, File outDir)
531426
if (in.containsDir("META-INF/services")) {
532427
// If the original APK contains the folder META-INF/services folder
533428
// that is used for service locators (like coroutines on android),
534-
// copy it to the destination folder so it does not get dropped.
429+
// copy it to the destination folder, so it does not get dropped.
535430
LOGGER.info("Copying META-INF/services directory");
536431
in.copyToDir(outDir, "META-INF/services");
537432
}
@@ -541,7 +436,7 @@ public void writeOriginalFiles(ExtFile apkFile, File outDir)
541436
}
542437
}
543438

544-
public void recordUncompressedFiles(ExtFile apkFile, Collection<String> uncompressedFilesOrExts) throws AndrolibException {
439+
private void recordUncompressedFiles(ExtFile apkFile, Collection<String> uncompressedFilesOrExts) throws AndrolibException {
545440
try {
546441
Directory unk = apkFile.getDirectory();
547442
Set<String> files = unk.getFiles(true);

0 commit comments

Comments
 (0)