diff --git a/android/deapexer.go b/android/deapexer.go index 2704b3ef7..61ae64ea5 100644 --- a/android/deapexer.go +++ b/android/deapexer.go @@ -83,6 +83,10 @@ type DeapexerInfo struct { // name of the java libraries exported from the apex // e.g. core-libart exportedModuleNames []string + + // name of the java libraries exported from the apex that should be dexpreopt'd with the .prof + // file embedded in the apex + dexpreoptProfileGuidedExportedModuleNames []string } // ApexModuleName returns the name of the APEX module that provided the info. @@ -121,6 +125,14 @@ func NewDeapexerInfo(apexModuleName string, exports map[string]WritablePath, mod } } +func (i *DeapexerInfo) GetDexpreoptProfileGuidedExportedModuleNames() []string { + return i.dexpreoptProfileGuidedExportedModuleNames +} + +func (i *DeapexerInfo) AddDexpreoptProfileGuidedExportedModuleNames(names ...string) { + i.dexpreoptProfileGuidedExportedModuleNames = append(i.dexpreoptProfileGuidedExportedModuleNames, names...) +} + type deapexerTagStruct struct { blueprint.BaseDependencyTag } @@ -143,6 +155,9 @@ type RequiredFilesFromPrebuiltApex interface { // the path to the extracted file will be stored in the DeapexerInfo using the APEX relative file // path as the key, The path can then be retrieved using the PrebuiltExportPath(key) method. RequiredFilesFromPrebuiltApex(ctx BaseModuleContext) []string + + // Returns true if a transitive dependency of an apex should use a .prof file to guide dexpreopt + UseProfileGuidedDexpreopt() bool } // Marker interface that identifies dependencies on modules that may require files from a prebuilt diff --git a/apex/deapexer.go b/apex/deapexer.go index 5ff622c5b..a6731080c 100644 --- a/apex/deapexer.go +++ b/apex/deapexer.go @@ -53,6 +53,10 @@ type DeapexerProperties struct { // all architectures, e.g. java. CommonModules []string + // List of modules that use an embedded .prof to guide optimization of the equivalent dexpreopt artifact + // This is a subset of CommonModules + DexpreoptProfileGuidedModules []string + // List of files exported from the .apex file by this module // // Each entry is a path from the apex root, e.g. javalib/core-libart.jar. @@ -128,6 +132,7 @@ func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) { if len(exports) > 0 { // Make the information available for other modules. di := android.NewDeapexerInfo(apexModuleName(ctx.ModuleName()), exports, p.properties.CommonModules) + di.AddDexpreoptProfileGuidedExportedModuleNames(p.properties.DexpreoptProfileGuidedModules...) android.SetProvider(ctx, android.DeapexerProvider, di) // Create a sorted list of the files that this exports. diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 551942d31..399d9b92f 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -629,6 +629,7 @@ func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.TopDownMutator // Compute the deapexer properties from the transitive dependencies of this module. commonModules := []string{} + dexpreoptProfileGuidedModules := []string{} exportedFiles := []string{} ctx.WalkDeps(func(child, parent android.Module) bool { tag := ctx.OtherModuleDependencyTag(child) @@ -642,9 +643,14 @@ func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.TopDownMutator if _, ok := tag.(android.RequiresFilesFromPrebuiltApexTag); ok { commonModules = append(commonModules, name) - requiredFiles := child.(android.RequiredFilesFromPrebuiltApex).RequiredFilesFromPrebuiltApex(ctx) + extract := child.(android.RequiredFilesFromPrebuiltApex) + requiredFiles := extract.RequiredFilesFromPrebuiltApex(ctx) exportedFiles = append(exportedFiles, requiredFiles...) + if extract.UseProfileGuidedDexpreopt() { + dexpreoptProfileGuidedModules = append(dexpreoptProfileGuidedModules, name) + } + // Visit the dependencies of this module just in case they also require files from the // prebuilt apex. return true @@ -657,7 +663,8 @@ func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.TopDownMutator deapexerProperties := &DeapexerProperties{ // Remove any duplicates from the common modules lists as a module may be included via a direct // dependency as well as transitive ones. - CommonModules: android.SortedUniqueStrings(commonModules), + CommonModules: android.SortedUniqueStrings(commonModules), + DexpreoptProfileGuidedModules: android.SortedUniqueStrings(dexpreoptProfileGuidedModules), } // Populate the exported files property in a fixed order. diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go index 6b2c39777..f6c53b270 100644 --- a/apex/systemserver_classpath_fragment_test.go +++ b/apex/systemserver_classpath_fragment_test.go @@ -221,8 +221,6 @@ func TestSystemServerClasspathFragmentWithContentNotInMake(t *testing.T) { } func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { - // TODO(spandandas): Fix the rules for profile guided dexpreopt of deapexed prebuilt jars - t.Skip() result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, @@ -294,8 +292,8 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { "javalib/bar.jar.prof", }) - assertProfileGuided(t, ctx, "foo", "android_common_myapex", false) - assertProfileGuided(t, ctx, "bar", "android_common_myapex", true) + assertProfileGuidedPrebuilt(t, ctx, "myapex", "foo", false) + assertProfileGuidedPrebuilt(t, ctx, "myapex", "bar", true) } func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { @@ -381,8 +379,6 @@ func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { } func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { - // TODO(spandandas): Fix the rules for profile guided dexpreopt of deapexed prebuilt jars - t.Skip() result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, @@ -447,8 +443,8 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { "javalib/bar.jar.prof", }) - assertProfileGuided(t, ctx, "foo", "android_common_myapex", false) - assertProfileGuided(t, ctx, "bar", "android_common_myapex", true) + assertProfileGuidedPrebuilt(t, ctx, "myapex", "foo", false) + assertProfileGuidedPrebuilt(t, ctx, "myapex", "bar", true) } func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) { @@ -458,3 +454,11 @@ func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName stri t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual) } } + +func assertProfileGuidedPrebuilt(t *testing.T, ctx *android.TestContext, apexName string, moduleName string, expected bool) { + dexpreopt := ctx.ModuleForTests(apexName, "android_common_"+apexName).Rule("dexpreopt." + moduleName) + actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=") + if expected != actual { + t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual) + } +} diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 2c13d99e9..7c45d3043 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -1105,6 +1105,10 @@ func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex return nil } +func (module *PrebuiltBootclasspathFragmentModule) UseProfileGuidedDexpreopt() bool { + return false +} + var _ android.RequiredFilesFromPrebuiltApex = (*PrebuiltBootclasspathFragmentModule)(nil) func prebuiltBootclasspathFragmentFactory() android.Module { diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 4c0a0a155..9db9b1b46 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -282,6 +282,17 @@ func (d *Dexpreopter) DexpreoptPrebuiltApexSystemServerJars(ctx android.ModuleCo d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/")) // generate the rules for creating the .odex and .vdex files for this system server jar dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName)) + + d.inputProfilePathOnHost = nil // reset: TODO(spandandas): Make dexpreopter stateless + if android.InList(libraryName, di.GetDexpreoptProfileGuidedExportedModuleNames()) { + // Set the profile path to guide optimization + prof := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName) + ".prof") + if prof == nil { + ctx.ModuleErrorf("Could not find a .prof file in this prebuilt apex") + } + d.inputProfilePathOnHost = prof + } + d.dexpreopt(ctx, libraryName, dexJarFile) } @@ -354,6 +365,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa var profileClassListing android.OptionalPath var profileBootListing android.OptionalPath profileIsTextListing := false + if d.inputProfilePathOnHost != nil { profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost) } else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) { diff --git a/java/java.go b/java/java.go index f806298bf..cd249edad 100644 --- a/java/java.go +++ b/java/java.go @@ -2463,6 +2463,10 @@ func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []st return requiredFilesFromPrebuiltApexForImport(name, &j.dexpreopter) } +func (j *Import) UseProfileGuidedDexpreopt() bool { + return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided) +} + // Add compile time check for interface implementation var _ android.IDEInfo = (*Import)(nil) var _ android.IDECustomizedModuleName = (*Import)(nil) diff --git a/java/sdk_library.go b/java/sdk_library.go index 2bf66449d..49e6727eb 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -3019,6 +3019,10 @@ func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseMo return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter) } +func (j *SdkLibraryImport) UseProfileGuidedDexpreopt() bool { + return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided) +} + // java_sdk_library_xml type sdkLibraryXml struct { android.ModuleBase diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go index 30dd55fa9..59c546634 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -313,6 +313,10 @@ func (module *prebuiltSystemServerClasspathModule) RequiredFilesFromPrebuiltApex return nil } +func (module *prebuiltSystemServerClasspathModule) UseProfileGuidedDexpreopt() bool { + return false +} + var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltSystemServerClasspathModule)(nil) func prebuiltSystemServerClasspathModuleFactory() android.Module {