Merge "Update virtual ab properties in misc_info.txt" into main
diff --git a/android/module.go b/android/module.go
index 2dd2f19..b9489b4 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1850,7 +1850,7 @@
 	Srcs Paths
 }
 
-var SourceFilesInfoKey = blueprint.NewProvider[SourceFilesInfo]()
+var SourceFilesInfoProvider = blueprint.NewProvider[SourceFilesInfo]()
 
 // FinalModuleBuildTargetsInfo is used by buildTargetSingleton to create checkbuild and
 // per-directory build targets. Only set on the final variant of each module
@@ -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
@@ -1890,15 +1891,16 @@
 
 type PrebuiltModuleInfo struct {
 	SourceExists bool
+	UsePrebuilt  bool
 }
 
 var PrebuiltModuleInfoProvider = blueprint.NewProvider[PrebuiltModuleInfo]()
 
-type HostToolProviderData struct {
+type HostToolProviderInfo struct {
 	HostToolPath OptionalPath
 }
 
-var HostToolProviderKey = blueprint.NewProvider[HostToolProviderData]()
+var HostToolProviderInfoProvider = blueprint.NewProvider[HostToolProviderInfo]()
 
 type SourceFileGenerator interface {
 	GeneratedSourceFiles() Paths
@@ -2085,7 +2087,7 @@
 	}
 
 	if sourceFileProducer, ok := m.module.(SourceFileProducer); ok {
-		SetProvider(ctx, SourceFilesInfoKey, SourceFilesInfo{Srcs: sourceFileProducer.Srcs()})
+		SetProvider(ctx, SourceFilesInfoProvider, SourceFilesInfo{Srcs: sourceFileProducer.Srcs()})
 	}
 
 	if ctx.IsFinalModule(m.module) {
@@ -2183,6 +2185,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 {
@@ -2200,10 +2213,11 @@
 	if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil {
 		SetProvider(ctx, PrebuiltModuleInfoProvider, PrebuiltModuleInfo{
 			SourceExists: p.Prebuilt().SourceExists(),
+			UsePrebuilt:  p.Prebuilt().UsePrebuilt(),
 		})
 	}
 	if h, ok := m.module.(HostToolProvider); ok {
-		SetProvider(ctx, HostToolProviderKey, HostToolProviderData{
+		SetProvider(ctx, HostToolProviderInfoProvider, HostToolProviderInfo{
 			HostToolPath: h.HostToolPath()})
 	}
 
@@ -2786,7 +2800,7 @@
 			if sourceFileProducer, ok := module.(SourceFileProducer); ok {
 				return sourceFileProducer.Srcs(), nil
 			}
-		} else if sourceFiles, ok := OtherModuleProvider(octx, module, SourceFilesInfoKey); ok {
+		} else if sourceFiles, ok := OtherModuleProvider(octx, module, SourceFilesInfoProvider); ok {
 			if tag != "" {
 				return nil, fmt.Errorf("module %q is a SourceFileProducer, which does not support tag %q", pathContextName(ctx, module), tag)
 			}
diff --git a/android/module_proxy.go b/android/module_proxy.go
index 8cc8fa1..afca0d7 100644
--- a/android/module_proxy.go
+++ b/android/module_proxy.go
@@ -11,6 +11,10 @@
 
 var _ Module = (*ModuleProxy)(nil)
 
+func (m ModuleProxy) IsNil() bool {
+	return m.module.IsNil()
+}
+
 func (m ModuleProxy) Name() string {
 	return m.module.Name()
 }
diff --git a/android/proto.go b/android/proto.go
index 66faa20..91d6732 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -75,7 +75,7 @@
 	}
 
 	ctx.VisitDirectDepsProxyWithTag(ProtoPluginDepTag, func(dep ModuleProxy) {
-		if h, ok := OtherModuleProvider(ctx, dep, HostToolProviderKey); !ok || !h.HostToolPath.Valid() {
+		if h, ok := OtherModuleProvider(ctx, dep, HostToolProviderInfoProvider); !ok || !h.HostToolPath.Valid() {
 			ctx.PropertyErrorf("proto.plugin", "module %q is not a host tool provider",
 				ctx.OtherModuleName(dep))
 		} else {
diff --git a/cc/cc.go b/cc/cc.go
index 57b5e3c..b525ccb 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/dexpreopt/config.go b/dexpreopt/config.go
index ee23b51..c5cafb1 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -507,36 +507,37 @@
 	// final variants, while prebuilt_postdeps needs to run before many of the
 	// PostDeps mutators, like the APEX mutators). Hence we need to dig out the
 	// prebuilt explicitly here instead.
-	var dex2oatModule android.Module
-	ctx.WalkDeps(func(child, parent android.Module) bool {
-		if parent == ctx.Module() && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag {
+	var dex2oatModule android.ModuleProxy
+	ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
+		prebuiltInfo, isPrebuilt := android.OtherModuleProvider(ctx, child, android.PrebuiltModuleInfoProvider)
+		if ctx.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag {
 			// Found the source module, or prebuilt module that has replaced the source.
 			dex2oatModule = child
-			if android.IsModulePrebuilt(child) {
+			if isPrebuilt {
 				return false // If it's the prebuilt we're done.
 			} else {
 				return true // Recurse to check if the source has a prebuilt dependency.
 			}
 		}
-		if parent == dex2oatModule && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag {
-			if p := android.GetEmbeddedPrebuilt(child); p != nil && p.UsePrebuilt() {
+		if ctx.EqualModules(parent, dex2oatModule) && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag {
+			if isPrebuilt && prebuiltInfo.UsePrebuilt {
 				dex2oatModule = child // Found a prebuilt that should be used.
 			}
 		}
 		return false
 	})
 
-	if dex2oatModule == nil {
+	if dex2oatModule.IsNil() {
 		// If this happens there's probably a missing call to AddToolDeps in DepsMutator.
 		panic(fmt.Sprintf("Failed to lookup %s dependency", dex2oatBin))
 	}
 
-	dex2oatPath := dex2oatModule.(android.HostToolProvider).HostToolPath()
-	if !dex2oatPath.Valid() {
+	dex2oatPath, ok := android.OtherModuleProvider(ctx, dex2oatModule, android.HostToolProviderInfoProvider)
+	if !ok || !dex2oatPath.HostToolPath.Valid() {
 		panic(fmt.Sprintf("Failed to find host tool path in %s", dex2oatModule))
 	}
 
-	return dex2oatPath.Path()
+	return dex2oatPath.HostToolPath.Path()
 }
 
 // createGlobalSoongConfig creates a GlobalSoongConfig from the current context.
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
index fb76687..6d845f7 100644
--- a/filesystem/vbmeta.go
+++ b/filesystem/vbmeta.go
@@ -173,6 +173,8 @@
 	algorithm := proptools.StringDefault(v.properties.Algorithm, "SHA256_RSA4096")
 	cmd.FlagWithArg("--algorithm ", algorithm)
 
+	cmd.FlagWithArg("--padding_size ", "4096")
+
 	cmd.FlagWithArg("--rollback_index ", v.rollbackIndexCommand(ctx))
 	ril := proptools.IntDefault(v.properties.Rollback_index_location, 0)
 	if ril < 0 {
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 9a8524b..65f74ce 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -349,7 +349,7 @@
 				// replaced the dependency.
 				module := android.PrebuiltGetPreferred(ctx, proxy)
 				tool := ctx.OtherModuleName(module)
-				if h, ok := android.OtherModuleProvider(ctx, module, android.HostToolProviderKey); ok {
+				if h, ok := android.OtherModuleProvider(ctx, module, android.HostToolProviderInfoProvider); ok {
 					// A HostToolProvider provides the path to a tool, which will be copied
 					// into the sandbox.
 					if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled {
diff --git a/java/aar.go b/java/aar.go
index 0db195c..b982b95 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -1455,7 +1455,7 @@
 	var transitiveStaticLibsImplementationJars []depset.DepSet[android.Path]
 	var transitiveStaticLibsResourceJars []depset.DepSet[android.Path]
 
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
 			tag := ctx.OtherModuleDependencyTag(module)
 			switch tag {
diff --git a/java/app.go b/java/app.go
index 6a4cd4b..f4c658c 100644
--- a/java/app.go
+++ b/java/app.go
@@ -673,7 +673,7 @@
 
 func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) {
 	var staticLibProguardFlagFiles android.Paths
-	ctx.VisitDirectDeps(func(m android.Module) {
+	ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
 		depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
 		staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.UnconditionallyExportedProguardFlags.ToList()...)
 		if ctx.OtherModuleDependencyTag(m) == staticLibTag {
@@ -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/java/base.go b/java/base.go
index 1e0d4bf..8e013b9 100644
--- a/java/base.go
+++ b/java/base.go
@@ -2151,7 +2151,7 @@
 	directStaticLibs := android.Paths{}
 	transitiveLibs := []depset.DepSet[android.Path]{}
 	transitiveStaticLibs := []depset.DepSet[android.Path]{}
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		// don't add deps of the prebuilt version of the same library
 		if ctx.ModuleName() == android.RemoveOptionalPrebuiltPrefix(module.Name()) {
 			return
@@ -2275,7 +2275,7 @@
 
 func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) {
 	var fromDeps []depset.DepSet[android.Path]
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		tag := ctx.OtherModuleDependencyTag(module)
 		if tag == staticLibTag {
 			if depInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
@@ -2433,7 +2433,7 @@
 	var transitiveStaticJarsImplementationLibs []depset.DepSet[android.Path]
 	var transitiveStaticJarsResourceLibs []depset.DepSet[android.Path]
 
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
@@ -2467,7 +2467,7 @@
 				deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
 				transitiveBootClasspathHeaderJars = append(transitiveBootClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
 			case sdkLibTag, libTag, instrumentationForTag:
-				if _, ok := module.(*Plugin); ok {
+				if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
 					ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a libs dependency", otherName)
 				}
 				deps.classpath = append(deps.classpath, dep.HeaderJars...)
@@ -2485,7 +2485,7 @@
 				deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
 				transitiveJava9ClasspathHeaderJars = append(transitiveJava9ClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
 			case staticLibTag:
-				if _, ok := module.(*Plugin); ok {
+				if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
 					ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a static_libs dependency", otherName)
 				}
 				deps.classpath = append(deps.classpath, dep.HeaderJars...)
@@ -2505,40 +2505,40 @@
 				transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, dep.TransitiveStaticLibsImplementationJars)
 				transitiveStaticJarsResourceLibs = append(transitiveStaticJarsResourceLibs, dep.TransitiveStaticLibsResourceJars)
 			case pluginTag:
-				if plugin, ok := module.(*Plugin); ok {
-					if plugin.pluginProperties.Processor_class != nil {
-						addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.pluginProperties.Processor_class)
+				if plugin, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
+					if plugin.ProcessorClass != nil {
+						addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.ProcessorClass)
 					} else {
 						addPlugins(&deps, dep.ImplementationAndResourcesJars)
 					}
 					// Turbine doesn't run annotation processors, so any module that uses an
 					// annotation processor that generates API is incompatible with the turbine
 					// optimization.
-					deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api)
+					deps.disableTurbine = deps.disableTurbine || plugin.GeneratesApi
 				} else {
 					ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
 				}
 			case errorpronePluginTag:
-				if _, ok := module.(*Plugin); ok {
+				if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
 					deps.errorProneProcessorPath = append(deps.errorProneProcessorPath, dep.ImplementationAndResourcesJars...)
 				} else {
 					ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
 				}
 			case exportedPluginTag:
-				if plugin, ok := module.(*Plugin); ok {
+				if plugin, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
 					j.exportedPluginJars = append(j.exportedPluginJars, dep.ImplementationAndResourcesJars...)
-					if plugin.pluginProperties.Processor_class != nil {
-						j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.pluginProperties.Processor_class)
+					if plugin.ProcessorClass != nil {
+						j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.ProcessorClass)
 					}
 					// Turbine doesn't run annotation processors, so any module that uses an
 					// annotation processor that generates API is incompatible with the turbine
 					// optimization.
-					j.exportedDisableTurbine = Bool(plugin.pluginProperties.Generates_api)
+					j.exportedDisableTurbine = plugin.GeneratesApi
 				} else {
 					ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
 				}
 			case kotlinPluginTag:
-				if _, ok := module.(*KotlinPlugin); ok {
+				if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok {
 					deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...)
 				} else {
 					ctx.PropertyErrorf("kotlin_plugins", "%q is not a kotlin_plugin module", otherName)
@@ -2550,21 +2550,21 @@
 					JavaInfo: dep,
 				})
 			}
-		} else if dep, ok := module.(android.SourceFileProducer); ok {
+		} else if dep, ok := android.OtherModuleProvider(ctx, module, android.SourceFilesInfoProvider); ok {
 			switch tag {
 			case sdkLibTag, libTag:
-				checkProducesJars(ctx, dep)
-				deps.classpath = append(deps.classpath, dep.Srcs()...)
-				deps.dexClasspath = append(deps.classpath, dep.Srcs()...)
+				checkProducesJars(ctx, dep, module)
+				deps.classpath = append(deps.classpath, dep.Srcs...)
+				deps.dexClasspath = append(deps.classpath, dep.Srcs...)
 				transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars,
-					depset.New(depset.PREORDER, dep.Srcs(), nil))
+					depset.New(depset.PREORDER, dep.Srcs, nil))
 			case staticLibTag:
-				checkProducesJars(ctx, dep)
-				deps.classpath = append(deps.classpath, dep.Srcs()...)
-				deps.staticJars = append(deps.staticJars, dep.Srcs()...)
-				deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
+				checkProducesJars(ctx, dep, module)
+				deps.classpath = append(deps.classpath, dep.Srcs...)
+				deps.staticJars = append(deps.staticJars, dep.Srcs...)
+				deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs...)
 
-				depHeaderJars := depset.New(depset.PREORDER, dep.Srcs(), nil)
+				depHeaderJars := depset.New(depset.PREORDER, dep.Srcs, nil)
 				transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, depHeaderJars)
 				transitiveStaticJarsHeaderLibs = append(transitiveStaticJarsHeaderLibs, depHeaderJars)
 				transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, depHeaderJars)
@@ -2740,7 +2740,7 @@
 	module := ctx.Module()
 	moduleName := module.Name()
 
-	ctx.VisitDirectDeps(func(m android.Module) {
+	ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
 		tag := ctx.OtherModuleDependencyTag(m)
 		// This logic mirrors that in (*Module).collectDeps above.  There are several places
 		// where we explicitly return RenameUseExclude, even though it is the default, to
@@ -2779,10 +2779,8 @@
 					//fmt.Printf("collectDirectDepsProviders: %v -> %v StubsLinkType unknown\n", module, m)
 					// Fall through to the heuristic logic.
 				}
-				switch reflect.TypeOf(m).String() {
-				case "*java.GeneratedJavaLibraryModule":
+				if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
 					// Probably a java_aconfig_library module.
-					// TODO: make this check better.
 					return RenameUseInclude
 				}
 				switch tag {
@@ -2805,7 +2803,7 @@
 				default:
 					return RenameUseExclude
 				}
-			} else if _, ok := m.(android.SourceFileProducer); ok {
+			} else if _, ok := android.OtherModuleProvider(ctx, m, android.SourceFilesInfoProvider); ok {
 				switch tag {
 				case sdkLibTag, libTag, staticLibTag:
 					return RenameUseInclude
diff --git a/java/dex.go b/java/dex.go
index 4a7e9dc..bc14290 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -320,7 +320,7 @@
 	// TODO(b/360905238): Remove SdkSystemServer exception after resolving missing class references.
 	if !dexParams.sdkVersion.Stable() || dexParams.sdkVersion.Kind == android.SdkSystemServer {
 		var proguardRaiseDeps classpath
-		ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
+		ctx.VisitDirectDepsProxyWithTag(proguardRaiseTag, func(m android.ModuleProxy) {
 			if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
 				proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
 			}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 2dda72b..49674b9 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -357,7 +357,7 @@
 		deps.aidlPreprocess = sdkDep.aidl
 	}
 
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
@@ -381,9 +381,9 @@
 				deps.classpath = append(deps.classpath, dep.HeaderJars...)
 				deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
 				deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
-			} else if dep, ok := module.(android.SourceFileProducer); ok {
-				checkProducesJars(ctx, dep)
-				deps.classpath = append(deps.classpath, dep.Srcs()...)
+			} else if dep, ok := android.OtherModuleProvider(ctx, module, android.SourceFilesInfoProvider); ok {
+				checkProducesJars(ctx, dep, module)
+				deps.classpath = append(deps.classpath, dep.Srcs...)
 			} else {
 				ctx.ModuleErrorf("depends on non-java module %q", otherName)
 			}
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index b1a9deb..c9a1f2b 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -97,7 +97,7 @@
 	// Save the classes jars even if this is not active as they may be used by modular hidden API
 	// processing.
 	classesJars := android.Paths{classesJar}
-	ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
+	ctx.VisitDirectDepsProxyWithTag(hiddenApiAnnotationsTag, func(dep android.ModuleProxy) {
 		if javaInfo, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
 			classesJars = append(classesJars, javaInfo.ImplementationJars...)
 		}
diff --git a/java/java.go b/java/java.go
index 3a1bc33..0a9381d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -640,11 +640,11 @@
 	transitiveStaticLibsResourceJars       []depset.DepSet[android.Path]
 }
 
-func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
-	for _, f := range dep.Srcs() {
+func checkProducesJars(ctx android.ModuleContext, dep android.SourceFilesInfo, module android.ModuleProxy) {
+	for _, f := range dep.Srcs {
 		if f.Ext() != ".jar" {
 			ctx.ModuleErrorf("genrule %q must generate files ending with .jar to be used as a libs or static_libs dependency",
-				ctx.OtherModuleName(dep.(blueprint.Module)))
+				ctx.OtherModuleName(module))
 		}
 	}
 }
@@ -2761,7 +2761,7 @@
 	var staticJars android.Paths
 	var staticResourceJars android.Paths
 	var staticHeaderJars android.Paths
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		tag := ctx.OtherModuleDependencyTag(module)
 		if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
 			switch tag {
@@ -3395,7 +3395,7 @@
 var inList = android.InList[string]
 
 // Add class loader context (CLC) of a given dependency to the current CLC.
-func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
+func addCLCFromDep(ctx android.ModuleContext, depModule android.ModuleProxy,
 	clcMap dexpreopt.ClassLoaderContextMap) {
 
 	dep, ok := android.OtherModuleProvider(ctx, depModule, JavaInfoProvider)
@@ -3455,7 +3455,7 @@
 	}
 }
 
-func addMissingOptionalUsesLibsFromDep(ctx android.ModuleContext, depModule android.Module,
+func addMissingOptionalUsesLibsFromDep(ctx android.ModuleContext, depModule android.ModuleProxy,
 	usesLibrary *usesLibrary) {
 
 	dep, ok := android.OtherModuleProvider(ctx, depModule, JavaInfoProvider)
diff --git a/java/lint.go b/java/lint.go
index cee25a8..3838745 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -398,7 +398,7 @@
 		}
 	}
 
-	extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag)
+	extraLintCheckModules := ctx.GetDirectDepsProxyWithTag(extraLintCheckTag)
 	for _, extraLintCheckModule := range extraLintCheckModules {
 		if dep, ok := android.OtherModuleProvider(ctx, extraLintCheckModule, JavaInfoProvider); ok {
 			l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars...)
@@ -423,7 +423,7 @@
 
 	depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml, baseline)
 
-	ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
+	ctx.VisitDirectDepsProxyWithTag(staticLibTag, func(dep android.ModuleProxy) {
 		if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok {
 			depSetsBuilder.Transitive(info)
 		}
diff --git a/java/plugin.go b/java/plugin.go
index 610c9fd..3534c7b 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -16,8 +16,21 @@
 
 import (
 	"android/soong/android"
+	"github.com/google/blueprint"
 )
 
+type JavaPluginInfo struct {
+	ProcessorClass *string
+	GeneratesApi   bool
+}
+
+var JavaPluginInfoProvider = blueprint.NewProvider[JavaPluginInfo]()
+
+type KotlinPluginInfo struct {
+}
+
+var KotlinPluginInfoProvider = blueprint.NewProvider[KotlinPluginInfo]()
+
 func init() {
 	registerJavaPluginBuildComponents(android.InitRegistrationContext)
 }
@@ -65,7 +78,22 @@
 	Generates_api *bool
 }
 
+func (p *Plugin) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	p.Library.GenerateAndroidBuildActions(ctx)
+
+	android.SetProvider(ctx, JavaPluginInfoProvider, JavaPluginInfo{
+		ProcessorClass: p.pluginProperties.Processor_class,
+		GeneratesApi:   Bool(p.pluginProperties.Generates_api),
+	})
+}
+
 // Plugin describes a kotlin_plugin module, a host java/kotlin library that will be used by kotlinc as a compiler plugin.
 type KotlinPlugin struct {
 	Library
 }
+
+func (p *KotlinPlugin) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	p.Library.GenerateAndroidBuildActions(ctx)
+
+	android.SetProvider(ctx, KotlinPluginInfoProvider, KotlinPluginInfo{})
+}
diff --git a/java/rro.go b/java/rro.go
index ab4fafa..44d5564 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -139,6 +139,25 @@
 	r.aapt.hasNoCode = true
 	// Do not remove resources without default values nor dedupe resource configurations with the same value
 	aaptLinkFlags := []string{"--no-resource-deduping", "--no-resource-removal"}
+
+	// Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
+	hasProduct := android.PrefixInList(r.aaptProperties.Aaptflags, "--product")
+	if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
+		aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
+	}
+
+	if !Bool(r.aaptProperties.Aapt_include_all_resources) {
+		// Product AAPT config
+		for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
+			aaptLinkFlags = append(aaptLinkFlags, "-c", aaptConfig)
+		}
+
+		// Product AAPT preferred config
+		if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
+			aaptLinkFlags = append(aaptLinkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
+		}
+	}
+
 	// Allow the override of "package name" and "overlay target package name"
 	manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
 	if overridden || r.overridableProperties.Package_name != nil {
diff --git a/rust/rust.go b/rust/rust.go
index 557bdc3..6428859 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()
@@ -1690,7 +1690,7 @@
 			}
 		}
 
-		if srcDep, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoKey); ok {
+		if srcDep, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoProvider); ok {
 			if android.IsSourceDepTagWithOutputTag(depTag, "") {
 				// These are usually genrules which don't have per-target variants.
 				directSrcDeps = append(directSrcDeps, srcDep)