Disable explicit R class filtering for instrumentation tests.
Currently, both android_test and android_instrumentation_test explicitly filter out all R classes from the test's deploy.jar when a test instruments another app rather than filtering out only the duplicate R classes.
Unfortunately, the android_test and android_instrumentation_test use differing CheckHashMismatchMode filter settings WARN and NONE respectively. Where NONE will cause the filterer to remove all duplicate classes from the test's deploy jar and WARN will not filter duplicate classes when the hash values differ
As such this cl introduces two flags:
1. Switch the CheckHashMismatchMode to NONE for android_test while keeping intact the whitelist for making hash mismatches a failure
2. Disable the explicit filtering of R classes.
RELNOTES: None.
PiperOrigin-RevId: 239852282
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index 4d15e1d..79936d7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -952,18 +952,22 @@
Artifact filter,
Artifact out,
CheckHashMismatchMode checkHashMismatch) {
- new ZipFilterBuilder(ruleContext)
- .setInputZip(in)
- .addFilterZips(ImmutableList.of(filter))
- .setOutputZip(out)
- .addFileTypeToFilter(".class")
- .setCheckHashMismatchMode(checkHashMismatch)
- .addExplicitFilter("R\\.class")
- .addExplicitFilter("R\\$.*\\.class")
- // These files are generated by databinding in both the target and the instrumentation app
- // with different contents. We want to keep the one from the target app.
- .addExplicitFilter("/BR\\.class$")
- .addExplicitFilter("/databinding/[^/]+Binding\\.class$")
- .build();
+ ZipFilterBuilder builder =
+ new ZipFilterBuilder(ruleContext)
+ .setInputZip(in)
+ .addFilterZips(ImmutableList.of(filter))
+ .setOutputZip(out)
+ .addFileTypeToFilter(".class")
+ .setCheckHashMismatchMode(checkHashMismatch)
+ // These files are generated by databinding in both the target and the instrumentation
+ // app with different contents. We want to keep the one from the target app.
+ .addExplicitFilter("/BR\\.class$")
+ .addExplicitFilter("/databinding/[^/]+Binding\\.class$");
+
+ if (getAndroidConfig(ruleContext).removeRClassesFromInstrumentationTestJar()) {
+ builder.addExplicitFilter("R\\.class").addExplicitFilter("R\\$.*\\.class");
+ }
+
+ builder.build();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
index cf6b244..7768ae7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
@@ -945,6 +945,31 @@
+ "https://developer.android.com/studio/command-line/aapt2#aapt2_changes")
public boolean incompatibleUseAapt2ByDefault;
+ @Option(
+ name = "experimental_remove_r_classes_from_instrumentation_test_jar",
+ defaultValue = "true",
+ documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
+ effectTags = {
+ OptionEffectTag.CHANGES_INPUTS,
+ },
+ help =
+ "If enabled and the test instruments an application, all the R classes from the test's "
+ + "deploy jar will be removed.")
+ public boolean removeRClassesFromInstrumentationTestJar;
+
+ @Option(
+ name = "experimental_always_filter_duplicate_classes_from_android_test",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
+ effectTags = {
+ OptionEffectTag.CHANGES_INPUTS,
+ },
+ help =
+ "If enabled and the android_test defines a binary_under_test, the class filterering "
+ + "applied to the test's deploy jar will always filter duplicate classes based "
+ + "solely on matching class and package name, ignoring hash values.")
+ public boolean alwaysFilterDuplicateClassesFromAndroidTest;
+
@Override
public FragmentOptions getHost() {
Options host = (Options) super.getHost();
@@ -1033,6 +1058,8 @@
private final boolean dataBindingUpdatedArgs;
private final boolean persistentBusyboxTools;
private final boolean filterRJarsFromAndroidTest;
+ private final boolean removeRClassesFromInstrumentationTestJar;
+ private final boolean alwaysFilterDuplicateClassesFromAndroidTest;
// Incompatible changes
private final boolean incompatibleUseAapt2ByDefault;
@@ -1082,6 +1109,10 @@
this.persistentBusyboxTools = options.persistentBusyboxTools;
this.filterRJarsFromAndroidTest = options.filterRJarsFromAndroidTest;
this.incompatibleUseAapt2ByDefault = options.incompatibleUseAapt2ByDefault;
+ this.removeRClassesFromInstrumentationTestJar =
+ options.removeRClassesFromInstrumentationTestJar;
+ this.alwaysFilterDuplicateClassesFromAndroidTest =
+ options.alwaysFilterDuplicateClassesFromAndroidTest;
if (incrementalDexingShardsAfterProguard < 0) {
throw new InvalidConfigurationException(
@@ -1319,4 +1350,12 @@
public boolean filterRJarsFromAndroidTest() {
return filterRJarsFromAndroidTest;
}
+
+ public boolean removeRClassesFromInstrumentationTestJar() {
+ return removeRClassesFromInstrumentationTestJar;
+ }
+
+ public boolean alwaysFilterDuplicateClassesFromAndroidTest() {
+ return alwaysFilterDuplicateClassesFromAndroidTest;
+ }
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
index d2eb7e0..856e19f 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
@@ -4277,7 +4277,7 @@
"--checkHashMismatch",
"IGNORE",
"--explicitFilters",
- "R\\.class,R\\$.*\\.class,/BR\\.class$,/databinding/[^/]+Binding\\.class$",
+ "/BR\\.class$,/databinding/[^/]+Binding\\.class$,R\\.class,R\\$.*\\.class",
"--outputMode",
"DONT_CARE");
}