From 9b9904aa3c97f9f2aa72a23d928770e0a141c983 Mon Sep 17 00:00:00 2001 From: corysmith Date: Mon, 13 Aug 2018 13:03:01 -0700 Subject: Correctly manage the ProtoApk lifecycle by ensuring it is closed when finished. Move finding used resources to ProtoResourceUsageAnalyzer for correctness and memory improvements. New report format: now records the kept resource along with the resource that keep it, as well maintaining the root status for each resource. Example line: {number/foo[isRoot: false] = 0x07f...} => [{array/foos[isRoot: true] = 0x...}...] RELNOTES: None PiperOrigin-RevId: 208529350 --- .../devtools/build/android/ResourcesZip.java | 45 +++++++++++++++++----- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'src/tools/android/java/com/google/devtools/build/android/ResourcesZip.java') diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourcesZip.java b/src/tools/android/java/com/google/devtools/build/android/ResourcesZip.java index c4998ce917..71b2daa14c 100644 --- a/src/tools/android/java/com/google/devtools/build/android/ResourcesZip.java +++ b/src/tools/android/java/com/google/devtools/build/android/ResourcesZip.java @@ -30,6 +30,7 @@ import com.google.devtools.build.android.aapt2.ProtoResourceUsageAnalyzer; import com.google.devtools.build.android.aapt2.ResourceCompiler; import com.google.devtools.build.android.aapt2.ResourceLinker; import com.google.devtools.build.android.proto.SerializeFormat.ToolAttributes; +import java.io.Closeable; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -43,6 +44,7 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; @@ -185,6 +187,9 @@ public class ResourcesZip { if (apkWithAssets != null) { ZipFile apkZip = new ZipFile(apkWithAssets.toString()); + if (apkZip.getEntry("assets/") == null) { + zip.addEntry("assets/", new byte[0], compress ? ZipEntry.DEFLATED : ZipEntry.STORED); + } apkZip .stream() .filter(entry -> entry.getName().startsWith("assets/")) @@ -196,7 +201,6 @@ public class ResourcesZip { throw new RuntimeException(e); } }); - zip.addEntry("assets/", new byte[0], compress ? ZipEntry.DEFLATED : ZipEntry.STORED); } else if (Files.exists(assetsRoot)) { ZipBuilderVisitorWithDirectories visitor = new ZipBuilderVisitorWithDirectories(zip, assetsRoot, "assets"); @@ -243,6 +247,21 @@ public class ResourcesZip { ImmutableList.of(workingDirectory), ImmutableList.of(assetsRoot), manifest)); } + /** + * Shrinks the apk using a protocol buffer apk. + * + * @param packages The packages of the dependencies. Used to analyze the java code for resource + * references. + * @param classJar Used to find resource references in java. + * @param proguardMapping Mapping used to decode java references. + * @param logFile Destination of the resource shrinker log. + * @param workingDirectory Temporary directory for intermediate artifacts. + * @return A ShrunkProtoApk, which must be closed when finished. + * @throws ParserConfigurationException thrown when the xml parsing not possible. + * @throws IOException thrown when the filesystem is going pear shaped. + * @throws SAXException thrown when the xml parsing goes badly. + */ + @CheckReturnValue public ShrunkProtoApk shrinkUsingProto( Set packages, Path classJar, @@ -254,14 +273,17 @@ public class ResourcesZip { try (final ProtoApk apk = ProtoApk.readFrom(proto)) { final Map> toolAttributes = toAttributes(); // record resources and manifest - new ProtoResourceUsageAnalyzer(packages, proguardMapping, logFile) - .shrink( + final ProtoResourceUsageAnalyzer analyzer = + new ProtoResourceUsageAnalyzer(packages, proguardMapping, logFile); + + final ProtoApk shrink = + analyzer.shrink( apk, classJar, shrunkApkProto, toolAttributes.getOrDefault(SdkConstants.ATTR_KEEP, ImmutableSet.of()), toolAttributes.getOrDefault(SdkConstants.ATTR_DISCARD, ImmutableSet.of())); - return new ShrunkProtoApk(shrunkApkProto, logFile, ids); + return new ShrunkProtoApk(shrink, logFile, ids); } } @@ -274,12 +296,12 @@ public class ResourcesZip { .collect(toMap(Entry::getKey, e -> ImmutableSet.copyOf(e.getValue().getValuesList()))); } - static class ShrunkProtoApk { - private final Path apk; + static class ShrunkProtoApk implements Closeable { + private final ProtoApk apk; private final Path report; private final Path ids; - ShrunkProtoApk(Path apk, Path report, Path ids) { + ShrunkProtoApk(ProtoApk apk, Path report, Path ids) { this.apk = apk; this.report = report; this.ids = ids; @@ -288,7 +310,7 @@ public class ResourcesZip { ShrunkProtoApk writeBinaryTo(ResourceLinker linker, Path binaryOut, boolean writeAsProto) throws IOException { Files.copy( - writeAsProto ? apk : linker.link(ProtoApk.readFrom(apk), ids), + writeAsProto ? apk.asApkPath() : linker.link(apk, ids), binaryOut, StandardCopyOption.REPLACE_EXISTING); return this; @@ -301,10 +323,15 @@ public class ResourcesZip { ShrunkProtoApk writeResourcesToZip(Path resourcesZip) throws IOException { try (final ZipBuilder zip = ZipBuilder.createFor(resourcesZip)) { - zip.addEntry("apk.pb", Files.readAllBytes(apk), ZipEntry.STORED); + zip.addEntry("apk.pb", Files.readAllBytes(apk.asApkPath()), ZipEntry.STORED); } return this; } + + @Override + public void close() throws IOException { + apk.close(); + } } static class ShrunkResources { -- cgit v1.2.3