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

Commit 42e1fc8d authored by Spandan Das's avatar Spandan Das Committed by Gerrit Code Review
Browse files

Merge "Align boot jar exclusion with apex_contributions" into main

parents aac48152 3d0d31a8
Loading
Loading
Loading
Loading
+124 −0
Original line number Diff line number Diff line
@@ -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))
	}
}
+17 −0
Original line number Diff line number Diff line
@@ -835,7 +835,21 @@ func (p *prebuiltCommon) providePrebuiltInfo(ctx android.ModuleContext) {
	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) {
	// Validate contents of classpath fragments
	validateApexClasspathFragments(ctx)

	p.apexKeysPath = writeApexKeys(ctx, p)
	// TODO(jungjw): Check the key validity.
	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) {
	// Validate contents of classpath fragments
	validateApexClasspathFragments(ctx)

	a.apexKeysPath = writeApexKeys(ctx, a)
	a.installFilename = a.InstallFilename()
	if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) {
+25 −2
Original line number Diff line number Diff line
@@ -590,13 +590,36 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext)
		// So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS.
		// TODO(b/202896428): Add better way to handle this.
		_, unknown = android.RemoveFromList("android.car-module", unknown)
		if isActiveModule(ctx, ctx.Module()) && len(unknown) > 0 {
		if isApexVariant(ctx) && len(unknown) > 0 {
			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
}

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.
func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput {