From 3317ce725d00bf9e000d8a0bf03e6780f2bce2ba Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Wed, 8 Feb 2023 01:19:19 +0800 Subject: [PATCH] Install system server jar profiles into the APEX. After this change, if profile-guided compilation is enabled for an APEX system server jar, the profile will be installed next to the jar with the ".prof" suffix, ("javalib/.jar.prof"). This file will later be used by odrefresh and dexpreopt from prebuilt APEX. Bug: 241823638 Test: m nothing Test: - 1. Patch ag/20581649 PS2. 2. banchan com.android.btservices x86_64 && m 3. Check that "javalib/service-bluetooth.jar.prof" exists in the APEX. Change-Id: Ibcfc6257dade92bd40a6d4b7368148717d0863b9 --- apex/apex.go | 15 +++++++ apex/systemserver_classpath_fragment_test.go | 34 +++++++++++++- dexpreopt/dexpreopt.go | 4 ++ java/dexpreopt.go | 47 +++++++++++++------- 4 files changed, 82 insertions(+), 18 deletions(-) diff --git a/apex/apex.go b/apex/apex.go index 3cdcd7985..af5b40e52 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1771,6 +1771,18 @@ func apexFileForJavaModuleWithFile(ctx android.BaseModuleContext, module javaMod return af } +func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile { + if dexpreopter, ok := module.(java.DexpreopterInterface); ok { + if profilePathOnHost := dexpreopter.ProfilePathOnHost(); profilePathOnHost != nil { + dirInApex := "javalib" + af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil) + af.customStem = module.Stem() + ".jar.prof" + return &af + } + } + return nil +} + // androidApp is an interface to handle all app modules (android_app, android_app_import, etc.) in // the same way. type androidApp interface { @@ -2465,6 +2477,9 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, case *java.Library, *java.SdkLibrary: af := apexFileForJavaModule(ctx, child.(javaModule)) vctx.filesInfo = append(vctx.filesInfo, af) + if profileAf := apexFileForJavaModuleProfile(ctx, child.(javaModule)); profileAf != nil { + vctx.filesInfo = append(vctx.filesInfo, *profileAf) + } return true // track transitive dependencies default: ctx.PropertyErrorf("systemserverclasspath_fragments", diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go index d03766448..c404a2e37 100644 --- a/apex/systemserver_classpath_fragment_test.go +++ b/apex/systemserver_classpath_fragment_test.go @@ -31,7 +31,7 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"), + dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"), ).RunTestWithBp(t, ` apex { name: "myapex", @@ -57,10 +57,23 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { ], } + java_library { + name: "bar", + srcs: ["c.java"], + installable: true, + dex_preopt: { + profile: "bar-art-profile", + }, + apex_available: [ + "myapex", + ], + } + systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", contents: [ "foo", + "bar", ], apex_available: [ "myapex", @@ -71,6 +84,8 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ "etc/classpaths/systemserverclasspath.pb", "javalib/foo.jar", + "javalib/bar.jar", + "javalib/bar.jar.prof", }) java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ @@ -236,7 +251,7 @@ func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo"), + dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"), ).RunTestWithBp(t, ` apex { name: "myapex", @@ -262,10 +277,23 @@ func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { ], } + java_library { + name: "bar", + srcs: ["c.java"], + dex_preopt: { + profile: "bar-art-profile", + }, + installable: true, + apex_available: [ + "myapex", + ], + } + systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", standalone_contents: [ "foo", + "bar", ], apex_available: [ "myapex", @@ -276,6 +304,8 @@ func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ "etc/classpaths/systemserverclasspath.pb", "javalib/foo.jar", + "javalib/bar.jar", + "javalib/bar.jar.prof", }) } diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index e3404a541..a590c72a5 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -101,6 +101,10 @@ func GenerateDexpreoptRule(ctx android.BuilderContext, globalSoong *GlobalSoongC } func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *ModuleConfig) bool { + if ctx.Config().UnbundledBuild() { + return true + } + if contains(global.DisablePreoptModules, module.Name) { return true } diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 77cbe9cf4..c4b0af441 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -27,6 +27,7 @@ type DexpreopterInterface interface { dexpreoptDisabled(ctx android.BaseModuleContext) bool DexpreoptBuiltInstalledForApex() []dexpreopterInstall AndroidMkEntriesForApex() []android.AndroidMkEntries + ProfilePathOnHost() android.Path } type dexpreopterInstall struct { @@ -103,6 +104,9 @@ type dexpreopter struct { // - Dexpreopt post-processing (using dexpreopt artifacts from a prebuilt system image to incrementally // dexpreopt another partition). configPath android.WritablePath + + // The path to the profile on host. + profilePathOnHost android.Path } type DexpreoptProperties struct { @@ -180,9 +184,8 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool { isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) if isApexVariant(ctx) { - // Don't preopt APEX variant module unless the module is an APEX system server jar and we are - // building the entire system image. - if !isApexSystemServerJar || ctx.Config().UnbundledBuild() { + // Don't preopt APEX variant module unless the module is an APEX system server jar. + if !isApexSystemServerJar { return true } } else { @@ -368,21 +371,29 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr installBase := filepath.Base(install.To) arch := filepath.Base(installDir) installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir) + isProfile := strings.HasSuffix(installBase, ".prof") + + if isProfile { + d.profilePathOnHost = install.From + } if isApexSystemServerJar { - // APEX variants of java libraries are hidden from Make, so their dexpreopt - // outputs need special handling. Currently, for APEX variants of java - // libraries, only those in the system server classpath are handled here. - // Preopting of boot classpath jars in the ART APEX are handled in - // java/dexpreopt_bootjars.go, and other APEX jars are not preopted. - // The installs will be handled by Make as sub-modules of the java library. - d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{ - name: arch + "-" + installBase, - moduleName: moduleName(ctx), - outputPathOnHost: install.From, - installDirOnDevice: installPath, - installFileOnDevice: installBase, - }) + // Profiles are handled separately because they are installed into the APEX. + if !isProfile { + // APEX variants of java libraries are hidden from Make, so their dexpreopt + // outputs need special handling. Currently, for APEX variants of java + // libraries, only those in the system server classpath are handled here. + // Preopting of boot classpath jars in the ART APEX are handled in + // java/dexpreopt_bootjars.go, and other APEX jars are not preopted. + // The installs will be handled by Make as sub-modules of the java library. + d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{ + name: arch + "-" + installBase, + moduleName: moduleName(ctx), + outputPathOnHost: install.From, + installDirOnDevice: installPath, + installFileOnDevice: installBase, + }) + } } else if !d.preventInstall { ctx.InstallFile(installPath, installBase, install.From) } @@ -404,3 +415,7 @@ func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries { } return entries } + +func (d *dexpreopter) ProfilePathOnHost() android.Path { + return d.profilePathOnHost +}