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;
-    }
-  }
-}