Implement android_binary.instruments attribute.
android_binary now takes an android_binary in the `instruments` attribute. If the attribute is explicitly specified, an AndroidInstrumentationInfo provider is included in the RuleConfiguredTarget, which android_instrumentation_test can use.
Having the provider allows android_instrumentation_test to check and fail if it tries to depend on an android_binary that is not instrumenting anything.
RELNOTES: None.
PiperOrigin-RevId: 173547240
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
index 1344581..c48dc11 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
@@ -621,6 +621,21 @@
RuleConfiguredTargetBuilder builder =
new RuleConfiguredTargetBuilder(ruleContext);
+ // If this is an instrumentation APK, create the provider for android_instrumentation_test.
+ if (ruleContext.attributes().isAttributeValueExplicitlySpecified("instruments")) {
+ Artifact targetApk =
+ ruleContext
+ .getPrerequisite("instruments", Mode.TARGET)
+ .getProvider(ApkProvider.class)
+ .getApk();
+ Artifact instrumentationApk = zipAlignedApk;
+
+ AndroidInstrumentationInfo instrumentationProvider =
+ new AndroidInstrumentationInfo(targetApk, instrumentationApk);
+
+ builder.addNativeDeclaredProvider(instrumentationProvider);
+ }
+
androidCommon.addTransitiveInfoProviders(
builder,
androidSemantics,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
index d1c6ed2..d3231d1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
@@ -26,6 +26,7 @@
import static com.google.devtools.build.lib.syntax.Type.STRING_DICT;
import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
import static com.google.devtools.build.lib.util.FileTypeSet.ANY_FILE;
+import static com.google.devtools.build.lib.util.FileTypeSet.NO_FILE;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -945,6 +946,11 @@
.cfg(HOST)
.exec()
.value(env.getToolsLabel("//tools/android:resource_extractor")))
+ .add(
+ attr("instruments", BuildType.LABEL)
+ .undocumented("blocked by android_instrumentation_test")
+ .allowedRuleClasses("android_binary")
+ .allowedFileTypes(NO_FILE))
.advertiseSkylarkProvider(SkylarkProviderIdentifier.forKey(JavaInfo.PROVIDER.getKey()))
.build();
}
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 c440200..8793c07 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
@@ -3777,4 +3777,37 @@
checkProguardLibJars(action, getAndroidJarPath());
}
+
+ @Test
+ public void testInstrumentationInfoProviderHasApks() throws Exception {
+ scratch.file(
+ "java/com/google/android/instr/BUILD",
+ "android_binary(name = 'b1',",
+ " srcs = ['b1.java'],",
+ " instruments = ':b2',",
+ " manifest = 'AndroidManifest.xml')",
+ "android_binary(name = 'b2',",
+ " srcs = ['b2.java'],",
+ " manifest = 'AndroidManifest.xml')");
+ ConfiguredTarget b1 = getConfiguredTarget("//java/com/google/android/instr:b1");
+ AndroidInstrumentationInfo provider = b1.get(AndroidInstrumentationInfo.PROVIDER);
+ assertThat(provider.getTargetApk()).isNotNull();
+ assertThat(provider.getTargetApk().prettyPrint())
+ .isEqualTo("java/com/google/android/instr/b2.apk");
+ assertThat(provider.getInstrumentationApk()).isNotNull();
+ assertThat(provider.getInstrumentationApk().prettyPrint())
+ .isEqualTo("java/com/google/android/instr/b1.apk");
+ }
+
+ @Test
+ public void testNoInstrumentationInfoProviderIfNotInstrumenting() throws Exception {
+ scratch.file(
+ "java/com/google/android/instr/BUILD",
+ "android_binary(name = 'b1',",
+ " srcs = ['b1.java'],",
+ " manifest = 'AndroidManifest.xml')");
+ ConfiguredTarget b1 = getConfiguredTarget("//java/com/google/android/instr:b1");
+ AndroidInstrumentationInfo provider = b1.get(AndroidInstrumentationInfo.PROVIDER);
+ assertThat(provider).isNull();
+ }
}