Convert stubLibraries, soongMetricsSingleton, sdkSingleton,
complianceMetadataSingleton, freezeApiSingleton and testSuiteFiles to
use ModuleProxy.

Bug: 377723687
Test: Unit tests and compare the ninja and mk files generated.
Change-Id: I91789633ff0d4e0ab170717caf0a6b4f63c38593
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index 35805a2..a6dbb8d 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -275,16 +275,18 @@
 	writerToCsv(csvWriter, columnNames)
 
 	rowId := -1
-	ctx.VisitAllModules(func(module Module) {
-		if !module.Enabled(ctx) {
+	ctx.VisitAllModuleProxies(func(module ModuleProxy) {
+		commonInfo, _ := OtherModuleProvider(ctx, module, CommonModuleInfoKey)
+		if !commonInfo.Enabled {
 			return
 		}
+
 		moduleType := ctx.ModuleType(module)
 		if moduleType == "package" {
 			metadataMap := map[string]string{
 				ComplianceMetadataProp.NAME:                            ctx.ModuleName(module),
 				ComplianceMetadataProp.MODULE_TYPE:                     ctx.ModuleType(module),
-				ComplianceMetadataProp.PKG_DEFAULT_APPLICABLE_LICENSES: strings.Join(module.base().primaryLicensesProperty.getStrings(), " "),
+				ComplianceMetadataProp.PKG_DEFAULT_APPLICABLE_LICENSES: strings.Join(commonInfo.PrimaryLicensesProperty.getStrings(), " "),
 			}
 			rowId = rowId + 1
 			metadata := []string{strconv.Itoa(rowId)}
@@ -294,8 +296,7 @@
 			writerToCsv(csvWriter, metadata)
 			return
 		}
-		if provider, ok := ctx.otherModuleProvider(module, ComplianceMetadataProvider); ok {
-			metadataInfo := provider.(*ComplianceMetadataInfo)
+		if metadataInfo, ok := OtherModuleProvider(ctx, module, ComplianceMetadataProvider); ok {
 			rowId = rowId + 1
 			metadata := []string{strconv.Itoa(rowId)}
 			for _, propertyName := range COMPLIANCE_METADATA_PROPS {
diff --git a/android/metrics.go b/android/metrics.go
index 6834b1b..dc51703 100644
--- a/android/metrics.go
+++ b/android/metrics.go
@@ -57,8 +57,8 @@
 
 func (soongMetricsSingleton) GenerateBuildActions(ctx SingletonContext) {
 	metrics := getSoongMetrics(ctx.Config())
-	ctx.VisitAllModules(func(m Module) {
-		if ctx.PrimaryModule(m) == m {
+	ctx.VisitAllModuleProxies(func(m ModuleProxy) {
+		if ctx.PrimaryModuleProxy(m) == m {
 			metrics.modules++
 		}
 		metrics.variants++
diff --git a/android/module.go b/android/module.go
index c4a8377..f359e9f 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1919,6 +1919,9 @@
 	IsStubsModule       bool
 	Host                bool
 	IsApexModule        bool
+	// The primary licenses property, may be nil, records license metadata for the module.
+	PrimaryLicensesProperty applicableLicensesProperty
+	Owner                   string
 }
 
 type ApiLevelOrPlatform struct {
@@ -2254,6 +2257,7 @@
 	buildComplianceMetadataProvider(ctx, m)
 
 	commonData := CommonModuleInfo{
+		Enabled:                          m.Enabled(ctx),
 		ReplacedByPrebuilt:               m.commonProperties.ReplacedByPrebuilt,
 		Target:                           m.commonProperties.CompileTarget,
 		SkipAndroidMkProcessing:          shouldSkipAndroidMkProcessing(ctx, m),
@@ -2261,6 +2265,8 @@
 		HideFromMake:                     m.commonProperties.HideFromMake,
 		SkipInstall:                      m.commonProperties.SkipInstall,
 		Host:                             m.Host(),
+		PrimaryLicensesProperty:          m.primaryLicensesProperty,
+		Owner:                            m.Owner(),
 	}
 	if mm, ok := m.module.(interface {
 		MinSdkVersion(ctx EarlyModuleContext) ApiLevel
@@ -2289,11 +2295,6 @@
 		commonData.SdkVersion = mm.SdkVersion()
 	}
 
-	if m.commonProperties.ForcedDisabled {
-		commonData.Enabled = false
-	} else {
-		commonData.Enabled = m.commonProperties.Enabled.GetOrDefault(m.ConfigurableEvaluator(ctx), !m.Os().DefaultDisabled)
-	}
 	if am, ok := m.module.(ApexModule); ok {
 		commonData.CanHaveApexVariants = am.CanHaveApexVariants()
 		commonData.NotAvailableForPlatform = am.NotAvailableForPlatform()
diff --git a/android/package.go b/android/package.go
index eb76751..385326e 100644
--- a/android/package.go
+++ b/android/package.go
@@ -56,7 +56,10 @@
 }
 
 func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
-	// Nothing to do.
+	ctx.SetProvider(CommonModuleInfoKey, CommonModuleInfo{
+		Enabled:                 true,
+		PrimaryLicensesProperty: p.primaryLicensesProperty,
+	})
 }
 
 func (p *packageModule) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 6b076b7..7273599 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -357,6 +357,17 @@
 	return true
 }
 
+func IsModulePreferredProxy(ctx OtherModuleProviderContext, module ModuleProxy) bool {
+	if OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ReplacedByPrebuilt {
+		// A source module that has been replaced by a prebuilt counterpart.
+		return false
+	}
+	if p, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok {
+		return p.UsePrebuilt
+	}
+	return true
+}
+
 // IsModulePrebuilt returns true if the module implements PrebuiltInterface and
 // has been initialized as a prebuilt and so returns a non-nil value from the
 // PrebuiltInterface.Prebuilt() method.
diff --git a/android/singleton.go b/android/singleton.go
index df22045..a03ea74 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -84,6 +84,9 @@
 	VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy))
 
 	PrimaryModule(module Module) Module
+
+	PrimaryModuleProxy(module ModuleProxy) ModuleProxy
+
 	IsFinalModule(module Module) bool
 
 	AddNinjaFileDeps(deps ...string)
@@ -271,6 +274,22 @@
 	}
 }
 
+func (s *singletonContextAdaptor) ModuleName(module blueprint.Module) string {
+	return s.SingletonContext.ModuleName(getWrappedModule(module))
+}
+
+func (s *singletonContextAdaptor) ModuleDir(module blueprint.Module) string {
+	return s.SingletonContext.ModuleDir(getWrappedModule(module))
+}
+
+func (s *singletonContextAdaptor) ModuleSubDir(module blueprint.Module) string {
+	return s.SingletonContext.ModuleSubDir(getWrappedModule(module))
+}
+
+func (s *singletonContextAdaptor) ModuleType(module blueprint.Module) string {
+	return s.SingletonContext.ModuleType(getWrappedModule(module))
+}
+
 func (s *singletonContextAdaptor) VisitAllModulesBlueprint(visit func(blueprint.Module)) {
 	s.SingletonContext.VisitAllModules(visit)
 }
@@ -315,6 +334,10 @@
 	return s.SingletonContext.PrimaryModule(module).(Module)
 }
 
+func (s *singletonContextAdaptor) PrimaryModuleProxy(module ModuleProxy) ModuleProxy {
+	return ModuleProxy{s.SingletonContext.PrimaryModuleProxy(module.module)}
+}
+
 func (s *singletonContextAdaptor) IsFinalModule(module Module) bool {
 	return s.SingletonContext.IsFinalModule(module)
 }
diff --git a/android/test_suites.go b/android/test_suites.go
index 18744f1..39317ec 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -17,6 +17,8 @@
 import (
 	"path/filepath"
 	"strings"
+
+	"github.com/google/blueprint"
 )
 
 func init() {
@@ -37,18 +39,24 @@
 	TestSuites() []string
 }
 
+type TestSuiteInfo struct {
+	TestSuites []string
+}
+
+var TestSuiteInfoProvider = blueprint.NewProvider[TestSuiteInfo]()
+
 func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) {
 	files := make(map[string]map[string]InstallPaths)
 
-	ctx.VisitAllModules(func(m Module) {
-		if tsm, ok := m.(TestSuiteModule); ok {
-			for _, testSuite := range tsm.TestSuites() {
+	ctx.VisitAllModuleProxies(func(m ModuleProxy) {
+		if tsm, ok := OtherModuleProvider(ctx, m, TestSuiteInfoProvider); ok {
+			for _, testSuite := range tsm.TestSuites {
 				if files[testSuite] == nil {
 					files[testSuite] = make(map[string]InstallPaths)
 				}
 				name := ctx.ModuleName(m)
 				files[testSuite][name] = append(files[testSuite][name],
-					OtherModuleProviderOrDefault(ctx, tsm, InstallFilesProvider).InstallFiles...)
+					OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider).InstallFiles...)
 			}
 		}
 	})
diff --git a/android/test_suites_test.go b/android/test_suites_test.go
index bf4de19..dda9329 100644
--- a/android/test_suites_test.go
+++ b/android/test_suites_test.go
@@ -110,6 +110,10 @@
 	for _, output := range f.props.Outputs {
 		ctx.InstallFile(pathForTestCases(ctx), output, nil)
 	}
+
+	SetProvider(ctx, TestSuiteInfoProvider, TestSuiteInfo{
+		TestSuites: f.TestSuites(),
+	})
 }
 
 func (f *fake_module) TestSuites() []string {
diff --git a/cc/cc.go b/cc/cc.go
index 45538b4..4bac0d1 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -162,6 +162,7 @@
 	OnlyInVendorRamdisk bool
 	InRecovery          bool
 	OnlyInRecovery      bool
+	InVendor            bool
 	Installable         *bool
 	// RelativeInstallPath returns the relative install path for this module.
 	RelativeInstallPath string
@@ -173,7 +174,8 @@
 	ImplementationModuleNameForMake string
 	IsStubsImplementationRequired   bool
 	// Symlinks returns a list of symlinks that should be created for this module.
-	Symlinks []string
+	Symlinks               []string
+	APIListCoverageXMLPath android.ModuleOutPath
 }
 
 var LinkableInfoProvider = blueprint.NewProvider[*LinkableInfo]()
@@ -2392,6 +2394,7 @@
 		OnlyInVendorRamdisk:  mod.OnlyInVendorRamdisk(),
 		InRecovery:           mod.InRecovery(),
 		OnlyInRecovery:       mod.OnlyInRecovery(),
+		InVendor:             mod.InVendor(),
 		Installable:          mod.Installable(),
 		RelativeInstallPath:  mod.RelativeInstallPath(),
 		// TODO(b/362509506): remove this once all apex_exclude uses are switched to stubs.
@@ -2401,16 +2404,14 @@
 		ImplementationModuleNameForMake: mod.ImplementationModuleNameForMake(),
 		Symlinks:                        mod.Symlinks(),
 	}
-	if mod.VersionedInterface() != nil {
-		info.IsStubsImplementationRequired = mod.VersionedInterface().IsStubsImplementationRequired()
-	}
-	return info
-}
 
-func setOutputFilesIfNotEmpty(ctx ModuleContext, files android.Paths, tag string) {
-	if len(files) > 0 {
-		ctx.SetOutputFiles(files, tag)
+	vi := mod.VersionedInterface()
+	if vi != nil {
+		info.IsStubsImplementationRequired = vi.IsStubsImplementationRequired()
+		info.APIListCoverageXMLPath = vi.GetAPIListCoverageXMLPath()
 	}
+
+	return info
 }
 
 func (c *Module) setOutputFiles(ctx ModuleContext) {
diff --git a/cc/stub_library.go b/cc/stub_library.go
index 9d7b5bc..21ef139 100644
--- a/cc/stub_library.go
+++ b/cc/stub_library.go
@@ -43,9 +43,9 @@
 }
 
 // Get target file name to be installed from this module
-func getInstalledFileName(ctx android.SingletonContext, m LinkableInterface) string {
+func getInstalledFileName(ctx android.SingletonContext, m android.ModuleProxy) string {
 	for _, ps := range android.OtherModuleProviderOrDefault(
-		ctx, m.Module(), android.InstallFilesProvider).PackagingSpecs {
+		ctx, m, android.InstallFilesProvider).PackagingSpecs {
 		if name := ps.FileName(); name != "" {
 			return name
 		}
@@ -57,18 +57,18 @@
 	// Visit all generated soong modules and store stub library file names.
 	stubLibraryMap := make(map[string]bool)
 	vendorStubLibraryMap := make(map[string]bool)
-	ctx.VisitAllModules(func(module android.Module) {
-		if m, ok := module.(VersionedLinkableInterface); ok {
-			if IsStubTarget(android.OtherModuleProviderOrDefault(ctx, m, LinkableInfoProvider)) {
-				if name := getInstalledFileName(ctx, m); name != "" {
+	ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+		if linkableInfo, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider); ok {
+			if IsStubTarget(linkableInfo) {
+				if name := getInstalledFileName(ctx, module); name != "" {
 					stubLibraryMap[name] = true
-					if m.InVendor() {
+					if linkableInfo.InVendor {
 						vendorStubLibraryMap[name] = true
 					}
 				}
 			}
-			if m.CcLibraryInterface() && android.IsModulePreferred(m) {
-				if p := m.VersionedInterface().GetAPIListCoverageXMLPath().String(); p != "" {
+			if linkableInfo.CcLibraryInterface && android.IsModulePreferredProxy(ctx, module) {
+				if p := linkableInfo.APIListCoverageXMLPath.String(); p != "" {
 					s.apiListCoverageXmlPaths = append(s.apiListCoverageXmlPaths, p)
 				}
 			}
diff --git a/java/ravenwood.go b/java/ravenwood.go
index 3b6c80b..c4078c5 100644
--- a/java/ravenwood.go
+++ b/java/ravenwood.go
@@ -267,6 +267,10 @@
 		moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, r.testConfig.String())
 	}
 	moduleInfoJSON.CompatibilitySuites = []string{"general-tests", "ravenwood-tests"}
+
+	android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+		TestSuites: r.TestSuites(),
+	})
 }
 
 func (r *ravenwoodTest) AndroidMkEntries() []android.AndroidMkEntries {
@@ -384,6 +388,10 @@
 
 	// Normal build should perform install steps
 	ctx.Phony(r.BaseModuleName(), android.PathForPhony(ctx, r.BaseModuleName()+"-install"))
+
+	android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+		TestSuites: r.TestSuites(),
+	})
 }
 
 // collectTransitiveJniDeps returns all JNI dependencies, including transitive
diff --git a/java/robolectric.go b/java/robolectric.go
index 43e17f9..5dcc7dd 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -279,6 +279,10 @@
 	} else {
 		moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
 	}
+
+	android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+		TestSuites: r.TestSuites(),
+	})
 }
 
 func generateSameDirRoboTestConfigJar(ctx android.ModuleContext, outputFile android.ModuleOutPath) {
@@ -416,6 +420,10 @@
 	android.SetProvider(ctx, RobolectricRuntimesInfoProvider, RobolectricRuntimesInfo{
 		Runtimes: r.runtimes,
 	})
+
+	android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+		TestSuites: r.TestSuites(),
+	})
 }
 
 func (r *robolectricRuntimes) InstallInTestcases() bool { return true }
diff --git a/java/sdk.go b/java/sdk.go
index 27b2434..8510959 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -358,7 +358,7 @@
 			"api_fingerprint",
 		}
 		count := 0
-		ctx.VisitAllModules(func(module android.Module) {
+		ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
 			name := ctx.ModuleName(module)
 			if android.InList(name, apiTxtFileModules) {
 				cmd.Inputs(android.OutputFilesForModule(ctx, module, ""))