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();