Generate info about the selected app variant in platform builds

This is a followup to aosp/2999198 and adds information about apps.

Each app will have an entry in this file with the following properties
- Name, mandatory
- Is_prebuilt, mandatory
- Prebuilt_info_file_path, optional

Implementation details
- Move prebuiltInfoProvider out of build/soong/apex to
  build/soong/android. This allows build/soong/java to use it.
- Introduce a new `prebuilt_info` prop to `android_app_set` and
  `android_app_import`
- All app module types will set a prebuiltInfoProvider in
  GenerateAndroidBuildActions, including the source app module types

Test: m nothing --no-skip-soong-tests
Test: m out/soong/prebuilt_info.json
Test: ls -l out/soong/prebuilt_info.json --human-readable
-rw------- 1 spandandas primarygroup 317K Mar 11 23:46 out/soong/prebuilt_info.json

Test: #modified trunk_staging.locally to select prebuilts of some
mainline apps. Spot-checked that `is_prebuilt` and
`prebuilt_info_file_path` get populated appropriately

Bug: 327480225
Change-Id: I5078e0ec26c9568194550909962b90111a5223f7
diff --git a/android/apex.go b/android/apex.go
index 4d36a93..8759905 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -976,3 +976,18 @@
 	// Map from the apex library name (without prebuilt_ prefix) to the dex file path on host
 	LibraryNameToDexJarPathOnHost map[string]Path
 }
+
+var PrebuiltInfoProvider = blueprint.NewProvider[PrebuiltInfo]()
+
+// contents of prebuilt_info.json
+type PrebuiltInfo struct {
+	// Name of the apex, without the prebuilt_ prefix
+	Name string
+
+	Is_prebuilt bool
+
+	// This is relative to root of the workspace.
+	// In case of mainline modules, this file contains the build_id that was used
+	// to generate the mainline module prebuilt.
+	Prebuilt_info_file_path string `json:",omitempty"`
+}
diff --git a/apex/apex.go b/apex/apex.go
index c688438..c662f2c 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2428,29 +2428,14 @@
 	a.providePrebuiltInfo(ctx)
 }
 
-var prebuiltInfoProvider = blueprint.NewProvider[prebuiltInfo]()
-
-// contents of prebuilt_info.json
-type prebuiltInfo struct {
-	// Name of the apex, without the prebuilt_ prefix
-	Name string
-
-	Is_prebuilt bool
-
-	// This is relative to root of the workspace.
-	// In case of mainline modules, this file contains the build_id that was used
-	// to generate the mainline module prebuilt.
-	Prebuilt_info_file_path string `json:",omitempty"`
-}
-
 // Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
 // with information about whether source or prebuilt of an apex was used during the build.
 func (a *apexBundle) providePrebuiltInfo(ctx android.ModuleContext) {
-	info := prebuiltInfo{
+	info := android.PrebuiltInfo{
 		Name:        a.Name(),
 		Is_prebuilt: false,
 	}
-	android.SetProvider(ctx, prebuiltInfoProvider, info)
+	android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
 }
 
 // Set a provider containing information about the jars and .prof provided by the apex
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 8aaddbe..e6ebff2 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -149,10 +149,10 @@
 }
 
 func (a *apexPrebuiltInfo) GenerateBuildActions(ctx android.SingletonContext) {
-	prebuiltInfos := []prebuiltInfo{}
+	prebuiltInfos := []android.PrebuiltInfo{}
 
 	ctx.VisitAllModules(func(m android.Module) {
-		prebuiltInfo, exists := android.SingletonModuleProvider(ctx, m, prebuiltInfoProvider)
+		prebuiltInfo, exists := android.SingletonModuleProvider(ctx, m, android.PrebuiltInfoProvider)
 		// Use prebuiltInfoProvider to filter out non apex soong modules.
 		// Use HideFromMake to filter out the unselected variants of a specific apex.
 		if exists && !m.IsHideFromMake() {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 34dfc46..ea847e1 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -827,15 +827,15 @@
 // Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
 // with information about whether source or prebuilt of an apex was used during the build.
 func (p *prebuiltCommon) providePrebuiltInfo(ctx android.ModuleContext) {
-	info := prebuiltInfo{
-		Name:        p.BaseModuleName(), // BaseModuleName ensures that this will not contain the prebuilt_ prefix.
+	info := android.PrebuiltInfo{
+		Name:        p.BaseModuleName(),
 		Is_prebuilt: true,
 	}
 	// If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json.
 	if p.prebuiltCommonProperties.Prebuilt_info != nil {
 		info.Prebuilt_info_file_path = android.PathForModuleSrc(ctx, *p.prebuiltCommonProperties.Prebuilt_info).String()
 	}
-	android.SetProvider(ctx, prebuiltInfoProvider, info)
+	android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
 }
 
 func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
diff --git a/java/app.go b/java/app.go
index 8209d4c..4f6f1f3 100755
--- a/java/app.go
+++ b/java/app.go
@@ -912,6 +912,13 @@
 	}
 
 	a.buildAppDependencyInfo(ctx)
+
+	providePrebuiltInfo(ctx,
+		prebuiltInfoProps{
+			baseModuleName: a.BaseModuleName(),
+			isPrebuilt:     false,
+		},
+	)
 }
 
 type appDepsInterface interface {
diff --git a/java/app_import.go b/java/app_import.go
index dc84fc2..7387e16 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -150,6 +150,11 @@
 	// If unspecified, follows the naming convention that the source module of
 	// the prebuilt is Name() without "prebuilt_" prefix
 	Source_module_name *string
+
+	// Path to the .prebuilt_info file of the prebuilt app.
+	// In case of mainline modules, the .prebuilt_info file contains the build_id that was used
+	// to generate the prebuilt.
+	Prebuilt_info *string `android:"path"`
 }
 
 func (a *AndroidAppImport) IsInstallable() bool {
@@ -413,6 +418,14 @@
 	}
 	android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles)
 
+	providePrebuiltInfo(ctx,
+		prebuiltInfoProps{
+			baseModuleName: a.BaseModuleName(),
+			isPrebuilt:     true,
+			prebuiltInfo:   a.properties.Prebuilt_info,
+		},
+	)
+
 	// TODO: androidmk converter jni libs
 }
 
diff --git a/java/app_set.go b/java/app_set.go
index d2d3b06..33d3ade 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -48,6 +48,11 @@
 	// Names of modules to be overridden. Listed modules can only be other apps
 	//	(in Make or Soong).
 	Overrides []string
+
+	// Path to the .prebuilt_info file of the prebuilt app.
+	// In case of mainline modules, the .prebuilt_info file contains the build_id that was used
+	// to generate the prebuilt.
+	Prebuilt_info *string `android:"path"`
 }
 
 type AndroidAppSet struct {
@@ -117,6 +122,27 @@
 	return result
 }
 
+type prebuiltInfoProps struct {
+	baseModuleName string
+	isPrebuilt     bool
+	prebuiltInfo   *string
+}
+
+// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
+// with information about whether source or prebuilt of an apex was used during the build.
+func providePrebuiltInfo(ctx android.ModuleContext, p prebuiltInfoProps) {
+	info := android.PrebuiltInfo{
+		Name:        p.baseModuleName,
+		Is_prebuilt: p.isPrebuilt,
+	}
+	// If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json.
+	if p.prebuiltInfo != nil {
+		prebuiltInfoFile := android.PathForModuleSrc(ctx, *p.prebuiltInfo)
+		info.Prebuilt_info_file_path = prebuiltInfoFile.String()
+	}
+	android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
+}
+
 func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
 	as.primaryOutput = android.PathForModuleOut(ctx, as.BaseModuleName()+".apk")
@@ -157,6 +183,15 @@
 		installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName())
 	}
 	ctx.InstallFileWithExtraFilesZip(installDir, as.BaseModuleName()+".apk", as.primaryOutput, as.packedOutput)
+
+	providePrebuiltInfo(ctx,
+		prebuiltInfoProps{
+			baseModuleName: as.BaseModuleName(),
+			isPrebuilt:     true,
+			prebuiltInfo:   as.properties.Prebuilt_info,
+		},
+	)
+
 }
 
 func (as *AndroidAppSet) InstallBypassMake() bool { return true }