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

Commit 749dc69a authored by Jooyung Han's avatar Jooyung Han
Browse files

apex/apk: enforce min_sdk_version of all deps

Enforce min_sdk_version for every payload dependency of updatable
APEX/APKs.

android.CheckMinSdkVersion() calls ApexModule.ShouldSupportSdkVersion
for every transitive dependency from APEX/APK modules to see if it
meets the min_sdk_version requirements.

The common implementation for apex/android_app is provided in
android/apex.go.

Bug: 145796956
Bug: 152655956
Bug: 153333044
Test: m nothing
Change-Id: I4a947dc94026df7cebd552b6e8ccdb4cc1f67170
parent 63a89ef8
Loading
Loading
Loading
Loading
+126 −0
Original line number Diff line number Diff line
@@ -124,6 +124,10 @@ type ApexModule interface {
	// the private part of the listed APEXes even when it is not included in the
	// APEXes.
	TestFor() []string

	// Returns nil if this module supports sdkVersion
	// Otherwise, returns error with reason
	ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion int) error
}

type ApexProperties struct {
@@ -477,3 +481,125 @@ func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion
		},
	})
}

// TODO(b/158059172): remove minSdkVersion allowlist
var minSdkVersionAllowlist = map[string]int{
	"adbd":                  30,
	"android.net.ipsec.ike": 30,
	"androidx-constraintlayout_constraintlayout-solver": 30,
	"androidx.annotation_annotation":                    28,
	"androidx.arch.core_core-common":                    28,
	"androidx.collection_collection":                    28,
	"androidx.lifecycle_lifecycle-common":               28,
	"apache-commons-compress":                           29,
	"bouncycastle_ike_digests":                          30,
	"brotli-java":                                       29,
	"captiveportal-lib":                                 28,
	"flatbuffer_headers":                                30,
	"framework-permission":                              30,
	"framework-statsd":                                  30,
	"gemmlowp_headers":                                  30,
	"ike-internals":                                     30,
	"kotlinx-coroutines-android":                        28,
	"kotlinx-coroutines-core":                           28,
	"libadb_crypto":                                     30,
	"libadb_pairing_auth":                               30,
	"libadb_pairing_connection":                         30,
	"libadb_pairing_server":                             30,
	"libadb_protos":                                     30,
	"libadb_tls_connection":                             30,
	"libadbconnection_client":                           30,
	"libadbconnection_server":                           30,
	"libadbd_core":                                      30,
	"libadbd_services":                                  30,
	"libadbd":                                           30,
	"libapp_processes_protos_lite":                      30,
	"libasyncio":                                        30,
	"libbrotli":                                         30,
	"libbuildversion":                                   30,
	"libcrypto_static":                                  30,
	"libcrypto_utils":                                   30,
	"libdiagnose_usb":                                   30,
	"libeigen":                                          30,
	"liblz4":                                            30,
	"libmdnssd":                                         30,
	"libneuralnetworks_common":                          30,
	"libneuralnetworks_headers":                         30,
	"libneuralnetworks":                                 30,
	"libprocpartition":                                  30,
	"libprotobuf-java-lite":                             30,
	"libprotoutil":                                      30,
	"libqemu_pipe":                                      30,
	"libstats_jni":                                      30,
	"libstatslog_statsd":                                30,
	"libstatsmetadata":                                  30,
	"libstatspull":                                      30,
	"libstatssocket":                                    30,
	"libsync":                                           30,
	"libtextclassifier_hash_headers":                    30,
	"libtextclassifier_hash_static":                     30,
	"libtflite_kernel_utils":                            30,
	"libwatchdog":                                       29,
	"libzstd":                                           30,
	"metrics-constants-protos":                          28,
	"net-utils-framework-common":                        29,
	"permissioncontroller-statsd":                       28,
	"philox_random_headers":                             30,
	"philox_random":                                     30,
	"service-permission":                                30,
	"service-statsd":                                    30,
	"statsd-aidl-ndk_platform":                          30,
	"statsd":                                            30,
	"tensorflow_headers":                                30,
	"xz-java":                                           29,
}

// Function called while walking an APEX's payload dependencies.
//
// Return true if the `to` module should be visited, false otherwise.
type PayloadDepsCallback func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool

// UpdatableModule represents updatable APEX/APK
type UpdatableModule interface {
	Module
	WalkPayloadDeps(ctx ModuleContext, do PayloadDepsCallback)
}

// CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version accordingly
func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion int) {
	// do not enforce min_sdk_version for host
	if ctx.Host() {
		return
	}

	// do not enforce for coverage build
	if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") || ctx.DeviceConfig().NativeCoverageEnabled() || ctx.DeviceConfig().ClangCoverageEnabled() {
		return
	}

	// do not enforce deps.min_sdk_version if APEX/APK doesn't set min_sdk_version or
	// min_sdk_version is not finalized (e.g. current or codenames)
	if minSdkVersion == FutureApiLevel {
		return
	}

	m.WalkPayloadDeps(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
		if externalDep {
			// external deps are outside the payload boundary, which is "stable" interface.
			// We don't have to check min_sdk_version for external dependencies.
			return false
		}
		if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
			return false
		}
		if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
			toName := ctx.OtherModuleName(to)
			if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver > minSdkVersion {
				ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v. Dependency path: %s",
					minSdkVersion, ctx.ModuleName(), err.Error(), ctx.GetPathString(false))
				return false
			}
		}
		return true
	})
}
+31 −10
Original line number Diff line number Diff line
@@ -1725,13 +1725,8 @@ func (c *flattenedApexContext) InstallBypassMake() bool {
	return true
}

// Function called while walking an APEX's payload dependencies.
//
// Return true if the `to` module should be visited, false otherwise.
type payloadDepsCallback func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool

// Visit dependencies that contributes to the payload of this APEX
func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext, do payloadDepsCallback) {
func (a *apexBundle) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) {
	ctx.WalkDeps(func(child, parent android.Module) bool {
		am, ok := child.(android.ApexModule)
		if !ok || !am.CanHaveApexVariants() {
@@ -1757,7 +1752,21 @@ func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext, do payloadDepsCa
}

func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int {
	ver := proptools.StringDefault(a.properties.Min_sdk_version, "current")
	ver := proptools.String(a.properties.Min_sdk_version)
	if ver == "" {
		return android.FutureApiLevel
	}
	// Treat the current codenames as "current", which means future API version (10000)
	// Otherwise, ApiStrToNum converts codename(non-finalized) to a value from [9000...]
	// and would fail to build against "current".
	if android.InList(ver, ctx.Config().PlatformVersionActiveCodenames()) {
		return android.FutureApiLevel
	}
	// In "REL" branch, "current" is mapped to finalized sdk version
	if ctx.Config().PlatformSdkCodename() == "REL" && ver == "current" {
		return ctx.Config().PlatformSdkVersionInt()
	}
	// Finalized codenames are OKAY and will be converted to int
	intVer, err := android.ApiStrToNum(ctx, ver)
	if err != nil {
		ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
@@ -1785,7 +1794,7 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
		return
	}

	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
	a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
		if externalDep {
			// As soon as the dependency graph crosses the APEX boundary, don't go further.
			return false
@@ -1821,6 +1830,17 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
	}
}

func (a *apexBundle) checkMinSdkVersion(ctx android.ModuleContext) {
	if a.testApex || a.vndkApex {
		return
	}
	// Meaningless to check min_sdk_version when building use_vendor modules against non-Trebleized targets
	if proptools.Bool(a.properties.Use_vendor) && ctx.DeviceConfig().VndkVersion() == "" {
		return
	}
	android.CheckMinSdkVersion(a, ctx, a.minSdkVersion(ctx))
}

// Ensures that a lib providing stub isn't statically linked
func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext) {
	// Practically, we only care about regular APEXes on the device.
@@ -1828,7 +1848,7 @@ func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext
		return
	}

	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
	a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
		if ccm, ok := to.(*cc.Module); ok {
			apexName := ctx.ModuleName()
			fromName := ctx.OtherModuleName(from)
@@ -1903,6 +1923,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {

	a.checkApexAvailability(ctx)
	a.checkUpdatable(ctx)
	a.checkMinSdkVersion(ctx)
	a.checkStaticLinkingToStubLibraries(ctx)

	handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
@@ -1936,7 +1957,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	})

	var filesInfo []apexFile
	// TODO(jiyong) do this using walkPayloadDeps
	// TODO(jiyong) do this using WalkPayloadDeps
	ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
		depTag := ctx.OtherModuleDependencyTag(child)
		if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
+230 −20
Original line number Diff line number Diff line
@@ -206,6 +206,7 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
	config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
	config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q")
	config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
	config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
	config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER")

	for _, handler := range handlers {
@@ -1104,13 +1105,13 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) {
	}{
		{
			name:          "should link to the latest",
			minSdkVersion: "current",
			minSdkVersion: "",
			shouldLink:    "30",
			shouldNotLink: []string{"29"},
		},
		{
			name:          "should link to llndk#29",
			minSdkVersion: "29",
			minSdkVersion: "min_sdk_version: \"29\",",
			shouldLink:    "29",
			shouldNotLink: []string{"30"},
		},
@@ -1123,7 +1124,7 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) {
				key: "myapex.key",
				use_vendor: true,
				native_shared_libs: ["mylib"],
				min_sdk_version: "`+tc.minSdkVersion+`",
				`+tc.minSdkVersion+`
			}

			apex_key {
@@ -1140,6 +1141,7 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) {
				system_shared_libs: [],
				stl: "none",
				apex_available: [ "myapex" ],
				min_sdk_version: "29",
			}

			cc_library {
@@ -1270,24 +1272,24 @@ func TestApexWithSystemLibsStubs(t *testing.T) {
	ensureContains(t, libFlags, "libdl/android_arm64_armv8-a_shared/libdl.so")
}

func TestApexUseStubsAccordingToMinSdkVersionInUnbundledBuild(t *testing.T) {
func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T) {
	// there are three links between liba --> libz
	// 1) myapex -> libx -> liba -> libz    : this should be #2 link, but fallback to #1
	// 2) otherapex -> liby -> liba -> libz : this should be #3 link
	// 1) myapex -> libx -> liba -> libz    : this should be #29 link, but fallback to #28
	// 2) otherapex -> liby -> liba -> libz : this should be #30 link
	// 3) (platform) -> liba -> libz        : this should be non-stub link
	ctx, _ := testApex(t, `
		apex {
			name: "myapex",
			key: "myapex.key",
			native_shared_libs: ["libx"],
			min_sdk_version: "2",
			min_sdk_version: "29",
		}

		apex {
			name: "otherapex",
			key: "myapex.key",
			native_shared_libs: ["liby"],
			min_sdk_version: "3",
			min_sdk_version: "30",
		}

		apex_key {
@@ -1302,6 +1304,7 @@ func TestApexUseStubsAccordingToMinSdkVersionInUnbundledBuild(t *testing.T) {
			system_shared_libs: [],
			stl: "none",
			apex_available: [ "myapex" ],
			min_sdk_version: "29",
		}

		cc_library {
@@ -1310,6 +1313,7 @@ func TestApexUseStubsAccordingToMinSdkVersionInUnbundledBuild(t *testing.T) {
			system_shared_libs: [],
			stl: "none",
			apex_available: [ "otherapex" ],
			min_sdk_version: "29",
		}

		cc_library {
@@ -1321,6 +1325,7 @@ func TestApexUseStubsAccordingToMinSdkVersionInUnbundledBuild(t *testing.T) {
				"//apex_available:anyapex",
				"//apex_available:platform",
			],
			min_sdk_version: "29",
		}

		cc_library {
@@ -1328,10 +1333,10 @@ func TestApexUseStubsAccordingToMinSdkVersionInUnbundledBuild(t *testing.T) {
			system_shared_libs: [],
			stl: "none",
			stubs: {
				versions: ["1", "3"],
				versions: ["28", "30"],
			},
		}
	`, withUnbundledBuild)
	`)

	expectLink := func(from, from_variant, to, to_variant string) {
		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
@@ -1343,13 +1348,13 @@ func TestApexUseStubsAccordingToMinSdkVersionInUnbundledBuild(t *testing.T) {
	}
	// platform liba is linked to non-stub version
	expectLink("liba", "shared", "libz", "shared")
	// liba in myapex is linked to #1
	expectLink("liba", "shared_myapex", "libz", "shared_1")
	expectNoLink("liba", "shared_myapex", "libz", "shared_3")
	// liba in myapex is linked to #28
	expectLink("liba", "shared_myapex", "libz", "shared_28")
	expectNoLink("liba", "shared_myapex", "libz", "shared_30")
	expectNoLink("liba", "shared_myapex", "libz", "shared")
	// liba in otherapex is linked to #3
	expectLink("liba", "shared_otherapex", "libz", "shared_3")
	expectNoLink("liba", "shared_otherapex", "libz", "shared_1")
	// liba in otherapex is linked to #30
	expectLink("liba", "shared_otherapex", "libz", "shared_30")
	expectNoLink("liba", "shared_otherapex", "libz", "shared_28")
	expectNoLink("liba", "shared_otherapex", "libz", "shared")
}

@@ -1374,6 +1379,7 @@ func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
			system_shared_libs: [],
			stl: "none",
			apex_available: [ "myapex" ],
			min_sdk_version: "R",
		}

		cc_library {
@@ -1407,7 +1413,7 @@ func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
	expectNoLink("libx", "shared_myapex", "libz", "shared")
}

func TestApexMinSdkVersionDefaultsToLatest(t *testing.T) {
func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
	ctx, _ := testApex(t, `
		apex {
			name: "myapex",
@@ -1516,6 +1522,7 @@ func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
			name: "libx",
			shared_libs: ["libbar"],
			apex_available: [ "myapex" ],
			min_sdk_version: "29",
		}

		cc_library {
@@ -1553,6 +1560,7 @@ func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
		cc_library {
			name: "libx",
			apex_available: [ "myapex" ],
			min_sdk_version: "29",
		}
	`)

@@ -1564,7 +1572,7 @@ func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
	ensureListNotContains(t, cm.Properties.AndroidMkStaticLibs, "libgcc_stripped")
}

func TestInvalidMinSdkVersion(t *testing.T) {
func TestApexMinSdkVersion_ErrorIfIncompatibleStubs(t *testing.T) {
	testApexError(t, `"libz" .*: not found a version\(<=29\)`, `
		apex {
			name: "myapex",
@@ -1585,6 +1593,7 @@ func TestInvalidMinSdkVersion(t *testing.T) {
			system_shared_libs: [],
			stl: "none",
			apex_available: [ "myapex" ],
			min_sdk_version: "29",
		}

		cc_library {
@@ -1596,12 +1605,44 @@ func TestInvalidMinSdkVersion(t *testing.T) {
			},
		}
	`)
}

func TestApexMinSdkVersion_ErrorIfIncompatibleVersion(t *testing.T) {
	testApexError(t, `module "mylib".*: should support min_sdk_version\(29\)`, `
		apex {
			name: "myapex",
			key: "myapex.key",
			native_shared_libs: ["mylib"],
			min_sdk_version: "29",
		}

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

		cc_library {
			name: "mylib",
			srcs: ["mylib.cpp"],
			system_shared_libs: [],
			stl: "none",
			apex_available: [
				"myapex",
			],
			min_sdk_version: "30",
		}
	`)
}

	testApexError(t, `"myapex" .*: min_sdk_version: SDK version should be .*`, `
func TestApexMinSdkVersion_Okay(t *testing.T) {
	testApex(t, `
		apex {
			name: "myapex",
			key: "myapex.key",
			min_sdk_version: "abc",
			native_shared_libs: ["libfoo"],
			java_libs: ["libbar"],
			min_sdk_version: "29",
		}

		apex_key {
@@ -1609,6 +1650,38 @@ func TestInvalidMinSdkVersion(t *testing.T) {
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}

		cc_library {
			name: "libfoo",
			srcs: ["mylib.cpp"],
			shared_libs: ["libfoo_dep"],
			apex_available: ["myapex"],
			min_sdk_version: "29",
		}

		cc_library {
			name: "libfoo_dep",
			srcs: ["mylib.cpp"],
			apex_available: ["myapex"],
			min_sdk_version: "29",
		}

		java_library {
			name: "libbar",
			sdk_version: "current",
			srcs: ["a.java"],
			static_libs: ["libbar_dep"],
			apex_available: ["myapex"],
			min_sdk_version: "29",
		}

		java_library {
			name: "libbar_dep",
			sdk_version: "current",
			srcs: ["a.java"],
			apex_available: ["myapex"],
			min_sdk_version: "29",
		}
	`)
}

@@ -1659,6 +1732,7 @@ func TestJavaStableSdkVersion(t *testing.T) {
					srcs: ["foo/bar/MyClass.java"],
					sdk_version: "current",
					apex_available: ["myapex"],
					min_sdk_version: "29",
				}
			`,
		},
@@ -1728,6 +1802,135 @@ func TestJavaStableSdkVersion(t *testing.T) {
	}
}

func TestApexMinSdkVersion_ErrorIfDepIsNewer(t *testing.T) {
	testApexError(t, `module "mylib2".*: should support min_sdk_version\(29\) for "myapex"`, `
		apex {
			name: "myapex",
			key: "myapex.key",
			native_shared_libs: ["mylib"],
			min_sdk_version: "29",
		}

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

		cc_library {
			name: "mylib",
			srcs: ["mylib.cpp"],
			shared_libs: ["mylib2"],
			system_shared_libs: [],
			stl: "none",
			apex_available: [
				"myapex",
			],
			min_sdk_version: "29",
		}

		// indirect part of the apex
		cc_library {
			name: "mylib2",
			srcs: ["mylib.cpp"],
			system_shared_libs: [],
			stl: "none",
			apex_available: [
				"myapex",
			],
			min_sdk_version: "30",
		}
	`)
}

func TestApexMinSdkVersion_ErrorIfDepIsNewer_Java(t *testing.T) {
	testApexError(t, `module "bar".*: should support min_sdk_version\(29\) for "myapex"`, `
		apex {
			name: "myapex",
			key: "myapex.key",
			apps: ["AppFoo"],
			min_sdk_version: "29",
		}

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

		android_app {
			name: "AppFoo",
			srcs: ["foo/bar/MyClass.java"],
			sdk_version: "current",
			min_sdk_version: "29",
			system_modules: "none",
			stl: "none",
			static_libs: ["bar"],
			apex_available: [ "myapex" ],
		}

		java_library {
			name: "bar",
			sdk_version: "current",
			srcs: ["a.java"],
			apex_available: [ "myapex" ],
		}
	`)
}

func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion(t *testing.T) {
	ctx, _ := testApex(t, `
		apex {
			name: "myapex",
			key: "myapex.key",
			native_shared_libs: ["mylib"],
			min_sdk_version: "29",
		}

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

		// mylib in myapex will link to mylib2#29
		// mylib in otherapex will link to mylib2(non-stub) in otherapex as well
		cc_library {
			name: "mylib",
			srcs: ["mylib.cpp"],
			shared_libs: ["mylib2"],
			system_shared_libs: [],
			stl: "none",
			apex_available: ["myapex", "otherapex"],
			min_sdk_version: "29",
		}

		cc_library {
			name: "mylib2",
			srcs: ["mylib.cpp"],
			system_shared_libs: [],
			stl: "none",
			apex_available: ["otherapex"],
			stubs: { versions: ["29", "30"] },
			min_sdk_version: "30",
		}

		apex {
			name: "otherapex",
			key: "myapex.key",
			native_shared_libs: ["mylib", "mylib2"],
			min_sdk_version: "30",
		}
	`)
	expectLink := func(from, from_variant, to, to_variant string) {
		ld := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
		libFlags := ld.Args["libFlags"]
		ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
	}
	expectLink("mylib", "shared_myapex", "mylib2", "shared_29")
	expectLink("mylib", "shared_otherapex", "mylib2", "shared_otherapex")
}

func TestFilesInSubDir(t *testing.T) {
	ctx, _ := testApex(t, `
		apex {
@@ -2217,6 +2420,7 @@ func TestMacro(t *testing.T) {
				"otherapex",
			],
			recovery_available: true,
			min_sdk_version: "29",
		}
		cc_library {
			name: "mylib2",
@@ -2228,6 +2432,7 @@ func TestMacro(t *testing.T) {
				"otherapex",
			],
			use_apex_name_macro: true,
			min_sdk_version: "29",
		}
	`)

@@ -4349,6 +4554,7 @@ func TestLegacyAndroid10Support(t *testing.T) {
			stl: "libc++",
			system_shared_libs: [],
			apex_available: [ "myapex" ],
			min_sdk_version: "29",
		}
	`, withUnbundledBuild)

@@ -4749,6 +4955,7 @@ func TestSymlinksFromApexToSystem(t *testing.T) {
				"myapex.updatable",
				"//apex_available:platform",
			],
			min_sdk_version: "current",
		}

		cc_library {
@@ -4761,6 +4968,7 @@ func TestSymlinksFromApexToSystem(t *testing.T) {
				"myapex.updatable",
				"//apex_available:platform",
			],
			min_sdk_version: "current",
		}

		java_library {
@@ -4774,6 +4982,7 @@ func TestSymlinksFromApexToSystem(t *testing.T) {
				"myapex.updatable",
				"//apex_available:platform",
			],
			min_sdk_version: "current",
		}

		java_library {
@@ -4786,6 +4995,7 @@ func TestSymlinksFromApexToSystem(t *testing.T) {
				"myapex.updatable",
				"//apex_available:platform",
			],
			min_sdk_version: "current",
		}
	`

+2 −2
Original line number Diff line number Diff line
@@ -234,7 +234,7 @@ func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs,
func (a *apexBundle) buildNoticeFiles(ctx android.ModuleContext, apexFileName string) android.NoticeOutputs {
	var noticeFiles android.Paths

	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
	a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
		if externalDep {
			// As soon as the dependency graph crosses the APEX boundary, don't go further.
			return false
@@ -733,7 +733,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) {
	}

	depInfos := android.DepNameToDepInfoMap{}
	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
	a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
		if from.Name() == to.Name() {
			// This can happen for cc.reuseObjTag. We are not interested in tracking this.
			// As soon as the dependency graph crosses the APEX boundary, don't go further.
+48 −0
Original line number Diff line number Diff line
@@ -2905,6 +2905,54 @@ func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu
	return true
}

// b/154667674: refactor this to handle "current" in a consistent way
func decodeSdkVersionString(ctx android.BaseModuleContext, versionString string) (int, error) {
	if versionString == "" {
		return 0, fmt.Errorf("not specified")
	}
	if versionString == "current" {
		if ctx.Config().PlatformSdkCodename() == "REL" {
			return ctx.Config().PlatformSdkVersionInt(), nil
		}
		return android.FutureApiLevel, nil
	}
	return android.ApiStrToNum(ctx, versionString)
}

func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
	// We ignore libclang_rt.* prebuilt libs since they declare sdk_version: 14(b/121358700)
	if strings.HasPrefix(ctx.OtherModuleName(c), "libclang_rt") {
		return nil
	}
	// b/154569636: set min_sdk_version correctly for toolchain_libraries
	if c.ToolchainLibrary() {
		return nil
	}
	// We don't check for prebuilt modules
	if _, ok := c.linker.(prebuiltLinkerInterface); ok {
		return nil
	}
	minSdkVersion := c.MinSdkVersion()
	if minSdkVersion == "apex_inherit" {
		return nil
	}
	if minSdkVersion == "" {
		// JNI libs within APK-in-APEX fall into here
		// Those are okay to set sdk_version instead
		// We don't have to check if this is a SDK variant because
		// non-SDK variant resets sdk_version, which works too.
		minSdkVersion = c.SdkVersion()
	}
	ver, err := decodeSdkVersionString(ctx, minSdkVersion)
	if err != nil {
		return err
	}
	if ver > sdkVersion {
		return fmt.Errorf("newer SDK(%v)", ver)
	}
	return nil
}

//
// Defaults
//
Loading