Output dex_preopt to SDK snapshot.

This is needed to determine whether we need to deapex the profile or
not.

Bug: 241823638
Test: m nothing
Test: -
  1. Patch ag/20582608 PS2.
  2. TARGET_BUILD_APPS=com.android.wifi packages/modules/common/build/mainline_modules_sdks.sh
  3. See the `dex_preopt` property being written.
Change-Id: I05177388c24be1ab315247ea85e7e3a8600cebd3
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index c4b0af4..fa52ae6 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -78,7 +78,8 @@
 }
 
 type dexpreopter struct {
-	dexpreoptProperties DexpreoptProperties
+	dexpreoptProperties       DexpreoptProperties
+	importDexpreoptProperties ImportDexpreoptProperties
 
 	installPath         android.InstallPath
 	uncompressedDex     bool
@@ -127,6 +128,18 @@
 		// profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
 		Profile *string `android:"path"`
 	}
+
+	Dex_preopt_result struct {
+		// True if profile-guided optimization is actually enabled.
+		Profile_guided bool
+	} `blueprint:"mutated"`
+}
+
+type ImportDexpreoptProperties struct {
+	Dex_preopt struct {
+		// If true, use the profile in the prebuilt APEX to guide optimization. Defaults to false.
+		Profile_guided *bool
+	}
 }
 
 func init() {
@@ -310,6 +323,8 @@
 		}
 	}
 
+	d.dexpreoptProperties.Dex_preopt_result.Profile_guided = profileClassListing.Valid()
+
 	// Full dexpreopt config, used to create dexpreopt build rules.
 	dexpreoptConfig := &dexpreopt.ModuleConfig{
 		Name:            moduleName(ctx),
diff --git a/java/java.go b/java/java.go
index 874f935..912779e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -795,6 +795,8 @@
 
 	// The value of the min_sdk_version property, translated into a number where possible.
 	MinSdkVersion *string `supported_build_releases:"Tiramisu+"`
+
+	DexPreoptProfileGuided *bool `supported_build_releases:"UpsideDownCake+"`
 }
 
 func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
@@ -812,6 +814,10 @@
 		canonical := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.ApiLevel.String())
 		p.MinSdkVersion = proptools.StringPtr(canonical)
 	}
+
+	if j.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
+		p.DexPreoptProfileGuided = proptools.BoolPtr(true)
+	}
 }
 
 func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -838,6 +844,11 @@
 		propertySet.AddProperty("permitted_packages", p.PermittedPackages)
 	}
 
+	dexPreoptSet := propertySet.AddPropertySet("dex_preopt")
+	if p.DexPreoptProfileGuided != nil {
+		dexPreoptSet.AddProperty("profile_guided", proptools.Bool(p.DexPreoptProfileGuided))
+	}
+
 	// Do not copy anything else to the snapshot.
 	if memberType.onlyCopyJarToSnapshot {
 		return
@@ -2192,6 +2203,7 @@
 	module.AddProperties(
 		&module.properties,
 		&module.dexer.dexProperties,
+		&module.importDexpreoptProperties,
 	)
 
 	module.initModuleAndImport(module)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index a2295f4..0478011 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2201,7 +2201,7 @@
 
 	allScopeProperties, scopeToProperties := createPropertiesInstance()
 	module.scopeProperties = scopeToProperties
-	module.AddProperties(&module.properties, allScopeProperties)
+	module.AddProperties(&module.properties, allScopeProperties, &module.importDexpreoptProperties)
 
 	// Initialize information common between source and prebuilt.
 	module.initCommon(module)
@@ -2994,6 +2994,8 @@
 	//
 	// This means that the device won't recognise this library as installed.
 	Max_device_sdk *string
+
+	DexPreoptProfileGuided *bool `supported_build_releases:"UpsideDownCake+"`
 }
 
 type scopeProperties struct {
@@ -3047,6 +3049,10 @@
 	s.On_bootclasspath_before = sdk.commonSdkLibraryProperties.On_bootclasspath_before
 	s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk
 	s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk
+
+	if sdk.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
+		s.DexPreoptProfileGuided = proptools.BoolPtr(true)
+	}
 }
 
 func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -3062,6 +3068,10 @@
 	if len(s.Permitted_packages) > 0 {
 		propertySet.AddProperty("permitted_packages", s.Permitted_packages)
 	}
+	dexPreoptSet := propertySet.AddPropertySet("dex_preopt")
+	if s.DexPreoptProfileGuided != nil {
+		dexPreoptSet.AddProperty("profile_guided", proptools.Bool(s.DexPreoptProfileGuided))
+	}
 
 	stem := s.Stem
 
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 2ade146..3a2ecc0 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -33,7 +33,8 @@
 
 	// Files needs by most of the tests.
 	android.MockFS{
-		"Test.java": nil,
+		"Test.java":   nil,
+		"art-profile": nil,
 	}.AddToFixture(),
 )
 
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index 2a17cdc..66c44c8 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -62,6 +62,9 @@
 				min_sdk_version: "2",
 				compile_dex: true,
 				permitted_packages: ["mylib"],
+				dex_preopt: {
+					profile: "art-profile",
+				},
 			}
 
 			java_sdk_library {
@@ -71,6 +74,9 @@
 				shared_library: false,
 				public: {enabled: true},
 				min_sdk_version: "2",
+				dex_preopt: {
+					profile: "art-profile",
+				},
 			}
 		`),
 	).RunTest(t)
@@ -105,6 +111,9 @@
     visibility: ["//visibility:public"],
     apex_available: ["myapex"],
     shared_library: false,
+    dex_preopt: {
+        profile_guided: true,
+    },
     public: {
         jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
         stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
@@ -122,6 +131,9 @@
     jars: ["java_systemserver_libs/snapshot/jars/are/invalid/mylib.jar"],
     min_sdk_version: "2",
     permitted_packages: ["mylib"],
+    dex_preopt: {
+        profile_guided: true,
+    },
 }
 
 prebuilt_systemserverclasspath_fragment {
@@ -199,6 +211,54 @@
 `)
 	})
 
+	t.Run("target-u", func(t *testing.T) {
+		testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "UpsideDownCake", `
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+    name: "mysdklibrary",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["myapex"],
+    shared_library: false,
+    dex_preopt: {
+        profile_guided: true,
+    },
+    public: {
+        jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+        stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+        current_api: "sdk_library/public/mysdklibrary.txt",
+        removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+        sdk_version: "current",
+    },
+}
+
+java_import {
+    name: "mylib",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["myapex"],
+    jars: ["java_systemserver_libs/snapshot/jars/are/invalid/mylib.jar"],
+    min_sdk_version: "2",
+    permitted_packages: ["mylib"],
+    dex_preopt: {
+        profile_guided: true,
+    },
+}
+
+prebuilt_systemserverclasspath_fragment {
+    name: "mysystemserverclasspathfragment",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["myapex"],
+    contents: [
+        "mylib",
+        "mysdklibrary",
+    ],
+}
+`)
+	})
+
 	t.Run("added-directly", func(t *testing.T) {
 		testSnapshotWithSystemServerClasspathFragment(t, commonSdk, `latest`, expectedLatestSnapshot)
 	})