From 9c4dc19f4e3b72b13d557cdfbab32dbc63f456d7 Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Thu, 9 Feb 2023 00:09:24 +0800 Subject: [PATCH 1/3] 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/dexpreopt.go | 17 +++++- java/java.go | 12 ++++ java/sdk_library.go | 12 +++- sdk/java_sdk_test.go | 3 +- ...systemserverclasspath_fragment_sdk_test.go | 60 +++++++++++++++++++ 5 files changed, 101 insertions(+), 3 deletions(-) diff --git a/java/dexpreopt.go b/java/dexpreopt.go index c4b0af441..fa52ae656 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -78,7 +78,8 @@ func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries { } type dexpreopter struct { - dexpreoptProperties DexpreoptProperties + dexpreoptProperties DexpreoptProperties + importDexpreoptProperties ImportDexpreoptProperties installPath android.InstallPath uncompressedDex bool @@ -127,6 +128,18 @@ type DexpreoptProperties struct { // 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 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr } } + 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 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) diff --git a/java/sdk_library.go b/java/sdk_library.go index a2295f4a6..0478011f3 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -2201,7 +2201,7 @@ func sdkLibraryImportFactory() android.Module { 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 @@ type sdkLibrarySdkMemberProperties struct { // // 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 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe 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 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo 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 2ade146b7..3a2ecc00c 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -33,7 +33,8 @@ var prepareForSdkTestWithJava = android.GroupFixturePreparers( // 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 2a17cdc3a..66c44c843 100644 --- a/sdk/systemserverclasspath_fragment_sdk_test.go +++ b/sdk/systemserverclasspath_fragment_sdk_test.go @@ -62,6 +62,9 @@ func testSnapshotWithSystemServerClasspathFragment(t *testing.T, sdk string, tar min_sdk_version: "2", compile_dex: true, permitted_packages: ["mylib"], + dex_preopt: { + profile: "art-profile", + }, } java_sdk_library { @@ -71,6 +74,9 @@ func testSnapshotWithSystemServerClasspathFragment(t *testing.T, sdk string, tar shared_library: false, public: {enabled: true}, min_sdk_version: "2", + dex_preopt: { + profile: "art-profile", + }, } `), ).RunTest(t) @@ -105,6 +111,9 @@ java_sdk_library_import { 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 @@ java_import { 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 { @@ -186,6 +198,54 @@ java_import { permitted_packages: ["mylib"], } +prebuilt_systemserverclasspath_fragment { + name: "mysystemserverclasspathfragment", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + contents: [ + "mylib", + "mysdklibrary", + ], +} +`) + }) + + 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, From 1f4542c85bfadbac6cd0860057e401393231f2e5 Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Wed, 15 Feb 2023 22:43:09 +0000 Subject: [PATCH 2/3] Add tests for the ignored "profile_guided: true" property. This is tricky and is worth some tests. Bug: 241823638 Test: m nothing Change-Id: I9c09451d075dca7563eb42c63812375cfd974fbf --- apex/systemserver_classpath_fragment_test.go | 61 ++++++++++++++++++-- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go index c404a2e37..1803fcfb9 100644 --- a/apex/systemserver_classpath_fragment_test.go +++ b/apex/systemserver_classpath_fragment_test.go @@ -15,10 +15,11 @@ package apex import ( - "android/soong/dexpreopt" + "strings" "testing" "android/soong/android" + "android/soong/dexpreopt" "android/soong/java" ) @@ -31,7 +32,7 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"), + dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar", "myapex:baz"), ).RunTestWithBp(t, ` apex { name: "myapex", @@ -69,11 +70,24 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { ], } + java_library { + name: "baz", + srcs: ["d.java"], + installable: true, + dex_preopt: { + profile_guided: true, // ignored + }, + apex_available: [ + "myapex", + ], + } + systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", contents: [ "foo", "bar", + "baz", ], apex_available: [ "myapex", @@ -81,17 +95,24 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { } `) - ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ + ctx := result.TestContext + + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ "etc/classpaths/systemserverclasspath.pb", "javalib/foo.jar", "javalib/bar.jar", "javalib/bar.jar.prof", + "javalib/baz.jar", }) - java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ + java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex_image", []string{ `myapex.key`, `mysystemserverclasspathfragment`, }) + + assertProfileGuided(t, ctx, "foo", "android_common_apex10000", false) + assertProfileGuided(t, ctx, "bar", "android_common_apex10000", true) + assertProfileGuided(t, ctx, "baz", "android_common_apex10000", false) } func TestSystemserverclasspathFragmentNoGeneratedProto(t *testing.T) { @@ -251,7 +272,7 @@ func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"), + dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar", "myapex:baz"), ).RunTestWithBp(t, ` apex { name: "myapex", @@ -289,11 +310,24 @@ func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { ], } + java_library { + name: "baz", + srcs: ["d.java"], + dex_preopt: { + profile_guided: true, // ignored + }, + installable: true, + apex_available: [ + "myapex", + ], + } + systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", standalone_contents: [ "foo", "bar", + "baz", ], apex_available: [ "myapex", @@ -301,12 +335,19 @@ func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { } `) - ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ + ctx := result.TestContext + + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ "etc/classpaths/systemserverclasspath.pb", "javalib/foo.jar", "javalib/bar.jar", "javalib/bar.jar.prof", + "javalib/baz.jar", }) + + assertProfileGuided(t, ctx, "foo", "android_common_apex10000", false) + assertProfileGuided(t, ctx, "bar", "android_common_apex10000", true) + assertProfileGuided(t, ctx, "baz", "android_common_apex10000", false) } func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { @@ -353,3 +394,11 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { `prebuilt_foo`, }) } + +func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) { + dexpreopt := ctx.ModuleForTests(moduleName, variant).Rule("dexpreopt") + actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=") + if expected != actual { + t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual) + } +} From 81e468171f4822d1f9a6a2aed78589c74a1ee940 Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Wed, 8 Feb 2023 21:56:07 +0800 Subject: [PATCH 3/3] 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(-) 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