Pass in generated proguard map in legacy resource shrinking

Bug: b/315763804
Change-Id: Ib3691868dd52a6758f8b2500b60b531a07932c7b
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index ad074ed..32d16c3 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -907,7 +907,9 @@
           }
         }
       }
-
+      if (options.androidResourceProguardMapStrings != null) {
+        resourceShrinkerBuilder.setProguardMapStrings(options.androidResourceProguardMapStrings);
+      }
       LegacyResourceShrinker shrinker = resourceShrinkerBuilder.build();
       ShrinkerResult shrinkerResult;
       if (options.resourceShrinkerConfiguration.isOptimizedShrinking()) {
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 405f214..2b20068 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -1177,13 +1177,21 @@
     MapConsumer mapConsumer =
         wrapExistingMapConsumerIfNotNull(
             internal.mapConsumer, partitionMapConsumer, MapConsumerToPartitionMapConsumer::new);
-    internal.mapConsumer =
+    mapConsumer =
         wrapExistingMapConsumerIfNotNull(
             mapConsumer,
             stringConsumer,
             nonNullStringConsumer ->
                 ProguardMapStringConsumer.builder().setStringConsumer(stringConsumer).build());
 
+    internal.mapConsumer =
+        wrapExistingMapConsumerIfNotNull(
+            mapConsumer,
+            androidResourceConsumer,
+            nonNulStringConsumer ->
+                ProguardMapStringConsumer.builder()
+                    .setStringConsumer(new ResourceShrinkerMapStringConsumer(internal))
+                    .build());
     // Amend the usage information consumer with options from the proguard configuration.
     internal.usageInformationConsumer =
         wrapStringConsumer(
@@ -1308,6 +1316,27 @@
     return optionConsumer;
   }
 
+  private static class ResourceShrinkerMapStringConsumer implements StringConsumer {
+
+    private final InternalOptions internal;
+    private StringBuilder resultBuilder = new StringBuilder();
+
+    public ResourceShrinkerMapStringConsumer(InternalOptions internal) {
+      this.internal = internal;
+    }
+
+    @Override
+    public void accept(String string, DiagnosticsHandler handler) {
+      resultBuilder.append(string);
+    }
+
+    @Override
+    public void finished(DiagnosticsHandler handler) {
+      internal.androidResourceProguardMapStrings = StringUtils.splitLines(resultBuilder.toString());
+      resultBuilder = null;
+    }
+  }
+
   private static class StandardOutConsumer extends StringConsumer.ForwardingConsumer {
 
     public StandardOutConsumer(StringConsumer consumer) {
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 26a4087..011fbfb 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -201,6 +201,8 @@
   public CancelCompilationChecker cancelCompilationChecker = null;
   public AndroidResourceProvider androidResourceProvider = null;
   public AndroidResourceConsumer androidResourceConsumer = null;
+  public List<String> androidResourceProguardMapStrings = null;
+
   public ResourceShrinkerConfiguration resourceShrinkerConfiguration =
       ResourceShrinkerConfiguration.DEFAULT_CONFIGURATION;
   public ResourceAccessAnalysis resourceAccessAnalysis = null;
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/obfuscation/ProguardMappingsRecorder.kt b/src/resourceshrinker/java/com/android/build/shrinker/obfuscation/ProguardMappingsRecorder.kt
index dd538c7..2e2aaca 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/obfuscation/ProguardMappingsRecorder.kt
+++ b/src/resourceshrinker/java/com/android/build/shrinker/obfuscation/ProguardMappingsRecorder.kt
@@ -24,9 +24,12 @@
 /**
  * Records obfuscation mappings from single file in proguard format.
  *
- * @param mappingsFile path to proguard.map file.
+ * @param mapping file lines or the mapping file path.
  */
-class ProguardMappingsRecorder(private val mappingsFile: Path) : ObfuscationMappingsRecorder {
+class ProguardMappingsRecorder(private val mappingLines: List<String>) : ObfuscationMappingsRecorder {
+
+    constructor(mappingsFile: Path)
+      : this(Files.readAllLines(mappingsFile, StandardCharsets.UTF_8));
 
     override fun recordObfuscationMappings(model: ResourceShrinkerModel) {
         model.obfuscatedClasses = extractObfuscatedResourceClasses()
@@ -41,9 +44,8 @@
         // com.package.R -> a.b:
         // com.package.R$style -> a.b.a:
         //     int Toolbar_android_gravity -> i1
-
         val builder = ObfuscatedClasses.Builder()
-        Files.readAllLines(mappingsFile, StandardCharsets.UTF_8).forEach { line ->
+        mappingLines.forEach { line ->
             when {
                 isMethodMapping(line) -> builder.addMethodMapping(extractMethodMapping(line))
                 isClassMapping(line) -> builder.addClassMapping(extractClassMapping(line))
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/LegacyResourceShrinker.java b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/LegacyResourceShrinker.java
index ad7ddfb..1c0a875 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/LegacyResourceShrinker.java
+++ b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/LegacyResourceShrinker.java
@@ -15,6 +15,7 @@
 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.obfuscation.ProguardMappingsRecorder;
 import com.android.build.shrinker.r8integration.R8ResourceShrinkerState.R8ResourceShrinkerModel;
 import com.android.build.shrinker.usages.DexFileAnalysisCallback;
 import com.android.build.shrinker.usages.ProtoAndroidManifestUsageRecorderKt;
@@ -48,6 +49,7 @@
   private final Map<String, byte[]> dexInputs;
   private final List<PathAndBytes> resFolderInputs;
   private final List<PathAndBytes> xmlInputs;
+  private List<String> proguardMapStrings;
   private final List<PathAndBytes> manifest;
   private final Map<PathAndBytes, FeatureSplit> resourceTables;
 
@@ -59,6 +61,7 @@
 
     private final List<PathAndBytes> manifests = new ArrayList<>();
     private final Map<PathAndBytes, FeatureSplit> resourceTables = new HashMap<>();
+    private List<String> proguardMapStrings;
 
     private Builder() {}
 
@@ -96,7 +99,11 @@
     public LegacyResourceShrinker build() {
       assert manifests != null && resourceTables != null;
       return new LegacyResourceShrinker(
-          dexInputs, resFolderInputs, manifests, resourceTables, xmlInputs);
+          dexInputs, resFolderInputs, manifests, resourceTables, xmlInputs, proguardMapStrings);
+    }
+
+    public void setProguardMapStrings(List<String> proguardMapStrings) {
+      this.proguardMapStrings = proguardMapStrings;
     }
   }
 
@@ -105,12 +112,14 @@
       List<PathAndBytes> resFolderInputs,
       List<PathAndBytes> manifests,
       Map<PathAndBytes, FeatureSplit> resourceTables,
-      List<PathAndBytes> xmlInputs) {
+      List<PathAndBytes> xmlInputs,
+      List<String> proguardMapStrings) {
     this.dexInputs = dexInputs;
     this.resFolderInputs = resFolderInputs;
     this.manifest = manifests;
     this.resourceTables = resourceTables;
     this.xmlInputs = xmlInputs;
+    this.proguardMapStrings = proguardMapStrings;
   }
 
   public static Builder builder() {
@@ -127,6 +136,10 @@
   }
 
   public ShrinkerResult shrinkModel(R8ResourceShrinkerModel model) throws IOException {
+    if (proguardMapStrings != null) {
+      new ProguardMappingsRecorder(proguardMapStrings).recordObfuscationMappings(model);
+      proguardMapStrings = null;
+    }
     for (Entry<String, 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_" + entry.getKey() + ".dex");
diff --git a/src/test/java/com/android/tools/r8/androidresources/RClassStaticValuesIgnoreTest.java b/src/test/java/com/android/tools/r8/androidresources/RClassStaticValuesIgnoreTest.java
index 96b9c4a..f423473 100644
--- a/src/test/java/com/android/tools/r8/androidresources/RClassStaticValuesIgnoreTest.java
+++ b/src/test/java/com/android/tools/r8/androidresources/RClassStaticValuesIgnoreTest.java
@@ -58,9 +58,8 @@
         .inspectShrunkenResources(
             resourceTableInspector -> {
               resourceTableInspector.assertContainsResourceWithName("string", "bar");
-              // TODO(b/315763804): We should not keep unused_string, which is only referenced
-              // from clinit on the R class
-              resourceTableInspector.assertContainsResourceWithName("string", "unused_string");
+              resourceTableInspector.assertDoesNotContainResourceWithName(
+                  "string", "unused_string");
             })
         .run(parameters.getRuntime(), FooBar.class)
         .assertSuccess();