Convert collectJniDeps to use ModuleProxy.

Bug: 377723687
Test: Unit tests and compare the ninja and mk files generated.
Change-Id: I36f8b339f70ab47be84c598231cb971145fc4ef7
diff --git a/android/module.go b/android/module.go
index 2dd2f19..089f127 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1872,6 +1872,7 @@
 	BaseModuleName          string
 	CanHaveApexVariants     bool
 	MinSdkVersion           string
+	SdkVersion              string
 	NotAvailableForPlatform bool
 	// There some subtle differences between this one and the one above.
 	NotInPlatform bool
@@ -2183,6 +2184,17 @@
 		commonData.MinSdkVersion = mm.MinSdkVersion()
 	}
 
+	if mm, ok := m.module.(interface {
+		SdkVersion(ctx EarlyModuleContext) ApiLevel
+	}); ok {
+		ver := mm.SdkVersion(ctx)
+		if !ver.IsNone() {
+			commonData.SdkVersion = ver.String()
+		}
+	} else if mm, ok := m.module.(interface{ SdkVersion() string }); ok {
+		commonData.SdkVersion = mm.SdkVersion()
+	}
+
 	if m.commonProperties.ForcedDisabled {
 		commonData.Enabled = false
 	} else {
diff --git a/cc/cc.go b/cc/cc.go
index 57b5e3c..16aa4a7 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -136,7 +136,11 @@
 	UnstrippedOutputFile android.Path
 	OutputFile           android.OptionalPath
 	CoverageFiles        android.Paths
-	SAbiDumpFiles        android.Paths
+	// CoverageOutputFile returns the output archive of gcno coverage information files.
+	CoverageOutputFile android.OptionalPath
+	SAbiDumpFiles      android.Paths
+	// Partition returns the partition string for this module.
+	Partition            string
 	CcLibrary            bool
 	CcLibraryInterface   bool
 	RustLibraryInterface bool
@@ -148,7 +152,9 @@
 	BaseModuleName       string
 	HasNonSystemVariants bool
 	IsLlndk              bool
-	InVendorOrProduct    bool
+	// True if the library is in the configs known NDK list.
+	IsNdk             bool
+	InVendorOrProduct bool
 	// SubName returns the modules SubName, used for image and NDK/SDK variations.
 	SubName             string
 	InRamdisk           bool
@@ -162,6 +168,8 @@
 	RelativeInstallPath string
 	// TODO(b/362509506): remove this once all apex_exclude uses are switched to stubs.
 	RustApexExclude bool
+	// Bootstrap tests if this module is allowed to use non-APEX version of libraries.
+	Bootstrap bool
 }
 
 var LinkableInfoProvider = blueprint.NewProvider[*LinkableInfo]()
@@ -2261,7 +2269,7 @@
 		android.SetProvider(ctx, CcObjectInfoProvider, ccObjectInfo)
 	}
 
-	linkableInfo := CreateCommonLinkableInfo(c)
+	linkableInfo := CreateCommonLinkableInfo(ctx, c)
 	if lib, ok := c.linker.(VersionedInterface); ok {
 		linkableInfo.StubsVersion = lib.StubsVersion()
 	}
@@ -2348,18 +2356,21 @@
 	}
 }
 
-func CreateCommonLinkableInfo(mod VersionedLinkableInterface) *LinkableInfo {
+func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableInterface) *LinkableInfo {
 	return &LinkableInfo{
 		StaticExecutable:     mod.StaticExecutable(),
 		HasStubsVariants:     mod.HasStubsVariants(),
 		OutputFile:           mod.OutputFile(),
 		UnstrippedOutputFile: mod.UnstrippedOutputFile(),
+		CoverageOutputFile:   mod.CoverageOutputFile(),
+		Partition:            mod.Partition(),
 		IsStubs:              mod.IsStubs(),
 		CcLibrary:            mod.CcLibrary(),
 		CcLibraryInterface:   mod.CcLibraryInterface(),
 		RustLibraryInterface: mod.RustLibraryInterface(),
 		BaseModuleName:       mod.BaseModuleName(),
 		IsLlndk:              mod.IsLlndk(),
+		IsNdk:                mod.IsNdk(ctx.Config()),
 		HasNonSystemVariants: mod.HasNonSystemVariants(),
 		SubName:              mod.SubName(),
 		InVendorOrProduct:    mod.InVendorOrProduct(),
@@ -2373,6 +2384,7 @@
 		RelativeInstallPath:  mod.RelativeInstallPath(),
 		// TODO(b/362509506): remove this once all apex_exclude uses are switched to stubs.
 		RustApexExclude: mod.RustApexExclude(),
+		Bootstrap:            mod.Bootstrap(),
 	}
 }
 
@@ -3601,14 +3613,23 @@
 	return depPaths
 }
 
-func ShouldUseStubForApex(ctx android.ModuleContext, parent, dep android.Module) bool {
+func ShouldUseStubForApex(ctx android.ModuleContext, parent android.Module, dep android.ModuleProxy) bool {
 	inVendorOrProduct := false
 	bootstrap := false
-	if linkable, ok := parent.(LinkableInterface); !ok {
-		ctx.ModuleErrorf("Not a Linkable module: %q", ctx.ModuleName())
+	if ctx.EqualModules(ctx.Module(), parent) {
+		if linkable, ok := parent.(LinkableInterface); !ok {
+			ctx.ModuleErrorf("Not a Linkable module: %q", ctx.ModuleName())
+		} else {
+			inVendorOrProduct = linkable.InVendorOrProduct()
+			bootstrap = linkable.Bootstrap()
+		}
 	} else {
-		inVendorOrProduct = linkable.InVendorOrProduct()
-		bootstrap = linkable.Bootstrap()
+		if linkable, ok := android.OtherModuleProvider(ctx, parent, LinkableInfoProvider); !ok {
+			ctx.ModuleErrorf("Not a Linkable module: %q", ctx.ModuleName())
+		} else {
+			inVendorOrProduct = linkable.InVendorOrProduct
+			bootstrap = linkable.Bootstrap
+		}
 	}
 
 	apexInfo, _ := android.OtherModuleProvider(ctx, parent, android.ApexInfoProvider)
@@ -3645,7 +3666,7 @@
 // library bar which provides stable interface and exists in the platform, foo uses the stub variant
 // of bar. If bar doesn't provide a stable interface (i.e. buildStubs() == false) or is in the
 // same APEX as foo, the non-stub variant of bar is used.
-func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibraryInfo, FlagExporterInfo) {
+func ChooseStubOrImpl(ctx android.ModuleContext, dep android.ModuleProxy) (SharedLibraryInfo, FlagExporterInfo) {
 	depTag := ctx.OtherModuleDependencyTag(dep)
 	libDepTag, ok := depTag.(libraryDependencyTag)
 	if !ok || !libDepTag.shared() {
diff --git a/java/app.go b/java/app.go
index 795eed1..f4c658c 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1113,18 +1113,23 @@
 			app.SdkVersion(ctx).Kind != android.SdkCorePlatform && !app.RequiresStableAPIs(ctx)
 	}
 	jniLib, prebuiltJniPackages := collectJniDeps(ctx, shouldCollectRecursiveNativeDeps,
-		checkNativeSdkVersion, func(parent, child android.Module) bool {
+		checkNativeSdkVersion, func(parent, child android.ModuleProxy) bool {
 			apkInApex := ctx.Module().(android.ApexModule).NotInPlatform()
-			childLinkable, _ := child.(cc.LinkableInterface)
-			parentLinkable, _ := parent.(cc.LinkableInterface)
-			useStubsOfDep := childLinkable.IsStubs()
-			if apkInApex && parentLinkable != nil {
-				vintf := childLinkable.(cc.VersionedLinkableInterface).VersionedInterface()
+			childLinkable, _ := android.OtherModuleProvider(ctx, child, cc.LinkableInfoProvider)
+			parentIsLinkable := false
+			if ctx.EqualModules(ctx.Module(), parent) {
+				parentLinkable, _ := ctx.Module().(cc.LinkableInterface)
+				parentIsLinkable = parentLinkable != nil
+			} else {
+				_, parentIsLinkable = android.OtherModuleProvider(ctx, parent, cc.LinkableInfoProvider)
+			}
+			useStubsOfDep := childLinkable.IsStubs
+			if apkInApex && parentIsLinkable {
 				// APK-in-APEX
 				// If the parent is a linkable interface, use stubs if the dependency edge crosses an apex boundary.
-				useStubsOfDep = useStubsOfDep || (vintf.HasStubsVariants() && cc.ShouldUseStubForApex(ctx, parent, child))
+				useStubsOfDep = useStubsOfDep || (childLinkable.HasStubsVariants && cc.ShouldUseStubForApex(ctx, parent, child))
 			}
-			return !childLinkable.IsNdk(ctx.Config()) && !useStubsOfDep
+			return !childLinkable.IsNdk && !useStubsOfDep
 		})
 
 	var certificates []Certificate
@@ -1160,22 +1165,22 @@
 func collectJniDeps(ctx android.ModuleContext,
 	shouldCollectRecursiveNativeDeps bool,
 	checkNativeSdkVersion bool,
-	filter func(parent, child android.Module) bool) ([]jniLib, android.Paths) {
+	filter func(parent, child android.ModuleProxy) bool) ([]jniLib, android.Paths) {
 	var jniLibs []jniLib
 	var prebuiltJniPackages android.Paths
 	seenModulePaths := make(map[string]bool)
 
-	ctx.WalkDeps(func(module android.Module, parent android.Module) bool {
+	ctx.WalkDepsProxy(func(module, parent android.ModuleProxy) bool {
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
 		if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) {
-			if dep, ok := module.(cc.LinkableInterface); ok {
+			if dep, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
 				if filter != nil && !filter(parent, module) {
 					return false
 				}
 
-				lib := dep.OutputFile()
+				lib := dep.OutputFile
 				if lib.Valid() {
 					path := lib.Path()
 					if seenModulePaths[path.String()] {
@@ -1183,7 +1188,8 @@
 					}
 					seenModulePaths[path.String()] = true
 
-					if checkNativeSdkVersion && dep.SdkVersion() == "" {
+					commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey)
+					if checkNativeSdkVersion && commonInfo.SdkVersion == "" {
 						ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not",
 							otherName)
 					}
@@ -1191,11 +1197,11 @@
 					jniLibs = append(jniLibs, jniLib{
 						name:           ctx.OtherModuleName(module),
 						path:           path,
-						target:         module.Target(),
-						coverageFile:   dep.CoverageOutputFile(),
-						unstrippedFile: dep.UnstrippedOutputFile(),
-						partition:      dep.Partition(),
-						installPaths:   android.OtherModuleProviderOrDefault(ctx, dep, android.InstallFilesProvider).InstallFiles,
+						target:         commonInfo.Target,
+						coverageFile:   dep.CoverageOutputFile,
+						unstrippedFile: dep.UnstrippedOutputFile,
+						partition:      dep.Partition,
+						installPaths:   android.OtherModuleProviderOrDefault(ctx, module, android.InstallFilesProvider).InstallFiles,
 					})
 				} else if ctx.Config().AllowMissingDependencies() {
 					ctx.AddMissingDependencies([]string{otherName})
diff --git a/rust/rust.go b/rust/rust.go
index 557bdc3..c7aabcd 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1120,7 +1120,7 @@
 		ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
 	}
 
-	linkableInfo := cc.CreateCommonLinkableInfo(mod)
+	linkableInfo := cc.CreateCommonLinkableInfo(ctx, mod)
 	linkableInfo.Static = mod.Static()
 	linkableInfo.Shared = mod.Shared()
 	linkableInfo.CrateName = mod.CrateName()