Apply apimapper instrument tool on android tests

Apimapper is a tool to instrument android tests to log potentail API calls at the run time.

The real tool is developed internally. We use a placeholder binary in
AOSP before the real tool is ready.

The tool will only take affect when the enviroment var EMMA_API_MAPPER
is set to true.

Test: m cts
Bug: 328699028

Change-Id: Iece53b8afdb9803334b7393527f4fa24e22f71a8
diff --git a/java/app.go b/java/app.go
index abd78b7..8768544 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1471,7 +1471,23 @@
 	return testConfig
 }
 
+func (a *AndroidTestHelperApp) DepsMutator(ctx android.BottomUpMutatorContext) {
+	if len(a.ApexProperties.Apex_available) == 0 && ctx.Config().IsEnvTrue("EMMA_API_MAPPER") {
+		// Instrument the android_test_helper target to log potential API calls at the run time.
+		// Contact android-xts-infra team before using the environment var EMMA_API_MAPPER.
+		ctx.AddVariationDependencies(nil, staticLibTag, "apimapper-helper-device-lib")
+		a.setApiMapper(true)
+	}
+	a.AndroidApp.DepsMutator(ctx)
+}
+
 func (a *AndroidTest) DepsMutator(ctx android.BottomUpMutatorContext) {
+	if len(a.ApexProperties.Apex_available) == 0 && ctx.Config().IsEnvTrue("EMMA_API_MAPPER") {
+		// Instrument the android_test_helper target to log potential API calls at the run time.
+		// Contact android-xts-infra team before using the environment var EMMA_API_MAPPER.
+		ctx.AddVariationDependencies(nil, staticLibTag, "apimapper-helper-device-lib")
+		a.setApiMapper(true)
+	}
 	a.AndroidApp.DepsMutator(ctx)
 }
 
diff --git a/java/base.go b/java/base.go
index 4cd6021..5ac965c 100644
--- a/java/base.go
+++ b/java/base.go
@@ -233,6 +233,10 @@
 	// Contributing api surface of the stub module. Is not visible to bp modules, and should
 	// only be set for stub submodules generated by the java_sdk_library
 	Stub_contributing_api *string `blueprint:"mutated"`
+
+	// If true, enable the "ApiMapper" tool on the output jar. "ApiMapper" is a tool to inject
+	// bytecode to log API calls.
+	ApiMapper bool `blueprint:"mutated"`
 }
 
 // Properties that are specific to device modules. Host module factories should not add these when
@@ -732,6 +736,10 @@
 		ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir())
 }
 
+func (j *Module) shouldApiMapper() bool {
+	return j.properties.ApiMapper
+}
+
 func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
 	return j.properties.Supports_static_instrumentation &&
 		j.shouldInstrument(ctx) &&
@@ -760,6 +768,10 @@
 	j.properties.Instrument = value
 }
 
+func (j *Module) setApiMapper(value bool) {
+	j.properties.ApiMapper = value
+}
+
 func (j *Module) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
 	return android.SdkSpecFrom(ctx, String(j.deviceProperties.Sdk_version))
 }
@@ -1591,6 +1603,18 @@
 		outputFile = ravenizerOutput
 	}
 
+	if j.shouldApiMapper() {
+		inputFile := outputFile
+		apiMapperFile := android.PathForModuleOut(ctx, "apimapper", jarName)
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        apimapper,
+			Description: "apimapper",
+			Input:       inputFile,
+			Output:      apiMapperFile,
+		})
+		outputFile = apiMapperFile
+	}
+
 	// Check package restrictions if necessary.
 	if len(j.properties.Permitted_packages) > 0 {
 		// Time stamp file created by the package check rule.
diff --git a/java/builder.go b/java/builder.go
index 49207e5..81b0feb 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -265,6 +265,13 @@
 		},
 	)
 
+	apimapper = pctx.AndroidStaticRule("apimapper",
+		blueprint.RuleParams{
+			Command:     "${apimapper} --in-jar $in --out-jar $out",
+			CommandDeps: []string{"${apimapper}"},
+		},
+	)
+
 	zipalign = pctx.AndroidStaticRule("zipalign",
 		blueprint.RuleParams{
 			Command: "if ! ${config.ZipAlign} -c -p 4 $in > /dev/null; then " +
@@ -315,6 +322,7 @@
 
 	pctx.HostBinToolVariable("aconfig", "aconfig")
 	pctx.HostBinToolVariable("ravenizer", "ravenizer")
+	pctx.HostBinToolVariable("apimapper", "apimapper")
 	pctx.HostBinToolVariable("keep-flagged-apis", "keep-flagged-apis")
 }