Pass unstripped JNI libraries to Make

Pass a list of unstripped JNI libraries to Make so that they can be
installed into the symbols directory.

Bug: 159726429
Test: forrest
Change-Id: Ieb4bffbb3d0a09f476da011399c5b8b1611929d7
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7595238..48f84a1 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -105,9 +105,10 @@
 		fmt.Fprintln(w, "LOCAL_MODULE :=", moduleName)
 		// /apex/<apex_name>/{lib|framework|...}
 		pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir)
+		var modulePath string
 		if apexType == flattenedApex {
 			// /system/apex/<name>/{lib|framework|...}
-			modulePath := filepath.Join(a.installDir.ToMakePath().String(), apexBundleName, fi.installDir)
+			modulePath = filepath.Join(a.installDir.ToMakePath().String(), apexBundleName, fi.installDir)
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", modulePath)
 			if a.primaryApexType && !symbolFilesNotNeeded {
 				fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
@@ -131,6 +132,7 @@
 				fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(fi.module.NoticeFiles().Strings(), " "))
 			}
 		} else {
+			modulePath = pathWhenActivated
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", pathWhenActivated)
 
 			// For non-flattend APEXes, the merged notice file is attached to the APEX itself.
@@ -193,8 +195,13 @@
 			// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
 			// we will have foo.apk.apk
 			fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.Stem(), ".apk"))
-			if app, ok := fi.module.(*java.AndroidApp); ok && len(app.JniCoverageOutputs()) > 0 {
-				fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", strings.Join(app.JniCoverageOutputs().Strings(), " "))
+			if app, ok := fi.module.(*java.AndroidApp); ok {
+				if jniCoverageOutputs := app.JniCoverageOutputs(); len(jniCoverageOutputs) > 0 {
+					fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", strings.Join(jniCoverageOutputs.Strings(), " "))
+				}
+				if jniLibSymbols := app.JNISymbolsInstalls(modulePath); len(jniLibSymbols) > 0 {
+					fmt.Fprintln(w, "LOCAL_SOONG_JNI_LIBS_SYMBOLS :=", jniLibSymbols.String())
+				}
 			}
 			fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk")
 		case appSet:
diff --git a/java/androidmk.go b/java/androidmk.go
index 618e15d..39b6377 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -370,9 +370,15 @@
 				entries.SetString("LOCAL_CERTIFICATE", app.certificate.AndroidMkString())
 				entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", app.getOverriddenPackages()...)
 
-				for _, jniLib := range app.installJniLibs {
-					entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name)
+				if app.embeddedJniLibs {
+					jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String())
+					entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String())
+				} else {
+					for _, jniLib := range app.jniLibs {
+						entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name)
+					}
 				}
+
 				if len(app.jniCoverageOutputs) > 0 {
 					entries.AddStrings("LOCAL_PREBUILT_COVERAGE_ARCHIVE", app.jniCoverageOutputs.Strings()...)
 				}
diff --git a/java/app.go b/java/app.go
index 98bce94..a012815 100755
--- a/java/app.go
+++ b/java/app.go
@@ -288,8 +288,10 @@
 
 	overridableAppProperties overridableAppProperties
 
-	installJniLibs     []jniLib
-	jniCoverageOutputs android.Paths
+	jniLibs                  []jniLib
+	installPathForJNISymbols android.Path
+	embeddedJniLibs          bool
+	jniCoverageOutputs       android.Paths
 
 	bundleFile android.Path
 
@@ -566,8 +568,7 @@
 	a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile)
 }
 
-func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
-
+func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath {
 	var installDir string
 	if ctx.ModuleName() == "framework-res" {
 		// framework-res.apk is installed as system/framework/framework-res.apk
@@ -577,7 +578,12 @@
 	} else {
 		installDir = filepath.Join("app", a.installApkName)
 	}
-	a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
+
+	return android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
+}
+
+func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
+	a.dexpreopter.installPath = a.installPath(ctx)
 	if a.deviceProperties.Uncompress_dex == nil {
 		// If the value was not force-set by the user, use reasonable default based on the module.
 		a.deviceProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
@@ -599,8 +605,10 @@
 func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
 	var jniJarFile android.WritablePath
 	if len(jniLibs) > 0 {
+		a.jniLibs = jniLibs
 		if a.shouldEmbedJnis(ctx) {
 			jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
+			a.installPathForJNISymbols = a.installPath(ctx).ToMakePath()
 			TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
 			for _, jni := range jniLibs {
 				if jni.coverageFile.Valid() {
@@ -618,13 +626,25 @@
 					}
 				}
 			}
-		} else {
-			a.installJniLibs = jniLibs
+			a.embeddedJniLibs = true
 		}
 	}
 	return jniJarFile
 }
 
+func (a *AndroidApp) JNISymbolsInstalls(installPath string) android.RuleBuilderInstalls {
+	var jniSymbols android.RuleBuilderInstalls
+	for _, jniLib := range a.jniLibs {
+		if jniLib.unstrippedFile != nil {
+			jniSymbols = append(jniSymbols, android.RuleBuilderInstall{
+				From: jniLib.unstrippedFile,
+				To:   filepath.Join(installPath, targetToJniDir(jniLib.target), jniLib.unstrippedFile.Base()),
+			})
+		}
+	}
+	return jniSymbols
+}
+
 func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext) {
 	// Collect NOTICE files from all dependencies.
 	seenModules := make(map[android.Module]bool)
@@ -840,10 +860,11 @@
 
 				if lib.Valid() {
 					jniLibs = append(jniLibs, jniLib{
-						name:         ctx.OtherModuleName(module),
-						path:         path,
-						target:       module.Target(),
-						coverageFile: dep.CoverageOutputFile(),
+						name:           ctx.OtherModuleName(module),
+						path:           path,
+						target:         module.Target(),
+						coverageFile:   dep.CoverageOutputFile(),
+						unstrippedFile: dep.UnstrippedOutputFile(),
 					})
 				} else {
 					ctx.ModuleErrorf("dependency %q missing output file", otherName)
diff --git a/java/java.go b/java/java.go
index 46ef98b..367b09c 100644
--- a/java/java.go
+++ b/java/java.go
@@ -635,10 +635,11 @@
 }
 
 type jniLib struct {
-	name         string
-	path         android.Path
-	target       android.Target
-	coverageFile android.OptionalPath
+	name           string
+	path           android.Path
+	target         android.Target
+	coverageFile   android.OptionalPath
+	unstrippedFile android.Path
 }
 
 func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {