From 9c4dc19f4e3b72b13d557cdfbab32dbc63f456d7 Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Thu, 9 Feb 2023 00:09:24 +0800 Subject: 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 --- java/java.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index 874f93576..912779e94 100644 --- a/java/java.go +++ b/java/java.go @@ -795,6 +795,8 @@ type librarySdkMemberProperties struct { // 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 @@ func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberCo 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 @@ func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberConte 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 @@ func ImportFactory() android.Module { module.AddProperties( &module.properties, &module.dexer.dexProperties, + &module.importDexpreoptProperties, ) module.initModuleAndImport(module) -- cgit v1.2.3-59-g8ed1b From 81e468171f4822d1f9a6a2aed78589c74a1ee940 Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Wed, 8 Feb 2023 21:56:07 +0800 Subject: Use the profiles in the APEX to dexpreopt system server jars. After this change, if "profile_guided: true" is set, profile-guided compilation will be enabled for the jar and the ".prof" file next to the jar in the APEX ("javalib/.jar.prof") will be used as the profile when dexpreopting for the prebuilt APEX. Bug: 241823638 Test: m nothing Test: - 1. (on internal master) Patch aosp/2426453. 2. Build the APEX bundle and the module SDK of com.android.wifi 3. (on tm-dev) Patch this CL and aosp/2141972. 4. Copy the APEX bundle and the module SDK built on step 2 to the source tree 5. Disable hiddenapi check 6. lunch cf_x86_64_phone-userdebug && m MODULE_BUILD_FROM_SOURCE=false com.google.android.wifi 7. cat out/soong/.intermediates/prebuilts/module_sdk/Wifi/current/prebuilt_service-wifi/android_common_com.android.wifi/dexpreopt/oat/x86_64/javalib.invocation 8. See the profile being used. Change-Id: I55a5a295e9c5d6f0564afb139c5fb7da91ab8cae --- apex/apex.go | 2 +- apex/systemserver_classpath_fragment_test.go | 58 +++++++++++++++++++++++++--- java/dexpreopt.go | 36 +++++++++++++---- java/java.go | 21 +++++++--- java/sdk_library.go | 14 +++++-- 5 files changed, 108 insertions(+), 23 deletions(-) (limited to 'java/java.go') diff --git a/apex/apex.go b/apex/apex.go index ff38773b8..8a8b19d0a 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1769,7 +1769,7 @@ func apexFileForJavaModuleWithFile(ctx android.BaseModuleContext, module javaMod func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile { if dexpreopter, ok := module.(java.DexpreopterInterface); ok { - if profilePathOnHost := dexpreopter.ProfilePathOnHost(); profilePathOnHost != nil { + if profilePathOnHost := dexpreopter.OutputProfilePathOnHost(); profilePathOnHost != nil { dirInApex := "javalib" af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil) af.customStem = module.Stem() + ".jar.prof" diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go index 1803fcfb9..f94e50f4f 100644 --- a/apex/systemserver_classpath_fragment_test.go +++ b/apex/systemserver_classpath_fragment_test.go @@ -222,7 +222,7 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"), + dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"), ).RunTestWithBp(t, ` prebuilt_apex { name: "myapex", @@ -245,11 +245,23 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { ], } + java_import { + name: "bar", + jars: ["bar.jar"], + dex_preopt: { + profile_guided: true, + }, + apex_available: [ + "myapex", + ], + } + prebuilt_systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", prefer: true, contents: [ "foo", + "bar", ], apex_available: [ "myapex", @@ -257,15 +269,27 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { } `) - java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{ + ctx := result.TestContext + + java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{ `myapex.apex.selector`, `prebuilt_mysystemserverclasspathfragment`, }) - java.CheckModuleDependencies(t, result.TestContext, "mysystemserverclasspathfragment", "android_common_myapex", []string{ + java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{ `myapex.deapexer`, + `prebuilt_bar`, `prebuilt_foo`, }) + + ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{ + "javalib/foo.jar", + "javalib/bar.jar", + "javalib/bar.jar.prof", + }) + + assertProfileGuided(t, ctx, "foo", "android_common_myapex", false) + assertProfileGuided(t, ctx, "bar", "android_common_myapex", true) } func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { @@ -354,7 +378,7 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo"), + dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"), ).RunTestWithBp(t, ` prebuilt_apex { name: "myapex", @@ -377,11 +401,23 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { ], } + java_import { + name: "bar", + jars: ["bar.jar"], + dex_preopt: { + profile_guided: true, + }, + apex_available: [ + "myapex", + ], + } + prebuilt_systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", prefer: true, standalone_contents: [ "foo", + "bar", ], apex_available: [ "myapex", @@ -389,10 +425,22 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { } `) - java.CheckModuleDependencies(t, result.TestContext, "mysystemserverclasspathfragment", "android_common_myapex", []string{ + ctx := result.TestContext + + java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{ `myapex.deapexer`, + `prebuilt_bar`, `prebuilt_foo`, }) + + ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{ + "javalib/foo.jar", + "javalib/bar.jar", + "javalib/bar.jar.prof", + }) + + assertProfileGuided(t, ctx, "foo", "android_common_myapex", false) + assertProfileGuided(t, ctx, "bar", "android_common_myapex", true) } func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) { diff --git a/java/dexpreopt.go b/java/dexpreopt.go index fa52ae656..e0a062902 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -23,11 +23,24 @@ import ( ) type DexpreopterInterface interface { - IsInstallable() bool // Structs that embed dexpreopter must implement this. + // True if the java module is to be dexed and installed on devices. + // Structs that embed dexpreopter must implement this. + IsInstallable() bool + + // True if dexpreopt is disabled for the java module. dexpreoptDisabled(ctx android.BaseModuleContext) bool + + // If the java module is to be installed into an APEX, this list contains information about the + // dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed + // outside of the APEX. DexpreoptBuiltInstalledForApex() []dexpreopterInstall + + // The Make entries to install the dexpreopt outputs. Derived from + // `DexpreoptBuiltInstalledForApex`. AndroidMkEntriesForApex() []android.AndroidMkEntries - ProfilePathOnHost() android.Path + + // See `dexpreopter.outputProfilePathOnHost`. + OutputProfilePathOnHost() android.Path } type dexpreopterInstall struct { @@ -106,8 +119,13 @@ type dexpreopter struct { // dexpreopt another partition). configPath android.WritablePath - // The path to the profile on host. - profilePathOnHost android.Path + // The path to the profile on host that dexpreopter generates. This is used as the input for + // dex2oat. + outputProfilePathOnHost android.Path + + // The path to the profile that dexpreopter accepts. It must be in the binary format. If this is + // set, it overrides the profile settings in `dexpreoptProperties`. + inputProfilePathOnHost android.Path } type DexpreoptProperties struct { @@ -308,7 +326,9 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr var profileClassListing android.OptionalPath var profileBootListing android.OptionalPath profileIsTextListing := false - if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) { + if d.inputProfilePathOnHost != nil { + profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost) + } else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) { // If dex_preopt.profile_guided is not set, default it based on the existence of the // dexprepot.profile option or the profile class listing. if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" { @@ -389,7 +409,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr isProfile := strings.HasSuffix(installBase, ".prof") if isProfile { - d.profilePathOnHost = install.From + d.outputProfilePathOnHost = install.From } if isApexSystemServerJar { @@ -431,6 +451,6 @@ func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries { return entries } -func (d *dexpreopter) ProfilePathOnHost() android.Path { - return d.profilePathOnHost +func (d *dexpreopter) OutputProfilePathOnHost() android.Path { + return d.outputProfilePathOnHost } diff --git a/java/java.go b/java/java.go index 912779e94..f1600d98a 100644 --- a/java/java.go +++ b/java/java.go @@ -2002,7 +2002,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { if di == nil { return // An error has been reported by FindDeapexerProviderForModule. } - if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(j.BaseModuleName())); dexOutputPath != nil { + dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(j.BaseModuleName()) + if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil { dexJarFile := makeDexJarPathFromPath(dexOutputPath) j.dexJarFile = dexJarFile installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName())) @@ -2011,6 +2012,11 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath) setUncompressDex(ctx, &j.dexpreopter, &j.dexer) j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex + + if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil { + j.dexpreopter.inputProfilePathOnHost = profilePath + } + j.dexpreopt(ctx, dexOutputPath) // Initialize the hiddenapi structure. @@ -2145,11 +2151,16 @@ func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, // requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or // java_sdk_library_import with the specified base module name requires to be exported from a // prebuilt_apex/apex_set. -func requiredFilesFromPrebuiltApexForImport(name string) []string { +func requiredFilesFromPrebuiltApexForImport(name string, d *dexpreopter) []string { + dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(name) // Add the dex implementation jar to the set of exported files. - return []string{ - apexRootRelativePathToJavaLib(name), + files := []string{ + dexJarFileApexRootRelative, + } + if BoolDefault(d.importDexpreoptProperties.Dex_preopt.Profile_guided, false) { + files = append(files, dexJarFileApexRootRelative+".prof") } + return files } // apexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for @@ -2162,7 +2173,7 @@ var _ android.RequiredFilesFromPrebuiltApex = (*Import)(nil) func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []string { name := j.BaseModuleName() - return requiredFilesFromPrebuiltApexForImport(name) + return requiredFilesFromPrebuiltApexForImport(name, &j.dexpreopter) } // Add compile time check for interface implementation diff --git a/java/sdk_library.go b/java/sdk_library.go index 0478011f3..591ec05d0 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -2445,18 +2445,24 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo if di == nil { return // An error has been reported by FindDeapexerProviderForModule. } - if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(module.BaseModuleName())); dexOutputPath != nil { + dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(module.BaseModuleName()) + if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil { dexJarFile := makeDexJarPathFromPath(dexOutputPath) module.dexJarFile = dexJarFile installPath := android.PathForModuleInPartitionInstall( - ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(module.BaseModuleName())) + ctx, "apex", ai.ApexVariationName, dexJarFileApexRootRelative) module.installFile = installPath module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil) - // Dexpreopting. module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, installPath) module.dexpreopter.isSDKLibrary = true module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &module.dexpreopter) + + if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil { + module.dexpreopter.inputProfilePathOnHost = profilePath + } + + // Dexpreopting. module.dexpreopt(ctx, dexOutputPath) } else { // This should never happen as a variant for a prebuilt_apex is only created if the @@ -2585,7 +2591,7 @@ var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil) func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string { name := module.BaseModuleName() - return requiredFilesFromPrebuiltApexForImport(name) + return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter) } // java_sdk_library_xml -- cgit v1.2.3-59-g8ed1b