Merge "Align boot jar exclusion with apex_contributions" into main

This commit is contained in:
Spandan Das
2024-05-16 23:57:13 +00:00
committed by Gerrit Code Review
3 changed files with 166 additions and 2 deletions

View File

@@ -795,3 +795,127 @@ func TestNonBootJarInFragment(t *testing.T) {
} }
`) `)
} }
// Source and prebuilt apex provide different set of boot jars
func TestNonBootJarMissingInPrebuiltFragment(t *testing.T) {
bp := `
apex {
name: "myapex",
key: "myapex.key",
bootclasspath_fragments: ["apex-fragment"],
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
java_library {
name: "foo",
srcs: ["b.java"],
installable: true,
apex_available: ["myapex"],
permitted_packages: ["foo"],
}
java_library {
name: "bar",
srcs: ["b.java"],
installable: true,
apex_available: ["myapex"],
permitted_packages: ["bar"],
}
bootclasspath_fragment {
name: "apex-fragment",
contents: ["foo", "bar"],
apex_available:[ "myapex" ],
hidden_api: {
split_packages: ["*"],
},
}
prebuilt_apex {
name: "com.google.android.myapex", // mainline prebuilt selection logic in soong relies on the naming convention com.google.android
apex_name: "myapex",
source_apex_name: "myapex",
src: "myapex.apex",
exported_bootclasspath_fragments: ["apex-fragment"],
}
java_import {
name: "foo",
jars: ["foo.jar"],
apex_available: ["myapex"],
permitted_packages: ["foo"],
}
prebuilt_bootclasspath_fragment {
name: "apex-fragment",
contents: ["foo"], // Unlike the source fragment, this is missing bar
apex_available:[ "myapex" ],
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_contributions {
name: "my_apex_contributions",
api_domain: "myapex",
contents: [%v],
}
`
testCases := []struct {
desc string
configuredBootJars []string
apexContributionContents string
errorExpected bool
}{
{
desc: "Source apex is selected, and APEX_BOOT_JARS is correctly configured for source apex builds",
configuredBootJars: []string{"myapex:foo", "myapex:bar"},
},
{
desc: "Source apex is selected, and APEX_BOOT_JARS is missing bar",
configuredBootJars: []string{"myapex:foo"},
errorExpected: true,
},
{
desc: "Prebuilt apex is selected, and APEX_BOOT_JARS is correctly configured for prebuilt apex build",
configuredBootJars: []string{"myapex:foo"},
apexContributionContents: `"prebuilt_com.google.android.myapex"`,
},
{
desc: "Prebuilt apex is selected, and APEX_BOOT_JARS is missing foo",
configuredBootJars: []string{"myapex:bar"},
apexContributionContents: `"prebuilt_com.google.android.myapex"`,
errorExpected: true,
},
}
for _, tc := range testCases {
fixture := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
PrepareForTestWithApexBuildComponents,
prepareForTestWithMyapex,
java.FixtureConfigureApexBootJars(tc.configuredBootJars...),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.BuildFlags = map[string]string{
"RELEASE_APEX_CONTRIBUTIONS_ART": "my_apex_contributions",
}
}),
)
if tc.errorExpected {
fixture = fixture.ExtendWithErrorHandler(
android.FixtureExpectsAtLeastOneErrorMatchingPattern(`in contents.*must also be declared in PRODUCT_APEX_BOOT_JARS`),
)
}
fixture.RunTestWithBp(t, fmt.Sprintf(bp, tc.apexContributionContents))
}
}

View File

@@ -835,7 +835,21 @@ func (p *prebuiltCommon) providePrebuiltInfo(ctx android.ModuleContext) {
android.SetProvider(ctx, android.PrebuiltInfoProvider, info) android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
} }
// Uses an object provided by its deps to validate that the contents of bcpf have been added to the global
// PRODUCT_APEX_BOOT_JARS
// This validation will only run on the apex which is active for this product/release_config
func validateApexClasspathFragments(ctx android.ModuleContext) {
ctx.VisitDirectDeps(func(m android.Module) {
if info, exists := android.OtherModuleProvider(ctx, m, java.ClasspathFragmentValidationInfoProvider); exists {
ctx.ModuleErrorf("%s in contents of %s must also be declared in PRODUCT_APEX_BOOT_JARS", info.UnknownJars, info.ClasspathFragmentModuleName)
}
})
}
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Validate contents of classpath fragments
validateApexClasspathFragments(ctx)
p.apexKeysPath = writeApexKeys(ctx, p) p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity. // TODO(jungjw): Check the key validity.
p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path() p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path()
@@ -1059,6 +1073,9 @@ func (a *ApexSet) ApexInfoMutator(mctx android.TopDownMutatorContext) {
} }
func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Validate contents of classpath fragments
validateApexClasspathFragments(ctx)
a.apexKeysPath = writeApexKeys(ctx, a) a.apexKeysPath = writeApexKeys(ctx, a)
a.installFilename = a.InstallFilename() a.installFilename = a.InstallFilename()
if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) { if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) {

View File

@@ -590,13 +590,36 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext)
// So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS. // So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS.
// TODO(b/202896428): Add better way to handle this. // TODO(b/202896428): Add better way to handle this.
_, unknown = android.RemoveFromList("android.car-module", unknown) _, unknown = android.RemoveFromList("android.car-module", unknown)
if isActiveModule(ctx, ctx.Module()) && len(unknown) > 0 { if isApexVariant(ctx) && len(unknown) > 0 {
ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown) if android.IsModulePrebuilt(ctx.Module()) {
// prebuilt bcpf. the validation of this will be done at the top-level apex
providerClasspathFragmentValidationInfoProvider(ctx, unknown)
} else if !disableSourceApexVariant(ctx) {
// source bcpf, and prebuilt apex are not selected.
ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
}
} }
} }
return jars return jars
} }
var ClasspathFragmentValidationInfoProvider = blueprint.NewProvider[ClasspathFragmentValidationInfo]()
type ClasspathFragmentValidationInfo struct {
ClasspathFragmentModuleName string
UnknownJars []string
}
// Set a provider with the list of jars that have not been added to PRODUCT_APEX_BOOT_JARS
// The validation will be done in the ctx of the top-level _selected_ apex
func providerClasspathFragmentValidationInfoProvider(ctx android.ModuleContext, unknown []string) {
info := ClasspathFragmentValidationInfo{
ClasspathFragmentModuleName: ctx.ModuleName(),
UnknownJars: unknown,
}
android.SetProvider(ctx, ClasspathFragmentValidationInfoProvider, info)
}
// generateHiddenAPIBuildActions generates all the hidden API related build rules. // generateHiddenAPIBuildActions generates all the hidden API related build rules.
func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput { func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput {