Stop writing the merged resources to xml.
Stop passing the merged xml resources to the resource shrinker.

RELNOTES: None
PiperOrigin-RevId: 209989758
diff --git a/src/test/java/com/google/devtools/build/android/AarGeneratorActionTest.java b/src/test/java/com/google/devtools/build/android/AarGeneratorActionTest.java
index 8066fe9..7f188d1 100644
--- a/src/test/java/com/google/devtools/build/android/AarGeneratorActionTest.java
+++ b/src/test/java/com/google/devtools/build/android/AarGeneratorActionTest.java
@@ -667,7 +667,7 @@
     Path assetsOut = working.resolve("assets");
 
     MergedAndroidData mergedData =
-        AndroidResourceMerger.mergeData(
+        AndroidResourceMerger.mergeDataAndWrite(
             primary,
             ImmutableList.of(d1, d2),
             ImmutableList.<DependencyAndroidData>of(),
diff --git a/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java b/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
index 65c3438..82c1475 100644
--- a/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
@@ -73,53 +73,17 @@
             new ScopedTemporaryDirectory("android_resources_tmp");
         ExecutorServiceCloser executorService = ExecutorServiceCloser.createWithFixedPoolOf(15)) {
       final Path tmp = scopedTmp.getPath();
-      final Path mergedAssets = tmp.resolve("merged_assets");
-      final Path mergedResources = tmp.resolve("merged_resources");
-      final Path filteredResources = tmp.resolve("filtered_resources");
-
       final Path densityManifest = tmp.resolve("manifest-filtered/AndroidManifest.xml");
-
       final Path processedManifest = tmp.resolve("manifest-processed/AndroidManifest.xml");
+      final Path symbols = tmp.resolve("symbols/symbols.bin");
       final Path databindingResourcesRoot =
           Files.createDirectories(tmp.resolve("android_data_binding_resources"));
       final Path compiledResources = Files.createDirectories(tmp.resolve("compiled"));
       final Path linkedOut = Files.createDirectories(tmp.resolve("linked"));
-
-      profiler.recordEndOf("setup").startTask("merging");
-
-      AndroidDataDeserializer dataDeserializer =
+      final AndroidDataDeserializer dataDeserializer =
           aaptConfigOptions.useCompiledResourcesForMerge
               ? AndroidCompiledDataDeserializer.withFilteredResources(options.prefilteredResources)
               : AndroidParsedDataDeserializer.withFilteredResources(options.prefilteredResources);
-
-      // Checks for merge conflicts.
-      MergedAndroidData mergedAndroidData =
-          AndroidResourceMerger.mergeData(
-                  ParsedAndroidData.from(options.primaryData),
-                  options.primaryData.getManifest(),
-                  ImmutableList.<SerializedAndroidData>builder()
-                      .addAll(options.directData)
-                      .addAll(options.directAssets)
-                      .build(),
-                  ImmutableList.<SerializedAndroidData>builder()
-                      .addAll(options.transitiveData)
-                      .addAll(options.transitiveAssets)
-                      .build(),
-                  mergedResources,
-                  mergedAssets,
-                  null /* cruncher. Aapt2 automatically chooses to crunch or not. */,
-                  options.packageType,
-                  options.symbolsOut,
-                  /* rclassWriter= */ null,
-                  dataDeserializer,
-                  options.throwOnResourceConflict,
-                  executorService)
-              .filter(
-                  new DensitySpecificResourceFilter(
-                      options.densities, filteredResources, mergedResources),
-                  new DensitySpecificManifestProcessor(options.densities, densityManifest));
-
-      profiler.recordEndOf("merging").startTask("compile");
       final ResourceCompiler compiler =
           ResourceCompiler.create(
               executorService,
@@ -128,6 +92,7 @@
               aaptConfigOptions.buildToolsVersion,
               aaptConfigOptions.generatePseudoLocale);
 
+      profiler.recordEndOf("setup").startTask("compile");
       CompiledResources compiled =
           options
               .primaryData
@@ -147,7 +112,40 @@
                   manifest ->
                       new DensitySpecificManifestProcessor(options.densities, densityManifest)
                           .process(manifest));
-      profiler.recordEndOf("compile").startTask("link");
+
+      profiler.recordEndOf("compile").startTask("merge");
+
+      // Checks for merge conflicts, and write the merged data out.
+      final Path symbolsBin =
+          AndroidResourceMerger.mergeDataToSymbols(
+              ParsedAndroidData.loadedFrom(
+                  ImmutableList.of(SerializedAndroidData.from(compiled)),
+                  executorService,
+                  // TODO(b/112848607): Remove when compiled merging is the default for aapt2.
+                  aaptConfigOptions.useCompiledResourcesForMerge
+                      ? dataDeserializer
+                      : AndroidCompiledDataDeserializer.withFilteredResources(
+                          options.prefilteredResources)),
+              new DensitySpecificManifestProcessor(options.densities, densityManifest)
+                  .process(options.primaryData.getManifest()),
+              ImmutableList.<SerializedAndroidData>builder()
+                  .addAll(options.directData)
+                  .addAll(options.directAssets)
+                  .build(),
+              ImmutableList.<SerializedAndroidData>builder()
+                  .addAll(options.transitiveData)
+                  .addAll(options.transitiveAssets)
+                  .build(),
+              options.packageType,
+              symbols,
+              dataDeserializer,
+              options.throwOnResourceConflict,
+              executorService);
+      if (options.symbolsOut != null) {
+        Files.copy(symbolsBin, options.symbolsOut);
+      }
+
+      profiler.recordEndOf("merge").startTask("link");
       // Write manifestOutput now before the dummy manifest is created.
       if (options.manifestOutput != null) {
         AndroidResourceOutputs.copyManifestToOutput(compiled, options.manifestOutput);
@@ -192,9 +190,7 @@
               .copyRTxtTo(options.rOutput);
       profiler.recordEndOf("link");
       if (options.resourcesOutput != null) {
-        packagedResources
-            .packageWith(mergedAndroidData.getResourceDir())
-            .writeTo(options.resourcesOutput, /* compress= */ false);
+        packagedResources.asArchive().writeTo(options.resourcesOutput, /* compress= */ false);
       }
     }
   }
diff --git a/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java b/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
index d5bd494..7fbc0f1 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
@@ -180,7 +180,7 @@
       // There aren't any dependencies, but we merge to combine primary resources from different
       // res/assets directories into a single res and single assets directory.
       MergedAndroidData mergedData =
-          AndroidResourceMerger.mergeData(
+          AndroidResourceMerger.mergeDataAndWrite(
               options.mainData,
               ImmutableList.<DependencyAndroidData>of(),
               ImmutableList.<DependencyAndroidData>of(),
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidAssetMergingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidAssetMergingAction.java
index aa74a74..1a91858 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidAssetMergingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidAssetMergingAction.java
@@ -127,7 +127,7 @@
     Preconditions.checkNotNull(options.primary);
 
     MergedAndroidData mergedData =
-        AndroidResourceMerger.mergeData(
+        AndroidResourceMerger.mergeDataAndWrite(
             options.primary,
             /* primaryManifest = */ null,
             options.directData,
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java b/src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java
index 021f787..05edf73 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidDataMerger.java
@@ -273,7 +273,7 @@
     }
   }
 
-  private UnwrittenMergedAndroidData doMerge(
+  UnwrittenMergedAndroidData doMerge(
       ParsedAndroidData transitive,
       ParsedAndroidData direct,
       ParsedAndroidData parsedPrimary,
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
index f77c4e1..9cd5dbe 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
@@ -17,6 +17,7 @@
 import com.android.builder.core.VariantType;
 import com.android.ide.common.internal.PngCruncher;
 import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.devtools.build.android.AndroidDataMerger.ContentComparingChecker;
 import com.google.devtools.build.android.AndroidDataMerger.PathComparingChecker;
@@ -30,6 +31,36 @@
 /** Collects all the functionality for an action to merge resources. */
 // TODO(bazel-team): Turn into an instance object, in order to use an external ExecutorService.
 public class AndroidResourceMerger {
+
+  /** Performs a merge of compiled android data. */
+  static Path mergeDataToSymbols(
+      ParsedAndroidData primary,
+      Path manifest,
+      ImmutableList<SerializedAndroidData> direct,
+      ImmutableList<SerializedAndroidData> transitive,
+      VariantType packageType,
+      Path symbolsOut,
+      AndroidDataDeserializer deserializer,
+      boolean throwOnResourceConflict,
+      ExecutorServiceCloser executorService)
+      throws IOException {
+    AndroidDataMerger merger =
+        AndroidDataMerger.createWithPathDeduplictor(
+            executorService, deserializer, new PathComparingChecker());
+    final UnwrittenMergedAndroidData merged =
+        merger.loadAndMerge(
+            transitive,
+            direct,
+            primary,
+            manifest,
+            packageType.equals(VariantType.DEFAULT),
+            throwOnResourceConflict);
+    AndroidDataSerializer serializer = AndroidDataSerializer.create();
+    merged.serializeTo(serializer);
+    serializer.flushTo(symbolsOut);
+    return symbolsOut;
+  }
+
   /** Thrown when there is a unexpected condition during merging. */
   public static class MergingException extends UserException {
 
@@ -53,7 +84,7 @@
   static final Logger logger = Logger.getLogger(AndroidResourceProcessor.class.getName());
 
   /** Merges all secondary resources with the primary resources. */
-  public static MergedAndroidData mergeData(
+  public static MergedAndroidData mergeDataAndWrite(
       final ParsedAndroidData primary,
       final Path primaryManifest,
       final List<? extends SerializedAndroidData> direct,
@@ -139,7 +170,7 @@
    * Merges all secondary resources with the primary resources, given that the primary resources
    * have not yet been parsed and serialized.
    */
-  public static MergedAndroidData mergeData(
+  public static MergedAndroidData mergeDataAndWrite(
       final UnvalidatedAndroidData primary,
       final List<? extends SerializedAndroidData> direct,
       final List<? extends SerializedAndroidData> transitive,
@@ -152,7 +183,7 @@
       boolean throwOnResourceConflict) {
     try (ExecutorServiceCloser executorService = ExecutorServiceCloser.createWithFixedPoolOf(15)) {
       final ParsedAndroidData parsedPrimary = ParsedAndroidData.from(primary);
-      return mergeData(
+      return mergeDataAndWrite(
           parsedPrimary,
           primary.getManifest(),
           direct,
@@ -175,7 +206,7 @@
    * Merges all secondary resources with the primary resources, given that the primary resources
    * have been separately parsed and serialized.
    */
-  public static MergedAndroidData mergeData(
+  public static MergedAndroidData mergeDataAndWrite(
       final SerializedAndroidData primary,
       final Path primaryManifest,
       final List<? extends SerializedAndroidData> direct,
@@ -192,7 +223,7 @@
     final AndroidDataDeserializer deserializer = AndroidParsedDataDeserializer.create();
     primary.deserialize(deserializer, primaryBuilder.consumers());
     ParsedAndroidData primaryData = primaryBuilder.build();
-    return mergeData(
+    return mergeDataAndWrite(
         primaryData,
         primaryManifest,
         direct,
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
index 9b9b87f..5d1ea13 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
@@ -253,7 +253,7 @@
       resourceClassWriter.setIncludeJavaFile(false);
 
       final MergedAndroidData mergedData =
-          AndroidResourceMerger.mergeData(
+          AndroidResourceMerger.mergeDataAndWrite(
               options.primaryData,
               options.primaryManifest,
               options.directData,
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
index 18dd203..940bdd0 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
@@ -420,7 +420,7 @@
               .asList();
 
       final MergedAndroidData mergedData =
-          AndroidResourceMerger.mergeData(
+          AndroidResourceMerger.mergeDataAndWrite(
               options.primaryData,
               ImmutableList.<SerializedAndroidData>builder()
                   .addAll(options.directData)
diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourcesZip.java b/src/tools/android/java/com/google/devtools/build/android/ResourcesZip.java
index 6e541ea..0c9f1b7 100644
--- a/src/tools/android/java/com/google/devtools/build/android/ResourcesZip.java
+++ b/src/tools/android/java/com/google/devtools/build/android/ResourcesZip.java
@@ -123,22 +123,16 @@
   /**
    * @param proto apk in proto format.
    * @param attributes Tooling attributes.
-   * @param resourcesRoot The root of the raw resources.
-   * @param apkWithAssets The apk containing assets.
    * @param resourceIds Optional path to a file containing the resource ids.
+   * @param packages Optional path to a file containing the dependency packages.
    */
   public static ResourcesZip fromApkWithProto(
-      Path proto,
-      Path attributes,
-      Path resourcesRoot,
-      Path apkWithAssets,
-      Path resourceIds,
-      Path packages) {
+      Path proto, Path attributes, Path resourceIds, Path packages) {
     return new ResourcesZip(
-        resourcesRoot,
+        /* resourcesRoot= */ null,
         /* assetsRoot= */ null,
         resourceIds != null && Files.exists(resourceIds) ? resourceIds : null,
-        apkWithAssets,
+        /* apkWithAssets= */ null,
         proto,
         attributes,
         packages);
@@ -165,15 +159,19 @@
                 throw new RuntimeException(e);
               }
             });
-    final Path packages = workingDirectory.resolve("packages.txt");
     return new ResourcesZip(
         Files.createDirectories(workingDirectory.resolve("res")),
         Files.createDirectories(workingDirectory.resolve("assets")),
-        workingDirectory.resolve("ids.txt"),
+        ifExists(workingDirectory.resolve("ids.txt")),
+        /** apkWithAssets */
         null,
-        workingDirectory.resolve("apk.pb"),
-        workingDirectory.resolve("tools.attributes.pb"),
-        Files.exists(packages) ? packages : null);
+        ifExists(workingDirectory.resolve("apk.pb")),
+        ifExists(workingDirectory.resolve("tools.attributes.pb")),
+        ifExists(workingDirectory.resolve("packages.txt")));
+  }
+
+  private static Path ifExists(Path path) {
+    return Files.exists(path) ? path : null;
   }
 
   /**
@@ -185,7 +183,7 @@
    */
   public void writeTo(Path output, boolean compress) throws IOException {
     try (final ZipBuilder zip = ZipBuilder.createFor(output)) {
-      if (Files.exists(resourcesRoot)) {
+      if (resourcesRoot != null && Files.exists(resourcesRoot)) {
         ZipBuilderVisitorWithDirectories visitor =
             new ZipBuilderVisitorWithDirectories(zip, resourcesRoot, "res");
         visitor.setCompress(compress);
@@ -199,7 +197,7 @@
         visitor.writeEntries();
       }
 
-      if (apkWithAssets != null) {
+      if (apkWithAssets != null && Files.exists(apkWithAssets)) {
         ZipFile apkZip = new ZipFile(apkWithAssets.toString());
         if (apkZip.getEntry("assets/") == null) {
           zip.addEntry("assets/", new byte[0], compress ? ZipEntry.DEFLATED : ZipEntry.STORED);
@@ -215,7 +213,7 @@
                     throw new RuntimeException(e);
                   }
                 });
-      } else if (Files.exists(assetsRoot)) {
+      } else if (assetsRoot != null && Files.exists(assetsRoot)) {
         ZipBuilderVisitorWithDirectories visitor =
             new ZipBuilderVisitorWithDirectories(zip, assetsRoot, "assets");
         visitor.setCompress(compress);
@@ -321,6 +319,10 @@
         : ImmutableList.of();
   }
 
+  Path asApk() {
+    return proto;
+  }
+
   static class ShrunkProtoApk implements Closeable {
     private final ProtoApk apk;
     private final Path report;
diff --git a/src/tools/android/java/com/google/devtools/build/android/SerializedAndroidData.java b/src/tools/android/java/com/google/devtools/build/android/SerializedAndroidData.java
index b2a81d3..562a9d9 100644
--- a/src/tools/android/java/com/google/devtools/build/android/SerializedAndroidData.java
+++ b/src/tools/android/java/com/google/devtools/build/android/SerializedAndroidData.java
@@ -15,6 +15,7 @@
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.android.aapt2.CompiledResources;
 import java.io.IOException;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
@@ -82,6 +83,10 @@
     this.symbols = symbols;
   }
 
+  public static SerializedAndroidData from(CompiledResources primary) {
+    return new SerializedAndroidData(ImmutableList.of(), ImmutableList.of(), "", primary.getZip());
+  }
+
   public void walk(final AndroidDataPathWalker pathWalker) throws IOException {
     for (Path path : resourceDirs) {
       pathWalker.walkResources(path);
diff --git a/src/tools/android/java/com/google/devtools/build/android/aapt2/PackagedResources.java b/src/tools/android/java/com/google/devtools/build/android/aapt2/PackagedResources.java
index f667b96..b023ff2 100644
--- a/src/tools/android/java/com/google/devtools/build/android/aapt2/PackagedResources.java
+++ b/src/tools/android/java/com/google/devtools/build/android/aapt2/PackagedResources.java
@@ -161,13 +161,8 @@
         packages);
   }
 
-  public ResourcesZip packageWith(Path resourceRoot) {
-    return ResourcesZip.fromApkWithProto(
-        proto, attributes, resourceRoot, apk, resourceIds, packages);
-  }
-
-  public Path getResourceIds() {
-    return resourceIds;
+  public ResourcesZip asArchive() {
+    return ResourcesZip.fromApkWithProto(proto, attributes, resourceIds, packages);
   }
 
   public Path getApk() {