Support native SOs in ravenwood runtime

Bug: 323931246
Test: m nothing --no-skip-soong-tests
Test: Manual test using a locally created build rule

Merged-in: Icd15d63c29560dc219dba07cc9db2a5e1b883532
Change-Id: Icd15d63c29560dc219dba07cc9db2a5e1b883532
diff --git a/java/ravenwood.go b/java/ravenwood.go
index e362003..dcb5c8b 100644
--- a/java/ravenwood.go
+++ b/java/ravenwood.go
@@ -30,13 +30,27 @@
 }
 
 var ravenwoodTag = dependencyTag{name: "ravenwood"}
+var ravenwoodJniTag = dependencyTag{name: "ravenwood-jni"}
 
 const ravenwoodUtilsName = "ravenwood-utils"
 const ravenwoodRuntimeName = "ravenwood-runtime"
 
+func getLibPath(archType android.ArchType) string {
+	if archType.Multilib == "lib64" {
+		return "lib64"
+	}
+	return "lib"
+}
+
+type ravenwoodTestProperties struct {
+	Jni_libs []string
+}
+
 type ravenwoodTest struct {
 	Library
 
+	ravenwoodTestProperties ravenwoodTestProperties
+
 	testProperties testProperties
 	testConfig     android.Path
 
@@ -48,7 +62,7 @@
 	module := &ravenwoodTest{}
 
 	module.addHostAndDeviceProperties()
-	module.AddProperties(&module.testProperties)
+	module.AddProperties(&module.testProperties, &module.ravenwoodTestProperties)
 
 	module.Module.dexpreopter.isTest = true
 	module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
@@ -86,6 +100,11 @@
 			ctx.AddVariationDependencies(nil, libTag, lib)
 		}
 	}
+
+	// Add jni libs
+	for _, lib := range r.ravenwoodTestProperties.Jni_libs {
+		ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), ravenwoodJniTag, lib)
+	}
 }
 
 func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -116,7 +135,15 @@
 	installConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig)
 	installDeps = append(installDeps, installConfig)
 
-	// Finally install our JAR with all dependencies
+	// Depend on the JNI libraries.
+	soInstallPath := installPath.Join(ctx, getLibPath(r.forceArchType))
+	for _, dep := range ctx.GetDirectDepsWithTag(ravenwoodJniTag) {
+		file := android.OutputFileForModule(ctx, dep, "")
+		installJni := ctx.InstallFile(soInstallPath, file.Base(), file)
+		installDeps = append(installDeps, installJni)
+	}
+
+	// Install our JAR with all dependencies
 	ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
 }
 
@@ -137,6 +164,8 @@
 
 type ravenwoodLibgroupProperties struct {
 	Libs []string
+
+	Jni_libs []string
 }
 
 type ravenwoodLibgroup struct {
@@ -172,6 +201,9 @@
 	for _, lib := range r.ravenwoodLibgroupProperties.Libs {
 		ctx.AddVariationDependencies(nil, ravenwoodTag, lib)
 	}
+	for _, lib := range r.ravenwoodLibgroupProperties.Jni_libs {
+		ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), ravenwoodJniTag, lib)
+	}
 }
 
 func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -185,6 +217,11 @@
 		libJar := android.OutputFileForModule(ctx, libModule, "")
 		ctx.InstallFile(installPath, lib+".jar", libJar)
 	}
+	soInstallPath := android.PathForModuleInstall(ctx, r.BaseModuleName()).Join(ctx, getLibPath(r.forceArchType))
+	for _, dep := range ctx.GetDirectDepsWithTag(ravenwoodJniTag) {
+		file := android.OutputFileForModule(ctx, dep, "")
+		ctx.InstallFile(soInstallPath, 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 2443ea8..a71391c 100644
--- a/java/ravenwood_test.go
+++ b/java/ravenwood_test.go
@@ -26,6 +26,17 @@
 		RegisterRavenwoodBuildComponents(ctx)
 	}),
 	android.FixtureAddTextFile("ravenwood/Android.bp", `
+		cc_library_shared {
+			name: "ravenwood-runtime-jni",
+			host_supported: true,
+			srcs: ["jni.cpp"],
+		}
+		cc_library_shared {
+			name: "ravenwood-runtime-jni2",
+			host_supported: true,
+			srcs: ["jni.cpp"],
+			stem: "libred",
+		}
 		java_library_static {
 			name: "framework-minus-apex.ravenwood",
 			srcs: ["Framework.java"],
@@ -44,6 +55,7 @@
 				"framework-minus-apex.ravenwood",
 				"framework-services.ravenwood",
 			],
+			jni_libs: ["ravenwood-runtime-jni", "ravenwood-runtime-jni2"],
 		}
 		android_ravenwood_libgroup {
 			name: "ravenwood-utils",
@@ -69,12 +81,15 @@
 	// Verify that our runtime depends on underlying libs
 	CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-runtime", "android_common", "framework-minus-apex.ravenwood")
 	CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-runtime", "android_common", "framework-services.ravenwood")
+	CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-runtime", "android_common", "ravenwood-runtime-jni")
 	CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-utils", "android_common", "framework-rules.ravenwood")
 
 	// Verify that we've emitted artifacts in expected location
 	runtime := ctx.ModuleForTests("ravenwood-runtime", "android_common")
 	runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-minus-apex.ravenwood.jar")
 	runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-services.ravenwood.jar")
+	runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni.so")
+	runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/libred.so")
 	utils := ctx.ModuleForTests("ravenwood-utils", "android_common")
 	utils.Output(installPathPrefix + "/ravenwood-utils/framework-rules.ravenwood.jar")
 }
@@ -88,9 +103,21 @@
 		PrepareForIntegrationTestWithJava,
 		prepareRavenwoodRuntime,
 	).RunTestWithBp(t, `
-		android_ravenwood_test {
+	cc_library_shared {
+		name: "jni-lib",
+		host_supported: true,
+		srcs: ["jni.cpp"],
+	}
+	cc_library_shared {
+		name: "jni-lib2",
+		host_supported: true,
+		srcs: ["jni.cpp"],
+		stem: "libblue",
+	}
+	android_ravenwood_test {
 			name: "ravenwood-test",
 			srcs: ["Test.java"],
+			jni_libs: ["jni-lib", "jni-lib2"],
 			sdk_version: "test_current",
 		}
 	`)
@@ -98,6 +125,7 @@
 	// Verify that our test depends on underlying libs
 	CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "ravenwood-buildtime")
 	CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "ravenwood-utils")
+	CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "jni-lib")
 
 	module := ctx.ModuleForTests("ravenwood-test", "android_common")
 	classpath := module.Rule("javac").Args["classpath"]
@@ -113,10 +141,14 @@
 	// Verify that we've emitted test artifacts in expected location
 	outputJar := module.Output(installPathPrefix + "/ravenwood-test/ravenwood-test.jar")
 	module.Output(installPathPrefix + "/ravenwood-test/ravenwood-test.config")
+	module.Output(installPathPrefix + "/ravenwood-test/lib64/jni-lib.so")
+	module.Output(installPathPrefix + "/ravenwood-test/lib64/libblue.so")
 
 	// Verify that we're going to install underlying libs
 	orderOnly := outputJar.OrderOnly.Strings()
 	android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/framework-minus-apex.ravenwood.jar")
 	android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/framework-services.ravenwood.jar")
+	android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/ravenwood-runtime-jni.so")
+	android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/libred.so")
 	android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-utils/framework-rules.ravenwood.jar")
 }