Implement host_common_data property for cc, java, rust and sh test modules

Implement the host_common_data property that will copy a host common
module into the test data directory.  This property can be used to
copy a custom Tradefed test runner jar alongside the test.

Bug: 262397555
Test: TestHostCommonData
Change-Id: Iacef0778254a3dda400c9e221f442c47d8db7b02
diff --git a/android/path_properties.go b/android/path_properties.go
index 55a4dc0..d769d58 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -54,12 +54,14 @@
 	var pathDeviceFirstPrefer32Properties []string
 	var pathDeviceCommonProperties []string
 	var pathCommonOsProperties []string
+	var pathHostCommonProperties []string
 	for _, ps := range props {
 		pathProperties = append(pathProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path")...)
 		pathDeviceFirstProperties = append(pathDeviceFirstProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first")...)
 		pathDeviceFirstPrefer32Properties = append(pathDeviceFirstPrefer32Properties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first_prefer32")...)
 		pathDeviceCommonProperties = append(pathDeviceCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_common")...)
 		pathCommonOsProperties = append(pathCommonOsProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_common_os")...)
+		pathHostCommonProperties = append(pathHostCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_host_common")...)
 	}
 
 	// Remove duplicates to avoid multiple dependencies.
@@ -68,6 +70,7 @@
 	pathDeviceFirstPrefer32Properties = FirstUniqueStrings(pathDeviceFirstPrefer32Properties)
 	pathDeviceCommonProperties = FirstUniqueStrings(pathDeviceCommonProperties)
 	pathCommonOsProperties = FirstUniqueStrings(pathCommonOsProperties)
+	pathHostCommonProperties = FirstUniqueStrings(pathHostCommonProperties)
 
 	// Add dependencies to anything that is a module reference.
 	for _, s := range pathProperties {
@@ -108,6 +111,12 @@
 			ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), sourceOrOutputDepTag(m, t), m)
 		}
 	}
+	// properties tagged "path_host_common" get the host common variant
+	for _, s := range pathHostCommonProperties {
+		if m, t := SrcIsModuleWithTag(s); m != "" {
+			ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), sourceOrOutputDepTag(m, t), m)
+		}
+	}
 	// properties tagged "path_common_os" get the CommonOs variant
 	for _, s := range pathCommonOsProperties {
 		if m, t := SrcIsModuleWithTag(s); m != "" {
diff --git a/cc/fuzz.go b/cc/fuzz.go
index a8e4cb7..bd3d8e4 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -353,6 +353,7 @@
 	fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data)
 	fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_common_data)...)
 	fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_first_data)...)
+	fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Host_common_data)...)
 
 	if fuzzPackagedModule.FuzzProperties.Dictionary != nil {
 		fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzPackagedModule.FuzzProperties.Dictionary)
diff --git a/cc/test.go b/cc/test.go
index b3b2ae8..ccd83fe 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -94,6 +94,11 @@
 	// of a host test.
 	Device_first_data []string `android:"path_device_first"`
 
+	// Same as data, but will add dependencies on modules using the host's os variation and
+	// the common arch variation. Useful for a device test that wants to depend on a host
+	// module, for example to include a custom Tradefed test runner.
+	Host_common_data []string `android:"path_host_common"`
+
 	// list of shared library modules that should be installed alongside the test
 	Data_libs []string `android:"arch_variant"`
 
@@ -345,6 +350,7 @@
 	dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
 	dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...)
 	dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_first_data)...)
+	dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Host_common_data)...)
 
 	for _, dataSrcPath := range dataSrcPaths {
 		test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 3fd79a7..83ccd89 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -427,6 +427,12 @@
 	// device's first architecture's variant. Can be useful to add device-built apps to the data
 	// of a host test.
 	Device_first_data []string `android:"path_device_first"`
+
+	// Same as data, but will add dependencies on modules using the host's os variation and
+	// the common arch variation. Useful for a device test that wants to depend on a host
+	// module, for example to include a custom Tradefed test runner.
+	Host_common_data []string `android:"path_host_common"`
+
 	// Optional dictionary to be installed to the fuzz target's output directory.
 	Dictionary *string `android:"path"`
 	// Define the fuzzing frameworks this fuzz target can be built for. If
diff --git a/java/app.go b/java/app.go
index 89d688d..f0e0c9a 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1620,6 +1620,7 @@
 	a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_common_data)...)
 	a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_data)...)
 	a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_prefer32_data)...)
+	a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Host_common_data)...)
 
 	// Install test deps
 	if !ctx.Config().KatiEnabled() {
diff --git a/java/java.go b/java/java.go
index c5dee0c..36601e0 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1527,6 +1527,11 @@
 	// host test.
 	Device_first_prefer32_data []string `android:"path_device_first_prefer32"`
 
+	// Same as data, but will add dependencies on modules using the host's os variation and
+	// the common arch variation. Useful for a device test that wants to depend on a host
+	// module, for example to include a custom Tradefed test runner.
+	Host_common_data []string `android:"path_host_common"`
+
 	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
 	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
 	// explicitly.
@@ -1825,6 +1830,7 @@
 	j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_common_data)...)
 	j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_first_data)...)
 	j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_first_prefer32_data)...)
+	j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Host_common_data)...)
 
 	j.extraTestConfigs = android.PathsForModuleSrc(ctx, j.testProperties.Test_options.Extra_test_configs)
 
diff --git a/java/java_test.go b/java/java_test.go
index f097762..b04ab17 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -627,6 +627,29 @@
 	}
 }
 
+func TestHostCommonData(t *testing.T) {
+	t.Parallel()
+	ctx, _ := testJava(t, `
+		java_library_host {
+			name: "host",
+			srcs: ["a.java"],
+		}
+
+		java_test {
+			name: "foo",
+			srcs: ["a.java"],
+			host_common_data: [":host"],
+		}
+	`)
+
+	foo := ctx.ModuleForTests(t, "foo", "android_common").Module().(*Test)
+	host := ctx.ModuleForTests(t, "host", ctx.Config().BuildOSCommonTarget.String()).Module().(*Library)
+
+	if g, w := foo.data.RelativeToTop().Strings(), []string{host.outputFile.RelativeToTop().String()}; !slices.Equal(g, w) {
+		t.Errorf("expected test data %q, got %q\n", w, g)
+	}
+}
+
 func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
 	t.Parallel()
 	bp := `
diff --git a/java/robolectric.go b/java/robolectric.go
index 43e17f9..e3df329 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -168,6 +168,7 @@
 	r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_common_data)...)
 	r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_data)...)
 	r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_prefer32_data)...)
+	r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Host_common_data)...)
 
 	var ok bool
 	var instrumentedApp *JavaInfo
diff --git a/rust/test.go b/rust/test.go
index b658ae2..99f365f 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -46,9 +46,16 @@
 	// the test
 	Data []string `android:"path,arch_variant"`
 
-	// Same as data, but will add dependencies on the device's
+	// Same as data, but adds dependencies on modules using the device's os variant, and common
+	// architecture's variant. Can be useful to add device-built apps to the data of a host
+	// test.
 	Device_common_data []string `android:"path_device_common"`
 
+	// Same as data, but will add dependencies on modules using the host's os variation and
+	// the common arch variation. Useful for a device test that wants to depend on a host
+	// module, for example to include a custom Tradefed test runner.
+	Host_common_data []string `android:"path_host_common"`
+
 	// list of shared library modules that should be installed alongside the test
 	Data_libs []string `android:"arch_variant"`
 
@@ -147,6 +154,7 @@
 
 	dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
 	dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...)
+	dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Host_common_data)...)
 
 	ctx.VisitDirectDepsProxyWithTag(dataLibDepTag, func(dep android.ModuleProxy) {
 		depName := ctx.OtherModuleName(dep)
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index d753d24..129ef04 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -130,6 +130,11 @@
 	// host test.
 	Device_first_data []string `android:"path_device_first"`
 
+	// Same as data, but will add dependencies on modules using the host's os variation and
+	// the common arch variation. Useful for a device test that wants to depend on a host
+	// module, for example to include a custom Tradefed test runner.
+	Host_common_data []string `android:"path_host_common"`
+
 	// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
 	// with root permission.
 	Require_root *bool
@@ -422,6 +427,7 @@
 	expandedData := android.PathsForModuleSrc(ctx, s.testProperties.Data)
 	expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_common_data)...)
 	expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_first_data)...)
+	expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Host_common_data)...)
 	// Emulate the data property for java_data dependencies.
 	for _, javaData := range ctx.GetDirectDepsProxyWithTag(shTestJavaDataTag) {
 		expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...)