Merge "Handle installation rules for co-existing prebuilts" into main

This commit is contained in:
Treehugger Robot
2024-01-11 18:46:58 +00:00
committed by Gerrit Code Review
9 changed files with 286 additions and 74 deletions

View File

@@ -102,7 +102,6 @@ func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleCo
ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name())
}
pi := &PrebuiltSelectionInfo{
baseModuleName: RemoveOptionalPrebuiltPrefix(content),
selectedModuleName: content,
metadataModuleName: m.Name(),
apiDomain: m.ApiDomain(),
@@ -126,7 +125,8 @@ func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleCo
// This provider will be used in prebuilt_select mutator to redirect deps
var PrebuiltSelectionInfoProvider = blueprint.NewMutatorProvider[PrebuiltSelectionInfoMap]("prebuilt_select")
// Map of baseModuleName to the selected source or prebuilt
// Map of selected module names to a metadata object
// The metadata contains information about the api_domain of the selected module
type PrebuiltSelectionInfoMap map[string]PrebuiltSelectionInfo
// Add a new entry to the map with some validations
@@ -134,18 +134,10 @@ func (pm *PrebuiltSelectionInfoMap) Add(ctx BaseModuleContext, p *PrebuiltSelect
if p == nil {
return
}
// Do not allow dups. If the base module (without the prebuilt_) has been added before, raise an exception.
if old, exists := (*pm)[p.baseModuleName]; exists {
ctx.ModuleErrorf("Cannot use Soong module: %s from apex_contributions: %s because it has been added previously as: %s from apex_contributions: %s\n",
p.selectedModuleName, p.metadataModuleName, old.selectedModuleName, old.metadataModuleName,
)
}
(*pm)[p.baseModuleName] = *p
(*pm)[p.selectedModuleName] = *p
}
type PrebuiltSelectionInfo struct {
// e.g. libc
baseModuleName string
// e.g. (libc|prebuilt_libc)
selectedModuleName string
// Name of the apex_contributions module
@@ -156,12 +148,9 @@ type PrebuiltSelectionInfo struct {
// Returns true if `name` is explicitly requested using one of the selected
// apex_contributions metadata modules.
func (p *PrebuiltSelectionInfoMap) IsSelected(baseModuleName, name string) bool {
if i, exists := (*p)[baseModuleName]; exists {
return i.selectedModuleName == name
} else {
return false
}
func (p *PrebuiltSelectionInfoMap) IsSelected(name string) bool {
_, exists := (*p)[name]
return exists
}
// Return the list of soong modules selected for this api domain

View File

@@ -391,12 +391,19 @@ func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel()
}
// Returns the name of the source module corresponding to a prebuilt module
// For source modules, it returns its own name
type baseModuleName interface {
BaseModuleName() string
}
// PrebuiltRenameMutator ensures that there always is a module with an
// undecorated name.
func PrebuiltRenameMutator(ctx BottomUpMutatorContext) {
m := ctx.Module()
if p := GetEmbeddedPrebuilt(m); p != nil {
name := m.base().BaseModuleName()
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
if !ctx.OtherModuleExists(name) {
ctx.Rename(name)
p.properties.PrebuiltRenamedToSource = true
@@ -413,7 +420,8 @@ func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) {
// If this module is a prebuilt, is enabled and has not been renamed to source then add a
// dependency onto the source if it is present.
if p := GetEmbeddedPrebuilt(m); p != nil && m.Enabled() && !p.properties.PrebuiltRenamedToSource {
name := m.base().BaseModuleName()
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
if ctx.OtherModuleReverseDependencyVariantExists(name) {
ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name)
p.properties.SourceExists = true
@@ -466,6 +474,13 @@ func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) {
})
} else if s, ok := ctx.Module().(Module); ok {
// Use `all_apex_contributions` for source vs prebuilt selection.
psi := PrebuiltSelectionInfoMap{}
ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(am Module) {
// The value of psi gets overwritten with the provider from the last visited prebuilt.
// But all prebuilts have the same value of the provider, so this should be idempontent.
psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
})
ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) {
p := GetEmbeddedPrebuilt(prebuiltModule)
if p.usePrebuilt(ctx, s, prebuiltModule) {
@@ -475,7 +490,18 @@ func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) {
s.ReplacedByPrebuilt()
}
})
// If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family
// Add source
allModules := []Module{s}
// Add each prebuilt
ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) {
allModules = append(allModules, prebuiltModule)
})
hideUnflaggedModules(ctx, psi, allModules)
}
// If this is `all_apex_contributions`, set a provider containing
// metadata about source vs prebuilts selection
if am, ok := m.(*allApexContributions); ok {
@@ -483,13 +509,41 @@ func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) {
}
}
// If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family
func hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoMap, allModulesInFamily []Module) {
var selectedModuleInFamily Module
// query all_apex_contributions to see if any module in this family has been selected
for _, moduleInFamily := range allModulesInFamily {
// validate that are no duplicates
if psi.IsSelected(moduleInFamily.Name()) {
if selectedModuleInFamily == nil {
// Store this so we can validate that there are no duplicates
selectedModuleInFamily = moduleInFamily
} else {
// There are duplicate modules from the same mainline module family
ctx.ModuleErrorf("Found duplicate variations of the same module in apex_contributions: %s and %s. Please remove one of these.\n", selectedModuleInFamily.Name(), moduleInFamily.Name())
}
}
}
// If a module has been selected, hide all other modules
if selectedModuleInFamily != nil {
for _, moduleInFamily := range allModulesInFamily {
if moduleInFamily.Name() != selectedModuleInFamily.Name() {
moduleInFamily.HideFromMake()
}
}
}
}
// PrebuiltPostDepsMutator replaces dependencies on the source module with dependencies on the
// prebuilt when both modules exist and the prebuilt should be used. When the prebuilt should not
// be used, disable installing it.
func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
m := ctx.Module()
if p := GetEmbeddedPrebuilt(m); p != nil {
name := m.base().BaseModuleName()
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
if p.properties.UsePrebuilt {
if p.properties.SourceExists {
ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
@@ -533,13 +587,13 @@ func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool {
// Stub library created by java_sdk_library_import
if p := GetEmbeddedPrebuilt(m); p != nil {
return psi.IsSelected(sln, PrebuiltNameFromSource(sln))
return psi.IsSelected(PrebuiltNameFromSource(sln))
}
// Stub library created by java_sdk_library
return psi.IsSelected(sln, sln)
return psi.IsSelected(sln)
}
return psi.IsSelected(m.base().BaseModuleName(), m.Name())
return psi.IsSelected(m.Name())
}
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt

View File

@@ -741,7 +741,7 @@ func TestPrebuiltErrorCannotListBothSourceAndPrebuiltInContributions(t *testing.
}
}),
)
testPrebuiltErrorWithFixture(t, `Cannot use Soong module: prebuilt_foo from apex_contributions: my_apex_contributions because it has been added previously as: foo from apex_contributions: my_apex_contributions`, `
testPrebuiltErrorWithFixture(t, `Found duplicate variations of the same module in apex_contributions: foo and prebuilt_foo. Please remove one of these`, `
source {
name: "foo",
}

View File

@@ -5374,7 +5374,7 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
dexJarBuildPath := p.DexJarBuildPath(moduleErrorfTestCtx{}).PathOrNil()
stem := android.RemoveOptionalPrebuiltPrefix(name)
android.AssertStringEquals(t, "DexJarBuildPath should be apex-related path.",
".intermediates/myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
".intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
android.NormalizePathForTesting(dexJarBuildPath))
}
@@ -5428,8 +5428,8 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
deapexerName := deapexerModuleName("myapex")
android.AssertStringEquals(t, "APEX module name from deapexer name", "myapex", apexModuleName(deapexerName))
deapexerName := deapexerModuleName("prebuilt_myapex")
android.AssertStringEquals(t, "APEX module name from deapexer name", "prebuilt_myapex", apexModuleName(deapexerName))
// Make sure that the deapexer has the correct input APEX.
deapexer := ctx.ModuleForTests(deapexerName, "android_common")
@@ -5652,8 +5652,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
@@ -5730,8 +5730,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
@@ -5744,7 +5744,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
myApex := ctx.ModuleForTests("myapex", "android_common_myapex").Module()
overrideNames := []string{
"",
"myapex",
"myjavalib.myapex",
"libfoo.myapex",
"libbar.myapex",
@@ -5919,8 +5919,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
@@ -6116,8 +6116,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
@@ -8320,9 +8320,9 @@ func TestAppSetBundlePrebuilt(t *testing.T) {
ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress)
// Check that the extractor produces the correct output file from the correct input file.
extractorOutput := "out/soong/.intermediates/myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks"
extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks"
m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
@@ -8347,10 +8347,10 @@ func TestApexSetApksModuleAssignment(t *testing.T) {
}
`)
m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
// Check that the extractor produces the correct apks file from the input module
extractorOutput := "out/soong/.intermediates/myapex.apex.extractor/android_common/extracted/myapex.apks"
extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.apks"
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
@@ -8420,7 +8420,7 @@ func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
PrepareForTestWithApexBuildComponents,
).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
"Multiple installable prebuilt APEXes provide ambiguous deapexers: com.android.art and com.mycompany.android.art"))
"Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art"))
bpBase := `
apex_set {
@@ -8548,7 +8548,7 @@ func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
module := result.Module("libfoo", "android_common_com.android.myapex")
usesLibraryDep := module.(java.UsesLibraryDependency)
android.AssertPathRelativeToTopEquals(t, "dex jar path",
"out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
"out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
usesLibraryDep.DexJarBuildPath(errCtx).Path())
})
@@ -8571,7 +8571,7 @@ func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
module := result.Module("libfoo", "android_common_com.android.myapex")
usesLibraryDep := module.(java.UsesLibraryDependency)
android.AssertPathRelativeToTopEquals(t, "dex jar path",
"out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
"out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
usesLibraryDep.DexJarBuildPath(errCtx).Path())
})
@@ -9144,7 +9144,7 @@ func TestApexSet(t *testing.T) {
}),
)
m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
// Check extract_apks tool parameters.
extractedApex := m.Output("extracted/myapex.apks")
@@ -9185,7 +9185,7 @@ func TestApexSet_NativeBridge(t *testing.T) {
}),
)
m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
// Check extract_apks tool parameters. No native bridge arch expected
extractedApex := m.Output("extracted/myapex.apks")
@@ -11570,12 +11570,12 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
{
desc: "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.contributions",
expectedBootJar: "out/soong/.intermediates/com.android.foo.deapexer/android_common/deapexer/javalib/framework-foo.jar",
expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.deapexer/android_common/deapexer/javalib/framework-foo.jar",
},
{
desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.v2.contributions",
expectedBootJar: "out/soong/.intermediates/com.android.foo.v2.deapexer/android_common/deapexer/javalib/framework-foo.jar",
expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.v2.deapexer/android_common/deapexer/javalib/framework-foo.jar",
},
}
@@ -11602,3 +11602,165 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
checkBootJarsForMonolithicHiddenapi(t, ctx, tc.expectedBootJar)
}
}
// Test that product packaging installs the selected mainline module (either source or a specific prebuilt)
// RELEASE_APEX_CONTIRBUTIONS_* build flags will be used to select the correct prebuilt for a specific release config
func TestInstallationRulesForMultipleApexPrebuilts(t *testing.T) {
// check that the LOCAL_MODULE in the generated mk file matches the name used in PRODUCT_PACKAGES
// Since the name used in PRODUCT_PACKAGES does not contain prebuilt_ prefix, LOCAL_MODULE should not contain any prefix either
checkLocalModuleName := func(t *testing.T, ctx *android.TestContext, soongApexModuleName string, expectedLocalModuleName string) {
// Variations are created based on apex_name
entries := android.AndroidMkEntriesForTest(t, ctx, ctx.ModuleForTests(soongApexModuleName, "android_common_com.android.foo").Module())
android.AssertStringEquals(t, "LOCAL_MODULE of the prebuilt apex must match the name listed in PRODUCT_PACKAGES", expectedLocalModuleName, entries[0].EntryMap["LOCAL_MODULE"][0])
}
// for a mainline module family, check that only the flagged soong module is visible to make
checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleName string, hiddenModuleNames []string) {
variation := func(moduleName string) string {
ret := "android_common_com.android.foo"
if moduleName == "com.google.android.foo" {
ret = "android_common_com.google.android.foo_com.android.foo"
}
return ret
}
visibleModule := ctx.ModuleForTests(visibleModuleName, variation(visibleModuleName)).Module()
android.AssertBoolEquals(t, "Apex "+visibleModuleName+" selected using apex_contributions should be visible to make", false, visibleModule.IsHideFromMake())
for _, hiddenModuleName := range hiddenModuleNames {
hiddenModule := ctx.ModuleForTests(hiddenModuleName, variation(hiddenModuleName)).Module()
android.AssertBoolEquals(t, "Apex "+hiddenModuleName+" not selected using apex_contributions should be hidden from make", true, hiddenModule.IsHideFromMake())
}
}
bp := `
apex_key {
name: "com.android.foo.key",
public_key: "com.android.foo.avbpubkey",
private_key: "com.android.foo.pem",
}
// AOSP source apex
apex {
name: "com.android.foo",
key: "com.android.foo.key",
updatable: false,
}
// Google source apex
override_apex {
name: "com.google.android.foo",
base: "com.android.foo",
key: "com.android.foo.key",
}
// Prebuilt Google APEX.
prebuilt_apex {
name: "com.google.android.foo",
apex_name: "com.android.foo",
src: "com.android.foo-arm.apex",
prefer: true, // prefer is set to true on both the prebuilts to induce an error if flagging is not present
}
// Another Prebuilt Google APEX
prebuilt_apex {
name: "com.google.android.foo.v2",
apex_name: "com.android.foo",
source_apex_name: "com.google.android.foo", // source_apex_name becomes LOCAL_MODULE in the generated mk file
src: "com.android.foo-arm.apex",
prefer: true, // prefer is set to true on both the prebuilts to induce an error if flagging is not present
}
// APEX contribution modules
apex_contributions {
name: "foo.source.contributions",
api_domain: "com.android.foo",
contents: ["com.google.android.foo"],
}
apex_contributions {
name: "foo.prebuilt.contributions",
api_domain: "com.android.foo",
contents: ["prebuilt_com.google.android.foo"],
}
apex_contributions {
name: "foo.prebuilt.v2.contributions",
api_domain: "com.android.foo",
contents: ["prebuilt_com.google.android.foo.v2"],
}
// This is an incompatible module because it selects multiple versions of the same mainline module
apex_contributions {
name: "foo.prebuilt.duplicate.contributions",
api_domain: "com.android.foo",
contents: [
"prebuilt_com.google.android.foo",
"prebuilt_com.google.android.foo.v2",
],
}
`
testCases := []struct {
desc string
selectedApexContributions string
expectedVisibleModuleName string
expectedHiddenModuleNames []string
expectedError string
}{
{
desc: "Source apex is selected, prebuilts should be hidden from make",
selectedApexContributions: "foo.source.contributions",
expectedVisibleModuleName: "com.google.android.foo",
expectedHiddenModuleNames: []string{"prebuilt_com.google.android.foo", "prebuilt_com.google.android.foo.v2"},
},
{
desc: "Prebuilt apex prebuilt_com.android.foo is selected, source and the other prebuilt should be hidden from make",
selectedApexContributions: "foo.prebuilt.contributions",
expectedVisibleModuleName: "prebuilt_com.google.android.foo",
expectedHiddenModuleNames: []string{"com.google.android.foo", "prebuilt_com.google.android.foo.v2"},
},
{
desc: "Prebuilt apex prebuilt_com.android.fooi.v2 is selected, source and the other prebuilt should be hidden from make",
selectedApexContributions: "foo.prebuilt.v2.contributions",
expectedVisibleModuleName: "prebuilt_com.google.android.foo.v2",
expectedHiddenModuleNames: []string{"com.google.android.foo", "prebuilt_com.google.android.foo"},
},
{
desc: "Multiple versions of a prebuilt apex is selected in the same release config",
selectedApexContributions: "foo.prebuilt.duplicate.contributions",
expectedError: "Found duplicate variations of the same module in apex_contributions: prebuilt_com.google.android.foo and prebuilt_com.google.android.foo.v2",
},
}
for _, tc := range testCases {
preparer := android.GroupFixturePreparers(
android.FixtureMergeMockFs(map[string][]byte{
"system/sepolicy/apex/com.android.foo-file_contexts": nil,
}),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.BuildFlags = map[string]string{
"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": tc.selectedApexContributions,
}
}),
)
if tc.expectedError != "" {
preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError))
testApex(t, bp, preparer)
return
}
ctx := testApex(t, bp, preparer)
// Check that the LOCAL_MODULE of the two prebuilts is com.android.foo
// This ensures that product packaging can pick them for installation if it has been flagged by apex_contributions
checkLocalModuleName(t, ctx, "prebuilt_com.google.android.foo", "com.google.android.foo")
checkLocalModuleName(t, ctx, "prebuilt_com.google.android.foo.v2", "com.google.android.foo")
// Check that
// 1. The contents of the selected apex_contributions are visible to make
// 2. The rest of the apexes in the mainline module family (source or other prebuilt) is hidden from make
checkHideFromMake(t, ctx, tc.expectedVisibleModuleName, tc.expectedHiddenModuleNames)
}
}

View File

@@ -374,7 +374,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
ensureExactDeapexedContents(t, result.TestContext, "com.android.art", "android_common", []string{
ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common", []string{
"etc/boot-image.prof",
"javalib/bar.jar",
"javalib/foo.jar",
@@ -529,16 +529,16 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
result := preparers.RunTestWithBp(t, fmt.Sprintf(bp, "enabled: false,"))
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
`com.android.art.apex.selector`,
`com.android.art.deapexer`,
`dex2oatd`,
`prebuilt_art-bootclasspath-fragment`,
`prebuilt_com.android.art.apex.selector`,
`prebuilt_com.android.art.deapexer`,
})
java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_com.android.art", []string{
`com.android.art.deapexer`,
`dex2oatd`,
`prebuilt_bar`,
`prebuilt_com.android.art.deapexer`,
`prebuilt_foo`,
})
@@ -548,7 +548,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
t.Run("enabled alternative APEX", func(t *testing.T) {
preparers.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
"Multiple installable prebuilt APEXes provide ambiguous deapexers: com.android.art and com.mycompany.android.art")).
"Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art")).
RunTestWithBp(t, fmt.Sprintf(bp, ""))
})
}

View File

@@ -199,7 +199,7 @@ func TestDexpreoptBootJarsWithPrebuiltArtApex(t *testing.T) {
"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
"out/soong/.intermediates/com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
"out/soong/.intermediates/prebuilt_com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
}
@@ -382,12 +382,12 @@ func TestDexpreoptProfileWithMultiplePrebuiltArtApexes(t *testing.T) {
{
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",
expectedProfile: "out/soong/.intermediates/prebuilt_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",
expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art.v2.deapexer/android_common/deapexer/etc/boot-image.prof",
},
}
for _, tc := range testCases {

View File

@@ -87,6 +87,12 @@ type PrebuiltCommonProperties struct {
// device (/apex/<apex_name>). If unspecified, follows the name property.
Apex_name *string
// Name of the source APEX that gets shadowed by this prebuilt
// e.g. com.mycompany.android.myapex
// If unspecified, follows the naming convention that the source apex of
// the prebuilt is Name() without "prebuilt_" prefix
Source_apex_name *string
ForceDisable bool `blueprint:"mutated"`
// whether the extracted apex file is installable.
@@ -126,7 +132,11 @@ func (p *prebuiltCommon) initPrebuiltCommon(module android.Module, properties *P
}
func (p *prebuiltCommon) ApexVariationName() string {
return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.ModuleBase.BaseModuleName())
return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.BaseModuleName())
}
func (p *prebuiltCommon) BaseModuleName() string {
return proptools.StringDefault(p.prebuiltCommonProperties.Source_apex_name, p.ModuleBase.BaseModuleName())
}
func (p *prebuiltCommon) Prebuilt() *android.Prebuilt {
@@ -226,6 +236,7 @@ func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries {
OutputFile: android.OptionalPathForPath(p.outputApex),
Include: "$(BUILD_PREBUILT)",
Host_required: p.hostRequired,
OverrideName: p.BaseModuleName(),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_MODULE_PATH", p.installDir.String())
@@ -436,7 +447,7 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) {
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
InApexVariants: []string{apexVariationName},
InApexModules: []string{p.ModuleBase.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix.
InApexModules: []string{p.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix.
ApexContents: []*android.ApexContents{apexContents},
ForPrebuiltApex: true,
}
@@ -742,13 +753,11 @@ var _ prebuiltApexModuleCreator = (*Prebuilt)(nil)
// V V V
// selector <--- deapexer <--- exported java lib
func (p *Prebuilt) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
baseModuleName := p.BaseModuleName()
apexSelectorModuleName := apexSelectorModuleName(baseModuleName)
apexSelectorModuleName := apexSelectorModuleName(p.Name())
createApexSelectorModule(ctx, apexSelectorModuleName, &p.properties.ApexFileProperties)
apexFileSource := ":" + apexSelectorModuleName
p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(baseModuleName), apexFileSource)
p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(p.Name()), apexFileSource)
// Add a source reference to retrieve the selected apex from the selector module.
p.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
@@ -762,7 +771,7 @@ func (p *prebuiltCommon) DepsMutator(ctx android.BottomUpMutatorContext) {
if p.hasExportedDeps() {
// Create a dependency from the prebuilt apex (prebuilt_apex/apex_set) to the internal deapexer module
// The deapexer will return a provider that will be bubbled up to the rdeps of apexes (e.g. dex_bootjars)
ctx.AddDependency(ctx.Module(), android.DeapexerTag, deapexerModuleName(p.BaseModuleName()))
ctx.AddDependency(ctx.Module(), android.DeapexerTag, deapexerModuleName(p.Name()))
}
}
@@ -1002,13 +1011,11 @@ var _ prebuiltApexModuleCreator = (*ApexSet)(nil)
// from those provided this creates an extractor module which extracts the appropriate .apex file
// from the zip file containing them.
func (a *ApexSet) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
baseModuleName := a.BaseModuleName()
apexExtractorModuleName := apexExtractorModuleName(baseModuleName)
apexExtractorModuleName := apexExtractorModuleName(a.Name())
createApexExtractorModule(ctx, apexExtractorModuleName, &a.properties.ApexExtractorProperties)
apexFileSource := ":" + apexExtractorModuleName
a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(baseModuleName), apexFileSource)
a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(a.Name()), apexFileSource)
// After passing the arch specific src properties to the creating the apex selector module
a.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)

View File

@@ -273,18 +273,18 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
`dex2oatd`,
`myapex.apex.selector`,
`myapex.deapexer`,
`prebuilt_myapex.apex.selector`,
`prebuilt_myapex.deapexer`,
`prebuilt_mysystemserverclasspathfragment`,
})
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
`myapex.deapexer`,
`prebuilt_bar`,
`prebuilt_foo`,
`prebuilt_myapex.deapexer`,
})
ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{
ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
@@ -430,12 +430,12 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
ctx := result.TestContext
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
`myapex.deapexer`,
`prebuilt_bar`,
`prebuilt_foo`,
`prebuilt_myapex.deapexer`,
})
ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{
ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",

View File

@@ -206,8 +206,8 @@ java_import {
checkBootJarsPackageCheckRule(t, result,
append(
[]string{
"out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core1.jar",
"out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core2.jar",
"out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core1.jar",
"out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core2.jar",
"out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar",
},
java.ApexBootJarDexJarPaths...,