Merge "Also package recursive jni_libs deps of android_apps as well as direct deps."
diff --git a/cc/cc.go b/cc/cc.go
index 512fe8e..7aa02fc 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -759,7 +759,7 @@
 	return inList(c.Name(), ndkMigratedLibs)
 }
 
-func (c *Module) isLlndk(config android.Config) bool {
+func (c *Module) IsLlndk(config android.Config) bool {
 	// Returns true for both LLNDK (public) and LLNDK-private libs.
 	return isLlndkLibrary(c.BaseModuleName(), config)
 }
@@ -999,7 +999,7 @@
 }
 
 func (ctx *moduleContextImpl) isLlndk(config android.Config) bool {
-	return ctx.mod.isLlndk(config)
+	return ctx.mod.IsLlndk(config)
 }
 
 func (ctx *moduleContextImpl) isLlndkPublic(config android.Config) bool {
@@ -1880,7 +1880,7 @@
 			return true
 		}
 
-		if to.isVndkSp() || to.isLlndk(ctx.Config()) || Bool(to.VendorProperties.Double_loadable) {
+		if to.isVndkSp() || to.IsLlndk(ctx.Config()) || Bool(to.VendorProperties.Double_loadable) {
 			return false
 		}
 
@@ -1895,7 +1895,7 @@
 	}
 	if module, ok := ctx.Module().(*Module); ok {
 		if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() {
-			if module.isLlndk(ctx.Config()) || Bool(module.VendorProperties.Double_loadable) {
+			if module.IsLlndk(ctx.Config()) || Bool(module.VendorProperties.Double_loadable) {
 				ctx.WalkDeps(check)
 			}
 		}
diff --git a/cc/sabi.go b/cc/sabi.go
index 8cef170..7c9c651 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -80,7 +80,7 @@
 
 func sabiDepsMutator(mctx android.TopDownMutatorContext) {
 	if c, ok := mctx.Module().(*Module); ok &&
-		((c.IsVndk() && c.UseVndk()) || c.isLlndk(mctx.Config()) ||
+		((c.IsVndk() && c.UseVndk()) || c.IsLlndk(mctx.Config()) ||
 			(c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) {
 		mctx.VisitDirectDeps(func(m android.Module) {
 			tag := mctx.OtherModuleDependencyTag(m)
diff --git a/java/app.go b/java/app.go
index 7595e36..aa9c78c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -167,18 +167,11 @@
 		a.aapt.deps(ctx, sdkDep)
 	}
 
+	tag := &jniDependencyTag{}
 	for _, jniTarget := range ctx.MultiTargets() {
 		variation := append(jniTarget.Variations(),
 			blueprint.Variation{Mutator: "link", Variation: "shared"})
-		tag := &jniDependencyTag{
-			target: jniTarget,
-		}
 		ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
-		if String(a.appProperties.Stl) == "c++_shared" {
-			if a.shouldEmbedJnis(ctx) {
-				ctx.AddFarVariationDependencies(variation, tag, "ndk_libc++_shared")
-			}
-		}
 	}
 
 	a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
@@ -471,7 +464,7 @@
 
 	dexJarFile := a.dexBuildActions(ctx)
 
-	jniLibs, certificateDeps := collectAppDeps(ctx)
+	jniLibs, certificateDeps := collectAppDeps(ctx, a.shouldEmbedJnis(ctx))
 	jniJarFile := a.jniBuildActions(jniLibs, ctx)
 
 	if ctx.Failed() {
@@ -507,22 +500,33 @@
 	}
 }
 
-func collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) {
+func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps bool) ([]jniLib, []Certificate) {
 	var jniLibs []jniLib
 	var certificates []Certificate
+	seenModulePaths := make(map[string]bool)
 
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.WalkDeps(func(module android.Module, parent android.Module) bool {
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
-		if jniTag, ok := tag.(*jniDependencyTag); ok {
+		if IsJniDepTag(tag) || tag == cc.SharedDepTag {
 			if dep, ok := module.(*cc.Module); ok {
+				if dep.IsLlndk(ctx.Config()) || dep.IsStubs() {
+					return false
+				}
+
 				lib := dep.OutputFile()
+				path := lib.Path()
+				if seenModulePaths[path.String()] {
+					return false
+				}
+				seenModulePaths[path.String()] = true
+
 				if lib.Valid() {
 					jniLibs = append(jniLibs, jniLib{
 						name:   ctx.OtherModuleName(module),
-						path:   lib.Path(),
-						target: jniTag.target,
+						path:   path,
+						target: module.Target(),
 					})
 				} else {
 					ctx.ModuleErrorf("dependency %q missing output file", otherName)
@@ -530,13 +534,19 @@
 			} else {
 				ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName)
 			}
-		} else if tag == certificateTag {
+
+			return shouldCollectRecursiveNativeDeps
+		}
+
+		if tag == certificateTag {
 			if dep, ok := module.(*AndroidAppCertificate); ok {
 				certificates = append(certificates, dep.Certificate)
 			} else {
 				ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
 			}
 		}
+
+		return false
 	})
 
 	return jniLibs, certificates
@@ -968,7 +978,7 @@
 		ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
 	}
 
-	_, certificates := collectAppDeps(ctx)
+	_, certificates := collectAppDeps(ctx, false)
 
 	// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
 	// TODO: LOCAL_PACKAGE_SPLITS
diff --git a/java/app_builder.go b/java/app_builder.go
index ec2f6da..5e7fbe6 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -200,14 +200,14 @@
 	}
 
 	if uncompressJNI {
-		jarArgs = append(jarArgs, "-L 0")
+		jarArgs = append(jarArgs, "-L", "0")
 	}
 
 	for _, j := range jniLibs {
 		deps = append(deps, j.path)
 		jarArgs = append(jarArgs,
-			"-P "+targetToJniDir(j.target),
-			"-f "+j.path.String())
+			"-P", targetToJniDir(j.target),
+			"-f", j.path.String())
 	}
 
 	ctx.Build(pctx, android.BuildParams{
diff --git a/java/app_test.go b/java/app_test.go
index 1800bb7..5cf0ba7 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1631,7 +1631,45 @@
 func TestStl(t *testing.T) {
 	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		cc_library {
+			name: "ndk_libunwind",
+			sdk_version: "current",
+			stl: "none",
+			system_shared_libs: [],
+		}
+
+		cc_library {
+			name: "libc.ndk.current",
+			sdk_version: "current",
+			stl: "none",
+			system_shared_libs: [],
+		}
+
+		cc_library {
+			name: "libm.ndk.current",
+			sdk_version: "current",
+			stl: "none",
+			system_shared_libs: [],
+		}
+
+		cc_library {
+			name: "libdl.ndk.current",
+			sdk_version: "current",
+			stl: "none",
+			system_shared_libs: [],
+		}
+
+		cc_object {
+			name: "ndk_crtbegin_so.27",
+		}
+
+		cc_object {
+			name: "ndk_crtend_so.27",
+		}
+
+		cc_library {
 			name: "libjni",
+			sdk_version: "current",
+			stl: "c++_shared",
 		}
 
 		android_test {
diff --git a/java/java.go b/java/java.go
index 59bfaf7..9745da4 100644
--- a/java/java.go
+++ b/java/java.go
@@ -466,7 +466,6 @@
 
 type jniDependencyTag struct {
 	blueprint.BaseDependencyTag
-	target android.Target
 }
 
 func IsJniDepTag(depTag blueprint.DependencyTag) bool {