Support resource APKs

- android_ravenwood_test can now have `resource_apk: "ANDROID_APP_MODULE"`.
This will copy the APK to the test directory as "ravenwood-res.apk".

- android_ravenwood_libgroup can now have `data: ["MODULE"]`.
We use this to add framework-res.apk (as `data:["framework-res"]`)
to the ravenwood runtime path.

Bug: 339614874
Test: m nothing --no-skip-soong-tests
Test: ATEST="atest --no-bazel-mode" $ANDROID_BUILD_TOP/frameworks/base/ravenwood/run-ravenwood-tests.sh
   Do it on both aosp/main and goog/main

Flag: EXEMPT: Host side change only

Change-Id: I36516fec068a6359688a1dbedcb10a49c4631441
diff --git a/java/ravenwood.go b/java/ravenwood.go
index 908619d..84c285c 100644
--- a/java/ravenwood.go
+++ b/java/ravenwood.go
@@ -33,6 +33,8 @@
 var ravenwoodLibContentTag = dependencyTag{name: "ravenwoodlibcontent"}
 var ravenwoodUtilsTag = dependencyTag{name: "ravenwoodutils"}
 var ravenwoodRuntimeTag = dependencyTag{name: "ravenwoodruntime"}
+var ravenwoodDataTag = dependencyTag{name: "ravenwooddata"}
+var ravenwoodTestResourceApkTag = dependencyTag{name: "ravenwoodtestresapk"}
 
 const ravenwoodUtilsName = "ravenwood-utils"
 const ravenwoodRuntimeName = "ravenwood-runtime"
@@ -53,6 +55,13 @@
 
 type ravenwoodTestProperties struct {
 	Jni_libs []string
+
+	// Specify another android_app module here to copy it to the test directory, so that
+	// the ravenwood test can access it.
+	// TODO: For now, we simply refer to another android_app module and copy it to the
+	// test directory. Eventually, android_ravenwood_test should support all the resource
+	// related properties and build resources from the `res/` directory.
+	Resource_apk *string
 }
 
 type ravenwoodTest struct {
@@ -114,6 +123,11 @@
 	for _, lib := range r.ravenwoodTestProperties.Jni_libs {
 		ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
 	}
+
+	// Resources APK
+	if resourceApk := proptools.String(r.ravenwoodTestProperties.Resource_apk); resourceApk != "" {
+		ctx.AddVariationDependencies(nil, ravenwoodTestResourceApkTag, resourceApk)
+	}
 }
 
 func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -175,6 +189,14 @@
 		installDeps = append(installDeps, installJni)
 	}
 
+	resApkInstallPath := installPath.Join(ctx, "ravenwood-res-apks")
+	if resApk := ctx.GetDirectDepsWithTag(ravenwoodTestResourceApkTag); len(resApk) > 0 {
+		for _, installFile := range resApk[0].FilesToInstall() {
+			installResApk := ctx.InstallFile(resApkInstallPath, "ravenwood-res.apk", installFile)
+			installDeps = append(installDeps, installResApk)
+		}
+	}
+
 	// Install our JAR with all dependencies
 	ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
 }
@@ -198,6 +220,9 @@
 	Libs []string
 
 	Jni_libs []string
+
+	// We use this to copy framework-res.apk to the ravenwood runtime directory.
+	Data []string
 }
 
 type ravenwoodLibgroup struct {
@@ -236,6 +261,9 @@
 	for _, lib := range r.ravenwoodLibgroupProperties.Jni_libs {
 		ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
 	}
+	for _, data := range r.ravenwoodLibgroupProperties.Data {
+		ctx.AddVariationDependencies(nil, ravenwoodDataTag, data)
+	}
 }
 
 func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -266,6 +294,13 @@
 		ctx.InstallFile(soInstallPath, jniLib.path.Base(), jniLib.path)
 	}
 
+	dataInstallPath := installPath.Join(ctx, "ravenwood-data")
+	for _, data := range r.ravenwoodLibgroupProperties.Data {
+		libModule := ctx.GetDirectDepWithTag(data, ravenwoodDataTag)
+		file := android.OutputFileForModule(ctx, libModule, "")
+		ctx.InstallFile(dataInstallPath, file.Base(), file)
+	}
+
 	// Normal build should perform install steps
 	ctx.Phony(r.BaseModuleName(), android.PathForPhony(ctx, r.BaseModuleName()+"-install"))
 }
diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go
index 5961264..d26db93 100644
--- a/java/ravenwood_test.go
+++ b/java/ravenwood_test.go
@@ -57,6 +57,14 @@
 			name: "framework-rules.ravenwood",
 			srcs: ["Rules.java"],
 		}
+		android_app {
+			name: "app1",
+            sdk_version: "current",
+		}
+		android_app {
+			name: "app2",
+            sdk_version: "current",
+		}
 		android_ravenwood_libgroup {
 			name: "ravenwood-runtime",
 			libs: [
@@ -67,6 +75,9 @@
 				"ravenwood-runtime-jni1",
 				"ravenwood-runtime-jni2",
 			],
+			data: [
+				"app1",
+			],
 		}
 		android_ravenwood_libgroup {
 			name: "ravenwood-utils",
@@ -102,6 +113,7 @@
 	runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni1.so")
 	runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/libred.so")
 	runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so")
+	runtime.Output(installPathPrefix + "/ravenwood-runtime/ravenwood-data/app1.apk")
 	utils := ctx.ModuleForTests("ravenwood-utils", "android_common")
 	utils.Output(installPathPrefix + "/ravenwood-utils/framework-rules.ravenwood.jar")
 }
@@ -143,6 +155,7 @@
 				"jni-lib2",
 				"ravenwood-runtime-jni2",
 			],
+			resource_apk: "app2",
 			sdk_version: "test_current",
 		}
 	`)
@@ -169,6 +182,7 @@
 	module.Output(installPathPrefix + "/ravenwood-test/lib64/jni-lib1.so")
 	module.Output(installPathPrefix + "/ravenwood-test/lib64/libblue.so")
 	module.Output(installPathPrefix + "/ravenwood-test/lib64/libpink.so")
+	module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-res.apk")
 
 	// ravenwood-runtime*.so are included in the runtime, so it shouldn't be emitted.
 	for _, o := range module.AllOutputs() {