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

Commit 4926ea3b authored by Aurimas Liutikas's avatar Aurimas Liutikas Committed by Automerger Merge Worker
Browse files

Merge "Fix the way manifest fixer detects optional <uses-library> entries." am: 15c82a10

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1794528

Change-Id: I4b456e8b73e90d175e3c06458b1a00e870e7ff48
parents 951f8669 15c82a10
Loading
Loading
Loading
Loading
+19 −8
Original line number Diff line number Diff line
@@ -193,6 +193,9 @@ type ClassLoaderContext struct {
	// The name of the library.
	Name string

	// If the library is optional or required.
	Optional bool

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

@@ -256,7 +259,7 @@ 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,
	hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) error {
	optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) error {

	// For prebuilts, library should have the same name as the source module.
	lib = android.RemoveOptionalPrebuiltPrefix(lib)
@@ -304,6 +307,7 @@ func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathCont

	clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
		Name:        lib,
		Optional:    optional,
		Host:        hostPath,
		Device:      devicePath,
		Subcontexts: subcontexts,
@@ -316,9 +320,9 @@ 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, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
	lib string, optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {

	err := clcMap.addContext(ctx, sdkVer, lib, hostPath, installPath, nestedClcMap)
	err := clcMap.addContext(ctx, sdkVer, lib, optional, hostPath, installPath, nestedClcMap)
	if err != nil {
		ctx.ModuleErrorf(err.Error())
	}
@@ -361,15 +365,21 @@ func (clcMap ClassLoaderContextMap) AddContextMap(otherClcMap ClassLoaderContext
// Returns top-level libraries in the CLC (conditional CLC, i.e. compatibility libraries are not
// 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.
func (clcMap ClassLoaderContextMap) UsesLibs() (ulibs []string) {
// Required and optional libraries are in separate lists.
func (clcMap ClassLoaderContextMap) UsesLibs() (required []string, optional []string) {
	if clcMap != nil {
		clcs := clcMap[AnySdkVersion]
		ulibs = make([]string, 0, len(clcs))
		required = make([]string, 0, len(clcs))
		optional = make([]string, 0, len(clcs))
		for _, clc := range clcs {
			ulibs = append(ulibs, clc.Name)
			if clc.Optional {
				optional = append(optional, clc.Name)
			} else {
				required = append(required, clc.Name)
			}
		}
	}
	return ulibs
	return required, optional
}

func (clcMap ClassLoaderContextMap) Dump() string {
@@ -388,7 +398,8 @@ func (clcMap ClassLoaderContextMap) Dump() string {
// TODO(b/132357300): remove "android.hidl.manager" and "android.hidl.base" for non-system apps.
//
func fixClassLoaderContext(clcMap ClassLoaderContextMap) {
	usesLibs := clcMap.UsesLibs()
	required, optional := clcMap.UsesLibs()
	usesLibs := append(required, optional...)

	for sdkVer, clcs := range clcMap {
		if sdkVer == AnySdkVersion {
+51 −37
Original line number Diff line number Diff line
@@ -49,32 +49,34 @@ func TestCLC(t *testing.T) {
	//
	ctx := testContext()

	optional := false

	m := make(ClassLoaderContextMap)

	m.AddContext(ctx, AnySdkVersion, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m.AddContext(ctx, AnySdkVersion, "b", buildPath(ctx, "b"), installPath(ctx, "b"), nil)
	m.AddContext(ctx, AnySdkVersion, "c", buildPath(ctx, "c"), installPath(ctx, "c"), nil)
	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)

	// Add some libraries with nested subcontexts.

	m1 := make(ClassLoaderContextMap)
	m1.AddContext(ctx, AnySdkVersion, "a1", buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
	m1.AddContext(ctx, AnySdkVersion, "b1", buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
	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)

	m2 := make(ClassLoaderContextMap)
	m2.AddContext(ctx, AnySdkVersion, "a2", buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
	m2.AddContext(ctx, AnySdkVersion, "b2", buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
	m2.AddContext(ctx, AnySdkVersion, "c2", buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
	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)

	m3 := make(ClassLoaderContextMap)
	m3.AddContext(ctx, AnySdkVersion, "a3", buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
	m3.AddContext(ctx, AnySdkVersion, "b3", buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
	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)

	m.AddContext(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), m2)
	m.AddContext(ctx, AnySdkVersion, "d", optional, 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", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
	m.AddContext(ctx, AnySdkVersion, "f", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
	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)

	// Merge map with implicit root library that is among toplevel contexts => does nothing.
	m.AddContextMap(m1, "c")
@@ -83,12 +85,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, buildPath(ctx, AndroidHidlManager), nil, nil)
	m.AddContext(ctx, 29, AndroidHidlBase, buildPath(ctx, AndroidHidlBase), nil, nil)
	m.AddContext(ctx, 29, AndroidHidlManager, optional, buildPath(ctx, AndroidHidlManager), nil, nil)
	m.AddContext(ctx, 29, AndroidHidlBase, optional, 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, buildPath(ctx, AndroidTestMock), nil, nil)
	m.AddContext(ctx, 30, AndroidTestMock, optional, buildPath(ctx, AndroidTestMock), nil, nil)

	valid, validationError := validateClassLoaderContext(m)

@@ -96,10 +98,10 @@ func TestCLC(t *testing.T) {

	var haveStr string
	var havePaths android.Paths
	var haveUsesLibs []string
	var haveUsesLibsReq, haveUsesLibsOpt []string
	if valid && validationError == nil {
		haveStr, havePaths = ComputeClassLoaderContext(m)
		haveUsesLibs = m.UsesLibs()
		haveUsesLibsReq, haveUsesLibsOpt = m.UsesLibs()
	}

	// Test that validation is successful (all paths are known).
@@ -148,20 +150,25 @@ func TestCLC(t *testing.T) {

	// Test for libraries that are added by the manifest_fixer.
	t.Run("uses libs", func(t *testing.T) {
		wantUsesLibs := []string{"a", "b", "c", "d", "f", "a3", "b3"}
		if !reflect.DeepEqual(wantUsesLibs, haveUsesLibs) {
			t.Errorf("\nwant uses libs: %s\nhave uses libs: %s", wantUsesLibs, haveUsesLibs)
		wantUsesLibsReq := []string{"a", "b", "c", "d", "f", "a3", "b3"}
		wantUsesLibsOpt := []string{}
		if !reflect.DeepEqual(wantUsesLibsReq, haveUsesLibsReq) {
			t.Errorf("\nwant required uses libs: %s\nhave required uses libs: %s", wantUsesLibsReq, haveUsesLibsReq)
		}
		if !reflect.DeepEqual(wantUsesLibsOpt, haveUsesLibsOpt) {
			t.Errorf("\nwant optional uses libs: %s\nhave optional uses libs: %s", wantUsesLibsOpt, haveUsesLibsOpt)
		}
	})
}

func TestCLCJson(t *testing.T) {
	ctx := testContext()
	optional := false
	m := make(ClassLoaderContextMap)
	m.AddContext(ctx, 28, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m.AddContext(ctx, 29, "b", buildPath(ctx, "b"), installPath(ctx, "b"), nil)
	m.AddContext(ctx, 30, "c", buildPath(ctx, "c"), installPath(ctx, "c"), nil)
	m.AddContext(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), nil)
	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)
	jsonCLC := toJsonClassLoaderContext(m)
	restored := fromJsonClassLoaderContext(ctx, jsonCLC)
	android.AssertIntEquals(t, "The size of the maps should be the same.", len(m), len(restored))
@@ -181,20 +188,25 @@ func TestCLCJson(t *testing.T) {
// Test that unknown library paths cause a validation error.
func testCLCUnknownPath(t *testing.T, whichPath string) {
	ctx := testContext()
	optional := false

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

	// The library should be added to <uses-library> tags by the manifest_fixer.
	t.Run("uses libs", func(t *testing.T) {
		haveUsesLibs := m.UsesLibs()
		wantUsesLibs := []string{"a"}
		if !reflect.DeepEqual(wantUsesLibs, haveUsesLibs) {
			t.Errorf("\nwant uses libs: %s\nhave uses libs: %s", wantUsesLibs, haveUsesLibs)
		haveUsesLibsReq, haveUsesLibsOpt := m.UsesLibs()
		wantUsesLibsReq := []string{"a"}
		wantUsesLibsOpt := []string{}
		if !reflect.DeepEqual(wantUsesLibsReq, haveUsesLibsReq) {
			t.Errorf("\nwant required uses libs: %s\nhave required uses libs: %s", wantUsesLibsReq, haveUsesLibsReq)
		}
		if !reflect.DeepEqual(wantUsesLibsOpt, haveUsesLibsOpt) {
			t.Errorf("\nwant optional uses libs: %s\nhave optional uses libs: %s", wantUsesLibsOpt, haveUsesLibsOpt)
		}
	})

@@ -216,10 +228,11 @@ func TestCLCUnknownInstallPath(t *testing.T) {
// An attempt to add conditional nested subcontext should fail.
func TestCLCNestedConditional(t *testing.T) {
	ctx := testContext()
	optional := false
	m1 := make(ClassLoaderContextMap)
	m1.AddContext(ctx, 42, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m1.AddContext(ctx, 42, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m := make(ClassLoaderContextMap)
	err := m.addContext(ctx, AnySdkVersion, "b", buildPath(ctx, "b"), installPath(ctx, "b"), m1)
	err := m.addContext(ctx, AnySdkVersion, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
	checkError(t, err, "nested class loader context shouldn't have conditional part")
}

@@ -227,11 +240,12 @@ func TestCLCNestedConditional(t *testing.T) {
// they end up in the order that agrees with PackageManager.
func TestCLCSdkVersionOrder(t *testing.T) {
	ctx := testContext()
	optional := false
	m := make(ClassLoaderContextMap)
	m.AddContext(ctx, 28, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
	m.AddContext(ctx, 29, "b", buildPath(ctx, "b"), installPath(ctx, "b"), nil)
	m.AddContext(ctx, 30, "c", buildPath(ctx, "c"), installPath(ctx, "c"), nil)
	m.AddContext(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), nil)
	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)

	valid, validationError := validateClassLoaderContext(m)

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

	for _, usesLib := range classLoaderContexts.UsesLibs() {
		if inList(usesLib, dexpreopt.OptionalCompatUsesLibs) {
			args = append(args, "--optional-uses-library", usesLib)
		} else {
	requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs()
	for _, usesLib := range requiredUsesLibs {
		args = append(args, "--uses-library", usesLib)
	}
	for _, usesLib := range optionalUsesLibs {
		args = append(args, "--optional-uses-library", usesLib)
	}

	if hasNoCode {
+2 −1
Original line number Diff line number Diff line
@@ -114,7 +114,8 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
						entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
					}

					entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.classLoaderContexts.UsesLibs()...)
					requiredUsesLibs, optionalUsesLibs := library.classLoaderContexts.UsesLibs()
					entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", append(requiredUsesLibs, optionalUsesLibs...)...)

					if len(library.additionalCheckedModules) != 0 {
						entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
+12 −8
Original line number Diff line number Diff line
@@ -649,8 +649,12 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
	a.usesLibrary.freezeEnforceUsesLibraries()

	// Add implicit SDK libraries to <uses-library> list.
	for _, usesLib := range a.classLoaderContexts.UsesLibs() {
		a.usesLibrary.addLib(usesLib, inList(usesLib, dexpreopt.OptionalCompatUsesLibs))
	requiredUsesLibs, optionalUsesLibs := a.classLoaderContexts.UsesLibs()
	for _, usesLib := range requiredUsesLibs {
		a.usesLibrary.addLib(usesLib, false)
	}
	for _, usesLib := range optionalUsesLibs {
		a.usesLibrary.addLib(usesLib, true)
	}

	// Check that the <uses-library> list is coherent with the manifest.
@@ -1220,17 +1224,17 @@ 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, usesLibTag, u.usesLibraryProperties.Uses_libs...)
		ctx.AddVariationDependencies(nil, usesLibTag, u.presentOptionalUsesLibs(ctx)...)
		ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs...)
		ctx.AddVariationDependencies(nil, usesLibOptTag, 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, usesLibCompat29Tag, dexpreopt.CompatUsesLibs29...)
			ctx.AddVariationDependencies(nil, usesLibCompat28Tag, dexpreopt.OptionalCompatUsesLibs28...)
			ctx.AddVariationDependencies(nil, usesLibCompat30Tag, dexpreopt.OptionalCompatUsesLibs30...)
			ctx.AddVariationDependencies(nil, usesLibCompat29ReqTag, dexpreopt.CompatUsesLibs29...)
			ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
			ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
		}
	}
}
@@ -1289,7 +1293,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,
			clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
				lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
		} else if ctx.Config().AllowMissingDependencies() {
			ctx.AddMissingDependencies([]string{dep})
Loading