Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 744a2a6b authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

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

parents 4593e41b 3576e769
Loading
Loading
Loading
Loading
+6 −17
Original line number Diff line number Diff line
@@ -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
+60 −6
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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",
		}
+185 −23
Original line number Diff line number Diff line
@@ -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)
	}
}
+5 −5
Original line number Diff line number Diff line
@@ -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, ""))
	})
}
Loading