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

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

Merge "apex: apex_available with prefix" into main

parents 2d2df8cb 9a419e28
Loading
Loading
Loading
Loading
+35 −4
Original line number Diff line number Diff line
@@ -280,6 +280,7 @@ type ApexProperties struct {
	//
	// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
	// "//apex_available:platform" refers to non-APEX partitions like "system.img".
	// Prefix pattern (com.foo.*) can be used to match with any APEX name with the prefix(com.foo.).
	// Default is ["//apex_available:platform"].
	Apex_available []string

@@ -491,10 +492,27 @@ func CheckAvailableForApex(what string, apex_available []string) bool {
	if len(apex_available) == 0 {
		return what == AvailableToPlatform
	}
	return InList(what, apex_available) ||
		(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
		(what == "com.google.mainline.primary.libs") || // TODO b/248601389
		(what == "com.google.mainline.go.primary.libs") // TODO b/248601389

	// TODO b/248601389
	if what == "com.google.mainline.primary.libs" || what == "com.google.mainline.go.primary.libs" {
		return true
	}

	for _, apex_name := range apex_available {
		// exact match.
		if apex_name == what {
			return true
		}
		// //apex_available:anyapex matches with any apex name, but not //apex_available:platform
		if apex_name == AvailableToAnyApex && what != AvailableToPlatform {
			return true
		}
		// prefix match.
		if strings.HasSuffix(apex_name, ".*") && strings.HasPrefix(what, strings.TrimSuffix(apex_name, "*")) {
			return true
		}
	}
	return false
}

// Implements ApexModule
@@ -523,6 +541,19 @@ func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
		if n == AvailableToPlatform || n == AvailableToAnyApex {
			continue
		}
		// Prefix pattern should end with .* and has at least two components.
		if strings.Contains(n, "*") {
			if !strings.HasSuffix(n, ".*") {
				mctx.PropertyErrorf("apex_available", "Wildcard should end with .* like com.foo.*")
			}
			if strings.Count(n, ".") < 2 {
				mctx.PropertyErrorf("apex_available", "Wildcard requires two or more components like com.foo.*")
			}
			if strings.Count(n, "*") != 1 {
				mctx.PropertyErrorf("apex_available", "Wildcard is not allowed in the middle.")
			}
			continue
		}
		if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
			mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n)
		}
+13 −2
Original line number Diff line number Diff line
@@ -2767,10 +2767,21 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
		if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
			return true
		}

		// Let's give some hint for apex_available
		hint := fmt.Sprintf("%q", apexName)

		if strings.HasPrefix(apexName, "com.") && !strings.HasPrefix(apexName, "com.android.") && strings.Count(apexName, ".") >= 2 {
			// In case of a partner APEX, prefix format might be an option.
			components := strings.Split(apexName, ".")
			components[len(components)-1] = "*"
			hint += fmt.Sprintf(" or %q", strings.Join(components, "."))
		}

		ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+
			"\n\nDependency path:%s\n\n"+
			"Consider adding %q to 'apex_available' property of %q",
			fromName, toName, ctx.GetPathString(true), apexName, toName)
			"Consider adding %s to 'apex_available' property of %q",
			fromName, toName, ctx.GetPathString(true), hint, toName)
		// Visit this module's dependencies to check and report any issues with their availability.
		return true
	})
+93 −0
Original line number Diff line number Diff line
@@ -6722,6 +6722,99 @@ func TestApexAvailable_CreatedForApex(t *testing.T) {
	}
}

func TestApexAvailable_PrefixMatch(t *testing.T) {

	for _, tc := range []struct {
		name          string
		apexAvailable string
		expectedError string
	}{
		{
			name:          "prefix matches correctly",
			apexAvailable: "com.foo.*",
		},
		{
			name:          "prefix doesn't match",
			apexAvailable: "com.bar.*",
			expectedError: `Consider .* "com.foo\.\*"`,
		},
		{
			name:          "short prefix",
			apexAvailable: "com.*",
			expectedError: "requires two or more components",
		},
		{
			name:          "wildcard not in the end",
			apexAvailable: "com.*.foo",
			expectedError: "should end with .*",
		},
		{
			name:          "wildcard in the middle",
			apexAvailable: "com.foo*.*",
			expectedError: "not allowed in the middle",
		},
		{
			name:          "hint with prefix pattern",
			apexAvailable: "//apex_available:platform",
			expectedError: "Consider adding \"com.foo.bar\" or \"com.foo.*\"",
		},
	} {
		t.Run(tc.name, func(t *testing.T) {
			errorHandler := android.FixtureExpectsNoErrors
			if tc.expectedError != "" {
				errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError)
			}
			context := android.GroupFixturePreparers(
				prepareForApexTest,
				android.FixtureMergeMockFs(android.MockFS{
					"system/sepolicy/apex/com.foo.bar-file_contexts": nil,
				}),
			).ExtendWithErrorHandler(errorHandler)

			context.RunTestWithBp(t, `
				apex {
					name: "com.foo.bar",
					key: "myapex.key",
					native_shared_libs: ["libfoo"],
					updatable: false,
				}

				apex_key {
					name: "myapex.key",
					public_key: "testkey.avbpubkey",
					private_key: "testkey.pem",
				}

				cc_library {
					name: "libfoo",
					stl: "none",
					system_shared_libs: [],
					apex_available: ["`+tc.apexAvailable+`"],
				}`)
		})
	}
	testApexError(t, `Consider adding "com.foo" to`, `
		apex {
			name: "com.foo", // too short for a partner apex
			key: "myapex.key",
			native_shared_libs: ["libfoo"],
			updatable: false,
		}

		apex_key {
			name: "myapex.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}

		cc_library {
			name: "libfoo",
			stl: "none",
			system_shared_libs: [],
		}
	`)
}

func TestOverrideApex(t *testing.T) {
	ctx := testApex(t, `
		apex {