Skip to content

Commit 40d427e

Browse files
authored
Extract class Framework from AndrolibResources (#3105)
1 parent 9c495ca commit 40d427e

File tree

6 files changed

+261
-224
lines changed

6 files changed

+261
-224
lines changed

brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import brut.androlib.exceptions.InFileNotFoundException;
2323
import brut.androlib.exceptions.OutDirExistsException;
2424
import brut.androlib.res.AndrolibResources;
25+
import brut.androlib.res.Framework;
2526
import brut.common.BrutException;
2627
import brut.directory.DirectoryException;
2728
import brut.directory.ExtFile;
@@ -271,23 +272,23 @@ private static void cmdBuild(CommandLine cli, Config config) {
271272

272273
private static void cmdInstallFramework(CommandLine cli, Config config) throws AndrolibException {
273274
String apkName = getLastArg(cli);
274-
new AndrolibResources(config).installFramework(new File(apkName));
275+
new Framework(config).installFramework(new File(apkName));
275276
}
276277

277278
private static void cmdListFrameworks(CommandLine cli, Config config) throws AndrolibException {
278-
new AndrolibResources(config).listFrameworkDirectory();
279+
new Framework(config).listFrameworkDirectory();
279280
}
280281

281282
private static void cmdPublicizeResources(CommandLine cli, Config config) throws AndrolibException {
282283
String apkName = getLastArg(cli);
283-
new AndrolibResources(config).publicizeResources(new File(apkName));
284+
new Framework(config).publicizeResources(new File(apkName));
284285
}
285286

286287
private static void cmdEmptyFrameworkDirectory(CommandLine cli, Config config) throws AndrolibException {
287288
if (cli.hasOption("f") || cli.hasOption("force")) {
288289
config.forceDeleteFramework = true;
289290
}
290-
new AndrolibResources(config).emptyFrameworkDirectory();
291+
new Framework(config).emptyFrameworkDirectory();
291292
}
292293

293294
private static String getLastArg(CommandLine cli) {

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import brut.androlib.meta.MetaInfo;
2121
import brut.androlib.meta.UsesFramework;
2222
import brut.androlib.res.AndrolibResources;
23+
import brut.androlib.res.Framework;
2324
import brut.androlib.res.data.ResConfigFlags;
2425
import brut.androlib.res.xml.ResXmlPatcher;
2526
import brut.androlib.src.SmaliBuilder;
@@ -570,11 +571,12 @@ private File[] parseUsesFramework(UsesFramework usesFramework)
570571
return null;
571572
}
572573

574+
Framework framework = new Framework(config);
573575
String tag = usesFramework.tag;
574576
File[] files = new File[ids.size()];
575577
int i = 0;
576578
for (int id : ids) {
577-
files[i++] = mAndRes.getFrameworkApk(id, tag);
579+
files[i++] = framework.getFrameworkApk(id, tag);
578580
}
579581
return files;
580582
}

brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java

Lines changed: 2 additions & 214 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ public ResPackage selectPkgWithMostResSpecs(ResPackage[] pkgs) {
139139

140140
public ResPackage loadFrameworkPkg(ResTable resTable, int id)
141141
throws AndrolibException {
142-
File apk = getFrameworkApk(id, config.frameworkTag);
142+
Framework framework = new Framework(config);
143+
File apk = framework.getFrameworkApk(id, config.frameworkTag);
143144

144145
LOGGER.info("Loading resource table from file: " + apk);
145146
mFramework = new ExtFile(apk);
@@ -819,215 +820,6 @@ private ResPackage[] getResPackagesFromApk(ExtFile apkFile, ResTable resTable, b
819820
}
820821
}
821822

822-
public File getFrameworkApk(int id, String frameTag)
823-
throws AndrolibException {
824-
File dir = getFrameworkDirectory();
825-
File apk;
826-
827-
if (frameTag != null) {
828-
apk = new File(dir, String.valueOf(id) + '-' + frameTag + ".apk");
829-
if (apk.exists()) {
830-
return apk;
831-
}
832-
}
833-
834-
apk = new File(dir, id + ".apk");
835-
if (apk.exists()) {
836-
return apk;
837-
}
838-
839-
if (id == 1) {
840-
try (InputStream in = getAndroidFrameworkResourcesAsStream();
841-
OutputStream out = Files.newOutputStream(apk.toPath())) {
842-
IOUtils.copy(in, out);
843-
return apk;
844-
} catch (IOException ex) {
845-
throw new AndrolibException(ex);
846-
}
847-
}
848-
849-
throw new CantFindFrameworkResException(id);
850-
}
851-
852-
public void emptyFrameworkDirectory() throws AndrolibException {
853-
File dir = getFrameworkDirectory();
854-
File apk;
855-
856-
apk = new File(dir, "1.apk");
857-
858-
if (! apk.exists()) {
859-
LOGGER.warning("Can't empty framework directory, no file found at: " + apk.getAbsolutePath());
860-
} else {
861-
try {
862-
if (apk.exists() && Objects.requireNonNull(dir.listFiles()).length > 1 && ! config.forceDeleteFramework) {
863-
LOGGER.warning("More than default framework detected. Please run command with `--force` parameter to wipe framework directory.");
864-
} else {
865-
for (File file : Objects.requireNonNull(dir.listFiles())) {
866-
if (file.isFile() && file.getName().endsWith(".apk")) {
867-
LOGGER.info("Removing " + file.getName() + " framework file...");
868-
//noinspection ResultOfMethodCallIgnored
869-
file.delete();
870-
}
871-
}
872-
}
873-
} catch (NullPointerException e) {
874-
throw new AndrolibException(e);
875-
}
876-
}
877-
}
878-
879-
public void listFrameworkDirectory() throws AndrolibException {
880-
File dir = getFrameworkDirectory();
881-
if (dir == null) {
882-
LOGGER.severe("No framework directory found. Nothing to list.");
883-
return;
884-
}
885-
886-
for (File file : Objects.requireNonNull(dir.listFiles())) {
887-
if (file.isFile() && file.getName().endsWith(".apk")) {
888-
LOGGER.info(file.getName());
889-
}
890-
}
891-
}
892-
893-
public void installFramework(File frameFile) throws AndrolibException {
894-
installFramework(frameFile, config.frameworkTag);
895-
}
896-
897-
public void installFramework(File frameFile, String tag)
898-
throws AndrolibException {
899-
InputStream in = null;
900-
ZipOutputStream out = null;
901-
try {
902-
ZipFile zip = new ZipFile(frameFile);
903-
ZipEntry entry = zip.getEntry("resources.arsc");
904-
905-
if (entry == null) {
906-
throw new AndrolibException("Can't find resources.arsc file");
907-
}
908-
909-
in = zip.getInputStream(entry);
910-
byte[] data = IOUtils.toByteArray(in);
911-
912-
ARSCData arsc = ARSCDecoder.decode(new ByteArrayInputStream(data), true, true);
913-
publicizeResources(data, arsc.getFlagsOffsets());
914-
915-
File outFile = new File(getFrameworkDirectory(), arsc
916-
.getOnePackage().getId()
917-
+ (tag == null ? "" : '-' + tag)
918-
+ ".apk");
919-
920-
out = new ZipOutputStream(Files.newOutputStream(outFile.toPath()));
921-
out.setMethod(ZipOutputStream.STORED);
922-
CRC32 crc = new CRC32();
923-
crc.update(data);
924-
entry = new ZipEntry("resources.arsc");
925-
entry.setSize(data.length);
926-
entry.setMethod(ZipOutputStream.STORED);
927-
entry.setCrc(crc.getValue());
928-
out.putNextEntry(entry);
929-
out.write(data);
930-
out.closeEntry();
931-
932-
//Write fake AndroidManifest.xml file to support original aapt
933-
entry = zip.getEntry("AndroidManifest.xml");
934-
if (entry != null) {
935-
in = zip.getInputStream(entry);
936-
byte[] manifest = IOUtils.toByteArray(in);
937-
CRC32 manifestCrc = new CRC32();
938-
manifestCrc.update(manifest);
939-
entry.setSize(manifest.length);
940-
entry.setCompressedSize(-1);
941-
entry.setCrc(manifestCrc.getValue());
942-
out.putNextEntry(entry);
943-
out.write(manifest);
944-
out.closeEntry();
945-
}
946-
947-
zip.close();
948-
LOGGER.info("Framework installed to: " + outFile);
949-
} catch (IOException ex) {
950-
throw new AndrolibException(ex);
951-
} finally {
952-
IOUtils.closeQuietly(in);
953-
IOUtils.closeQuietly(out);
954-
}
955-
}
956-
957-
public void publicizeResources(File arscFile) throws AndrolibException {
958-
byte[] data = new byte[(int) arscFile.length()];
959-
960-
try(InputStream in = Files.newInputStream(arscFile.toPath());
961-
OutputStream out = Files.newOutputStream(arscFile.toPath())) {
962-
//noinspection ResultOfMethodCallIgnored
963-
in.read(data);
964-
publicizeResources(data);
965-
out.write(data);
966-
} catch (IOException ex){
967-
throw new AndrolibException(ex);
968-
}
969-
}
970-
971-
public void publicizeResources(byte[] arsc) throws AndrolibException {
972-
publicizeResources(arsc, ARSCDecoder.decode(new ByteArrayInputStream(arsc), true, true).getFlagsOffsets());
973-
}
974-
975-
public void publicizeResources(byte[] arsc, FlagsOffset[] flagsOffsets) {
976-
for (FlagsOffset flags : flagsOffsets) {
977-
int offset = flags.offset + 3;
978-
int end = offset + 4 * flags.count;
979-
while (offset < end) {
980-
arsc[offset] |= (byte) 0x40;
981-
offset += 4;
982-
}
983-
}
984-
}
985-
986-
public File getFrameworkDirectory() throws AndrolibException {
987-
if (mFrameworkDirectory != null) {
988-
return mFrameworkDirectory;
989-
}
990-
991-
String path;
992-
993-
// use default framework path or specified on the command line
994-
path = config.frameworkDirectory;
995-
996-
File dir = new File(path);
997-
998-
if (!dir.isDirectory() && dir.isFile()) {
999-
throw new AndrolibException("--frame-path is set to a file, not a directory.");
1000-
}
1001-
1002-
if (dir.getParentFile() != null && dir.getParentFile().isFile()) {
1003-
throw new AndrolibException("Please remove file at " + dir.getParentFile());
1004-
}
1005-
1006-
if (! dir.exists()) {
1007-
if (! dir.mkdirs()) {
1008-
if (config.frameworkDirectory != null) {
1009-
LOGGER.severe("Can't create Framework directory: " + dir);
1010-
}
1011-
throw new AndrolibException(String.format(
1012-
"Can't create directory: (%s). Pass a writable path with --frame-path {DIR}. ", dir
1013-
));
1014-
}
1015-
}
1016-
1017-
if (config.frameworkDirectory == null) {
1018-
if (! dir.canWrite()) {
1019-
LOGGER.severe(String.format("WARNING: Could not write to (%1$s), using %2$s instead...",
1020-
dir.getAbsolutePath(), System.getProperty("java.io.tmpdir")));
1021-
LOGGER.severe("Please be aware this is a volatile directory and frameworks could go missing, " +
1022-
"please utilize --frame-path if the default storage directory is unavailable");
1023-
1024-
dir = new File(System.getProperty("java.io.tmpdir"));
1025-
}
1026-
}
1027-
1028-
mFrameworkDirectory = dir;
1029-
return dir;
1030-
}
1031823

1032824
private File getAaptBinaryFile() throws AndrolibException {
1033825
try {
@@ -1044,10 +836,6 @@ private int getAaptVersion() {
1044836
return config.isAapt2() ? 2 : 1;
1045837
}
1046838

1047-
public InputStream getAndroidFrameworkResourcesAsStream() {
1048-
return Jar.class.getResourceAsStream("/brut/androlib/android-framework.jar");
1049-
}
1050-
1051839
public void close() throws IOException {
1052840
if (mFramework != null) {
1053841
mFramework.close();

0 commit comments

Comments
 (0)