Revert "Initial setup for doing legacy resource shrinking in R8"
This reverts commit 988e2977fe9080929bde61bfe20a8a9d9e6e60ad.
Reason for revert: broke bots
Change-Id: I99706d725a780ad164cd26675af37c42f3b182e0
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index e19a8ad..9964d6e 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -7,9 +7,6 @@
import static com.android.tools.r8.utils.AssertionUtils.forTesting;
import static com.android.tools.r8.utils.ExceptionUtils.unwrapExecutionException;
-import com.android.build.shrinker.r8integration.LegacyResourceShrinker;
-import com.android.build.shrinker.r8integration.LegacyResourceShrinker.ShrinkerResult;
-import com.android.tools.r8.DexIndexedConsumer.ForwardingConsumer;
import com.android.tools.r8.androidapi.ApiReferenceStubber;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryKeepRuleGenerator;
import com.android.tools.r8.dex.ApplicationReader;
@@ -78,7 +75,6 @@
import com.android.tools.r8.optimize.proto.ProtoNormalizer;
import com.android.tools.r8.optimize.redundantbridgeremoval.RedundantBridgeRemover;
import com.android.tools.r8.origin.CommandLineOrigin;
-import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.profile.art.ArtProfileCompletenessChecker;
import com.android.tools.r8.profile.rewriting.ProfileCollectionAdditions;
import com.android.tools.r8.repackaging.Repackaging;
@@ -109,11 +105,9 @@
import com.android.tools.r8.synthesis.SyntheticFinalization;
import com.android.tools.r8.synthesis.SyntheticItems;
import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.Pair;
-import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.ResourceTracing;
import com.android.tools.r8.utils.SelfRetraceTest;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
@@ -124,8 +118,6 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -133,8 +125,6 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
-import javax.xml.parsers.ParserConfigurationException;
-import org.xml.sax.SAXException;
/**
* The R8 compiler.
@@ -840,29 +830,17 @@
new DesugaredLibraryKeepRuleGenerator(appView).runIfNecessary(timing);
- List<Pair<Integer, byte[]>> dexFileContent = new ArrayList<>();
if (options.androidResourceProvider != null && options.androidResourceConsumer != null) {
- options.programConsumer =
- new ForwardingConsumer((DexIndexedConsumer) options.programConsumer) {
- @Override
- public void accept(
- int fileIndex,
- ByteDataView data,
- Set<String> descriptors,
- DiagnosticsHandler handler) {
- dexFileContent.add(new Pair<>(fileIndex, data.copyByteData()));
- super.accept(fileIndex, data, descriptors, handler);
- }
- };
+ // Currently this is simply a pass through of all resources.
+ writeAndroidResources(
+ options.androidResourceProvider, options.androidResourceConsumer, appView.reporter());
}
assert appView.verifyMovedMethodsHaveOriginalMethodPosition();
+
// Generate the resulting application resources.
writeApplication(appView, inputApp, executorService);
- if (options.androidResourceProvider != null && options.androidResourceConsumer != null) {
- shrinkResources(dexFileContent);
- }
assert appView.getDontWarnConfiguration().validate(options);
options.printWarnings();
@@ -878,68 +856,14 @@
}
}
- private void shrinkResources(List<Pair<Integer, byte[]>> dexFileContent) {
- LegacyResourceShrinker.Builder resourceShrinkerBuilder = LegacyResourceShrinker.builder();
- Reporter reporter = options.reporter;
- dexFileContent.forEach(p -> resourceShrinkerBuilder.addDexInput(p.getFirst(), p.getSecond()));
- try {
- Collection<AndroidResourceInput> androidResources =
- options.androidResourceProvider.getAndroidResources();
- for (AndroidResourceInput androidResource : androidResources) {
- try {
- byte[] bytes = androidResource.getByteStream().readAllBytes();
- Path path = Paths.get(androidResource.getPath().location());
- switch (androidResource.getKind()) {
- case MANIFEST:
- resourceShrinkerBuilder.setManifest(path, bytes);
- break;
- case RES_FOLDER_FILE:
- resourceShrinkerBuilder.addResFolderInput(path, bytes);
- break;
- case RESOURCE_TABLE:
- resourceShrinkerBuilder.setResourceTable(path, bytes);
- break;
- case XML_FILE:
- resourceShrinkerBuilder.addXmlInput(path, bytes);
- break;
- case UNKNOWN:
- break;
- }
- } catch (IOException e) {
- reporter.error(new ExceptionDiagnostic(e, androidResource.getOrigin()));
- }
- }
-
- LegacyResourceShrinker shrinker = resourceShrinkerBuilder.build();
- ShrinkerResult shrinkerResult = shrinker.run();
- AndroidResourceConsumer androidResourceConsumer = options.androidResourceConsumer;
- Set<String> toKeep = shrinkerResult.getResFolderEntriesToKeep();
- for (AndroidResourceInput androidResource : androidResources) {
- switch (androidResource.getKind()) {
- case MANIFEST:
- case UNKNOWN:
- androidResourceConsumer.accept(
- new R8PassThroughAndroidResource(androidResource, reporter), reporter);
- break;
- case RESOURCE_TABLE:
- androidResourceConsumer.accept(
- new R8AndroidResourceWithData(
- androidResource, reporter, shrinkerResult.getResourceTableInProtoFormat()),
- reporter);
- break;
- case RES_FOLDER_FILE:
- case XML_FILE:
- if (toKeep.contains(androidResource.getPath().location())) {
- androidResourceConsumer.accept(
- new R8PassThroughAndroidResource(androidResource, reporter), reporter);
- }
- break;
- }
- }
- androidResourceConsumer.finished(reporter);
- } catch (ParserConfigurationException | SAXException | ResourceException | IOException e) {
- reporter.error(new ExceptionDiagnostic(e));
- }
+ private void writeAndroidResources(
+ AndroidResourceProvider androidResourceProvider,
+ AndroidResourceConsumer androidResourceConsumer,
+ DiagnosticsHandler diagnosticsHandler) {
+ ResourceTracing resourceTracing = ResourceTracing.getImpl();
+ resourceTracing.setConsumer(androidResourceConsumer);
+ resourceTracing.setProvider(androidResourceProvider);
+ resourceTracing.done(diagnosticsHandler);
}
private static boolean allReferencesAssignedApiLevel(
@@ -1169,58 +1093,4 @@
}
ExceptionUtils.withMainProgramHandler(() -> run(args));
}
-
- private abstract static class R8AndroidResourceBase implements AndroidResourceOutput {
-
- protected final AndroidResourceInput androidResource;
- protected final Reporter reporter;
-
- public R8AndroidResourceBase(AndroidResourceInput androidResource, Reporter reporter) {
- this.androidResource = androidResource;
- this.reporter = reporter;
- }
-
- @Override
- public ResourcePath getPath() {
- return androidResource.getPath();
- }
-
- @Override
- public Origin getOrigin() {
- return androidResource.getOrigin();
- }
- }
-
- private static class R8PassThroughAndroidResource extends R8AndroidResourceBase {
-
- public R8PassThroughAndroidResource(AndroidResourceInput androidResource, Reporter reporter) {
- super(androidResource, reporter);
- }
-
- @Override
- public ByteDataView getByteDataView() {
- try {
- return ByteDataView.of(ByteStreams.toByteArray(androidResource.getByteStream()));
- } catch (IOException | ResourceException e) {
- reporter.error(new ExceptionDiagnostic(e, androidResource.getOrigin()));
- }
- return null;
- }
- }
-
- private static class R8AndroidResourceWithData extends R8AndroidResourceBase {
-
- private final byte[] data;
-
- public R8AndroidResourceWithData(
- AndroidResourceInput androidResource, Reporter reporter, byte[] data) {
- super(androidResource, reporter);
- this.data = data;
- }
-
- @Override
- public ByteDataView getByteDataView() {
- return ByteDataView.of(data);
- }
- }
}
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/ResourceShrinkerImpl.kt b/src/resourceshrinker/java/com/android/build/shrinker/ResourceShrinkerImpl.kt
index 153f1ce..1136085 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/ResourceShrinkerImpl.kt
+++ b/src/resourceshrinker/java/com/android/build/shrinker/ResourceShrinkerImpl.kt
@@ -301,11 +301,6 @@
.any { it.isReachable }
}
-fun ResourceStore.isJarPathReachable(path: String) : Boolean {
- val (_, folder, name) = path.split('/', limit = 3)
- return isJarPathReachable(folder, name);
-}
-
private fun ResourceStore.getResourceId(
folder: String,
name: String
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/graph/ProtoResourcesGraphBuilder.kt b/src/resourceshrinker/java/com/android/build/shrinker/graph/ProtoResourcesGraphBuilder.kt
index a0a1f76..130e585 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/graph/ProtoResourcesGraphBuilder.kt
+++ b/src/resourceshrinker/java/com/android/build/shrinker/graph/ProtoResourcesGraphBuilder.kt
@@ -21,7 +21,6 @@
import com.android.aapt.Resources.FileReference
import com.android.aapt.Resources.FileReference.Type.PROTO_XML
import com.android.aapt.Resources.Reference
-import com.android.aapt.Resources.ResourceTable
import com.android.aapt.Resources.XmlAttribute
import com.android.aapt.Resources.XmlElement
import com.android.aapt.Resources.XmlNode
@@ -57,23 +56,12 @@
* @param resourceTable path to resource table in proto format.
*/
class ProtoResourcesGraphBuilder(
- private val resourceRoot: ResFolderFileTree,
- private val resourceTableProducer: (ResourceShrinkerModel) -> ResourceTable
+ private val resourceRoot: Path,
+ private val resourceTable: Path
) : ResourcesGraphBuilder {
- constructor(resourceRootPath: Path, resourceTablePath: Path) : this(
- object : ResFolderFileTree {
- override fun getEntryByName(pathInRes: String): ByteArray {
- val lazyVal : ByteArray by lazy {
- Files.readAllBytes(resourceRootPath.resolve(pathInRes))
- }
- return lazyVal
- }
- },
- { model -> model.readResourceTable(resourceTablePath) }
- )
override fun buildGraph(model: ResourceShrinkerModel) {
- resourceTableProducer(model).entriesSequence()
+ model.readResourceTable(resourceTable).entriesSequence()
.map { (id, _, _, entry) ->
model.resourceStore.getResource(id)?.let {
ReferencesForResourceFinder(resourceRoot, model, entry, it)
@@ -83,12 +71,9 @@
.forEach { it.findReferences() }
}
}
-interface ResFolderFileTree {
- fun getEntryByName(pathInRes: String) : ByteArray
-}
private class ReferencesForResourceFinder(
- private val resourcesRoot: ResFolderFileTree,
+ private val resourcesRoot: Path,
private val model: ResourceShrinkerModel,
private val entry: Entry,
private val current: Resource
@@ -211,9 +196,10 @@
}
private fun findFromFile(file: FileReference) {
- val bytes = resourcesRoot.getEntryByName(file.path.substringAfter("res/"))
+ val path = resourcesRoot.resolve(file.path.substringAfter("res/"))
+ val bytes: ByteArray by lazy { Files.readAllBytes(path) }
val content: String by lazy { String(bytes, StandardCharsets.UTF_8) }
- val extension = Ascii.toLowerCase(file.path.substringAfterLast('.'))
+ val extension = Ascii.toLowerCase(path.fileName.toString()).substringAfter('.')
when {
file.type == PROTO_XML -> fillFromXmlNode(XmlNode.parseFrom(bytes))
extension in listOf("html", "htm") -> webTokenizers.tokenizeHtml(content)
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/LegacyResourceShrinker.java b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/LegacyResourceShrinker.java
deleted file mode 100644
index 9fd4163..0000000
--- a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/LegacyResourceShrinker.java
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.build.shrinker.r8integration;
-
-import static java.nio.charset.StandardCharsets.UTF_16BE;
-import static java.nio.charset.StandardCharsets.UTF_16LE;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.android.aapt.Resources.ResourceTable;
-import com.android.aapt.Resources.XmlNode;
-import com.android.build.shrinker.NoDebugReporter;
-import com.android.build.shrinker.ResourceShrinkerImplKt;
-import com.android.build.shrinker.ResourceTableUtilKt;
-import com.android.build.shrinker.graph.ProtoResourcesGraphBuilder;
-import com.android.build.shrinker.graph.ResFolderFileTree;
-import com.android.build.shrinker.r8integration.R8ResourceShrinkerState.R8ResourceShrinkerModel;
-import com.android.build.shrinker.usages.DexFileAnalysisCallback;
-import com.android.build.shrinker.usages.ProtoAndroidManifestUsageRecorderKt;
-import com.android.build.shrinker.usages.R8ResourceShrinker;
-import com.android.build.shrinker.usages.ToolsAttributeUsageRecorderKt;
-import com.android.ide.common.resources.usage.ResourceStore;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringReader;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.xml.parsers.ParserConfigurationException;
-import org.jetbrains.annotations.NotNull;
-import org.xml.sax.SAXException;
-
-public class LegacyResourceShrinker {
- private final Map<Integer, byte[]> dexInputs;
- private final List<PathAndBytes> resFolderInputs;
- private final List<PathAndBytes> xmlInputs;
- private final PathAndBytes manifest;
- private final PathAndBytes resourceTable;
-
- public static class Builder {
-
- private final Map<Integer, byte[]> dexInputs = new HashMap<>();
- private final List<PathAndBytes> resFolderInputs = new ArrayList<>();
- private final List<PathAndBytes> xmlInputs = new ArrayList<>();
-
- private PathAndBytes manifest;
- private PathAndBytes resourceTable;
-
- private Builder() {}
-
- public Builder setManifest(Path path, byte[] bytes) {
- this.manifest = new PathAndBytes(bytes, path);
- return this;
- }
-
- public Builder setResourceTable(Path path, byte[] bytes) {
- this.resourceTable = new PathAndBytes(bytes, path);
- return this;
- }
-
- public Builder addDexInput(int index, byte[] bytes) {
- dexInputs.put(index, bytes);
- return this;
- }
-
- public Builder addResFolderInput(Path path, byte[] bytes) {
- resFolderInputs.add(new PathAndBytes(bytes, path));
- return this;
- }
-
- public Builder addXmlInput(Path path, byte[] bytes) {
- xmlInputs.add(new PathAndBytes(bytes, path));
- return this;
- }
-
- public LegacyResourceShrinker build() {
- assert manifest != null && resourceTable != null;
- return new LegacyResourceShrinker(
- dexInputs, resFolderInputs, manifest, resourceTable, xmlInputs);
- }
- }
-
- private LegacyResourceShrinker(
- Map<Integer, byte[]> dexInputs,
- List<PathAndBytes> resFolderInputs,
- PathAndBytes manifest,
- PathAndBytes resourceTable,
- List<PathAndBytes> xmlInputs) {
- this.dexInputs = dexInputs;
- this.resFolderInputs = resFolderInputs;
- this.manifest = manifest;
- this.resourceTable = resourceTable;
- this.xmlInputs = xmlInputs;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public ShrinkerResult run() throws IOException, ParserConfigurationException, SAXException {
- R8ResourceShrinkerModel model = new R8ResourceShrinkerModel(NoDebugReporter.INSTANCE, false);
- ResourceTable loadedResourceTable = ResourceTable.parseFrom(resourceTable.bytes);
- model.instantiateFromResourceTable(loadedResourceTable);
- for (Entry<Integer, byte[]> entry : dexInputs.entrySet()) {
- // The analysis needs an origin for the dex files, synthesize an easy recognizable one.
- Path inMemoryR8 = Paths.get("in_memory_r8_classes" + entry.getKey() + ".dex");
- R8ResourceShrinker.runResourceShrinkerAnalysis(
- entry.getValue(), inMemoryR8, new DexFileAnalysisCallback(inMemoryR8, model));
- }
- ProtoAndroidManifestUsageRecorderKt.recordUsagesFromNode(
- XmlNode.parseFrom(manifest.bytes), model);
- for (PathAndBytes xmlInput : xmlInputs) {
- ToolsAttributeUsageRecorderKt.processRawXml(getUtfReader(xmlInput.getBytes()), model);
- }
- new ProtoResourcesGraphBuilder(
- new ResFolderFileTree() {
- Map<String, PathAndBytes> pathToBytes =
- new ImmutableMap.Builder<String, PathAndBytes>()
- .putAll(
- xmlInputs.stream()
- .collect(Collectors.toMap(PathAndBytes::getPathWithoutRes, a -> a)))
- .putAll(
- resFolderInputs.stream()
- .collect(Collectors.toMap(PathAndBytes::getPathWithoutRes, a -> a)))
- .build();
-
- @Override
- public byte[] getEntryByName(@NotNull String pathInRes) {
- return pathToBytes.get(pathInRes).getBytes();
- }
- },
- unused -> loadedResourceTable)
- .buildGraph(model);
- ResourceStore resourceStore = model.getResourceStore();
- resourceStore.processToolsAttributes();
- model.keepPossiblyReferencedResources();
- ImmutableSet.Builder<String> resEntriesToKeep = new ImmutableSet.Builder<>();
- for (PathAndBytes xmlInput : Iterables.concat(xmlInputs, resFolderInputs)) {
- if (ResourceShrinkerImplKt.isJarPathReachable(resourceStore, xmlInput.path.toString())) {
- resEntriesToKeep.add(xmlInput.path.toString());
- }
- }
- List<Integer> resourceIdsToRemove =
- model.getResourceStore().getResources().stream()
- .filter(r -> !r.isReachable())
- .map(r -> r.value)
- .collect(Collectors.toList());
- ResourceTable shrunkenResourceTable =
- ResourceTableUtilKt.nullOutEntriesWithIds(loadedResourceTable, resourceIdsToRemove);
- return new ShrinkerResult(resEntriesToKeep.build(), shrunkenResourceTable.toByteArray());
- }
-
- // Lifted from com/android/utils/XmlUtils.java which we can't easily update internal dependency
- // for.
- /**
- * Returns a character reader for the given bytes, which must be a UTF encoded file.
- *
- * <p>The reader does not need to be closed by the caller (because the file is read in full in one
- * shot and the resulting array is then wrapped in a byte array input stream, which does not need
- * to be closed.)
- */
- public static Reader getUtfReader(byte[] bytes) throws IOException {
- int length = bytes.length;
- if (length == 0) {
- return new StringReader("");
- }
-
- switch (bytes[0]) {
- case (byte) 0xEF:
- {
- if (length >= 3 && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) {
- // UTF-8 BOM: EF BB BF: Skip it
- return new InputStreamReader(new ByteArrayInputStream(bytes, 3, length - 3), UTF_8);
- }
- break;
- }
- case (byte) 0xFE:
- {
- if (length >= 2 && bytes[1] == (byte) 0xFF) {
- // UTF-16 Big Endian BOM: FE FF
- return new InputStreamReader(new ByteArrayInputStream(bytes, 2, length - 2), UTF_16BE);
- }
- break;
- }
- case (byte) 0xFF:
- {
- if (length >= 2 && bytes[1] == (byte) 0xFE) {
- if (length >= 4 && bytes[2] == (byte) 0x00 && bytes[3] == (byte) 0x00) {
- // UTF-32 Little Endian BOM: FF FE 00 00
- return new InputStreamReader(
- new ByteArrayInputStream(bytes, 4, length - 4), "UTF-32LE");
- }
-
- // UTF-16 Little Endian BOM: FF FE
- return new InputStreamReader(new ByteArrayInputStream(bytes, 2, length - 2), UTF_16LE);
- }
- break;
- }
- case (byte) 0x00:
- {
- if (length >= 4
- && bytes[0] == (byte) 0x00
- && bytes[1] == (byte) 0x00
- && bytes[2] == (byte) 0xFE
- && bytes[3] == (byte) 0xFF) {
- // UTF-32 Big Endian BOM: 00 00 FE FF
- return new InputStreamReader(
- new ByteArrayInputStream(bytes, 4, length - 4), "UTF-32BE");
- }
- break;
- }
- }
-
- // No byte order mark: Assume UTF-8 (where the BOM is optional).
- return new InputStreamReader(new ByteArrayInputStream(bytes), UTF_8);
- }
-
- public static class ShrinkerResult {
- private final Set<String> resFolderEntriesToKeep;
- private final byte[] resourceTableInProtoFormat;
-
- public ShrinkerResult(Set<String> resFolderEntriesToKeep, byte[] resourceTableInProtoFormat) {
- this.resFolderEntriesToKeep = resFolderEntriesToKeep;
- this.resourceTableInProtoFormat = resourceTableInProtoFormat;
- }
-
- public byte[] getResourceTableInProtoFormat() {
- return resourceTableInProtoFormat;
- }
-
- public Set<String> getResFolderEntriesToKeep() {
- return resFolderEntriesToKeep;
- }
- }
-
- private static class PathAndBytes {
- private final byte[] bytes;
- private final Path path;
-
- private PathAndBytes(byte[] bytes, Path path) {
- this.bytes = bytes;
- this.path = path;
- }
-
- public Path getPath() {
- return path;
- }
-
- public String getPathWithoutRes() {
- assert path.toString().startsWith("res/");
- return path.toString().substring(4);
- }
-
- public byte[] getBytes() {
- return bytes;
- }
- }
-}
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
index d8ac6a9..5f9bec6 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
+++ b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
@@ -32,7 +32,7 @@
r8ResourceShrinkerModel.instantiateFromResourceTable(inputStream);
}
- public static class R8ResourceShrinkerModel extends ResourceShrinkerModel {
+ private static class R8ResourceShrinkerModel extends ResourceShrinkerModel {
public R8ResourceShrinkerModel(
ShrinkerDebugReporter debugReporter, boolean supportMultipackages) {
@@ -40,29 +40,25 @@
}
// Similar to instantiation in ProtoResourceTableGatherer, but using an inputstream.
- void instantiateFromResourceTable(InputStream inputStream) {
+ public void instantiateFromResourceTable(InputStream inputStream) {
try {
ResourceTable resourceTable = ResourceTable.parseFrom(inputStream);
- instantiateFromResourceTable(resourceTable);
+ ResourceTableUtilKt.entriesSequence(resourceTable)
+ .iterator()
+ .forEachRemaining(
+ entryWrapper -> {
+ ResourceType resourceType = ResourceType.fromClassName(entryWrapper.getType());
+ if (resourceType != ResourceType.STYLEABLE) {
+ this.addResource(
+ resourceType,
+ entryWrapper.getPackageName(),
+ ResourcesUtil.resourceNameToFieldName(entryWrapper.getEntry().getName()),
+ entryWrapper.getId());
+ }
+ });
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
-
- void instantiateFromResourceTable(ResourceTable resourceTable) {
- ResourceTableUtilKt.entriesSequence(resourceTable)
- .iterator()
- .forEachRemaining(
- entryWrapper -> {
- ResourceType resourceType = ResourceType.fromClassName(entryWrapper.getType());
- if (resourceType != ResourceType.STYLEABLE) {
- this.addResource(
- resourceType,
- entryWrapper.getPackageName(),
- ResourcesUtil.resourceNameToFieldName(entryWrapper.getEntry().getName()),
- entryWrapper.getId());
- }
- });
- }
}
}
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/usages/DexUsageRecorder.kt b/src/resourceshrinker/java/com/android/build/shrinker/usages/DexUsageRecorder.kt
index 5d6a0df..3f1a676 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/usages/DexUsageRecorder.kt
+++ b/src/resourceshrinker/java/com/android/build/shrinker/usages/DexUsageRecorder.kt
@@ -56,7 +56,7 @@
}
}
-class DexFileAnalysisCallback(
+private class DexFileAnalysisCallback(
private val path: Path,
private val model: ResourceShrinkerModel
) : AnalysisCallback {
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/usages/ProtoAndroidManifestUsageRecorder.kt b/src/resourceshrinker/java/com/android/build/shrinker/usages/ProtoAndroidManifestUsageRecorder.kt
index 77bb8f6..4e6aa3e 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/usages/ProtoAndroidManifestUsageRecorder.kt
+++ b/src/resourceshrinker/java/com/android/build/shrinker/usages/ProtoAndroidManifestUsageRecorder.kt
@@ -34,25 +34,25 @@
recordUsagesFromNode(root, model)
}
-}
-fun recordUsagesFromNode(node: XmlNode, model: ResourceShrinkerModel) {
- // Records only resources from element attributes that have reference items with resolved
- // ids or names.
- if (!node.hasElement()) {
- return
- }
- node.element.attributeList.asSequence()
- .filter { it.hasCompiledItem() }
- .map { it.compiledItem }
- .filter { it.hasRef() }
- .map { it.ref }
- .flatMap {
- // If resource id is available prefer this id to name.
- when {
- it.id != 0 -> listOfNotNull(model.resourceStore.getResource(it.id))
- else -> model.resourceStore.getResourcesFromUrl("@${it.name}")
- }.asSequence()
+ private fun recordUsagesFromNode(node: XmlNode, model: ResourceShrinkerModel) {
+ // Records only resources from element attributes that have reference items with resolved
+ // ids or names.
+ if (!node.hasElement()) {
+ return
}
- .forEach { ResourceUsageModel.markReachable(it) }
- node.element.childList.forEach { recordUsagesFromNode(it, model) }
+ node.element.attributeList.asSequence()
+ .filter { it.hasCompiledItem() }
+ .map { it.compiledItem }
+ .filter { it.hasRef() }
+ .map { it.ref }
+ .flatMap {
+ // If resource id is available prefer this id to name.
+ when {
+ it.id != 0 -> listOfNotNull(model.resourceStore.getResource(it.id))
+ else -> model.resourceStore.getResourcesFromUrl("@${it.name}")
+ }.asSequence()
+ }
+ .forEach { ResourceUsageModel.markReachable(it) }
+ node.element.childList.forEach { recordUsagesFromNode(it, model) }
+ }
}
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/usages/ToolsAttributeUsageRecorder.kt b/src/resourceshrinker/java/com/android/build/shrinker/usages/ToolsAttributeUsageRecorder.kt
index 8e43cd8..0dae39a 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/usages/ToolsAttributeUsageRecorder.kt
+++ b/src/resourceshrinker/java/com/android/build/shrinker/usages/ToolsAttributeUsageRecorder.kt
@@ -16,11 +16,9 @@
package com.android.build.shrinker.usages
-import com.android.SdkConstants.TOOLS_NS_NAME
import com.android.SdkConstants.VALUE_STRICT
import com.android.build.shrinker.ResourceShrinkerModel
import com.android.utils.XmlUtils
-import com.google.common.collect.ImmutableMap
import com.google.common.collect.ImmutableMap.copyOf
import java.io.Reader
import java.nio.file.Files
@@ -39,6 +37,9 @@
* @param rawResourcesPath path to folder with resources in raw format.
*/
class ToolsAttributeUsageRecorder(val rawResourcesPath: Path) : ResourceUsageRecorder {
+ companion object {
+ private val TOOLS_NAMESPACE = "http://schemas.android.com/tools"
+ }
override fun recordUsages(model: ResourceShrinkerModel) {
Files.walk(rawResourcesPath)
@@ -47,48 +48,42 @@
}
private fun processRawXml(path: Path, model: ResourceShrinkerModel) {
- processRawXml(XmlUtils.getUtfReader(path.toFile()), model)
- }
-}
-
-fun processRawXml(reader: Reader, model: ResourceShrinkerModel) {
- processResourceToolsAttributes(reader).forEach { key, value ->
- when (key) {
- "keep" -> model.resourceStore.recordKeepToolAttribute(value)
- "discard" -> model.resourceStore.recordDiscardToolAttribute(value)
- "shrinkMode" ->
- if (value == VALUE_STRICT) {
- model.resourceStore.safeMode = false
- }
- }
- }
-}
-
-fun processResourceToolsAttributes(utfReader: Reader?): ImmutableMap<String, String> {
- val toolsAttributes = mutableMapOf<String, String>()
- utfReader.use { reader: Reader? ->
- val factory = XMLInputFactory.newInstance()
- val xmlStreamReader = factory.createXMLStreamReader(reader)
-
- var rootElementProcessed = false
- while (!rootElementProcessed && xmlStreamReader.hasNext()) {
- xmlStreamReader.next()
- if (xmlStreamReader.isStartElement) {
- if (xmlStreamReader.localName == "resources") {
- for (i in 0 until xmlStreamReader.attributeCount) {
- val namespace = "http://schemas.android.com/tools"
- if (xmlStreamReader.getAttributeNamespace(i) == namespace) {
- toolsAttributes.put(
- xmlStreamReader.getAttributeLocalName(i),
- xmlStreamReader.getAttributeValue(i)
- )
- }
+ processResourceToolsAttributes(path).forEach { key, value ->
+ when (key) {
+ "keep" -> model.resourceStore.recordKeepToolAttribute(value)
+ "discard" -> model.resourceStore.recordDiscardToolAttribute(value)
+ "shrinkMode" ->
+ if (value == VALUE_STRICT) {
+ model.resourceStore.safeMode = false
}
- }
- rootElementProcessed = true
}
}
}
- return copyOf(toolsAttributes)
-}
+ private fun processResourceToolsAttributes(path: Path): Map<String, String> {
+ val toolsAttributes = mutableMapOf<String, String>()
+ XmlUtils.getUtfReader(path.toFile()).use { reader: Reader ->
+ val factory = XMLInputFactory.newInstance()
+ val xmlStreamReader = factory.createXMLStreamReader(reader)
+
+ var rootElementProcessed = false
+ while (!rootElementProcessed && xmlStreamReader.hasNext()) {
+ xmlStreamReader.next()
+ if (xmlStreamReader.isStartElement) {
+ if (xmlStreamReader.localName == "resources") {
+ for (i in 0 until xmlStreamReader.attributeCount) {
+ if (xmlStreamReader.getAttributeNamespace(i) == TOOLS_NAMESPACE) {
+ toolsAttributes.put(
+ xmlStreamReader.getAttributeLocalName(i),
+ xmlStreamReader.getAttributeValue(i)
+ )
+ }
+ }
+ }
+ rootElementProcessed = true
+ }
+ }
+ }
+ return copyOf(toolsAttributes)
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index d55e5c5..238594e 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestBase.Backend;
-import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
import com.android.tools.r8.benchmarks.BenchmarkResults;
import com.android.tools.r8.dexsplitter.SplitterTestBase.RunInterface;
import com.android.tools.r8.dexsplitter.SplitterTestBase.SplitRunner;
@@ -17,7 +16,6 @@
import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
import com.android.tools.r8.keepanno.KeepEdgeAnnotationsTest;
import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.profile.art.ArtProfileConsumer;
import com.android.tools.r8.profile.art.ArtProfileProvider;
import com.android.tools.r8.profile.art.model.ExternalArtProfile;
@@ -83,7 +81,6 @@
private final List<Path> mainDexRulesFiles = new ArrayList<>();
private final List<String> applyMappingMaps = new ArrayList<>();
private final List<Path> features = new ArrayList<>();
- private Path resourceShrinkerOutput = null;
private PartitionMapConsumer partitionMapConsumer = null;
@Override
@@ -144,7 +141,6 @@
}
class Box {
-
private List<ProguardConfigurationRule> syntheticProguardRules;
private ProguardConfiguration proguardConfiguration;
}
@@ -170,8 +166,7 @@
graphConsumer,
getMinApiLevel(),
features,
- residualArtProfiles,
- resourceShrinkerOutput);
+ residualArtProfiles);
switch (allowedDiagnosticMessages) {
case ALL:
compileResult.getDiagnosticMessages().assertAllDiagnosticsMatch(new IsAnything<>());
@@ -873,25 +868,4 @@
this.partitionMapConsumer = partitionMapConsumer;
return self();
}
-
- public T addAndroidResources(AndroidTestResource testResource) throws IOException {
- return addAndroidResources(
- testResource, getState().getNewTempFile("resourceshrinkeroutput.zip"));
- }
-
- public T addAndroidResources(AndroidTestResource testResource, Path output) throws IOException {
- addResourceShrinkerProviderAndConsumer(testResource.getResourceZip(), output);
- return addProgramClassFileData(testResource.getRClass().getClassFileData());
- }
-
- private T addResourceShrinkerProviderAndConsumer(Path resources, Path output) throws IOException {
- resourceShrinkerOutput = output;
- getBuilder()
- .setAndroidResourceProvider(
- new ArchiveProtoAndroidResourceProvider(resources, new PathOrigin(resources)));
- getBuilder()
- .setAndroidResourceConsumer(
- new ArchiveProtoAndroidResourceConsumer(resourceShrinkerOutput));
- return self();
- }
}
diff --git a/src/test/java/com/android/tools/r8/R8TestCompileResult.java b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
index 82997e9..1ca26f0 100644
--- a/src/test/java/com/android/tools/r8/R8TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
@@ -6,10 +6,8 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.ResourceTableInspector;
import com.android.tools.r8.dexsplitter.SplitterTestBase.SplitRunner;
import com.android.tools.r8.profile.art.model.ExternalArtProfile;
import com.android.tools.r8.profile.art.utils.ArtProfileInspector;
@@ -21,7 +19,6 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThrowingBiConsumer;
import com.android.tools.r8.utils.ThrowingConsumer;
-import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.graphinspector.GraphInspector;
@@ -39,7 +36,6 @@
private final CollectingGraphConsumer graphConsumer;
private final List<Path> features;
private final List<ExternalArtProfile> residualArtProfiles;
- private final Path resourceShrinkerOutput;
R8TestCompileResult(
TestState state,
@@ -52,8 +48,7 @@
CollectingGraphConsumer graphConsumer,
int minApiLevel,
List<Path> features,
- List<ExternalArtProfile> residualArtProfiles,
- Path resourceShrinkerOutput) {
+ List<ExternalArtProfile> residualArtProfiles) {
super(state, app, minApiLevel, outputMode, libraryDesugaringTestConfiguration);
this.proguardConfiguration = proguardConfiguration;
this.syntheticProguardRules = syntheticProguardRules;
@@ -61,7 +56,6 @@
this.graphConsumer = graphConsumer;
this.features = features;
this.residualArtProfiles = residualArtProfiles;
- this.resourceShrinkerOutput = resourceShrinkerOutput;
}
@Override
@@ -155,15 +149,6 @@
return self();
}
- public <E extends Throwable> R8TestCompileResult inspectShrunkenResources(
- Consumer<ResourceTableInspector> consumer) throws IOException {
- assertNotNull(resourceShrinkerOutput);
- consumer.accept(
- new ResourceTableInspector(
- ZipUtils.readSingleEntry(resourceShrinkerOutput, "resources.pb")));
- return self();
- }
-
public GraphInspector graphInspector() throws IOException {
assert graphConsumer != null;
return new GraphInspector(graphConsumer, inspector());
diff --git a/src/test/java/com/android/tools/r8/TestBuilder.java b/src/test/java/com/android/tools/r8/TestBuilder.java
index 84ccfd9..4e98e36 100644
--- a/src/test/java/com/android/tools/r8/TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestBuilder.java
@@ -136,6 +136,10 @@
return addProgramClasses(classes).addInnerClasses(classes);
}
+ public T addAndroidResources(AndroidTestResource testResource) throws IOException {
+ return addProgramClassFileData(testResource.getRClass().getClassFileData());
+ }
+
public T addInnerClasses(Class<?>... classes) throws IOException {
return addInnerClasses(Arrays.asList(classes));
}
diff --git a/src/test/java/com/android/tools/r8/androidresources/AndroidResourceTestingUtils.java b/src/test/java/com/android/tools/r8/androidresources/AndroidResourceTestingUtils.java
index 30960ee..c1dde31 100644
--- a/src/test/java/com/android/tools/r8/androidresources/AndroidResourceTestingUtils.java
+++ b/src/test/java/com/android/tools/r8/androidresources/AndroidResourceTestingUtils.java
@@ -6,10 +6,6 @@
import static com.android.tools.r8.TestBase.javac;
import static com.android.tools.r8.TestBase.transformer;
-import com.android.aapt.Resources;
-import com.android.aapt.Resources.ConfigValue;
-import com.android.aapt.Resources.Item;
-import com.android.aapt.Resources.ResourceTable;
import com.android.tools.r8.TestRuntime.CfRuntime;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
@@ -20,20 +16,16 @@
import com.android.tools.r8.utils.StreamUtils;
import com.android.tools.r8.utils.ZipUtils;
import com.google.common.collect.MoreCollectors;
-import com.google.protobuf.InvalidProtocolBufferException;
-import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.stream.Collectors;
-import org.junit.Assert;
import org.junit.rules.TemporaryFolder;
public class AndroidResourceTestingUtils {
@@ -111,92 +103,6 @@
}
}
- // Easy traversable resource table.
- public static class TestResourceTable {
- private Map<String, ResourceNameToValueMapping> mapping = new HashMap<>();
-
- private TestResourceTable(ResourceTable resourceTable) {
- // For now, we don't have any test that use multiple packages.
- assert resourceTable.getPackageCount() == 1;
- for (Resources.Type type : resourceTable.getPackage(0).getTypeList()) {
- String typeName = type.getName();
- mapping.put(typeName, new ResourceNameToValueMapping(type));
- }
- }
-
- public static TestResourceTable parseFrom(byte[] bytes) throws InvalidProtocolBufferException {
- return new TestResourceTable(ResourceTable.parseFrom(bytes));
- }
-
- public boolean containsValueFor(String type, String name) {
- return mapping.containsKey(type) && mapping.get(type).containsValueFor(name);
- }
-
- public static class ResourceNameToValueMapping {
- private final Map<String, List<ResourceValue>> mapping = new HashMap<>();
-
- public ResourceNameToValueMapping(Resources.Type type) {
- for (Resources.Entry entry : type.getEntryList()) {
- String name = entry.getName();
- List<ResourceValue> entries = new ArrayList<>();
- for (ConfigValue configValue : entry.getConfigValueList()) {
- Item item = configValue.getValue().getItem();
- // Currently supporting files and strings, we just flatten this to strings for easy
- // testing.
- if (item.hasFile()) {
- entries.add(
- new ResourceValue(item.getFile().getPath(), configValue.getConfig().toString()));
- } else if (item.hasStr()) {
- entries.add(
- new ResourceValue(item.getStr().getValue(), configValue.getConfig().toString()));
- }
- mapping.put(name, entries);
- }
- }
- }
-
- public boolean containsValueFor(String name) {
- return mapping.containsKey(name);
- }
-
- public static class ResourceValue {
-
- private final String value;
- private final String config;
-
- public ResourceValue(String value, String config) {
- this.value = value;
- this.config = config;
- }
-
- public String getValue() {
- return value;
- }
-
- public String getConfig() {
- return config;
- }
- }
- }
- }
-
- public static class ResourceTableInspector {
-
- private final TestResourceTable testResourceTable;
-
- public ResourceTableInspector(byte[] bytes) throws InvalidProtocolBufferException {
- testResourceTable = TestResourceTable.parseFrom(bytes);
- }
-
- public void assertContainsResourceWithName(String type, String name) {
- Assert.assertTrue(testResourceTable.containsValueFor(type, name));
- }
-
- public void assertDoesNotContainResourceWithName(String type, String name) {
- Assert.assertFalse(testResourceTable.containsValueFor(type, name));
- }
- }
-
public static class AndroidTestResourceBuilder {
private String manifest;
private final Map<String, String> stringValues = new TreeMap<>();
@@ -254,13 +160,13 @@
FileUtils.writeTextFile(
temp.newFolder("res", "values").toPath().resolve("strings.xml"),
createStringResourceXml());
-
}
if (drawables.size() > 0) {
- File drawableFolder = temp.newFolder("res", "drawable");
for (Entry<String, byte[]> entry : drawables.entrySet()) {
FileUtils.writeToFile(
- drawableFolder.toPath().resolve(entry.getKey()), null, entry.getValue());
+ temp.newFolder("res", "drawable").toPath().resolve(entry.getKey()),
+ null,
+ entry.getValue());
}
}
diff --git a/src/test/java/com/android/tools/r8/androidresources/AndroidResourcesPassthroughTest.java b/src/test/java/com/android/tools/r8/androidresources/AndroidResourcesPassthroughTest.java
new file mode 100644
index 0000000..41754aa
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/androidresources/AndroidResourcesPassthroughTest.java
@@ -0,0 +1,85 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.androidresources;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.ArchiveProtoAndroidResourceConsumer;
+import com.android.tools.r8.ArchiveProtoAndroidResourceProvider;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
+import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.ZipUtils;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AndroidResourcesPassthroughTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection parameters() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ String manifestPath = "AndroidManifest.xml";
+ String resourcePath = "resources.pb";
+ String pngPath = "res/drawable/foo.png";
+
+ AndroidTestResource testResource =
+ new AndroidTestResourceBuilder()
+ .withSimpleManifestAndAppNameString()
+ .addDrawable("foo.png", AndroidResourceTestingUtils.TINY_PNG)
+ .build(temp);
+ Path resources = testResource.getResourceZip();
+ Path output = temp.newFile("resources_out.zip").toPath();
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .setMinApi(parameters)
+ .addOptionsModification(
+ o -> {
+ o.androidResourceProvider =
+ new ArchiveProtoAndroidResourceProvider(resources, new PathOrigin(resources));
+ o.androidResourceConsumer = new ArchiveProtoAndroidResourceConsumer(output);
+ })
+ .addKeepMainRule(FooBar.class)
+ .run(parameters.getRuntime(), FooBar.class)
+ .assertSuccessWithOutputLines("Hello World");
+ assertArrayEquals(
+ ZipUtils.readSingleEntry(output, manifestPath),
+ ZipUtils.readSingleEntry(resources, manifestPath));
+ assertArrayEquals(
+ ZipUtils.readSingleEntry(output, resourcePath),
+ ZipUtils.readSingleEntry(resources, resourcePath));
+ assertArrayEquals(
+ ZipUtils.readSingleEntry(output, pngPath), ZipUtils.readSingleEntry(resources, pngPath));
+ String rClassContent =
+ FileUtils.readTextFile(
+ testResource.getRClass().getJavaFilePath(), Charset.defaultCharset());
+ assertThat(rClassContent, containsString("app_name"));
+ assertThat(rClassContent, containsString("foo"));
+ }
+
+ public static class FooBar {
+
+ public static void main(String[] args) {
+ System.out.println("Hello World");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/androidresources/SimpleNoCodeReferenceAndroidResourceTest.java b/src/test/java/com/android/tools/r8/androidresources/SimpleNoCodeReferenceAndroidResourceTest.java
deleted file mode 100644
index 34b2b9a..0000000
--- a/src/test/java/com/android/tools/r8/androidresources/SimpleNoCodeReferenceAndroidResourceTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.androidresources;
-
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
-import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
-import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.ResourceTableInspector;
-import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.ZipUtils;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Path;
-import java.util.Arrays;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class SimpleNoCodeReferenceAndroidResourceTest extends TestBase {
-
- @Parameter(0)
- public TestParameters parameters;
-
- @Parameters(name = "{0}")
- public static TestParametersCollection parameters() {
- return getTestParameters().withDexRuntimes().withAllApiLevels().build();
- }
-
- @Test
- public void testR8() throws Exception {
- String manifestPath = "AndroidManifest.xml";
- String resourcePath = "resources.pb";
- String pngPath = "res/drawable/foo.png";
-
- AndroidTestResource testResource =
- new AndroidTestResourceBuilder()
- .withSimpleManifestAndAppNameString()
- .addDrawable("foo.png", AndroidResourceTestingUtils.TINY_PNG)
- .addDrawable("bar.png", AndroidResourceTestingUtils.TINY_PNG)
- .build(temp);
- Path resources = testResource.getResourceZip();
- Path output = temp.newFile("resources_out.zip").toPath();
- testForR8(parameters.getBackend())
- .addInnerClasses(getClass())
- .setMinApi(parameters)
- .addAndroidResources(testResource, output)
- .addKeepMainRule(FooBar.class)
- .compile()
- .inspectShrunkenResources(
- shrunkenInspector -> {
- // Reachable from the manifest
- shrunkenInspector.assertContainsResourceWithName("string", "app_name");
- // Not reachable from anything
- shrunkenInspector.assertDoesNotContainResourceWithName("drawable", "foo");
- shrunkenInspector.assertDoesNotContainResourceWithName("drawable", "bar");
- try {
- assertFalse(ZipUtils.containsEntry(output, pngPath));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- })
- .run(parameters.getRuntime(), FooBar.class)
- .assertSuccessWithOutputLines("Hello World");
- // We don't touch the manifest
- assertArrayEquals(
- ZipUtils.readSingleEntry(output, manifestPath),
- ZipUtils.readSingleEntry(resources, manifestPath));
-
- String rClassContent =
- FileUtils.readTextFile(
- testResource.getRClass().getJavaFilePath(), Charset.defaultCharset());
- assertFalse(
- Arrays.equals(
- ZipUtils.readSingleEntry(output, resourcePath),
- ZipUtils.readSingleEntry(resources, resourcePath)));
- assertThat(rClassContent, containsString("app_name"));
- assertThat(rClassContent, containsString("foo"));
- assertThat(rClassContent, containsString("bar"));
- assertTrue(ZipUtils.containsEntry(resources, pngPath));
- ResourceTableInspector resourceTableInspector =
- new ResourceTableInspector(
- ZipUtils.readSingleEntry(testResource.getResourceZip(), resourcePath));
- resourceTableInspector.assertContainsResourceWithName("string", "app_name");
- resourceTableInspector.assertContainsResourceWithName("drawable", "foo");
- resourceTableInspector.assertContainsResourceWithName("drawable", "bar");
- }
-
- public static class FooBar {
-
- public static void main(String[] args) {
- System.out.println("Hello World");
- }
- }
-}
diff --git a/src/test/java/com/android/tools/r8/androidresources/TestShrinkingWithCodeReferences.java b/src/test/java/com/android/tools/r8/androidresources/TestShrinkingWithCodeReferences.java
deleted file mode 100644
index 00b000f..0000000
--- a/src/test/java/com/android/tools/r8/androidresources/TestShrinkingWithCodeReferences.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.androidresources;
-
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
-import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TestShrinkingWithCodeReferences extends TestBase {
-
- @Parameter(0)
- public TestParameters parameters;
-
- @Parameters(name = "{0}")
- public static TestParametersCollection parameters() {
- return getTestParameters().withDexRuntimes().withAllApiLevels().build();
- }
-
- public static AndroidTestResource getTestResources(TemporaryFolder temp) throws Exception {
- return new AndroidTestResourceBuilder()
- .withSimpleManifestAndAppNameString()
- .addRClassInitializeWithDefaultValues(R.string.class, R.drawable.class)
- .build(temp);
- }
-
- @Test
- public void testR8() throws Exception {
- testForR8(parameters.getBackend())
- .setMinApi(parameters)
- .addProgramClasses(FooBar.class)
- .addAndroidResources(getTestResources(temp))
- .addKeepMainRule(FooBar.class)
- .compile()
- .inspectShrunkenResources(
- resourceTableInspector -> {
- resourceTableInspector.assertContainsResourceWithName("string", "bar");
- resourceTableInspector.assertContainsResourceWithName("string", "foo");
- resourceTableInspector.assertContainsResourceWithName("drawable", "foobar");
- resourceTableInspector.assertDoesNotContainResourceWithName(
- "string", "unused_string");
- resourceTableInspector.assertDoesNotContainResourceWithName(
- "drawable", "unused_drawable");
- })
- .run(parameters.getRuntime(), FooBar.class)
- .assertSuccess();
- }
-
- public static class FooBar {
-
- public static void main(String[] args) {
- if (System.currentTimeMillis() == 0) {
- System.out.println(R.drawable.foobar);
- System.out.println(R.string.bar);
- System.out.println(R.string.foo);
- }
- }
- }
-
- public static class R {
-
- public static class string {
-
- public static int bar;
- public static int foo;
- public static int unused_string;
- }
-
- public static class drawable {
-
- public static int foobar;
- public static int unused_drawable;
- }
- }
-}