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