Merge "Revert "Update clang version to clang-r510928"" into main
diff --git a/android/deapexer.go b/android/deapexer.go
index 2704b3e..61ae64e 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -83,6 +83,10 @@
// 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 (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 @@
// 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/android/util.go b/android/util.go
index 51313ce..363b31c 100644
--- a/android/util.go
+++ b/android/util.go
@@ -15,6 +15,7 @@
package android
import (
+ "cmp"
"fmt"
"path/filepath"
"reflect"
@@ -106,15 +107,8 @@
return SortedKeys(m)
}
-type Ordered interface {
- ~string |
- ~float32 | ~float64 |
- ~int | ~int8 | ~int16 | ~int32 | ~int64 |
- ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
-}
-
// SortedKeys returns the keys of the given map in the ascending order.
-func SortedKeys[T Ordered, V any](m map[T]V) []T {
+func SortedKeys[T cmp.Ordered, V any](m map[T]V) []T {
if len(m) == 0 {
return nil
}
diff --git a/android/util_test.go b/android/util_test.go
index 699135b..8e73d83 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -15,6 +15,7 @@
package android
import (
+ "cmp"
"fmt"
"reflect"
"strconv"
@@ -650,7 +651,7 @@
}
}
-func testSortedKeysHelper[K Ordered, V any](t *testing.T, name string, input map[K]V, expected []K) {
+func testSortedKeysHelper[K cmp.Ordered, V any](t *testing.T, name string, input map[K]V, expected []K) {
t.Helper()
t.Run(name, func(t *testing.T) {
actual := SortedKeys(input)
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 5ff622c..a673108 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -53,6 +53,10 @@
// 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 @@
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 551942d..399d9b9 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -629,6 +629,7 @@
// 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 @@
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 @@
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 6b2c397..f6c53b2 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -221,8 +221,6 @@
}
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 @@
"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 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 @@
"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 @@
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/androidmk.go b/java/androidmk.go
index c86dcf4..b523594 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -209,9 +209,10 @@
return []android.AndroidMkEntries{}
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
- Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+ Class: "JAVA_LIBRARIES",
+ OverrideName: prebuilt.BaseModuleName(),
+ OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
+ Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 2c13d99..7c45d30 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -1105,6 +1105,10 @@
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 4c0a0a1..9db9b1b 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -282,6 +282,17 @@
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 @@
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 d536ca1..cd249ed 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1837,6 +1837,7 @@
func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
apiContributions := al.properties.Api_contributions
addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") &&
+ !ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") &&
proptools.BoolDefault(al.properties.Enable_validation, true)
for _, apiContributionName := range apiContributions {
ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
@@ -2089,6 +2090,11 @@
// that depend on this module, as well as to aidl for this module.
Export_include_dirs []string
}
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
}
type Import struct {
@@ -2162,12 +2168,16 @@
return j.properties.Jars
}
+func (j *Import) BaseModuleName() string {
+ return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
+}
+
func (j *Import) Name() string {
return j.prebuilt.Name(j.ModuleBase.Name())
}
func (j *Import) Stem() string {
- return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
+ return proptools.StringDefault(j.properties.Stem, j.BaseModuleName())
}
func (a *Import) JacocoReportClassesFile() android.Path {
@@ -2453,6 +2463,10 @@
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/java_test.go b/java/java_test.go
index 0891ab6..42301d8 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -24,6 +24,7 @@
"strings"
"testing"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/aconfig"
@@ -2521,3 +2522,105 @@
apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
apiScopePublic.apiLibraryModuleName("foo")))
}
+
+func TestMultiplePrebuilts(t *testing.T) {
+ bp := `
+ // an rdep
+ java_library {
+ name: "foo",
+ libs: ["bar"],
+ }
+
+ // multiple variations of dep
+ // source
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ }
+ // prebuilt "v1"
+ java_import {
+ name: "bar",
+ jars: ["bar.jar"],
+ }
+ // prebuilt "v2"
+ java_import {
+ name: "bar.v2",
+ source_module_name: "bar",
+ jars: ["bar.v1.jar"],
+ }
+
+ // selectors
+ apex_contributions {
+ name: "myapex_contributions",
+ contents: ["%v"],
+ }
+ `
+ hasDep := func(ctx *android.TestResult, m android.Module, wantDep android.Module) bool {
+ t.Helper()
+ var found bool
+ ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
+ }
+
+ hasFileWithStem := func(m android.TestingModule, stem string) bool {
+ t.Helper()
+ for _, o := range m.AllOutputs() {
+ _, file := filepath.Split(o)
+ if file == stem+".jar" {
+ return true
+ }
+ }
+ return false
+ }
+
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ expectedDependencyName string
+ }{
+ {
+ desc: "Source library is selected using apex_contributions",
+ selectedDependencyName: "bar",
+ expectedDependencyName: "bar",
+ },
+ {
+ desc: "Prebuilt library v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_bar",
+ expectedDependencyName: "prebuilt_bar",
+ },
+ {
+ desc: "Prebuilt library v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_bar.v2",
+ expectedDependencyName: "prebuilt_bar.v2",
+ },
+ }
+
+ for _, tc := range testCases {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+ }
+ }),
+ ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
+
+ // check that rdep gets the correct variation of dep
+ foo := ctx.ModuleForTests("foo", "android_common")
+ expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_common")
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", foo.Module().Name(), tc.expectedDependencyName), true, hasDep(ctx, foo.Module(), expectedDependency.Module()))
+
+ // check that output file of dep is always bar.jar
+ // The filename should be agnostic to source/prebuilt/prebuilt_version
+ android.AssertBoolEquals(t, fmt.Sprintf("could not find bar.jar in outputs of %s. All Outputs %v\n", tc.expectedDependencyName, expectedDependency.AllOutputs()), true, hasFileWithStem(expectedDependency, "bar"))
+
+ // check LOCAL_MODULE of the selected module name
+ // the prebuilt should have the same LOCAL_MODULE when exported to make
+ entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, expectedDependency.Module())[0]
+ android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "bar", entries.EntryMap["LOCAL_MODULE"][0])
+ }
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 2bf6644..49e6727 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -3019,6 +3019,10 @@
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 30dd55f..59c5466 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -313,6 +313,10 @@
return nil
}
+func (module *prebuiltSystemServerClasspathModule) UseProfileGuidedDexpreopt() bool {
+ return false
+}
+
var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltSystemServerClasspathModule)(nil)
func prebuiltSystemServerClasspathModuleFactory() android.Module {