Merge "Avoid race condition over ExportedSystemIncludeDirs"
diff --git a/android/apex.go b/android/apex.go
index 30152db..47f07ca 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -124,6 +124,10 @@
 	// 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 @@
 		},
 	})
 }
+
+// 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
+	})
+}
diff --git a/android/hooks.go b/android/hooks.go
index f43a007..85fc081 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -120,6 +120,7 @@
 
 type InstallHookContext interface {
 	ModuleContext
+	SrcPath() Path
 	Path() InstallPath
 	Symlink() bool
 }
@@ -134,10 +135,17 @@
 
 type installHookContext struct {
 	ModuleContext
+	srcPath Path
 	path    InstallPath
 	symlink bool
 }
 
+var _ InstallHookContext = &installHookContext{}
+
+func (x *installHookContext) SrcPath() Path {
+	return x.srcPath
+}
+
 func (x *installHookContext) Path() InstallPath {
 	return x.path
 }
@@ -146,10 +154,11 @@
 	return x.symlink
 }
 
-func (x *hooks) runInstallHooks(ctx ModuleContext, path InstallPath, symlink bool) {
+func (x *hooks) runInstallHooks(ctx ModuleContext, srcPath Path, path InstallPath, symlink bool) {
 	if len(x.install) > 0 {
 		mctx := &installHookContext{
 			ModuleContext: ctx,
+			srcPath:       srcPath,
 			path:          path,
 			symlink:       symlink,
 		}
diff --git a/android/module.go b/android/module.go
index f24047c..ac3394d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1959,7 +1959,7 @@
 	rule blueprint.Rule, deps []Path) InstallPath {
 
 	fullInstallPath := installPath.Join(m, name)
-	m.module.base().hooks.runInstallHooks(m, fullInstallPath, false)
+	m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
 
 	if !m.skipInstall(fullInstallPath) {
 
@@ -1993,7 +1993,7 @@
 
 func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
 	fullInstallPath := installPath.Join(m, name)
-	m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
+	m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
 
 	if !m.skipInstall(fullInstallPath) {
 
@@ -2022,7 +2022,7 @@
 // (e.g. /apex/...)
 func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
 	fullInstallPath := installPath.Join(m, name)
-	m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
+	m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
 
 	if !m.skipInstall(fullInstallPath) {
 		m.Build(pctx, BuildParams{
diff --git a/android/override_module.go b/android/override_module.go
index 7e58890..6b246db 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -42,6 +42,11 @@
 	setOverridingProperties(properties []interface{})
 
 	getOverrideModuleProperties() *OverrideModuleProperties
+
+	// Internal funcs to handle interoperability between override modules and prebuilts.
+	// i.e. cases where an overriding module, too, is overridden by a prebuilt module.
+	setOverriddenByPrebuilt(overridden bool)
+	getOverriddenByPrebuilt() bool
 }
 
 // Base module struct for override module types
@@ -49,6 +54,8 @@
 	moduleProperties OverrideModuleProperties
 
 	overridingProperties []interface{}
+
+	overriddenByPrebuilt bool
 }
 
 type OverrideModuleProperties struct {
@@ -74,6 +81,14 @@
 	return proptools.String(o.moduleProperties.Base)
 }
 
+func (o *OverrideModuleBase) setOverriddenByPrebuilt(overridden bool) {
+	o.overriddenByPrebuilt = overridden
+}
+
+func (o *OverrideModuleBase) getOverriddenByPrebuilt() bool {
+	return o.overriddenByPrebuilt
+}
+
 func InitOverrideModule(m OverrideModule) {
 	m.setOverridingProperties(m.GetProperties())
 
@@ -208,21 +223,24 @@
 // next phase.
 func overrideModuleDepsMutator(ctx BottomUpMutatorContext) {
 	if module, ok := ctx.Module().(OverrideModule); ok {
-		// Skip this overriding module if there's a prebuilt module that overrides it with prefer flag.
-		overriddenByPrebuilt := false
+		base := String(module.getOverrideModuleProperties().Base)
+		if !ctx.OtherModuleExists(base) {
+			ctx.PropertyErrorf("base", "%q is not a valid module name", base)
+			return
+		}
+		// See if there's a prebuilt module that overrides this override module with prefer flag,
+		// in which case we call SkipInstall on the corresponding variant later.
 		ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(dep Module) {
 			prebuilt, ok := dep.(PrebuiltInterface)
 			if !ok {
 				panic("PrebuiltDepTag leads to a non-prebuilt module " + dep.Name())
 			}
 			if prebuilt.Prebuilt().UsePrebuilt() {
-				overriddenByPrebuilt = true
+				module.setOverriddenByPrebuilt(true)
 				return
 			}
 		})
-		if !overriddenByPrebuilt {
-			ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)
-		}
+		ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)
 	}
 }
 
@@ -258,6 +276,10 @@
 		ctx.AliasVariation(variants[0])
 		for i, o := range overrides {
 			mods[i+1].(OverridableModule).override(ctx, o)
+			if o.getOverriddenByPrebuilt() {
+				// The overriding module itself, too, is overridden by a prebuilt. Skip its installation.
+				mods[i+1].SkipInstall()
+			}
 		}
 	} else if o, ok := ctx.Module().(OverrideModule); ok {
 		// Create a variant of the overriding module with its own name. This matches the above local
diff --git a/apex/apex.go b/apex/apex.go
index e308d48..c330f82 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -16,7 +16,6 @@
 
 import (
 	"fmt"
-	"path"
 	"path/filepath"
 	"sort"
 	"strings"
@@ -369,7 +368,6 @@
 		"libbinderthreadstateutils",
 		"libbluetooth-types-header",
 		"libbufferhub_headers",
-		"libc_scudo",
 		"libcodec2",
 		"libcodec2_headers",
 		"libcodec2_hidl@1.0",
@@ -1243,7 +1241,7 @@
 	container_certificate_file android.Path
 	container_private_key_file android.Path
 
-	fileContexts android.Path
+	fileContexts android.WritablePath
 
 	// list of files to be included in this apex
 	filesInfo []apexFile
@@ -1725,13 +1723,8 @@
 	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 +1750,21 @@
 }
 
 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 +1792,7 @@
 		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 +1828,17 @@
 	}
 }
 
+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 +1846,7 @@
 		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 +1921,7 @@
 
 	a.checkApexAvailability(ctx)
 	a.checkUpdatable(ctx)
+	a.checkMinSdkVersion(ctx)
 	a.checkStaticLinkingToStubLibraries(ctx)
 
 	handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
@@ -1936,7 +1955,7 @@
 	})
 
 	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 {
@@ -2175,22 +2194,6 @@
 	a.installDir = android.PathForModuleInstall(ctx, "apex")
 	a.filesInfo = filesInfo
 
-	if a.properties.ApexType != zipApex {
-		if a.properties.File_contexts == nil {
-			a.fileContexts = android.PathForSource(ctx, "system/sepolicy/apex", ctx.ModuleName()+"-file_contexts")
-		} else {
-			a.fileContexts = android.PathForModuleSrc(ctx, *a.properties.File_contexts)
-			if a.Platform() {
-				if matched, err := path.Match("system/sepolicy/**/*", a.fileContexts.String()); err != nil || !matched {
-					ctx.PropertyErrorf("file_contexts", "should be under system/sepolicy, but %q", a.fileContexts)
-				}
-			}
-		}
-		if !android.ExistentPathForSource(ctx, a.fileContexts.String()).Valid() {
-			ctx.PropertyErrorf("file_contexts", "cannot find file_contexts file: %q", a.fileContexts)
-			return
-		}
-	}
 	// Optimization. If we are building bundled APEX, for the files that are gathered due to the
 	// transitive dependencies, don't place them inside the APEX, but place a symlink pointing
 	// the same library in the system partition, thus effectively sharing the same libraries
@@ -2214,6 +2217,8 @@
 	// prepare apex_manifest.json
 	a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)
 
+	a.buildFileContexts(ctx)
+
 	a.setCertificateAndPrivateKey(ctx)
 	if a.properties.ApexType == flattenedApex {
 		a.buildFlattenedApex(ctx)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 3d5886e..f1638c3 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -206,6 +206,7 @@
 	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 @@
 	}{
 		{
 			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 @@
 				key: "myapex.key",
 				use_vendor: true,
 				native_shared_libs: ["mylib"],
-				min_sdk_version: "`+tc.minSdkVersion+`",
+				`+tc.minSdkVersion+`
 			}
 
 			apex_key {
@@ -1140,6 +1141,7 @@
 				system_shared_libs: [],
 				stl: "none",
 				apex_available: [ "myapex" ],
+				min_sdk_version: "29",
 			}
 
 			cc_library {
@@ -1270,24 +1272,24 @@
 	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 @@
 			system_shared_libs: [],
 			stl: "none",
 			apex_available: [ "myapex" ],
+			min_sdk_version: "29",
 		}
 
 		cc_library {
@@ -1310,6 +1313,7 @@
 			system_shared_libs: [],
 			stl: "none",
 			apex_available: [ "otherapex" ],
+			min_sdk_version: "29",
 		}
 
 		cc_library {
@@ -1321,6 +1325,7 @@
 				"//apex_available:anyapex",
 				"//apex_available:platform",
 			],
+			min_sdk_version: "29",
 		}
 
 		cc_library {
@@ -1328,10 +1333,10 @@
 			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 @@
 	}
 	// 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 @@
 			system_shared_libs: [],
 			stl: "none",
 			apex_available: [ "myapex" ],
+			min_sdk_version: "R",
 		}
 
 		cc_library {
@@ -1407,7 +1413,7 @@
 	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 @@
 			name: "libx",
 			shared_libs: ["libbar"],
 			apex_available: [ "myapex" ],
+			min_sdk_version: "29",
 		}
 
 		cc_library {
@@ -1553,6 +1560,7 @@
 		cc_library {
 			name: "libx",
 			apex_available: [ "myapex" ],
+			min_sdk_version: "29",
 		}
 	`)
 
@@ -1564,7 +1572,7 @@
 	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 @@
 			system_shared_libs: [],
 			stl: "none",
 			apex_available: [ "myapex" ],
+			min_sdk_version: "29",
 		}
 
 		cc_library {
@@ -1596,12 +1605,15 @@
 			},
 		}
 	`)
+}
 
-	testApexError(t, `"myapex" .*: min_sdk_version: SDK version should be .*`, `
+func TestApexMinSdkVersion_ErrorIfIncompatibleVersion(t *testing.T) {
+	testApexError(t, `module "mylib".*: should support min_sdk_version\(29\)`, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
-			min_sdk_version: "abc",
+			native_shared_libs: ["mylib"],
+			min_sdk_version: "29",
 		}
 
 		apex_key {
@@ -1609,6 +1621,67 @@
 			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",
+		}
+	`)
+}
+
+func TestApexMinSdkVersion_Okay(t *testing.T) {
+	testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["libfoo"],
+			java_libs: ["libbar"],
+			min_sdk_version: "29",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			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 @@
 					srcs: ["foo/bar/MyClass.java"],
 					sdk_version: "current",
 					apex_available: ["myapex"],
+					min_sdk_version: "29",
 				}
 			`,
 		},
@@ -1728,6 +1802,135 @@
 	}
 }
 
+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 @@
 				"otherapex",
 			],
 			recovery_available: true,
+			min_sdk_version: "29",
 		}
 		cc_library {
 			name: "mylib2",
@@ -2228,6 +2432,7 @@
 				"otherapex",
 			],
 			use_apex_name_macro: true,
+			min_sdk_version: "29",
 		}
 	`)
 
@@ -3275,110 +3480,104 @@
 	}
 }
 
-func TestFileContexts(t *testing.T) {
+func TestFileContexts_FindInDefaultLocationIfNotSet(t *testing.T) {
 	ctx, _ := testApex(t, `
-	apex {
-		name: "myapex",
-		key: "myapex.key",
-	}
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+		}
 
-	apex_key {
-		name: "myapex.key",
-		public_key: "testkey.avbpubkey",
-		private_key: "testkey.pem",
-	}
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
 	`)
 	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
-	apexRule := module.Rule("apexRule")
-	actual := apexRule.Args["file_contexts"]
-	expected := "system/sepolicy/apex/myapex-file_contexts"
-	if actual != expected {
-		t.Errorf("wrong file_contexts. expected %q. actual %q", expected, actual)
-	}
+	rule := module.Output("file_contexts")
+	ensureContains(t, rule.RuleParams.Command, "cat system/sepolicy/apex/myapex-file_contexts")
+}
 
+func TestFileContexts_ShouldBeUnderSystemSepolicyForSystemApexes(t *testing.T) {
 	testApexError(t, `"myapex" .*: file_contexts: should be under system/sepolicy`, `
-	apex {
-		name: "myapex",
-		key: "myapex.key",
-		file_contexts: "my_own_file_contexts",
-	}
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			file_contexts: "my_own_file_contexts",
+		}
 
-	apex_key {
-		name: "myapex.key",
-		public_key: "testkey.avbpubkey",
-		private_key: "testkey.pem",
-	}
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
 	`, withFiles(map[string][]byte{
 		"my_own_file_contexts": nil,
 	}))
+}
 
+func TestFileContexts_ProductSpecificApexes(t *testing.T) {
 	testApexError(t, `"myapex" .*: file_contexts: cannot find`, `
-	apex {
-		name: "myapex",
-		key: "myapex.key",
-		product_specific: true,
-		file_contexts: "product_specific_file_contexts",
-	}
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			product_specific: true,
+			file_contexts: "product_specific_file_contexts",
+		}
 
-	apex_key {
-		name: "myapex.key",
-		public_key: "testkey.avbpubkey",
-		private_key: "testkey.pem",
-	}
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
 	`)
 
-	ctx, _ = testApex(t, `
-	apex {
-		name: "myapex",
-		key: "myapex.key",
-		product_specific: true,
-		file_contexts: "product_specific_file_contexts",
-	}
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			product_specific: true,
+			file_contexts: "product_specific_file_contexts",
+		}
 
-	apex_key {
-		name: "myapex.key",
-		public_key: "testkey.avbpubkey",
-		private_key: "testkey.pem",
-	}
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
 	`, withFiles(map[string][]byte{
 		"product_specific_file_contexts": nil,
 	}))
-	module = ctx.ModuleForTests("myapex", "android_common_myapex_image")
-	apexRule = module.Rule("apexRule")
-	actual = apexRule.Args["file_contexts"]
-	expected = "product_specific_file_contexts"
-	if actual != expected {
-		t.Errorf("wrong file_contexts. expected %q. actual %q", expected, actual)
-	}
+	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+	rule := module.Output("file_contexts")
+	ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
+}
 
-	ctx, _ = testApex(t, `
-	apex {
-		name: "myapex",
-		key: "myapex.key",
-		product_specific: true,
-		file_contexts: ":my-file-contexts",
-	}
+func TestFileContexts_SetViaFileGroup(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			product_specific: true,
+			file_contexts: ":my-file-contexts",
+		}
 
-	apex_key {
-		name: "myapex.key",
-		public_key: "testkey.avbpubkey",
-		private_key: "testkey.pem",
-	}
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
 
-	filegroup {
-		name: "my-file-contexts",
-		srcs: ["product_specific_file_contexts"],
-	}
+		filegroup {
+			name: "my-file-contexts",
+			srcs: ["product_specific_file_contexts"],
+		}
 	`, withFiles(map[string][]byte{
 		"product_specific_file_contexts": nil,
 	}))
-	module = ctx.ModuleForTests("myapex", "android_common_myapex_image")
-	apexRule = module.Rule("apexRule")
-	actual = apexRule.Args["file_contexts"]
-	expected = "product_specific_file_contexts"
-	if actual != expected {
-		t.Errorf("wrong file_contexts. expected %q. actual %q", expected, actual)
-	}
+	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+	rule := module.Output("file_contexts")
+	ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
 }
 
 func TestApexKeyFromOtherModule(t *testing.T) {
@@ -4349,6 +4548,7 @@
 			stl: "libc++",
 			system_shared_libs: [],
 			apex_available: [ "myapex" ],
+			min_sdk_version: "29",
 		}
 	`, withUnbundledBuild)
 
@@ -4749,6 +4949,7 @@
 				"myapex.updatable",
 				"//apex_available:platform",
 			],
+			min_sdk_version: "current",
 		}
 
 		cc_library {
@@ -4761,6 +4962,7 @@
 				"myapex.updatable",
 				"//apex_available:platform",
 			],
+			min_sdk_version: "current",
 		}
 
 		java_library {
@@ -4774,6 +4976,7 @@
 				"myapex.updatable",
 				"//apex_available:platform",
 			],
+			min_sdk_version: "current",
 		}
 
 		java_library {
@@ -4786,6 +4989,7 @@
 				"myapex.updatable",
 				"//apex_available:platform",
 			],
+			min_sdk_version: "current",
 		}
 	`
 
@@ -5393,7 +5597,7 @@
 	apexKeysText := ctx.SingletonForTests("apex_keys_text")
 	content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
 	ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
-	ensureNotContains(t, content, "myapex.apex")
+	ensureContains(t, content, `name="myapex.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
 }
 
 func TestAllowedFiles(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index af43417..ede11d0 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -17,6 +17,7 @@
 import (
 	"encoding/json"
 	"fmt"
+	"path"
 	"path/filepath"
 	"runtime"
 	"sort"
@@ -231,10 +232,42 @@
 	})
 }
 
+func (a *apexBundle) buildFileContexts(ctx android.ModuleContext) {
+	if a.properties.ApexType == zipApex {
+		return
+	}
+	var fileContexts android.Path
+	if a.properties.File_contexts == nil {
+		fileContexts = android.PathForSource(ctx, "system/sepolicy/apex", ctx.ModuleName()+"-file_contexts")
+	} else {
+		fileContexts = android.PathForModuleSrc(ctx, *a.properties.File_contexts)
+	}
+	if a.Platform() {
+		if matched, err := path.Match("system/sepolicy/**/*", fileContexts.String()); err != nil || !matched {
+			ctx.PropertyErrorf("file_contexts", "should be under system/sepolicy, but %q", fileContexts)
+			return
+		}
+	}
+	if !android.ExistentPathForSource(ctx, fileContexts.String()).Valid() {
+		ctx.PropertyErrorf("file_contexts", "cannot find file_contexts file: %q", a.fileContexts)
+		return
+	}
+
+	output := android.PathForModuleOut(ctx, "file_contexts")
+	rule := android.NewRuleBuilder()
+	rule.Command().Text("rm").FlagWithOutput("-f ", output)
+	rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output)
+	rule.Command().Text("echo").Text(">>").Output(output)
+	rule.Command().Text("echo").Flag("/apex_manifest\\\\.pb u:object_r:system_file:s0").Text(">>").Output(output)
+	rule.Build(pctx, ctx, "file_contexts."+a.Name(), "Generate file_contexts")
+
+	a.fileContexts = output.OutputPath
+}
+
 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 +766,7 @@
 	}
 
 	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.
diff --git a/apex/key.go b/apex/key.go
index a68f6e1..d2d5786 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -160,12 +160,6 @@
 				presigned: true,
 				partition: m.PartitionTag(ctx.DeviceConfig()),
 			}
-
-			for _, om := range m.Overrides() {
-				if _, ok := apexKeyMap[om]; ok {
-					delete(apexKeyMap, om)
-				}
-			}
 			apexKeyMap[m.BaseModuleName()] = entry
 		}
 	})
diff --git a/cc/cc.go b/cc/cc.go
index ebdb46c..c3b0d88 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2905,6 +2905,54 @@
 	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
 //
diff --git a/cc/linker.go b/cc/linker.go
index c9cbd9b..58f8a29 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -298,17 +298,6 @@
 			}
 		}
 
-		if inList("libc_scudo", deps.SharedLibs) {
-			// libc_scudo is an alternate implementation of all
-			// allocation functions (malloc, free), that uses
-			// the scudo allocator instead of the default native
-			// allocator. If this library is in the list, make
-			// sure it's first so it properly overrides the
-			// allocation functions of all other shared libraries.
-			_, deps.SharedLibs = removeFromList("libc_scudo", deps.SharedLibs)
-			deps.SharedLibs = append([]string{"libc_scudo"}, deps.SharedLibs...)
-		}
-
 		// If libc and libdl are both in system_shared_libs make sure libdl comes after libc
 		// to avoid loading libdl before libc.
 		if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index c4d7708..acdc581 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -145,6 +145,7 @@
 		libraryDecorator: library,
 	}
 	module.installer = nil
+	module.Properties.Sdk_version = StringPtr("minimum")
 	module.Properties.HideFromMake = true
 	module.Properties.AlwaysSdk = true
 	module.Properties.Sdk_version = StringPtr("current")
diff --git a/cc/sanitize.go b/cc/sanitize.go
index aaaf694..72ad6d7 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -408,16 +408,6 @@
 		return deps
 	}
 
-	if ctx.Device() {
-		if Bool(sanitize.Properties.Sanitize.Address) {
-			// Compiling asan and having libc_scudo in the same
-			// executable will cause the executable to crash.
-			// Remove libc_scudo since it is only used to override
-			// allocation functions which asan already overrides.
-			_, deps.SharedLibs = removeFromList("libc_scudo", deps.SharedLibs)
-		}
-	}
-
 	return deps
 }
 
diff --git a/cc/testing.go b/cc/testing.go
index 479b424..b5cf45c 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -273,6 +273,7 @@
 			vendor_available: true,
 			recovery_available: true,
 			host_supported: true,
+			min_sdk_version: "29",
 			apex_available: [
 				"//apex_available:platform",
 				"//apex_available:anyapex",
@@ -287,6 +288,7 @@
 			vendor_available: true,
 			recovery_available: true,
 			host_supported: true,
+			min_sdk_version: "29",
 			vndk: {
 				enabled: true,
 				support_system_process: true,
@@ -305,6 +307,7 @@
 			host_supported: false,
 			vendor_available: true,
 			recovery_available: true,
+			min_sdk_version: "29",
 			apex_available: [
 				"//apex_available:platform",
 				"//apex_available:anyapex",
@@ -338,6 +341,7 @@
 			recovery_available: true,
 			vendor_available: true,
 			native_bridge_supported: true,
+			min_sdk_version: "29",
 			stl: "none",
 		}
 
@@ -365,6 +369,7 @@
 			recovery_available: true,
 			vendor_available: true,
 			native_bridge_supported: true,
+			min_sdk_version: "29",
 			stl: "none",
 		}
 
diff --git a/genrule/genrule.go b/genrule/genrule.go
index f6904f1..8b80871 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -559,6 +559,12 @@
 	}
 }
 
+func (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+	// Because generated outputs are checked by client modules(e.g. cc_library, ...)
+	// we can safely ignore the check here.
+	return nil
+}
+
 func generatorFactory(taskGenerator taskFunc, props ...interface{}) *Module {
 	module := &Module{
 		taskGenerator: taskGenerator,
diff --git a/java/aar.go b/java/aar.go
index 074ead4..500788f 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -762,6 +762,10 @@
 	return a.depIsInSameApex(ctx, dep)
 }
 
+func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+	return nil
+}
+
 var _ android.PrebuiltInterface = (*Import)(nil)
 
 // android_library_import imports an `.aar` file into the build graph as if it was built with android_library.
diff --git a/java/app.go b/java/app.go
index c568516..37a6453 100755
--- a/java/app.go
+++ b/java/app.go
@@ -421,8 +421,10 @@
 		if String(a.deviceProperties.Min_sdk_version) == "" {
 			ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.")
 		}
+
 		if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil {
 			a.checkJniLibsSdkVersion(ctx, minSdkVersion)
+			android.CheckMinSdkVersion(a, ctx, int(minSdkVersion))
 		} else {
 			ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
 		}
@@ -862,13 +864,13 @@
 	return jniLibs, certificates
 }
 
-func (a *AndroidApp) walkPayloadDeps(ctx android.ModuleContext,
-	do func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool)) {
-
+func (a *AndroidApp) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) {
 	ctx.WalkDeps(func(child, parent android.Module) bool {
 		isExternal := !a.DepIsInSameApex(ctx, child)
 		if am, ok := child.(android.ApexModule); ok {
-			do(ctx, parent, am, isExternal)
+			if !do(ctx, parent, am, isExternal) {
+				return false
+			}
 		}
 		return !isExternal
 	})
@@ -880,7 +882,7 @@
 	}
 
 	depsInfo := android.DepNameToDepInfoMap{}
-	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+	a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
 		depName := to.Name()
 		if info, exist := depsInfo[depName]; exist {
 			info.From = append(info.From, from.Name())
@@ -900,6 +902,7 @@
 				MinSdkVersion: toMinSdkVersion,
 			}
 		}
+		return true
 	})
 
 	a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(), depsInfo)
@@ -1563,6 +1566,11 @@
 	return sdkSpecFrom("")
 }
 
+func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+	// Do not check for prebuilts against the min_sdk_version of enclosing APEX
+	return nil
+}
+
 func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
 	props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
 
diff --git a/java/app_test.go b/java/app_test.go
index e45ba70..120dc00 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -473,6 +473,24 @@
 	}
 }
 
+func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) {
+	testJavaError(t, `module "bar".*: should support min_sdk_version\(29\)`, cc.GatherRequiredDepsForTest(android.Android)+`
+		android_app {
+			name: "foo",
+			srcs: ["a.java"],
+			updatable: true,
+			sdk_version: "current",
+			min_sdk_version: "29",
+			static_libs: ["bar"],
+		}
+
+		java_library {
+			name: "bar",
+			sdk_version: "current",
+		}
+	`)
+}
+
 func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) {
 	testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		android_app {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 7f1afd6..f1b7178 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -173,7 +173,7 @@
 			profileBootListing = android.ExistentPathForSource(ctx,
 				ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot")
 			profileIsTextListing = true
-		} else {
+		} else if global.ProfileDir != "" {
 			profileClassListing = android.ExistentPathForSource(ctx,
 				global.ProfileDir, ctx.ModuleName()+".prof")
 		}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index a0b7edf..73b897a 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1325,7 +1325,6 @@
 			cmd.Flag("--exclude-documentation-from-stubs")
 		}
 	}
-	cmd.FlagWithArg("--hide ", "ShowingMemberInHiddenClass") // b/159121253 -- remove it once all the violations are fixed.
 }
 
 func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
diff --git a/java/java.go b/java/java.go
index 7a42557..5b31630 100644
--- a/java/java.go
+++ b/java/java.go
@@ -44,7 +44,7 @@
 			PropertyName: "java_libs",
 		},
 		func(j *Library) android.Path {
-			implementationJars := j.ImplementationJars()
+			implementationJars := j.ImplementationAndResourcesJars()
 			if len(implementationJars) != 1 {
 				panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
 			}
@@ -1887,6 +1887,24 @@
 	return j.depIsInSameApex(ctx, dep)
 }
 
+func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+	sdkSpec := j.minSdkVersion()
+	if !sdkSpec.specified() {
+		return fmt.Errorf("min_sdk_version is not specified")
+	}
+	if sdkSpec.kind == sdkCore {
+		return nil
+	}
+	ver, err := sdkSpec.effectiveVersion(ctx)
+	if err != nil {
+		return err
+	}
+	if int(ver) > sdkVersion {
+		return fmt.Errorf("newer SDK(%v)", ver)
+	}
+	return nil
+}
+
 func (j *Module) Stem() string {
 	return proptools.StringDefault(j.deviceProperties.Stem, j.Name())
 }
@@ -2651,6 +2669,11 @@
 	return j.depIsInSameApex(ctx, dep)
 }
 
+func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+	// Do not check for prebuilts against the min_sdk_version of enclosing APEX
+	return nil
+}
+
 // Add compile time check for interface implementation
 var _ android.IDEInfo = (*Import)(nil)
 var _ android.IDECustomizedModuleName = (*Import)(nil)
@@ -2820,6 +2843,11 @@
 	return j.dexJarFile
 }
 
+func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+	// we don't check prebuilt modules for sdk_version
+	return nil
+}
+
 // dex_import imports a `.jar` file containing classes.dex files.
 //
 // A dex_import module cannot be used as a dependency of a java_* or android_* module, it can only be installed
diff --git a/java/lint.go b/java/lint.go
index fac9a19..b73d6a5 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -88,7 +88,7 @@
 }
 
 func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
-	rule *android.RuleBuilder) (projectXMLPath, configXMLPath, cacheDir android.WritablePath, deps android.Paths) {
+	rule *android.RuleBuilder) (projectXMLPath, configXMLPath, cacheDir, homeDir android.WritablePath, deps android.Paths) {
 
 	var resourcesList android.WritablePath
 	if len(l.resources) > 0 {
@@ -106,6 +106,7 @@
 	// Lint looks for a lint.xml file next to the project.xml file, give it one.
 	configXMLPath = android.PathForModuleOut(ctx, "lint", "lint.xml")
 	cacheDir = android.PathForModuleOut(ctx, "lint", "cache")
+	homeDir = android.PathForModuleOut(ctx, "lint", "home")
 
 	srcJarDir := android.PathForModuleOut(ctx, "lint-srcjars")
 	srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars)
@@ -154,8 +155,11 @@
 	cmd.FlagForEachArg("--extra_checks_jar ", l.extraLintCheckJars.Strings())
 	deps = append(deps, l.extraLintCheckJars...)
 
-	// The cache tag in project.xml is relative to the project.xml file.
-	cmd.FlagWithArg("--cache_dir ", "cache")
+	cmd.FlagWithArg("--root_dir ", "$PWD")
+
+	// The cache tag in project.xml is relative to the root dir, or the project.xml file if
+	// the root dir is not set.
+	cmd.FlagWithArg("--cache_dir ", cacheDir.String())
 
 	cmd.FlagWithInput("@",
 		android.PathForSource(ctx, "build/soong/java/lint_defaults.txt"))
@@ -165,7 +169,7 @@
 	cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
 	cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
 
-	return projectXMLPath, configXMLPath, cacheDir, deps
+	return projectXMLPath, configXMLPath, cacheDir, homeDir, deps
 }
 
 // generateManifest adds a command to the rule to write a dummy manifest cat contains the
@@ -207,18 +211,19 @@
 		l.manifest = manifest
 	}
 
-	projectXML, lintXML, cacheDir, deps := l.writeLintProjectXML(ctx, rule)
+	projectXML, lintXML, cacheDir, homeDir, deps := l.writeLintProjectXML(ctx, rule)
 
 	l.outputs.html = android.PathForModuleOut(ctx, "lint-report.html")
 	l.outputs.text = android.PathForModuleOut(ctx, "lint-report.txt")
 	l.outputs.xml = android.PathForModuleOut(ctx, "lint-report.xml")
 
-	rule.Command().Text("rm -rf").Flag(cacheDir.String())
-	rule.Command().Text("mkdir -p").Flag(cacheDir.String())
+	rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
+	rule.Command().Text("mkdir -p").Flag(cacheDir.String()).Flag(homeDir.String())
 
 	rule.Command().
 		Text("(").
 		Flag("JAVA_OPTS=-Xmx2048m").
+		FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()).
 		FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath(ctx)).
 		FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXmlPath(ctx)).
 		Tool(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/bin/lint")).
@@ -239,7 +244,7 @@
 		Text("|| (").Text("cat").Input(l.outputs.text).Text("; exit 7)").
 		Text(")")
 
-	rule.Command().Text("rm -rf").Flag(cacheDir.String())
+	rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
 
 	rule.Build(pctx, ctx, "lint", "lint")
 }
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 676557e..91869ed 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1905,6 +1905,11 @@
 	return false
 }
 
+func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+	// we don't check prebuilt modules for sdk_version
+	return nil
+}
+
 func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
 	return module.commonOutputFiles(tag)
 }
@@ -2071,6 +2076,11 @@
 	// do nothing
 }
 
+func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+	// sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked
+	return nil
+}
+
 // File path to the runtime implementation library
 func (module *sdkLibraryXml) implPath() string {
 	implName := proptools.String(module.properties.Lib_name)
diff --git a/python/python.go b/python/python.go
index 8b912be..a6c9e2a 100644
--- a/python/python.go
+++ b/python/python.go
@@ -251,6 +251,18 @@
 	return android.OptionalPathForPath(p.installer.(*binaryDecorator).path)
 }
 
+func (p *Module) OutputFiles(tag string) (android.Paths, error) {
+	switch tag {
+	case "":
+		if outputFile := p.installSource; outputFile.Valid() {
+			return android.Paths{outputFile.Path()}, nil
+		}
+		return android.Paths{}, nil
+	default:
+		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+	}
+}
+
 func (p *Module) isEmbeddedLauncherEnabled(actual_version string) bool {
 	switch actual_version {
 	case pyVersion2:
diff --git a/scripts/lint-project-xml.py b/scripts/lint-project-xml.py
index 7ab4f01..38c57ca 100755
--- a/scripts/lint-project-xml.py
+++ b/scripts/lint-project-xml.py
@@ -77,6 +77,8 @@
                       help='mark the module as a test.')
   parser.add_argument('--cache_dir', dest='cache_dir',
                       help='directory to use for cached file.')
+  parser.add_argument('--root_dir', dest='root_dir',
+                      help='directory to use for root dir.')
   group = parser.add_argument_group('check arguments', 'later arguments override earlier ones.')
   group.add_argument('--fatal_check', dest='checks', action=check_action('fatal'), default=[],
                      help='treat a lint issue as a fatal error.')
@@ -162,6 +164,8 @@
 
   f.write("<?xml version='1.0' encoding='utf-8'?>\n")
   f.write("<project>\n")
+  if args.root_dir:
+    f.write("  <root dir='%s' />\n" % args.root_dir)
   f.write("  <module name='%s' android='true' %sdesugar='full' >\n" % (args.name, "library='true' " if args.library else ""))
   if args.manifest:
     f.write("    <manifest file='%s' %s/>\n" % (args.manifest, test_attr))
diff --git a/scripts/rustfmt.toml b/scripts/rustfmt.toml
new file mode 100644
index 0000000..617d425
--- /dev/null
+++ b/scripts/rustfmt.toml
@@ -0,0 +1,5 @@
+# Android Format Style
+
+edition = "2018"
+use_small_heuristics = "Max"
+newline_style = "Unix"
diff --git a/scripts/transitive-deps.sh b/scripts/transitive-deps.sh
index c6f8b76..ba36ba4 100755
--- a/scripts/transitive-deps.sh
+++ b/scripts/transitive-deps.sh
@@ -56,7 +56,7 @@
                     temporary / intermediate files.
   -sep=<delim>      Use 'delim' as output field separator between notice
                     checksum and notice filename in notice output.
-                    e.g. sep='\t'
+                    e.g. sep='\\t'
                     (Default space)
   -csv              Shorthand for -sep=','
   -directories=<f>  Output directory names of dependencies to 'f'.
@@ -280,7 +280,7 @@
           notices=)
             notices_out=$(expr "${flag}" : '^.*=\(.*\)$');;
           *)
-            die "Unknown flag ${1}";;
+            die "${usage}\n\nUnknown flag ${1}";;
         esac
       ;;
       *)
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 77a4e94..7496b20 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -23,6 +23,7 @@
 
 	fs := map[string][]byte{
 		"Test.java":              nil,
+		"resource.test":          nil,
 		"aidl/foo/bar/Test.aidl": nil,
 
 		// For java_sdk_library
@@ -348,6 +349,7 @@
 		java_library {
 			name: "myjavalib",
 			srcs: ["Test.java"],
+			java_resources: ["resource.txt"],
 			aidl: {
 				export_include_dirs: ["aidl"],
 			},
@@ -381,7 +383,7 @@
 
 `),
 		checkAllCopyRules(`
-.intermediates/myjavalib/android_common/javac/myjavalib.jar -> java/myjavalib.jar
+.intermediates/myjavalib/android_common/withres/myjavalib.jar -> java/myjavalib.jar
 aidl/foo/bar/Test.aidl -> aidl/aidl/foo/bar/Test.aidl
 `),
 	)
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 7bb267d..f28b2b6 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -107,6 +107,8 @@
 
 	testProperties TestProperties
 
+	installDir android.InstallPath
+
 	data       android.Paths
 	testConfig android.Path
 }
@@ -176,13 +178,13 @@
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(entries *android.AndroidMkEntries) {
 				s.customAndroidMkEntries(entries)
+				entries.SetString("LOCAL_MODULE_RELATIVE_PATH", proptools.String(s.properties.Sub_dir))
 			},
 		},
 	}}
 }
 
 func (s *ShBinary) customAndroidMkEntries(entries *android.AndroidMkEntries) {
-	entries.SetString("LOCAL_MODULE_RELATIVE_PATH", proptools.String(s.properties.Sub_dir))
 	entries.SetString("LOCAL_MODULE_SUFFIX", "")
 	entries.SetString("LOCAL_MODULE_STEM", s.outputFilePath.Rel())
 	if len(s.properties.Symlinks) > 0 {
@@ -201,8 +203,14 @@
 	} else if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
 		testDir = filepath.Join(testDir, ctx.Arch().ArchType.String())
 	}
-	installDir := android.PathForModuleInstall(ctx, testDir, proptools.String(s.properties.Sub_dir))
-	s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
+	if s.SubDir() != "" {
+		// Don't add the module name to the installation path if sub_dir is specified for backward
+		// compatibility.
+		s.installDir = android.PathForModuleInstall(ctx, testDir, s.SubDir())
+	} else {
+		s.installDir = android.PathForModuleInstall(ctx, testDir, s.Name())
+	}
+	s.installedFile = ctx.InstallExecutable(s.installDir, s.outputFilePath.Base(), s.outputFilePath)
 
 	s.data = android.PathsForModuleSrc(ctx, s.testProperties.Data)
 
@@ -229,7 +237,7 @@
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(entries *android.AndroidMkEntries) {
 				s.customAndroidMkEntries(entries)
-
+				entries.SetPath("LOCAL_MODULE_PATH", s.installDir.ToMakePath())
 				entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...)
 				if s.testConfig != nil {
 					entries.SetPath("LOCAL_FULL_TEST_CONFIG", s.testConfig)
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index 6c0d96a..3bfe611 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -55,7 +55,27 @@
 	return ctx, config
 }
 
-func TestShTestTestData(t *testing.T) {
+func TestShTestSubDir(t *testing.T) {
+	ctx, config := testShBinary(t, `
+		sh_test {
+			name: "foo",
+			src: "test.sh",
+			sub_dir: "foo_test"
+		}
+	`)
+
+	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
+
+	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+
+	expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo_test"
+	actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
+	if expectedPath != actualPath {
+		t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath)
+	}
+}
+
+func TestShTest(t *testing.T) {
 	ctx, config := testShBinary(t, `
 		sh_test {
 			name: "foo",
@@ -71,10 +91,17 @@
 	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
 
 	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
-	expected := []string{":testdata/data1", ":testdata/sub/data2"}
-	actual := entries.EntryMap["LOCAL_TEST_DATA"]
-	if !reflect.DeepEqual(expected, actual) {
-		t.Errorf("Unexpected test data expected: %q, actual: %q", expected, actual)
+
+	expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo"
+	actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
+	if expectedPath != actualPath {
+		t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath)
+	}
+
+	expectedData := []string{":testdata/data1", ":testdata/sub/data2"}
+	actualData := entries.EntryMap["LOCAL_TEST_DATA"]
+	if !reflect.DeepEqual(expectedData, actualData) {
+		t.Errorf("Unexpected test data expected: %q, actual: %q", expectedData, actualData)
 	}
 }
 
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 9f27647..768c8e5 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -310,6 +310,10 @@
 		}}
 }
 
+func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+	return fmt.Errorf("sysprop_library is not supposed to be part of apex modules")
+}
+
 // sysprop_library creates schematized APIs from sysprop description files (.sysprop).
 // Both Java and C++ modules can link against sysprop_library, and API stability check
 // against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh)