Propagate profile_guided requirement of imports to top-level apex

For prebuilts, the dexpreopt rules of system server jars are now
generated from the context of the top-level prebuilt apex and not in the
context of the shim java_import modules. Since
`dex_preopt.profile_guided` property is defined in java_import, this
needs to be bubbled up to the top-level apex. This will be done using
deapxerInfo. If profile_guided of a transitive java_import is true, the deapexed .prof file will be
set as dexreopter.inputProfilePathOnHost before invoking
dexpreopter.dexpreopt. This ensures that only that java_import undergoes
profile guided dexpreopt, and not every other transitive java_import

Test: go test ./apex -run TestPrebuiltStandaloneSystemserverclasspathFragmentContents
Test: lunch cf_x86_64_only_phone-next-userdebug && m
$ANDROID_PRODUCT_OUT/system/framework/oat/x86_64/apex@com.android.art@javalib@service-art.jar@classes.odex
Test: du -sh
$ANDROID_PRODUCT_OUT/system/framework/oat/x86_64/apex@com.android.art@javalib@service-art.jar@classes.odex
24K

Bug: 308790457
Change-Id: Ibf46ecb400b3f126b243fc8d27b08d9a1aa4cc97
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 5ff622c..a673108 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -53,6 +53,10 @@
 	// all architectures, e.g. java.
 	CommonModules []string
 
+	// List of modules that use an embedded .prof to guide optimization of the equivalent dexpreopt artifact
+	// This is a subset of CommonModules
+	DexpreoptProfileGuidedModules []string
+
 	// List of files exported from the .apex file by this module
 	//
 	// Each entry is a path from the apex root, e.g. javalib/core-libart.jar.
@@ -128,6 +132,7 @@
 	if len(exports) > 0 {
 		// Make the information available for other modules.
 		di := android.NewDeapexerInfo(apexModuleName(ctx.ModuleName()), exports, p.properties.CommonModules)
+		di.AddDexpreoptProfileGuidedExportedModuleNames(p.properties.DexpreoptProfileGuidedModules...)
 		android.SetProvider(ctx, android.DeapexerProvider, di)
 
 		// Create a sorted list of the files that this exports.
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 551942d..399d9b9 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -629,6 +629,7 @@
 
 	// Compute the deapexer properties from the transitive dependencies of this module.
 	commonModules := []string{}
+	dexpreoptProfileGuidedModules := []string{}
 	exportedFiles := []string{}
 	ctx.WalkDeps(func(child, parent android.Module) bool {
 		tag := ctx.OtherModuleDependencyTag(child)
@@ -642,9 +643,14 @@
 		if _, ok := tag.(android.RequiresFilesFromPrebuiltApexTag); ok {
 			commonModules = append(commonModules, name)
 
-			requiredFiles := child.(android.RequiredFilesFromPrebuiltApex).RequiredFilesFromPrebuiltApex(ctx)
+			extract := child.(android.RequiredFilesFromPrebuiltApex)
+			requiredFiles := extract.RequiredFilesFromPrebuiltApex(ctx)
 			exportedFiles = append(exportedFiles, requiredFiles...)
 
+			if extract.UseProfileGuidedDexpreopt() {
+				dexpreoptProfileGuidedModules = append(dexpreoptProfileGuidedModules, name)
+			}
+
 			// Visit the dependencies of this module just in case they also require files from the
 			// prebuilt apex.
 			return true
@@ -657,7 +663,8 @@
 	deapexerProperties := &DeapexerProperties{
 		// Remove any duplicates from the common modules lists as a module may be included via a direct
 		// dependency as well as transitive ones.
-		CommonModules: android.SortedUniqueStrings(commonModules),
+		CommonModules:                 android.SortedUniqueStrings(commonModules),
+		DexpreoptProfileGuidedModules: android.SortedUniqueStrings(dexpreoptProfileGuidedModules),
 	}
 
 	// Populate the exported files property in a fixed order.
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index 6b2c397..f6c53b2 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -221,8 +221,6 @@
 }
 
 func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
-	// TODO(spandandas): Fix the rules for profile guided dexpreopt of deapexed prebuilt jars
-	t.Skip()
 	result := android.GroupFixturePreparers(
 		prepareForTestWithSystemserverclasspathFragment,
 		prepareForTestWithMyapex,
@@ -294,8 +292,8 @@
 		"javalib/bar.jar.prof",
 	})
 
-	assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
-	assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
+	assertProfileGuidedPrebuilt(t, ctx, "myapex", "foo", false)
+	assertProfileGuidedPrebuilt(t, ctx, "myapex", "bar", true)
 }
 
 func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) {
@@ -381,8 +379,6 @@
 }
 
 func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
-	// TODO(spandandas): Fix the rules for profile guided dexpreopt of deapexed prebuilt jars
-	t.Skip()
 	result := android.GroupFixturePreparers(
 		prepareForTestWithSystemserverclasspathFragment,
 		prepareForTestWithMyapex,
@@ -447,8 +443,8 @@
 		"javalib/bar.jar.prof",
 	})
 
-	assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
-	assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
+	assertProfileGuidedPrebuilt(t, ctx, "myapex", "foo", false)
+	assertProfileGuidedPrebuilt(t, ctx, "myapex", "bar", true)
 }
 
 func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) {
@@ -458,3 +454,11 @@
 		t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
 	}
 }
+
+func assertProfileGuidedPrebuilt(t *testing.T, ctx *android.TestContext, apexName string, moduleName string, expected bool) {
+	dexpreopt := ctx.ModuleForTests(apexName, "android_common_"+apexName).Rule("dexpreopt." + moduleName)
+	actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=")
+	if expected != actual {
+		t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
+	}
+}