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

Commit 0b1c70ef authored by Ulya Trafimovich's avatar Ulya Trafimovich
Browse files

Don't add `uses_libs`/`optional_uses_libs` to the manifest_fixer.

These properties specify libraries that cannot be implicitly inferred by
Soong. If these properties are added to Android.bp, this can only be for
the reason that there is a <uses-library> tag in the manifest which is
unknown to the build system. Adding them to the manifest_fixer doesn't
make sense: if they are not in the manifest, they should be removed from
Android.bp as well.

Bug: 132357300
Test: $ lunch aosp_cf_x86_64_phone-userdebug && m && launch_cvd
      $ adb wait-for-device && adb root && adb logcat \
        | grep -E 'ClassLoaderContext [a-z ]+ mismatch'
        # empty grep output, no errors
Change-Id: Ic6eb5268a954ef3be7f06a181ec72af99000c547
parent 99d5a0f5
Loading
Loading
Loading
Loading
+29 −6
Original line number Diff line number Diff line
@@ -196,6 +196,10 @@ type ClassLoaderContext struct {
	// If the library is optional or required.
	Optional bool

	// If the library is implicitly infered by Soong (as opposed to explicitly added via `uses_libs`
	// or `optional_uses_libs`.
	Implicit bool

	// On-host build path to the library dex file (used in dex2oat argument --class-loader-context).
	Host android.Path

@@ -258,8 +262,9 @@ const UnknownInstallLibraryPath = "error"
const AnySdkVersion int = android.FutureApiLevelInt

// Add class loader context for the given library to the map entry for the given SDK version.
func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
	optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) error {
func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int,
	lib string, optional, implicit bool, hostPath, installPath android.Path,
	nestedClcMap ClassLoaderContextMap) error {

	// For prebuilts, library should have the same name as the source module.
	lib = android.RemoveOptionalPrebuiltPrefix(lib)
@@ -308,6 +313,7 @@ func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathCont
	clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
		Name:        lib,
		Optional:    optional,
		Implicit:    implicit,
		Host:        hostPath,
		Device:      devicePath,
		Subcontexts: subcontexts,
@@ -320,9 +326,10 @@ func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathCont
// about paths). For the subset of libraries that are used in dexpreopt, their build/install paths
// are validated later before CLC is used (in validateClassLoaderContext).
func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, sdkVer int,
	lib string, optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
	lib string, optional, implicit bool, hostPath, installPath android.Path,
	nestedClcMap ClassLoaderContextMap) {

	err := clcMap.addContext(ctx, sdkVer, lib, optional, hostPath, installPath, nestedClcMap)
	err := clcMap.addContext(ctx, sdkVer, lib, optional, implicit, hostPath, installPath, nestedClcMap)
	if err != nil {
		ctx.ModuleErrorf(err.Error())
	}
@@ -366,13 +373,15 @@ func (clcMap ClassLoaderContextMap) AddContextMap(otherClcMap ClassLoaderContext
// included). This is the list of libraries that should be in the <uses-library> tags in the
// manifest. Some of them may be present in the source manifest, others are added by manifest_fixer.
// Required and optional libraries are in separate lists.
func (clcMap ClassLoaderContextMap) UsesLibs() (required []string, optional []string) {
func (clcMap ClassLoaderContextMap) usesLibs(implicit bool) (required []string, optional []string) {
	if clcMap != nil {
		clcs := clcMap[AnySdkVersion]
		required = make([]string, 0, len(clcs))
		optional = make([]string, 0, len(clcs))
		for _, clc := range clcs {
			if clc.Optional {
			if implicit && !clc.Implicit {
				// Skip, this is an explicit library and we need only the implicit ones.
			} else if clc.Optional {
				optional = append(optional, clc.Name)
			} else {
				required = append(required, clc.Name)
@@ -382,6 +391,14 @@ func (clcMap ClassLoaderContextMap) UsesLibs() (required []string, optional []st
	return required, optional
}

func (clcMap ClassLoaderContextMap) UsesLibs() ([]string, []string) {
	return clcMap.usesLibs(false)
}

func (clcMap ClassLoaderContextMap) ImplicitUsesLibs() ([]string, []string) {
	return clcMap.usesLibs(true)
}

func (clcMap ClassLoaderContextMap) Dump() string {
	jsonCLC := toJsonClassLoaderContext(clcMap)
	bytes, err := json.MarshalIndent(jsonCLC, "", "  ")
@@ -524,6 +541,8 @@ func computeClassLoaderContextRec(clcs []*ClassLoaderContext) (string, string, a
// the same as Soong representation except that SDK versions and paths are represented with strings.
type jsonClassLoaderContext struct {
	Name        string
	Optional    bool
	Implicit    bool
	Host        string
	Device      string
	Subcontexts []*jsonClassLoaderContext
@@ -555,6 +574,8 @@ func fromJsonClassLoaderContextRec(ctx android.PathContext, jClcs []*jsonClassLo
	for _, clc := range jClcs {
		clcs = append(clcs, &ClassLoaderContext{
			Name:        clc.Name,
			Optional:    clc.Optional,
			Implicit:    clc.Implicit,
			Host:        constructPath(ctx, clc.Host),
			Device:      clc.Device,
			Subcontexts: fromJsonClassLoaderContextRec(ctx, clc.Subcontexts),
@@ -579,6 +600,8 @@ func toJsonClassLoaderContextRec(clcs []*ClassLoaderContext) []*jsonClassLoaderC
	for i, clc := range clcs {
		jClcs[i] = &jsonClassLoaderContext{
			Name:        clc.Name,
			Optional:    clc.Optional,
			Implicit:    clc.Implicit,
			Host:        clc.Host.String(),
			Device:      clc.Device,
			Subcontexts: toJsonClassLoaderContextRec(clc.Subcontexts),
+33 −28
Original line number Diff line number Diff line
@@ -50,33 +50,34 @@ func TestCLC(t *testing.T) {
	ctx := testContext()

	optional := false
	implicit := true

	m := make(ClassLoaderContextMap)

	m.AddContext(ctx, AnySdkVersion, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m.AddContext(ctx, AnySdkVersion, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
	m.AddContext(ctx, AnySdkVersion, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
	m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m.AddContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
	m.AddContext(ctx, AnySdkVersion, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)

	// Add some libraries with nested subcontexts.

	m1 := make(ClassLoaderContextMap)
	m1.AddContext(ctx, AnySdkVersion, "a1", optional, buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
	m1.AddContext(ctx, AnySdkVersion, "b1", optional, buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
	m1.AddContext(ctx, AnySdkVersion, "a1", optional, implicit, buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
	m1.AddContext(ctx, AnySdkVersion, "b1", optional, implicit, buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)

	m2 := make(ClassLoaderContextMap)
	m2.AddContext(ctx, AnySdkVersion, "a2", optional, buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
	m2.AddContext(ctx, AnySdkVersion, "b2", optional, buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
	m2.AddContext(ctx, AnySdkVersion, "c2", optional, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
	m2.AddContext(ctx, AnySdkVersion, "a2", optional, implicit, buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
	m2.AddContext(ctx, AnySdkVersion, "b2", optional, implicit, buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
	m2.AddContext(ctx, AnySdkVersion, "c2", optional, implicit, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)

	m3 := make(ClassLoaderContextMap)
	m3.AddContext(ctx, AnySdkVersion, "a3", optional, buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
	m3.AddContext(ctx, AnySdkVersion, "b3", optional, buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
	m3.AddContext(ctx, AnySdkVersion, "a3", optional, implicit, buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
	m3.AddContext(ctx, AnySdkVersion, "b3", optional, implicit, buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)

	m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
	m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
	// When the same library is both in conditional and unconditional context, it should be removed
	// from conditional context.
	m.AddContext(ctx, 42, "f", optional, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
	m.AddContext(ctx, AnySdkVersion, "f", optional, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
	m.AddContext(ctx, 42, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
	m.AddContext(ctx, AnySdkVersion, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)

	// Merge map with implicit root library that is among toplevel contexts => does nothing.
	m.AddContextMap(m1, "c")
@@ -85,12 +86,12 @@ func TestCLC(t *testing.T) {
	m.AddContextMap(m3, "m_g")

	// Compatibility libraries with unknown install paths get default paths.
	m.AddContext(ctx, 29, AndroidHidlManager, optional, buildPath(ctx, AndroidHidlManager), nil, nil)
	m.AddContext(ctx, 29, AndroidHidlBase, optional, buildPath(ctx, AndroidHidlBase), nil, nil)
	m.AddContext(ctx, 29, AndroidHidlManager, optional, implicit, buildPath(ctx, AndroidHidlManager), nil, nil)
	m.AddContext(ctx, 29, AndroidHidlBase, optional, implicit, buildPath(ctx, AndroidHidlBase), nil, nil)

	// Add "android.test.mock" to conditional CLC, observe that is gets removed because it is only
	// needed as a compatibility library if "android.test.runner" is in CLC as well.
	m.AddContext(ctx, 30, AndroidTestMock, optional, buildPath(ctx, AndroidTestMock), nil, nil)
	m.AddContext(ctx, 30, AndroidTestMock, optional, implicit, buildPath(ctx, AndroidTestMock), nil, nil)

	valid, validationError := validateClassLoaderContext(m)

@@ -164,11 +165,12 @@ func TestCLC(t *testing.T) {
func TestCLCJson(t *testing.T) {
	ctx := testContext()
	optional := false
	implicit := true
	m := make(ClassLoaderContextMap)
	m.AddContext(ctx, 28, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m.AddContext(ctx, 29, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
	m.AddContext(ctx, 30, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
	m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
	m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
	m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
	m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
	jsonCLC := toJsonClassLoaderContext(m)
	restored := fromJsonClassLoaderContext(ctx, jsonCLC)
	android.AssertIntEquals(t, "The size of the maps should be the same.", len(m), len(restored))
@@ -189,12 +191,13 @@ func TestCLCJson(t *testing.T) {
func testCLCUnknownPath(t *testing.T, whichPath string) {
	ctx := testContext()
	optional := false
	implicit := true

	m := make(ClassLoaderContextMap)
	if whichPath == "build" {
		m.AddContext(ctx, AnySdkVersion, "a", optional, nil, nil, nil)
		m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, nil, nil, nil)
	} else {
		m.AddContext(ctx, AnySdkVersion, "a", optional, buildPath(ctx, "a"), nil, nil)
		m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), nil, nil)
	}

	// The library should be added to <uses-library> tags by the manifest_fixer.
@@ -229,10 +232,11 @@ func TestCLCUnknownInstallPath(t *testing.T) {
func TestCLCNestedConditional(t *testing.T) {
	ctx := testContext()
	optional := false
	implicit := true
	m1 := make(ClassLoaderContextMap)
	m1.AddContext(ctx, 42, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m1.AddContext(ctx, 42, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m := make(ClassLoaderContextMap)
	err := m.addContext(ctx, AnySdkVersion, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
	err := m.addContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
	checkError(t, err, "nested class loader context shouldn't have conditional part")
}

@@ -241,11 +245,12 @@ func TestCLCNestedConditional(t *testing.T) {
func TestCLCSdkVersionOrder(t *testing.T) {
	ctx := testContext()
	optional := false
	implicit := true
	m := make(ClassLoaderContextMap)
	m.AddContext(ctx, 28, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m.AddContext(ctx, 29, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
	m.AddContext(ctx, 30, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
	m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
	m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
	m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
	m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)

	valid, validationError := validateClassLoaderContext(m)

+3 −1
Original line number Diff line number Diff line
@@ -71,7 +71,9 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
		args = append(args, "--use-embedded-dex")
	}

	requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs()
	// manifest_fixer should add only the implicit SDK libraries inferred by Soong, not those added
	// explicitly via `uses_libs`/`optional_uses_libs`.
	requiredUsesLibs, optionalUsesLibs := classLoaderContexts.ImplicitUsesLibs()
	for _, usesLib := range requiredUsesLibs {
		args = append(args, "--uses-library", usesLib)
	}
+19 −8
Original line number Diff line number Diff line
@@ -1224,17 +1224,28 @@ func (u *usesLibrary) addLib(lib string, optional bool) {

func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs bool) {
	if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() {
		ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs...)
		ctx.AddVariationDependencies(nil, usesLibOptTag, u.presentOptionalUsesLibs(ctx)...)
		reqTag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false, false)
		ctx.AddVariationDependencies(nil, reqTag, u.usesLibraryProperties.Uses_libs...)

		optTag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true, false)
		ctx.AddVariationDependencies(nil, optTag, u.presentOptionalUsesLibs(ctx)...)

		// Only add these extra dependencies if the module depends on framework libs. This avoids
		// creating a cyclic dependency:
		//     e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
		if hasFrameworkLibs {
			// Dexpreopt needs paths to the dex jars of these libraries in order to construct
			// class loader context for dex2oat. Add them as a dependency with a special tag.
			ctx.AddVariationDependencies(nil, usesLibCompat29ReqTag, dexpreopt.CompatUsesLibs29...)
			ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
			ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
			// Add implicit <uses-library> dependencies on compatibility libraries. Some of them are
			// optional, and some required --- this depends on the most common usage of the library
			// and may be wrong for some apps (they need explicit `uses_libs`/`optional_uses_libs`).

			compat28OptTag := makeUsesLibraryDependencyTag(28, true, true)
			ctx.AddVariationDependencies(nil, compat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)

			compat29ReqTag := makeUsesLibraryDependencyTag(29, false, true)
			ctx.AddVariationDependencies(nil, compat29ReqTag, dexpreopt.CompatUsesLibs29...)

			compat30OptTag := makeUsesLibraryDependencyTag(30, true, true)
			ctx.AddVariationDependencies(nil, compat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
		}
	}
}
@@ -1293,7 +1304,7 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
				replaceInList(u.usesLibraryProperties.Uses_libs, dep, libName)
				replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
			}
			clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
			clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional, tag.implicit,
				lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
		} else if ctx.Config().AllowMissingDependencies() {
			ctx.AddMissingDependencies([]string{dep})
+1 −8
Original line number Diff line number Diff line
@@ -2398,14 +2398,7 @@ func TestUsesLibraries(t *testing.T) {
	expectManifestFixerArgs := `--extract-native-libs=true ` +
		`--uses-library qux ` +
		`--uses-library quuz ` +
		`--uses-library foo ` + // TODO(b/132357300): "foo" should not be passed to manifest_fixer
		`--uses-library com.non.sdk.lib ` + // TODO(b/132357300): "com.non.sdk.lib" should not be passed to manifest_fixer
		`--uses-library runtime-library ` +
		`--uses-library runtime-required-x ` + // TODO(b/132357300): "runtime-required-x" should not be passed to manifest_fixer
		`--uses-library runtime-required-y ` + // TODO(b/132357300): "runtime-required-y" should not be passed to manifest_fixer
		`--optional-uses-library bar ` + // TODO(b/132357300): "bar" should not be passed to manifest_fixer
		`--optional-uses-library runtime-optional-x ` + // TODO(b/132357300): "runtime-optional-x" should not be passed to manifest_fixer
		`--optional-uses-library runtime-optional-y` // TODO(b/132357300): "runtime-optional-y" should not be passed to manifest_fixer
		`--uses-library runtime-library`
	android.AssertStringEquals(t, "manifest_fixer args", expectManifestFixerArgs, actualManifestFixerArgs)

	// Test that all libraries are verified (library order matters).
Loading