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/<name>.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
This commit is contained in:
Jiakai Zhang
2023-02-08 21:56:07 +08:00
parent 1f4542c85b
commit 81e468171f
5 changed files with 108 additions and 23 deletions

View File

@@ -1769,7 +1769,7 @@ func apexFileForJavaModuleWithFile(ctx android.BaseModuleContext, module javaMod
func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile { func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile {
if dexpreopter, ok := module.(java.DexpreopterInterface); ok { if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
if profilePathOnHost := dexpreopter.ProfilePathOnHost(); profilePathOnHost != nil { if profilePathOnHost := dexpreopter.OutputProfilePathOnHost(); profilePathOnHost != nil {
dirInApex := "javalib" dirInApex := "javalib"
af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil) af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil)
af.customStem = module.Stem() + ".jar.prof" af.customStem = module.Stem() + ".jar.prof"

View File

@@ -222,7 +222,7 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
result := android.GroupFixturePreparers( result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment, prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex, prepareForTestWithMyapex,
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"), dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"),
).RunTestWithBp(t, ` ).RunTestWithBp(t, `
prebuilt_apex { prebuilt_apex {
name: "myapex", 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 { prebuilt_systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment", name: "mysystemserverclasspathfragment",
prefer: true, prefer: true,
contents: [ contents: [
"foo", "foo",
"bar",
], ],
apex_available: [ apex_available: [
"myapex", "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`, `myapex.apex.selector`,
`prebuilt_mysystemserverclasspathfragment`, `prebuilt_mysystemserverclasspathfragment`,
}) })
java.CheckModuleDependencies(t, result.TestContext, "mysystemserverclasspathfragment", "android_common_myapex", []string{ java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
`myapex.deapexer`, `myapex.deapexer`,
`prebuilt_bar`,
`prebuilt_foo`, `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) { func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) {
@@ -354,7 +378,7 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
result := android.GroupFixturePreparers( result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment, prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex, prepareForTestWithMyapex,
dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo"), dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"),
).RunTestWithBp(t, ` ).RunTestWithBp(t, `
prebuilt_apex { prebuilt_apex {
name: "myapex", 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 { prebuilt_systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment", name: "mysystemserverclasspathfragment",
prefer: true, prefer: true,
standalone_contents: [ standalone_contents: [
"foo", "foo",
"bar",
], ],
apex_available: [ apex_available: [
"myapex", "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`, `myapex.deapexer`,
`prebuilt_bar`,
`prebuilt_foo`, `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) { func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) {

View File

@@ -23,11 +23,24 @@ import (
) )
type DexpreopterInterface interface { 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 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 DexpreoptBuiltInstalledForApex() []dexpreopterInstall
// The Make entries to install the dexpreopt outputs. Derived from
// `DexpreoptBuiltInstalledForApex`.
AndroidMkEntriesForApex() []android.AndroidMkEntries AndroidMkEntriesForApex() []android.AndroidMkEntries
ProfilePathOnHost() android.Path
// See `dexpreopter.outputProfilePathOnHost`.
OutputProfilePathOnHost() android.Path
} }
type dexpreopterInstall struct { type dexpreopterInstall struct {
@@ -106,8 +119,13 @@ type dexpreopter struct {
// dexpreopt another partition). // dexpreopt another partition).
configPath android.WritablePath configPath android.WritablePath
// The path to the profile on host. // The path to the profile on host that dexpreopter generates. This is used as the input for
profilePathOnHost android.Path // 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 { type DexpreoptProperties struct {
@@ -308,7 +326,9 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
var profileClassListing android.OptionalPath var profileClassListing android.OptionalPath
var profileBootListing android.OptionalPath var profileBootListing android.OptionalPath
profileIsTextListing := false 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 // If dex_preopt.profile_guided is not set, default it based on the existence of the
// dexprepot.profile option or the profile class listing. // dexprepot.profile option or the profile class listing.
if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" { 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") isProfile := strings.HasSuffix(installBase, ".prof")
if isProfile { if isProfile {
d.profilePathOnHost = install.From d.outputProfilePathOnHost = install.From
} }
if isApexSystemServerJar { if isApexSystemServerJar {
@@ -431,6 +451,6 @@ func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries {
return entries return entries
} }
func (d *dexpreopter) ProfilePathOnHost() android.Path { func (d *dexpreopter) OutputProfilePathOnHost() android.Path {
return d.profilePathOnHost return d.outputProfilePathOnHost
} }

View File

@@ -2002,7 +2002,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if di == nil { if di == nil {
return // An error has been reported by FindDeapexerProviderForModule. 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) dexJarFile := makeDexJarPathFromPath(dexOutputPath)
j.dexJarFile = dexJarFile j.dexJarFile = dexJarFile
installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName())) 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) j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath)
setUncompressDex(ctx, &j.dexpreopter, &j.dexer) setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
j.dexpreopter.inputProfilePathOnHost = profilePath
}
j.dexpreopt(ctx, dexOutputPath) j.dexpreopt(ctx, dexOutputPath)
// Initialize the hiddenapi structure. // 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 // 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 // java_sdk_library_import with the specified base module name requires to be exported from a
// prebuilt_apex/apex_set. // 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. // Add the dex implementation jar to the set of exported files.
return []string{ files := []string{
apexRootRelativePathToJavaLib(name), 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 // 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 { func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []string {
name := j.BaseModuleName() name := j.BaseModuleName()
return requiredFilesFromPrebuiltApexForImport(name) return requiredFilesFromPrebuiltApexForImport(name, &j.dexpreopter)
} }
// Add compile time check for interface implementation // Add compile time check for interface implementation

View File

@@ -2445,18 +2445,24 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
if di == nil { if di == nil {
return // An error has been reported by FindDeapexerProviderForModule. 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) dexJarFile := makeDexJarPathFromPath(dexOutputPath)
module.dexJarFile = dexJarFile module.dexJarFile = dexJarFile
installPath := android.PathForModuleInPartitionInstall( installPath := android.PathForModuleInPartitionInstall(
ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(module.BaseModuleName())) ctx, "apex", ai.ApexVariationName, dexJarFileApexRootRelative)
module.installFile = installPath module.installFile = installPath
module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil) module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
// Dexpreopting.
module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, installPath) module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, installPath)
module.dexpreopter.isSDKLibrary = true module.dexpreopter.isSDKLibrary = true
module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &module.dexpreopter) module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &module.dexpreopter)
if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
module.dexpreopter.inputProfilePathOnHost = profilePath
}
// Dexpreopting.
module.dexpreopt(ctx, dexOutputPath) module.dexpreopt(ctx, dexOutputPath)
} else { } else {
// This should never happen as a variant for a prebuilt_apex is only created if the // 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 { func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
name := module.BaseModuleName() name := module.BaseModuleName()
return requiredFilesFromPrebuiltApexForImport(name) return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter)
} }
// java_sdk_library_xml // java_sdk_library_xml