Skip packaging cross container cc deps of apk-in-apex

With this change, apk-in-apex will skip packaging a cc library
dependency if the dependency is part of the platform or part of a
different apex.

Bug: 375473764
Test: go test ./java ./apex
Test: presubmits

Change-Id: I91351973c2c941c7531e9f7d4879049eab766a12
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 5b5fe5f..2ca74a6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -12137,34 +12137,32 @@
 			},
 			dependencyPath: []string{"myapex", "libjni", "libbar", "libplatform"},
 		},
-		// TODO: embedded JNI in apps should be checked too, but Soong currently just packages the transitive
-		//  JNI libraries even if they came from another apex.
-		//{
-		//	name:           "app jni library dependency in other apex",
-		//	bpModifier:     addToSharedLibs("libembeddedjni", "libotherapex#impl"),
-		//	dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libotherapex"},
-		//},
-		//{
-		//	name: "transitive app jni library dependency in other apex",
-		//	bpModifier: func(bp *bpmodify.Blueprint) {
-		//		addToSharedLibs("libembeddedjni", "libbar")(bp)
-		//		addToSharedLibs("libbar", "libotherapex#impl")(bp)
-		//	},
-		//	dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libbar", "libotherapex"},
-		//},
-		//{
-		//	name:           "app jni library dependency in platform",
-		//	bpModifier:     addToSharedLibs("libembeddedjni", "libplatform#impl"),
-		//	dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libplatform"},
-		//},
-		//{
-		//	name: "transitive app jni library dependency in platform",
-		//	bpModifier: func(bp *bpmodify.Blueprint) {
-		//		addToSharedLibs("libembeddedjni", "libbar")(bp)
-		//		addToSharedLibs("libbar", "libplatform#impl")(bp)
-		//	},
-		//	dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libbar", "libplatform"},
-		//},
+		{
+			name:           "app jni library dependency in other apex",
+			bpModifier:     addToSharedLibs("libembeddedjni", "libotherapex#impl"),
+			dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libotherapex"},
+		},
+		{
+			name: "transitive app jni library dependency in other apex",
+			bpModifier: func(bp *bpmodify.Blueprint) {
+				addToSharedLibs("libembeddedjni", "libbar")(bp)
+				addToSharedLibs("libbar", "libotherapex#impl")(bp)
+			},
+			dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libbar", "libotherapex"},
+		},
+		{
+			name:           "app jni library dependency in platform",
+			bpModifier:     addToSharedLibs("libembeddedjni", "libplatform#impl"),
+			dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libplatform"},
+		},
+		{
+			name: "transitive app jni library dependency in platform",
+			bpModifier: func(bp *bpmodify.Blueprint) {
+				addToSharedLibs("libembeddedjni", "libbar")(bp)
+				addToSharedLibs("libbar", "libplatform#impl")(bp)
+			},
+			dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libbar", "libplatform"},
+		},
 		{
 			name:           "binary dependency in other apex",
 			bpModifier:     addToSharedLibs("mybin", "libotherapex#impl"),
diff --git a/cc/cc.go b/cc/cc.go
index 65ab686..03f738f 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3345,17 +3345,17 @@
 	return depPaths
 }
 
-func ShouldUseStubForApex(ctx android.ModuleContext, dep android.Module) bool {
+func ShouldUseStubForApex(ctx android.ModuleContext, parent, dep android.Module) bool {
 	inVendorOrProduct := false
 	bootstrap := false
-	if linkable, ok := ctx.Module().(LinkableInterface); !ok {
-		panic(fmt.Errorf("Not a Linkable module: %q", ctx.ModuleName()))
+	if linkable, ok := parent.(LinkableInterface); !ok {
+		ctx.ModuleErrorf("Not a Linkable module: %q", ctx.ModuleName())
 	} else {
 		inVendorOrProduct = linkable.InVendorOrProduct()
 		bootstrap = linkable.Bootstrap()
 	}
 
-	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+	apexInfo, _ := android.OtherModuleProvider(ctx, parent, android.ApexInfoProvider)
 
 	useStubs := false
 
@@ -3402,7 +3402,7 @@
 
 	if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedStubLibraries) > 0 {
 		// when to use (unspecified) stubs, use the latest one.
-		if ShouldUseStubForApex(ctx, dep) {
+		if ShouldUseStubForApex(ctx, ctx.Module(), dep) {
 			stubs := sharedLibraryStubsInfo.SharedStubLibraries
 			toUse := stubs[len(stubs)-1]
 			sharedLibraryInfo = toUse.SharedLibraryInfo
diff --git a/cc/linkable.go b/cc/linkable.go
index ef204eb..1a9a9ab 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -135,6 +135,10 @@
 	// IsNdk returns true if the library is in the configs known NDK list.
 	IsNdk(config android.Config) bool
 
+	// HasStubsVariants true if this module is a stub or has a sibling variant
+	// that is a stub.
+	HasStubsVariants() bool
+
 	// IsStubs returns true if the this is a stubs library.
 	IsStubs() bool
 
diff --git a/java/app.go b/java/app.go
index 7f80160..832a083 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1082,7 +1082,17 @@
 			app.SdkVersion(ctx).Kind != android.SdkCorePlatform && !app.RequiresStableAPIs(ctx)
 	}
 	jniLib, prebuiltJniPackages := collectJniDeps(ctx, shouldCollectRecursiveNativeDeps,
-		checkNativeSdkVersion, func(dep cc.LinkableInterface) bool { return !dep.IsNdk(ctx.Config()) && !dep.IsStubs() })
+		checkNativeSdkVersion, func(parent, child android.Module) bool {
+			childLinkable, _ := child.(cc.LinkableInterface)
+			parentLinkable, _ := parent.(cc.LinkableInterface)
+			useStubsOfDep := childLinkable.IsStubs()
+			if parent.(android.ApexModule).NotInPlatform() && parentLinkable != nil {
+				// APK-in-APEX
+				// If the parent is a linkable interface, use stubs if the dependency edge crosses an apex boundary.
+				useStubsOfDep = useStubsOfDep || (childLinkable.HasStubsVariants() && cc.ShouldUseStubForApex(ctx, parent, child))
+			}
+			return !childLinkable.IsNdk(ctx.Config()) && !useStubsOfDep
+		})
 
 	var certificates []Certificate
 
@@ -1117,7 +1127,7 @@
 func collectJniDeps(ctx android.ModuleContext,
 	shouldCollectRecursiveNativeDeps bool,
 	checkNativeSdkVersion bool,
-	filter func(cc.LinkableInterface) bool) ([]jniLib, android.Paths) {
+	filter func(parent, child android.Module) bool) ([]jniLib, android.Paths) {
 	var jniLibs []jniLib
 	var prebuiltJniPackages android.Paths
 	seenModulePaths := make(map[string]bool)
@@ -1128,7 +1138,7 @@
 
 		if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) {
 			if dep, ok := module.(cc.LinkableInterface); ok {
-				if filter != nil && !filter(dep) {
+				if filter != nil && !filter(parent, module) {
 					return false
 				}
 
diff --git a/rust/rust.go b/rust/rust.go
index 48f946e..eeb228c 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -722,6 +722,10 @@
 	return false
 }
 
+func (mod *Module) HasStubsVariants() bool {
+	return false
+}
+
 func (mod *Module) IsStubs() bool {
 	return false
 }