summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/apex.go12
-rw-r--r--android/apex_contributions.go12
-rw-r--r--apex/apex.go18
-rw-r--r--apex/dexpreopt_bootjars_test.go150
-rw-r--r--apex/prebuilt.go25
-rw-r--r--java/bootclasspath_fragment.go6
-rw-r--r--java/dexpreopt_bootjars.go80
-rw-r--r--java/dexpreopt_config.go2
-rw-r--r--java/sdk_library_test.go8
-rw-r--r--java/testing.go6
10 files changed, 297 insertions, 22 deletions
diff --git a/android/apex.go b/android/apex.go
index c0907a758..b4bb67c78 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -954,3 +954,15 @@ type ApexTestInterface interface {
// Return true if the apex bundle is an apex_test
IsTestApex() bool
}
+
+var ApexExportsInfoProvider = blueprint.NewProvider[ApexExportsInfo]()
+
+// ApexExportsInfo contains information about the artifacts provided by apexes to dexpreopt and hiddenapi
+type ApexExportsInfo struct {
+ // Canonical name of this APEX. Used to determine the path to the activated APEX on
+ // device (/apex/<apex_name>)
+ ApexName string
+
+ // Path to the image profile file on host (or empty, if profile is not generated).
+ ProfilePathOnHost Path
+}
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index 34941c091..a30964080 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -164,6 +164,18 @@ func (p *PrebuiltSelectionInfoMap) IsSelected(baseModuleName, name string) bool
}
}
+// Return the list of soong modules selected for this api domain
+// In the case of apexes, it is the canonical name of the apex on device (/apex/<apex_name>)
+func (p *PrebuiltSelectionInfoMap) GetSelectedModulesForApiDomain(apiDomain string) []string {
+ selected := []string{}
+ for _, entry := range *p {
+ if entry.apiDomain == apiDomain {
+ selected = append(selected, entry.selectedModuleName)
+ }
+ }
+ return selected
+}
+
// This module type does not have any build actions.
func (a *allApexContributions) GenerateAndroidBuildActions(ctx ModuleContext) {
}
diff --git a/apex/apex.go b/apex/apex.go
index 56559b16b..b70484cbe 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2371,6 +2371,24 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.buildApex(ctx)
a.buildApexDependencyInfo(ctx)
a.buildLintReports(ctx)
+
+ // Set a provider for dexpreopt of bootjars
+ a.provideApexExportsInfo(ctx)
+}
+
+// Set a provider containing information about the jars and .prof provided by the apex
+// Apexes built from source retrieve this information by visiting `bootclasspath_fragments`
+// Used by dex_bootjars to generate the boot image
+func (a *apexBundle) provideApexExportsInfo(ctx android.ModuleContext) {
+ ctx.VisitDirectDepsWithTag(bcpfTag, func(child android.Module) {
+ if info, ok := android.OtherModuleProvider(ctx, child, java.BootclasspathFragmentApexContentInfoProvider); ok {
+ exports := android.ApexExportsInfo{
+ ApexName: a.ApexVariationName(),
+ ProfilePathOnHost: info.ProfilePathOnHost(),
+ }
+ ctx.SetProvider(android.ApexExportsInfoProvider, exports)
+ }
+ })
}
// apexBootclasspathFragmentFiles returns the list of apexFile structures defining the files that
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index 2e828cade..9d745193d 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -252,3 +252,153 @@ func TestDexpreoptBootZip(t *testing.T) {
testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs, false)
}
+
+// Multiple ART apexes might exist in the tree.
+// The profile should correspond to the apex selected using release build flags
+func TestDexpreoptProfileWithMultiplePrebuiltArtApexes(t *testing.T) {
+ ruleFile := "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art"
+ bp := `
+ // Platform.
+
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+ }
+
+ // Source ART APEX.
+
+ java_library {
+ name: "core-oj",
+ srcs: ["core-oj.java"],
+ installable: true,
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ contents: ["core-oj"],
+ apex_available: [
+ "com.android.art",
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ apex_key {
+ name: "com.android.art.key",
+ public_key: "com.android.art.avbpubkey",
+ private_key: "com.android.art.pem",
+ }
+
+ apex {
+ name: "com.android.art",
+ key: "com.android.art.key",
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ updatable: false,
+ }
+
+ // Prebuilt ART APEX.
+
+ prebuilt_bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ prebuilt_apex {
+ name: "com.android.art",
+ apex_name: "com.android.art",
+ src: "com.android.art-arm.apex",
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ }
+
+ // Another Prebuilt ART APEX
+ prebuilt_apex {
+ name: "com.android.art.v2",
+ apex_name: "com.android.art", // Used to determine the API domain
+ src: "com.android.art-arm.apex",
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ }
+
+ // APEX contribution modules
+
+ apex_contributions {
+ name: "art.source.contributions",
+ api_domain: "com.android.art",
+ contents: ["com.android.art"],
+ }
+
+ apex_contributions {
+ name: "art.prebuilt.contributions",
+ api_domain: "com.android.art",
+ contents: ["prebuilt_com.android.art"],
+ }
+
+ apex_contributions {
+ name: "art.prebuilt.v2.contributions",
+ api_domain: "com.android.art",
+ contents: ["com.android.art.v2"], // prebuilt_ prefix is missing because of prebuilt_rename mutator
+ }
+
+ `
+
+ testCases := []struct {
+ desc string
+ selectedArtApexContributions string
+ expectedProfile string
+ }{
+ {
+ desc: "Source apex com.android.art is selected, profile should come from source java library",
+ selectedArtApexContributions: "art.source.contributions",
+ expectedProfile: "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.art is selected, profile should come from .prof deapexed from the prebuilt",
+ selectedArtApexContributions: "art.prebuilt.contributions",
+ expectedProfile: "out/soong/.intermediates/com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.art.v2 is selected, profile should come from .prof deapexed from the prebuilt",
+ selectedArtApexContributions: "art.prebuilt.v2.contributions",
+ expectedProfile: "out/soong/.intermediates/com.android.art.v2.deapexer/android_common/deapexer/etc/boot-image.prof",
+ },
+ }
+ for _, tc := range testCases {
+ result := android.GroupFixturePreparers(
+ java.PrepareForTestWithDexpreopt,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureConfigureBootJars("com.android.art:core-oj"),
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithArtApex,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ART": tc.selectedArtApexContributions,
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+
+ dexBootJars := result.ModuleForTests("dex_bootjars", "android_common")
+ rule := dexBootJars.Output(ruleFile)
+
+ inputs := rule.Implicits.Strings()
+ android.AssertStringListContains(t, tc.desc, inputs, tc.expectedProfile)
+ }
+}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index b13ecc2fd..37a9ff5a1 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -769,6 +769,25 @@ func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
p.apexInfoMutator(mctx)
}
+// Set a provider containing information about the jars and .prof provided by the apex
+// Apexes built from prebuilts retrieve this information by visiting its internal deapexer module
+// Used by dex_bootjars to generate the boot image
+func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext) {
+ if !p.hasExportedDeps() {
+ // nothing to do
+ return
+ }
+ if di, err := android.FindDeapexerProviderForModule(ctx); err == nil {
+ exports := android.ApexExportsInfo{
+ ApexName: p.ApexVariationName(),
+ ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex),
+ }
+ ctx.SetProvider(android.ApexExportsInfoProvider, exports)
+ } else {
+ ctx.ModuleErrorf(err.Error())
+ }
+}
+
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity.
@@ -793,6 +812,9 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// dexpreopt any system server jars if present
p.dexpreoptSystemServerJars(ctx)
+ // provide info used for generating the boot image
+ p.provideApexExportsInfo(ctx)
+
// Save the files that need to be made available to Make.
p.initApexFilesForAndroidMk(ctx)
@@ -1012,6 +1034,9 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// dexpreopt any system server jars if present
a.dexpreoptSystemServerJars(ctx)
+ // provide info used for generating the boot image
+ a.provideApexExportsInfo(ctx)
+
// Save the files that need to be made available to Make.
a.initApexFilesForAndroidMk(ctx)
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 83030b51e..010dbec8f 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -534,7 +534,7 @@ func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleC
if profile != nil {
info.profilePathOnHost = profile
- info.profileInstallPathInApex = profileInstallPathInApex
+ info.profileInstallPathInApex = ProfileInstallPathInApex
}
// Make the apex content info available for other modules.
@@ -1074,7 +1074,7 @@ func (module *PrebuiltBootclasspathFragmentModule) produceBootImageProfile(ctx a
return nil // An error has been reported by FindDeapexerProviderForModule.
}
- return di.PrebuiltExportPath(profileInstallPathInApex)
+ return di.PrebuiltExportPath(ProfileInstallPathInApex)
}
func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path {
@@ -1094,7 +1094,7 @@ var _ commonBootclasspathFragment = (*PrebuiltBootclasspathFragmentModule)(nil)
func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
for _, apex := range module.ApexProperties.Apex_available {
if isProfileProviderApex(ctx, apex) {
- return []string{profileInstallPathInApex}
+ return []string{ProfileInstallPathInApex}
}
}
return nil
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 5a19945b4..e158ed362 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -21,6 +21,7 @@ import (
"android/soong/android"
"android/soong/dexpreopt"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -224,8 +225,9 @@ var artApexNames = []string{
}
var (
- dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"}
- dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments")
+ dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"}
+ dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments")
+ apexContributionsMetadataDepTag = dependencyTag{name: "all_apex_contributions"}
)
func init() {
@@ -502,6 +504,11 @@ type dexpreoptBootJars struct {
dexpreoptConfigForMake android.WritablePath
}
+func (dbj *dexpreoptBootJars) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Create a dependency on all_apex_contributions to determine the selected mainline module
+ ctx.AddDependency(ctx.Module(), apexContributionsMetadataDepTag, "all_apex_contributions")
+}
+
func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) {
if _, ok := ctx.Module().(*dexpreoptBootJars); !ok {
return
@@ -520,6 +527,14 @@ func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) {
}
// For accessing the boot jars.
addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJarDepTag)
+ // Create a dependency on the apex selected using RELEASE_APEX_CONTRIBUTIONS_*
+ // TODO: b/308174306 - Remove the direct depedendency edge to the java_library (source/prebuilt) once all mainline modules
+ // have been flagged using RELEASE_APEX_CONTRIBUTIONS_*
+ apexes := []string{}
+ for i := 0; i < config.modules.Len(); i++ {
+ apexes = append(apexes, config.modules.Apex(i))
+ }
+ addDependenciesOntoSelectedBootImageApexes(ctx, android.FirstUniqueStrings(apexes)...)
}
if ctx.OtherModuleExists("platform-bootclasspath") {
@@ -532,6 +547,28 @@ func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) {
}
}
+// Create a dependency from dex_bootjars to the specific apexes selected using all_apex_contributions
+// This dependency will be used to get the path to the deapexed dex boot jars and profile (via a provider)
+func addDependenciesOntoSelectedBootImageApexes(ctx android.BottomUpMutatorContext, apexes ...string) {
+ psi := android.PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDepsWithTag(apexContributionsMetadataDepTag, func(am android.Module) {
+ if ctx.OtherModuleHasProvider(am, android.PrebuiltSelectionInfoProvider) {
+ psi = ctx.OtherModuleProvider(am, android.PrebuiltSelectionInfoProvider).(android.PrebuiltSelectionInfoMap)
+ }
+ })
+ for _, apex := range apexes {
+ for _, selected := range psi.GetSelectedModulesForApiDomain(apex) {
+ // We need to add a dep on only the apex listed in `contents` of the selected apex_contributions module
+ // This is not available in a structured format in `apex_contributions`, so this hack adds a dep on all `contents`
+ // (some modules like art.module.public.api do not have an apex variation since it is a pure stub module that does not get installed)
+ apexVariationOfSelected := append(ctx.Target().Variations(), blueprint.Variation{Mutator: "apex", Variation: apex})
+ if ctx.OtherModuleDependencyVariantExists(apexVariationOfSelected, selected) {
+ ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, selected)
+ }
+ }
+ }
+}
+
func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module {
return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
fragments := make(map[string]android.Module)
@@ -823,6 +860,27 @@ type bootImageVariantOutputs struct {
config *bootImageVariant
}
+// Returns the profile file for an apex
+// This information can come from two mechanisms
+// 1. New: Direct deps to _selected_ apexes. The apexes return a BootclasspathFragmentApexContentInfo
+// 2. Legacy: An edge to bootclasspath_fragment module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
+// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
+func getProfilePathForApex(ctx android.ModuleContext, apexName string, apexNameToBcpInfoMap map[string]android.ApexExportsInfo) android.Path {
+ if info, exists := apexNameToBcpInfoMap[apexName]; exists {
+ return info.ProfilePathOnHost
+ }
+ // TODO: b/308174306 - Remove the legacy mechanism
+ fragment := getBootclasspathFragmentByApex(ctx, apexName)
+ if fragment == nil {
+ ctx.ModuleErrorf("Boot image config imports profile from '%[2]s', but a "+
+ "bootclasspath_fragment for APEX '%[2]s' doesn't exist or is not added as a "+
+ "dependency of dex_bootjars",
+ apexName)
+ return nil
+ }
+ return fragment.(commonBootclasspathFragment).getProfilePath()
+}
+
// Generate boot image build rules for a specific target.
func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) bootImageVariantOutputs {
@@ -865,6 +923,13 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
+ apexNameToBcpInfoMap := map[string]android.ApexExportsInfo{}
+ ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(am android.Module) {
+ if info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider); exists {
+ apexNameToBcpInfoMap[info.ApexName] = info
+ }
+ })
+
cmd.Tool(globalSoong.Dex2oat).
Flag("--avoid-storing-invocation").
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
@@ -877,16 +942,7 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
}
for _, apex := range image.profileImports {
- fragment := getBootclasspathFragmentByApex(ctx, apex)
- if fragment == nil {
- ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but a "+
- "bootclasspath_fragment for APEX '%[2]s' doesn't exist or is not added as a "+
- "dependency of dex_bootjars",
- image.name,
- apex)
- return bootImageVariantOutputs{}
- }
- importedProfile := fragment.(commonBootclasspathFragment).getProfilePath()
+ importedProfile := getProfilePathForApex(ctx, apex, apexNameToBcpInfoMap)
if importedProfile == nil {
ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+
"doesn't provide a profile",
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 2bd696c3d..254b2c1b0 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -45,7 +45,7 @@ var (
frameworkBootImageName = "boot"
mainlineBootImageName = "mainline"
bootImageStem = "boot"
- profileInstallPathInApex = "etc/boot-image.prof"
+ ProfileInstallPathInApex = "etc/boot-image.prof"
)
// getImageNames returns an ordered list of image names. The order doesn't matter but needs to be
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 0965fc2c7..63419d6b1 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -950,6 +950,7 @@ func TestJavaSdkLibraryImport_WithSource(t *testing.T) {
})
CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
+ `all_apex_contributions`,
`prebuilt_sdklib.stubs`,
`sdklib.impl`,
// This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the
@@ -1022,6 +1023,7 @@ func testJavaSdkLibraryImport_Preferred(t *testing.T, prefer string, preparer an
})
CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
+ `all_apex_contributions`,
`dex2oatd`,
`prebuilt_sdklib.stubs`,
`prebuilt_sdklib.stubs.source`,
@@ -1085,9 +1087,6 @@ func TestSdkLibraryImport_MetadataModuleSupersedesPreferred(t *testing.T) {
"prebuilt_sdklib.source_preferred_using_legacy_flags",
],
}
- all_apex_contributions {
- name: "all_apex_contributions",
- }
java_sdk_library {
name: "sdklib.prebuilt_preferred_using_legacy_flags",
srcs: ["a.java"],
@@ -1169,9 +1168,6 @@ func TestSdkLibraryImport_MetadataModuleSupersedesPreferred(t *testing.T) {
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib.source_preferred_using_legacy_flags", "sdklib.prebuilt_preferred_using_legacy_flags"),
- android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- android.RegisterApexContributionsBuildComponents(ctx)
- }),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.BuildFlags = map[string]string{
"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
diff --git a/java/testing.go b/java/testing.go
index d55cffc40..5959c49e4 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -383,6 +383,7 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
RegisterSystemModulesBuildComponents(ctx)
registerSystemserverClasspathBuildComponents(ctx)
registerLintBuildComponents(ctx)
+ android.RegisterApexContributionsBuildComponents(ctx)
}
// gatherRequiredDepsForTest gathers the module definitions used by
@@ -570,6 +571,11 @@ func gatherRequiredDepsForTest() string {
}
`
+ bp += `
+ all_apex_contributions {
+ name: "all_apex_contributions",
+ }
+`
return bp
}