Merge "Add a better error message for missing api files"
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 2ee9c42..4a25119 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -371,7 +371,11 @@
 	var cqueryOutput string
 	var err error
 
-	err = os.Mkdir(absolutePath(context.intermediatesDir()), 0777)
+	intermediatesDirPath := absolutePath(context.intermediatesDir())
+	if _, err := os.Stat(intermediatesDirPath); os.IsNotExist(err) {
+		err = os.Mkdir(intermediatesDirPath, 0777)
+	}
+
 	if err != nil {
 		return err
 	}
diff --git a/android/config.go b/android/config.go
index 1f52b6c..8090889 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1026,6 +1026,10 @@
 	return c.multilibConflicts[arch]
 }
 
+func (c *config) PrebuiltHiddenApiDir(ctx PathContext) string {
+	return String(c.productVariables.PrebuiltHiddenApiDir)
+}
+
 func (c *deviceConfig) Arches() []Arch {
 	var arches []Arch
 	for _, target := range c.config.Targets[Android] {
diff --git a/android/module.go b/android/module.go
index 17035bb..d189d1a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2434,10 +2434,6 @@
 	m.commonProperties.System_ext_specific = boolPtr(false)
 }
 
-func (m *ModuleBase) EnableNativeBridgeSupportByDefault() {
-	m.commonProperties.Native_bridge_supported = boolPtr(true)
-}
-
 func (m *ModuleBase) MakeAsSystemExt() {
 	m.commonProperties.Vendor = boolPtr(false)
 	m.commonProperties.Proprietary = boolPtr(false)
diff --git a/android/neverallow.go b/android/neverallow.go
index 031b3f4..7455e6a 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -51,7 +51,6 @@
 func init() {
 	AddNeverAllowRules(createIncludeDirsRules()...)
 	AddNeverAllowRules(createTrebleRules()...)
-	AddNeverAllowRules(createMediaRules()...)
 	AddNeverAllowRules(createJavaDeviceForHostRules()...)
 	AddNeverAllowRules(createCcSdkVariantRules()...)
 	AddNeverAllowRules(createUncompressDexRules()...)
@@ -132,14 +131,6 @@
 	}
 }
 
-func createMediaRules() []Rule {
-	return []Rule{
-		NeverAllow().
-			With("libs", "updatable-media").
-			Because("updatable-media includes private APIs. Use updatable_media_stubs instead."),
-	}
-}
-
 func createJavaDeviceForHostRules() []Rule {
 	javaDeviceForHostProjectsAllowedList := []string{
 		"external/guava",
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 8c7a538..b761065 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -190,19 +190,6 @@
 		},
 	},
 	{
-		name: "dependency on updatable-media",
-		fs: map[string][]byte{
-			"Android.bp": []byte(`
-				java_library {
-					name: "needs_updatable_media",
-					libs: ["updatable-media"],
-				}`),
-		},
-		expectedErrors: []string{
-			"updatable-media includes private APIs. Use updatable_media_stubs instead.",
-		},
-	},
-	{
 		name: "java_device_for_host",
 		fs: map[string][]byte{
 			"Android.bp": []byte(`
diff --git a/android/variable.go b/android/variable.go
index 48c4be6..9b3ed17 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -367,6 +367,8 @@
 	BoardKernelModuleInterfaceVersions []string `json:",omitempty"`
 
 	BoardMoveRecoveryResourcesToVendorBoot *bool `json:",omitempty"`
+
+	PrebuiltHiddenApiDir *string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
@@ -438,13 +440,15 @@
 
 	variableValues := reflect.ValueOf(a.variableProperties).Elem().FieldByName("Product_variables")
 
+	productVariables := reflect.ValueOf(mctx.Config().productVariables)
+
 	for i := 0; i < variableValues.NumField(); i++ {
 		variableValue := variableValues.Field(i)
 		name := variableValues.Type().Field(i).Name
 		property := "product_variables." + proptools.PropertyNameForField(name)
 
 		// Check that the variable was set for the product
-		val := reflect.ValueOf(mctx.Config().productVariables).FieldByName(name)
+		val := productVariables.FieldByName(name)
 		if !val.IsValid() || val.Kind() != reflect.Ptr || val.IsNil() {
 			continue
 		}
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 81691f1..a5cfb83 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -572,6 +572,7 @@
 prebuilt_libunwind(minSdkVersion:(no version))
 prebuilt_test_framework-sdkextensions(minSdkVersion:(no version))
 server_configurable_flags(minSdkVersion:29)
+service-media-s(minSdkVersion:29)
 service-permission(minSdkVersion:current)
 service-statsd(minSdkVersion:current)
 SettingsLibActionBarShadow(minSdkVersion:21)
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 0b114f8..4408283 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -126,8 +126,18 @@
 
 		moduleName := a.fullModuleName(apexBundleName, &fi)
 
-		if !android.InList(moduleName, moduleNames) {
-			moduleNames = append(moduleNames, moduleName)
+		// This name will be added to LOCAL_REQUIRED_MODULES of the APEX. We need to be
+		// arch-specific otherwise we will end up installing both ABIs even when only
+		// either of the ABI is requested.
+		aName := moduleName
+		switch fi.multilib {
+		case "lib32":
+			aName = aName + ":32"
+		case "lib64":
+			aName = aName + ":64"
+		}
+		if !android.InList(aName, moduleNames) {
+			moduleNames = append(moduleNames, aName)
 		}
 
 		if linkToSystemLib {
diff --git a/apex/apex.go b/apex/apex.go
index 4a9a9a3..507d3ed 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -29,6 +29,7 @@
 	"android/soong/android"
 	"android/soong/bpf"
 	"android/soong/cc"
+	"android/soong/dexpreopt"
 	prebuilt_etc "android/soong/etc"
 	"android/soong/filesystem"
 	"android/soong/java"
@@ -440,6 +441,8 @@
 	transitiveDep bool
 	isJniLib      bool
 
+	multilib string
+
 	// TODO(jiyong): remove this
 	module android.Module
 }
@@ -459,6 +462,7 @@
 		ret.requiredModuleNames = module.RequiredModuleNames()
 		ret.targetRequiredModuleNames = module.TargetRequiredModuleNames()
 		ret.hostRequiredModuleNames = module.HostRequiredModuleNames()
+		ret.multilib = module.Target().Arch.ArchType.Multilib
 	}
 	return ret
 }
@@ -720,9 +724,15 @@
 	ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
 	ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
 
-	// With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
-	if a.artApex && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
-		ctx.AddFarVariationDependencies(commonVariation, javaLibTag, "jacocoagent")
+	if a.artApex {
+		// With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
+		if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+			ctx.AddFarVariationDependencies(commonVariation, javaLibTag, "jacocoagent")
+		}
+		// The ART boot image depends on dex2oat to compile it.
+		if !java.SkipDexpreoptBootJars(ctx) {
+			dexpreopt.RegisterToolDeps(ctx)
+		}
 	}
 
 	// Dependencies for signing
@@ -1428,6 +1438,7 @@
 }
 
 var _ javaModule = (*java.Library)(nil)
+var _ javaModule = (*java.Import)(nil)
 var _ javaModule = (*java.SdkLibrary)(nil)
 var _ javaModule = (*java.DexImport)(nil)
 var _ javaModule = (*java.SdkLibraryImport)(nil)
@@ -1520,6 +1531,9 @@
 		if dt, ok := depTag.(dependencyTag); ok && !dt.payload {
 			return false
 		}
+		if depTag == dexpreopt.Dex2oatDepTag {
+			return false
+		}
 
 		ai := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo)
 		externalDep := !android.InList(ctx.ModuleName(), ai.InApexes)
@@ -1629,7 +1643,7 @@
 				}
 			case javaLibTag:
 				switch child.(type) {
-				case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport:
+				case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
 					af := apexFileForJavaModule(ctx, child.(javaModule))
 					if !af.ok() {
 						ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
@@ -1841,10 +1855,10 @@
 		return
 	}
 
-	// Specific to the ART apex: dexpreopt artifacts for libcore Java libraries. Build rules are
-	// generated by the dexpreopt singleton, and here we access build artifacts via the global
-	// boot image config.
 	if a.artApex {
+		// Specific to the ART apex: dexpreopt artifacts for libcore Java libraries. Build rules are
+		// generated by the dexpreopt singleton, and here we access build artifacts via the global
+		// boot image config.
 		for arch, files := range java.DexpreoptedArtApexJars(ctx) {
 			dirInApex := filepath.Join("javalib", arch.String())
 			for _, f := range files {
@@ -1853,6 +1867,11 @@
 				filesInfo = append(filesInfo, af)
 			}
 		}
+		// Call GetGlobalSoongConfig to initialize it, which may be necessary if dexpreopt is
+		// disabled for libraries/apps, but boot images are still needed.
+		if !java.SkipDexpreoptBootJars(ctx) {
+			dexpreopt.GetGlobalSoongConfig(ctx)
+		}
 	}
 
 	// Remove duplicates in filesInfo
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 42b2404..d288414 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4515,6 +4515,34 @@
 	`)
 }
 
+func TestApexWithJavaImport(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			java_libs: ["myjavaimport"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_import {
+			name: "myjavaimport",
+			apex_available: ["myapex"],
+			jars: ["my.jar"],
+			compile_dex: true,
+		}
+	`)
+
+	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+	apexRule := module.Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+	ensureContains(t, copyCmds, "image.apex/javalib/myjavaimport.jar")
+}
+
 func TestApexWithApps(t *testing.T) {
 	ctx, _ := testApex(t, `
 		apex {
@@ -5652,7 +5680,7 @@
 	ensureNotContains(t, androidMk, "LOCAL_MODULE := prebuilt_myotherlib.myapex\n")
 	ensureNotContains(t, androidMk, "LOCAL_MODULE := myotherlib.myapex\n")
 	// `myapex` should have `myotherlib` in its required line, not `prebuilt_myotherlib`
-	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += mylib.myapex myotherlib apex_manifest.pb.myapex apex_pubkey.myapex\n")
+	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += mylib.myapex:64 myotherlib:64 apex_manifest.pb.myapex apex_pubkey.myapex\n")
 }
 
 func TestApexWithJniLibs(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index bc1b566..e6bc3bd 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -786,6 +786,9 @@
 		compressRule.Build("compressRule", "Generate unsigned compressed APEX file")
 
 		signedCompressedOutputFile := android.PathForModuleOut(ctx, a.Name()+".capex")
+		if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_SIGNAPK") {
+			args["outCommaList"] = signedCompressedOutputFile.String()
+		}
 		ctx.Build(pctx, android.BuildParams{
 			Rule:        rule,
 			Description: "sign compressedApex",
diff --git a/cc/cc.go b/cc/cc.go
index 90335b3..75b13fd 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -256,11 +256,27 @@
 	// Deprecated. true is the default, false is invalid.
 	Clang *bool `android:"arch_variant"`
 
-	// Minimum sdk version supported when compiling against the ndk. Setting this property causes
-	// two variants to be built, one for the platform and one for apps.
+	// The API level that this module is built against. The APIs of this API level will be
+	// visible at build time, but use of any APIs newer than min_sdk_version will render the
+	// module unloadable on older devices.  In the future it will be possible to weakly-link new
+	// APIs, making the behavior match Java: such modules will load on older devices, but
+	// calling new APIs on devices that do not support them will result in a crash.
+	//
+	// This property has the same behavior as sdk_version does for Java modules. For those
+	// familiar with Android Gradle, the property behaves similarly to how compileSdkVersion
+	// does for Java code.
+	//
+	// In addition, setting this property causes two variants to be built, one for the platform
+	// and one for apps.
 	Sdk_version *string
 
-	// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+	// Minimum OS API level supported by this C or C++ module. This property becomes the value
+	// of the __ANDROID_API__ macro. When the C or C++ module is included in an APEX or an APK,
+	// this property is also used to ensure that the min_sdk_version of the containing module is
+	// not older (i.e. less) than this module's min_sdk_version. When not set, this property
+	// defaults to the value of sdk_version.  When this is set to "apex_inherit", this tracks
+	// min_sdk_version of the containing APEX. When the module
+	// is not built for an APEX, "apex_inherit" defaults to sdk_version.
 	Min_sdk_version *string
 
 	// If true, always create an sdk variant and don't create a platform variant.
@@ -441,6 +457,8 @@
 	canUseSdk() bool
 	useSdk() bool
 	sdkVersion() string
+	minSdkVersion() string
+	isSdkVariant() bool
 	useVndk() bool
 	isNdk(config android.Config) bool
 	IsLlndk() bool
@@ -469,6 +487,7 @@
 	nativeCoverage() bool
 	directlyInAnyApex() bool
 	isPreventInstall() bool
+	isCfiAssemblySupportEnabled() bool
 }
 
 type ModuleContext interface {
@@ -1058,7 +1077,8 @@
 }
 
 func (c *Module) canUseSdk() bool {
-	return c.Os() == android.Android && !c.UseVndk() && !c.InRamdisk() && !c.InRecovery() && !c.InVendorRamdisk()
+	return c.Os() == android.Android && c.Target().NativeBridge == android.NativeBridgeDisabled &&
+		!c.UseVndk() && !c.InRamdisk() && !c.InRecovery() && !c.InVendorRamdisk()
 }
 
 func (c *Module) UseSdk() bool {
@@ -1243,6 +1263,11 @@
 	return c.kytheFiles
 }
 
+func (c *Module) isCfiAssemblySupportEnabled() bool {
+	return c.sanitize != nil &&
+		Bool(c.sanitize.Properties.Sanitize.Config.Cfi_assembly_support)
+}
+
 type baseModuleContext struct {
 	android.BaseModuleContext
 	moduleContextImpl
@@ -1313,6 +1338,29 @@
 	return ""
 }
 
+func (ctx *moduleContextImpl) minSdkVersion() string {
+	ver := ctx.mod.MinSdkVersion()
+	if ver == "apex_inherit" && !ctx.isForPlatform() {
+		ver = ctx.apexSdkVersion().String()
+	}
+	if ver == "apex_inherit" || ver == "" {
+		ver = ctx.sdkVersion()
+	}
+	// Also make sure that minSdkVersion is not greater than sdkVersion, if they are both numbers
+	sdkVersionInt, err := strconv.Atoi(ctx.sdkVersion())
+	minSdkVersionInt, err2 := strconv.Atoi(ver)
+	if err == nil && err2 == nil {
+		if sdkVersionInt < minSdkVersionInt {
+			return strconv.Itoa(sdkVersionInt)
+		}
+	}
+	return ver
+}
+
+func (ctx *moduleContextImpl) isSdkVariant() bool {
+	return ctx.mod.IsSdkVariant()
+}
+
 func (ctx *moduleContextImpl) useVndk() bool {
 	return ctx.mod.UseVndk()
 }
@@ -1408,6 +1456,10 @@
 	return ctx.mod.Properties.PreventInstall
 }
 
+func (ctx *moduleContextImpl) isCfiAssemblySupportEnabled() bool {
+	return ctx.mod.isCfiAssemblySupportEnabled()
+}
+
 func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
 	return &Module{
 		hod:      hod,
diff --git a/cc/cc_test.go b/cc/cc_test.go
index eef13da..0cd83a7 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -4543,137 +4543,309 @@
 	}
 }
 
-func checkHasImplicitDep(t *testing.T, m android.TestingModule, name string) {
-	implicits := m.Rule("ld").Implicits
-	for _, lib := range implicits {
-		if strings.Contains(lib.Rel(), name) {
-			return
-		}
-	}
+type MemtagNoteType int
 
-	t.Errorf("%q is not found in implicit deps of module %q", name, m.Module().(*Module).Name())
-}
+const (
+	None MemtagNoteType = iota + 1
+	Sync
+	Async
+)
 
-func checkDoesNotHaveImplicitDep(t *testing.T, m android.TestingModule, name string) {
-	implicits := m.Rule("ld").Implicits
-	for _, lib := range implicits {
-		if strings.Contains(lib.Rel(), name) {
-			t.Errorf("%q is found in implicit deps of module %q", name, m.Module().(*Module).Name())
-		}
+func (t MemtagNoteType) str() string {
+	switch t {
+	case None:
+		return "none"
+	case Sync:
+		return "sync"
+	case Async:
+		return "async"
+	default:
+		panic("invalid note type")
 	}
 }
 
-func TestSanitizeMemtagHeap(t *testing.T) {
-	rootBp := `
-		cc_library_static {
-			name: "libstatic",
-			sanitize: { memtag_heap: true },
-		}
+func checkHasMemtagNote(t *testing.T, m android.TestingModule, expected MemtagNoteType) {
+	note_async := "note_memtag_heap_async"
+	note_sync := "note_memtag_heap_sync"
 
-		cc_library_shared {
-			name: "libshared",
-			sanitize: { memtag_heap: true },
+	found := None
+	implicits := m.Rule("ld").Implicits
+	for _, lib := range implicits {
+		if strings.Contains(lib.Rel(), note_async) {
+			found = Async
+			break
+		} else if strings.Contains(lib.Rel(), note_sync) {
+			found = Sync
+			break
 		}
+	}
 
-		cc_library {
-			name: "libboth",
-			sanitize: { memtag_heap: true },
-		}
+	if found != expected {
+		t.Errorf("Wrong Memtag note in target %q: found %q, expected %q", m.Module().(*Module).Name(), found.str(), expected.str())
+	}
+}
 
-		cc_binary {
-			name: "binary",
-			shared_libs: [ "libshared" ],
-			static_libs: [ "libstatic" ],
-		}
-
-		cc_binary {
-			name: "binary_true",
-			sanitize: { memtag_heap: true },
-		}
-
-		cc_binary {
-			name: "binary_true_sync",
-			sanitize: { memtag_heap: true, diag: { memtag_heap: true }, },
-		}
-
-		cc_binary {
-			name: "binary_false",
-			sanitize: { memtag_heap: false },
-		}
-
+func makeMemtagTestConfig(t *testing.T) android.Config {
+	templateBp := `
 		cc_test {
-			name: "test",
+			name: "%[1]s_test",
 			gtest: false,
 		}
 
 		cc_test {
-			name: "test_true",
-			gtest: false,
-			sanitize: { memtag_heap: true },
-		}
-
-		cc_test {
-			name: "test_false",
+			name: "%[1]s_test_false",
 			gtest: false,
 			sanitize: { memtag_heap: false },
 		}
 
 		cc_test {
-			name: "test_true_async",
+			name: "%[1]s_test_true",
+			gtest: false,
+			sanitize: { memtag_heap: true },
+		}
+
+		cc_test {
+			name: "%[1]s_test_true_nodiag",
 			gtest: false,
 			sanitize: { memtag_heap: true, diag: { memtag_heap: false }  },
 		}
 
-		`
+		cc_test {
+			name: "%[1]s_test_true_diag",
+			gtest: false,
+			sanitize: { memtag_heap: true, diag: { memtag_heap: true }  },
+		}
 
-	subdirAsyncBp := `
 		cc_binary {
-			name: "binary_async",
+			name: "%[1]s_binary",
+		}
+
+		cc_binary {
+			name: "%[1]s_binary_false",
+			sanitize: { memtag_heap: false },
+		}
+
+		cc_binary {
+			name: "%[1]s_binary_true",
+			sanitize: { memtag_heap: true },
+		}
+
+		cc_binary {
+			name: "%[1]s_binary_true_nodiag",
+			sanitize: { memtag_heap: true, diag: { memtag_heap: false }  },
+		}
+
+		cc_binary {
+			name: "%[1]s_binary_true_diag",
+			sanitize: { memtag_heap: true, diag: { memtag_heap: true }  },
 		}
 		`
-
-	subdirSyncBp := `
-		cc_binary {
-			name: "binary_sync",
-		}
-		`
+	subdirDefaultBp := fmt.Sprintf(templateBp, "default")
+	subdirExcludeBp := fmt.Sprintf(templateBp, "exclude")
+	subdirSyncBp := fmt.Sprintf(templateBp, "sync")
+	subdirAsyncBp := fmt.Sprintf(templateBp, "async")
 
 	mockFS := map[string][]byte{
-		"subdir_async/Android.bp": []byte(subdirAsyncBp),
-		"subdir_sync/Android.bp":  []byte(subdirSyncBp),
+		"subdir_default/Android.bp": []byte(subdirDefaultBp),
+		"subdir_exclude/Android.bp": []byte(subdirExcludeBp),
+		"subdir_sync/Android.bp":    []byte(subdirSyncBp),
+		"subdir_async/Android.bp":   []byte(subdirAsyncBp),
 	}
 
-	config := TestConfig(buildDir, android.Android, nil, rootBp, mockFS)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
-	config.TestProductVariables.MemtagHeapAsyncIncludePaths = []string{"subdir_async"}
+	return TestConfig(buildDir, android.Android, nil, "", mockFS)
+}
+
+func TestSanitizeMemtagHeap(t *testing.T) {
+	variant := "android_arm64_armv8-a"
+
+	config := makeMemtagTestConfig(t)
+	config.TestProductVariables.MemtagHeapExcludePaths = []string{"subdir_exclude"}
 	config.TestProductVariables.MemtagHeapSyncIncludePaths = []string{"subdir_sync"}
+	config.TestProductVariables.MemtagHeapAsyncIncludePaths = []string{"subdir_async"}
 	ctx := CreateTestContext(config)
 	ctx.Register()
 
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp", "subdir_sync/Android.bp", "subdir_async/Android.bp"})
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp", "subdir_default/Android.bp", "subdir_exclude/Android.bp", "subdir_sync/Android.bp", "subdir_async/Android.bp"})
 	android.FailIfErrored(t, errs)
 	_, errs = ctx.PrepareBuildActions(config)
 	android.FailIfErrored(t, errs)
 
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_diag", variant), Sync)
+}
+
+func TestSanitizeMemtagHeapWithSanitizeDevice(t *testing.T) {
 	variant := "android_arm64_armv8-a"
-	note_async := "note_memtag_heap_async"
-	note_sync := "note_memtag_heap_sync"
-	note_any := "note_memtag_"
 
-	checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared"), note_any)
-	checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("libboth", "android_arm64_armv8-a_shared"), note_any)
+	config := makeMemtagTestConfig(t)
+	config.TestProductVariables.MemtagHeapExcludePaths = []string{"subdir_exclude"}
+	config.TestProductVariables.MemtagHeapSyncIncludePaths = []string{"subdir_sync"}
+	config.TestProductVariables.MemtagHeapAsyncIncludePaths = []string{"subdir_async"}
+	config.TestProductVariables.SanitizeDevice = []string{"memtag_heap"}
+	ctx := CreateTestContext(config)
+	ctx.Register()
 
-	checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("binary", variant), note_any)
-	checkHasImplicitDep(t, ctx.ModuleForTests("binary_true", variant), note_async)
-	checkHasImplicitDep(t, ctx.ModuleForTests("binary_true_sync", variant), note_sync)
-	checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("binary_false", variant), note_any)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp", "subdir_default/Android.bp", "subdir_exclude/Android.bp", "subdir_sync/Android.bp", "subdir_async/Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
 
-	checkHasImplicitDep(t, ctx.ModuleForTests("test", variant), note_sync)
-	checkHasImplicitDep(t, ctx.ModuleForTests("test_true", variant), note_async)
-	checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("test_false", variant), note_any)
-	checkHasImplicitDep(t, ctx.ModuleForTests("test_true_async", variant), note_async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_true_diag", variant), Sync)
 
-	checkHasImplicitDep(t, ctx.ModuleForTests("binary_async", variant), note_async)
-	checkHasImplicitDep(t, ctx.ModuleForTests("binary_sync", variant), note_sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_true", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_diag", variant), Sync)
+}
+
+func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) {
+	variant := "android_arm64_armv8-a"
+
+	config := makeMemtagTestConfig(t)
+	config.TestProductVariables.MemtagHeapExcludePaths = []string{"subdir_exclude"}
+	config.TestProductVariables.MemtagHeapSyncIncludePaths = []string{"subdir_sync"}
+	config.TestProductVariables.MemtagHeapAsyncIncludePaths = []string{"subdir_async"}
+	config.TestProductVariables.SanitizeDevice = []string{"memtag_heap"}
+	config.TestProductVariables.SanitizeDeviceDiag = []string{"memtag_heap"}
+	ctx := CreateTestContext(config)
+	ctx.Register()
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp", "subdir_default/Android.bp", "subdir_exclude/Android.bp", "subdir_sync/Android.bp", "subdir_async/Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("default_binary_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("exclude_binary_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("async_binary_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_test_true_diag", variant), Sync)
+
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_false", variant), None)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true", variant), Sync)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_nodiag", variant), Async)
+	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_diag", variant), Sync)
 }
diff --git a/cc/compiler.go b/cc/compiler.go
index eb2b566..5f30d3d 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -404,7 +404,12 @@
 
 	target := "-target " + tc.ClangTriple()
 	if ctx.Os().Class == android.Device {
-		version := ctx.sdkVersion()
+		// When built for the non-updateble part of platform, minSdkVersion doesn't matter.
+		// It matters only when building we are building for modules that can be unbundled.
+		version := "current"
+		if !ctx.isForPlatform() || ctx.isSdkVariant() {
+			version = ctx.minSdkVersion()
+		}
 		if version == "" || version == "current" {
 			target += strconv.Itoa(android.FutureApiLevelInt)
 		} else {
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 3282958..35dd10f 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -141,6 +141,13 @@
 		// Warnings from clang-10
 		// Nested and array designated initialization is nice to have.
 		"-Wno-c99-designator",
+
+		// Calls to the APIs that are newer than the min sdk version of the caller should be
+		// guarded with __builtin_available.
+		"-Wunguarded-availability",
+		// This macro allows the bionic versioning.h to indirectly determine whether the
+		// option -Wunguarded-availability is on or not.
+		"-D__ANDROID_UNGUARDED_AVAILABILITY__",
 	}, " "))
 
 	pctx.StaticVariable("ClangExtraCppflags", strings.Join([]string{
diff --git a/cc/config/global.go b/cc/config/global.go
index c34f936..c62f784 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -53,6 +53,7 @@
 		"-Werror=date-time",
 		"-Werror=pragma-pack",
 		"-Werror=pragma-pack-suspicious-include",
+		"-Werror=string-plus-int",
 		"-Werror=unreachable-code-loop-increment",
 	}
 
@@ -116,8 +117,13 @@
 	}
 
 	noOverrideGlobalCflags = []string{
+		"-Werror=bool-operation",
+		"-Werror=implicit-int-float-conversion",
+		"-Werror=int-in-bool-context",
 		"-Werror=int-to-pointer-cast",
 		"-Werror=pointer-to-int-cast",
+		"-Werror=string-compare",
+		"-Werror=xor-used-as-pow",
 		// http://b/161386391 for -Wno-void-pointer-to-enum-cast
 		"-Wno-void-pointer-to-enum-cast",
 		// http://b/161386391 for -Wno-void-pointer-to-int-cast
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index 286bb53..107ae7d 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -35,6 +35,7 @@
 	"android.hardware.security.sharedsecret-ndk_platform",
 	"android.hardware.security.sharedsecret-unstable-ndk_platform",
 	"android.hardware.vibrator-ndk_platform",
+	"android.hardware.weaver-unstable-ndk_platform",
 	"android.system.keystore2-unstable-ndk_platform",
 	"libbinder",
 	"libcrypto",
diff --git a/cc/coverage.go b/cc/coverage.go
index acf98dd..5b5ccf2 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -58,6 +58,8 @@
 func getClangProfileLibraryName(ctx ModuleContextIntf) string {
 	if ctx.useSdk() {
 		return "libprofile-clang-extras_ndk"
+	} else if ctx.isCfiAssemblySupportEnabled() {
+		return "libprofile-clang-extras_cfi_support"
 	} else {
 		return "libprofile-clang-extras"
 	}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index a5c43fe..10de889 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -354,6 +354,5 @@
 func NdkLibraryFactory() android.Module {
 	module := newStubLibrary()
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
-	module.ModuleBase.EnableNativeBridgeSupportByDefault()
 	return module
 }
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index 793ab37..8d522d0 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -70,7 +70,6 @@
 // ./prebuilts/ndk/current/platforms/android-<sdk_version>/arch-$(HOST_ARCH)/usr/lib/<NAME>.o.
 func NdkPrebuiltObjectFactory() android.Module {
 	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
-	module.ModuleBase.EnableNativeBridgeSupportByDefault()
 	module.linker = &ndkPrebuiltObjectLinker{
 		objectLinker: objectLinker{
 			baseLinker: NewBaseLinker(nil),
@@ -150,7 +149,6 @@
 	module.Properties.AlwaysSdk = true
 	module.Properties.Sdk_version = StringPtr("current")
 	module.stl.Properties.Stl = StringPtr("none")
-	module.ModuleBase.EnableNativeBridgeSupportByDefault()
 	return module.Init()
 }
 
diff --git a/cc/sanitize.go b/cc/sanitize.go
index af17490..8eeb355 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -267,6 +267,12 @@
 		return
 	}
 
+	// cc_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {memtag_heap}).
+	if ctx.testBinary() && s.Memtag_heap == nil {
+		s.Memtag_heap = boolPtr(true)
+		s.Diag.Memtag_heap = boolPtr(true)
+	}
+
 	var globalSanitizers []string
 	var globalSanitizersDiag []string
 
@@ -358,27 +364,29 @@
 			s.Diag.Cfi = boolPtr(true)
 		}
 
+		if found, globalSanitizersDiag = removeFromList("memtag_heap", globalSanitizersDiag); found &&
+			s.Diag.Memtag_heap == nil && Bool(s.Memtag_heap) {
+			s.Diag.Memtag_heap = boolPtr(true)
+		}
+
 		if len(globalSanitizersDiag) > 0 {
 			ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0])
 		}
 	}
 
-	// cc_test targets default to SYNC MemTag.
-	if ctx.testBinary() && s.Memtag_heap == nil {
-		if !ctx.Config().MemtagHeapDisabledForPath(ctx.ModuleDir()) {
-			s.Memtag_heap = boolPtr(true)
-			s.Diag.Memtag_heap = boolPtr(true)
-		}
-	}
-
 	// Enable Memtag for all components in the include paths (for Aarch64 only)
-	if s.Memtag_heap == nil && ctx.Arch().ArchType == android.Arm64 {
+	if ctx.Arch().ArchType == android.Arm64 {
 		if ctx.Config().MemtagHeapSyncEnabledForPath(ctx.ModuleDir()) {
-			s.Memtag_heap = boolPtr(true)
-			s.Diag.Memtag_heap = boolPtr(true)
+			if s.Memtag_heap == nil {
+				s.Memtag_heap = boolPtr(true)
+			}
+			if s.Diag.Memtag_heap == nil {
+				s.Diag.Memtag_heap = boolPtr(true)
+			}
 		} else if ctx.Config().MemtagHeapAsyncEnabledForPath(ctx.ModuleDir()) {
-			s.Memtag_heap = boolPtr(true)
-			s.Diag.Memtag_heap = boolPtr(false)
+			if s.Memtag_heap == nil {
+				s.Memtag_heap = boolPtr(true)
+			}
 		}
 	}
 
diff --git a/cc/sdk.go b/cc/sdk.go
index ec57f06..2c3fec3 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -38,18 +38,31 @@
 			ctx.CreateVariations("sdk")
 		} else if m.UseSdk() || m.SplitPerApiLevel() {
 			modules := ctx.CreateVariations("", "sdk")
+
+			// Clear the sdk_version property for the platform (non-SDK) variant so later code
+			// doesn't get confused by it.
 			modules[0].(*Module).Properties.Sdk_version = nil
+
+			// Mark the SDK variant.
 			modules[1].(*Module).Properties.IsSdkVariant = true
 
 			if ctx.Config().UnbundledBuildApps() {
+				// For an unbundled apps build, hide the platform variant from Make.
 				modules[0].(*Module).Properties.HideFromMake = true
 				modules[0].(*Module).Properties.PreventInstall = true
 			} else {
+				// For a platform build, mark the SDK variant so that it gets a ".sdk" suffix when
+				// exposed to Make.
 				modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
 				modules[1].(*Module).Properties.PreventInstall = true
 			}
 			ctx.AliasVariation("")
 		} else {
+			if m, ok := ctx.Module().(*Module); ok {
+				// Clear the sdk_version property for modules that don't have an SDK variant so
+				// later code doesn't get confused by it.
+				m.Properties.Sdk_version = nil
+			}
 			ctx.CreateVariations("")
 			ctx.AliasVariation("")
 		}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index f52ecb4..feddfc0 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -27,8 +27,9 @@
 // GlobalConfig stores the configuration for dex preopting. The fields are set
 // from product variables via dex_preopt_config.mk.
 type GlobalConfig struct {
-	DisablePreopt        bool     // disable preopt for all modules
-	DisablePreoptModules []string // modules with preopt disabled by product-specific config
+	DisablePreopt           bool     // disable preopt for all modules (excluding boot images)
+	DisablePreoptBootImages bool     // disable prepot for boot images
+	DisablePreoptModules    []string // modules with preopt disabled by product-specific config
 
 	OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server
 
@@ -79,12 +80,10 @@
 	CpuVariant             map[android.ArchType]string // cpu variant for each architecture
 	InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture
 
-	// Only used for boot image
-	DirtyImageObjects android.OptionalPath // path to a dirty-image-objects file
-	BootImageProfiles android.Paths        // path to a boot-image-profile.txt file
-	BootFlags         string               // extra flags to pass to dex2oat for the boot image
-	Dex2oatImageXmx   string               // max heap size for dex2oat for the boot image
-	Dex2oatImageXms   string               // initial heap size for dex2oat for the boot image
+	BootImageProfiles android.Paths // path to a boot-image-profile.txt file
+	BootFlags         string        // extra flags to pass to dex2oat for the boot image
+	Dex2oatImageXmx   string        // max heap size for dex2oat for the boot image
+	Dex2oatImageXms   string        // initial heap size for dex2oat for the boot image
 }
 
 // GlobalSoongConfig contains the global config that is generated from Soong,
@@ -178,7 +177,6 @@
 
 		// Copies of entries in GlobalConfig that are not constructable without extra parameters.  They will be
 		// used to construct the real value manually below.
-		DirtyImageObjects string
 		BootImageProfiles []string
 	}
 
@@ -189,7 +187,6 @@
 	}
 
 	// Construct paths that require a PathContext.
-	config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
 	config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
 
 	return config.GlobalConfig, nil
@@ -234,8 +231,9 @@
 		return ctx.Config().Once(testGlobalConfigOnceKey, func() interface{} {
 			// Nope, return a config with preopting disabled
 			return globalConfigAndRaw{&GlobalConfig{
-				DisablePreopt:          true,
-				DisableGenerateProfile: true,
+				DisablePreopt:           true,
+				DisablePreoptBootImages: true,
+				DisableGenerateProfile:  true,
 			}, nil}
 		})
 	}).(globalConfigAndRaw)
@@ -305,7 +303,7 @@
 	}
 }
 
-var dex2oatDepTag = struct {
+var Dex2oatDepTag = struct {
 	blueprint.BaseDependencyTag
 }{}
 
@@ -316,7 +314,7 @@
 func RegisterToolDeps(ctx android.BottomUpMutatorContext) {
 	dex2oatBin := dex2oatModuleName(ctx.Config())
 	v := ctx.Config().BuildOSTarget.Variations()
-	ctx.AddFarVariationDependencies(v, dex2oatDepTag, dex2oatBin)
+	ctx.AddFarVariationDependencies(v, Dex2oatDepTag, dex2oatBin)
 }
 
 func dex2oatPathFromDep(ctx android.ModuleContext) android.Path {
@@ -332,7 +330,7 @@
 	// prebuilt explicitly here instead.
 	var dex2oatModule android.Module
 	ctx.WalkDeps(func(child, parent android.Module) bool {
-		if parent == ctx.Module() && ctx.OtherModuleDependencyTag(child) == dex2oatDepTag {
+		if parent == ctx.Module() && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag {
 			// Found the source module, or prebuilt module that has replaced the source.
 			dex2oatModule = child
 			if p, ok := child.(android.PrebuiltInterface); ok && p.Prebuilt() != nil {
@@ -385,10 +383,10 @@
 
 // The main reason for this Once cache for GlobalSoongConfig is to make the
 // dex2oat path available to singletons. In ordinary modules we get it through a
-// dex2oatDepTag dependency, but in singletons there's no simple way to do the
+// Dex2oatDepTag dependency, but in singletons there's no simple way to do the
 // same thing and ensure the right variant is selected, hence this cache to make
 // the resolved path available to singletons. This means we depend on there
-// being at least one ordinary module with a dex2oatDepTag dependency.
+// being at least one ordinary module with a Dex2oatDepTag dependency.
 //
 // TODO(b/147613152): Implement a way to deal with dependencies from singletons,
 // and then possibly remove this cache altogether (but the use in
@@ -545,7 +543,6 @@
 		EmptyDirectory:                     "empty_dir",
 		CpuVariant:                         nil,
 		InstructionSetFeatures:             nil,
-		DirtyImageObjects:                  android.OptionalPath{},
 		BootImageProfiles:                  nil,
 		BootFlags:                          "",
 		Dex2oatImageXmx:                    "",
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 2b3fbae..5ef4a90 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -20,6 +20,7 @@
 	"android/soong/android"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 )
 
 func init() {
@@ -30,10 +31,24 @@
 	android.ModuleBase
 	android.PackagingBase
 
+	properties filesystemProperties
+
 	output     android.OutputPath
 	installDir android.InstallPath
 }
 
+type filesystemProperties struct {
+	// When set to true, sign the image with avbtool. Default is false.
+	Use_avb *bool
+
+	// Path to the private key that avbtool will use to sign this filesystem image.
+	// TODO(jiyong): allow apex_key to be specified here
+	Avb_private_key *string `android:"path"`
+
+	// Hash and signing algorithm for avbtool. Default is SHA256_RSA4096.
+	Avb_algorithm *string
+}
+
 // android_filesystem packages a set of modules and their transitive dependencies into a filesystem
 // image. The filesystem images are expected to be mounted in the target device, which means the
 // modules in the filesystem image are built for the target device (i.e. Android, not Linux host).
@@ -41,6 +56,7 @@
 // partitions like system.img. For example, cc_library modules are placed under ./lib[64] directory.
 func filesystemFactory() android.Module {
 	module := &filesystem{}
+	module.AddProperties(&module.properties)
 	android.InitPackageModule(module)
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	return module
@@ -72,21 +88,12 @@
 		FlagWithArg("-d ", rootDir.String()). // zipsync wipes this. No need to clear.
 		Input(zipFile)
 
-	mkuserimg := ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs")
-	propFile := android.PathForModuleOut(ctx, "prop").OutputPath
-	// TODO(jiyong): support more filesystem types other than ext4
-	propsText := fmt.Sprintf(`mount_point=system\n`+
-		`fs_type=ext4\n`+
-		`use_dynamic_partition_size=true\n`+
-		`ext_mkuserimg=%s\n`, mkuserimg.String())
-	builder.Command().Text("echo").Flag("-e").Flag(`"` + propsText + `"`).
-		Text(">").Output(propFile).
-		Implicit(mkuserimg)
-
+	propFile, toolDeps := f.buildPropFile(ctx)
 	f.output = android.PathForModuleOut(ctx, f.installFileName()).OutputPath
 	builder.Command().BuiltTool("build_image").
 		Text(rootDir.String()). // input directory
 		Input(propFile).
+		Implicits(toolDeps).
 		Output(f.output).
 		Text(rootDir.String()) // directory where to find fs_config_files|dirs
 
@@ -97,6 +104,56 @@
 	ctx.InstallFile(f.installDir, f.installFileName(), f.output)
 }
 
+func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) {
+	type prop struct {
+		name  string
+		value string
+	}
+
+	var props []prop
+	var deps android.Paths
+	addStr := func(name string, value string) {
+		props = append(props, prop{name, value})
+	}
+	addPath := func(name string, path android.Path) {
+		props = append(props, prop{name, path.String()})
+		deps = append(deps, path)
+	}
+
+	// TODO(jiyong): support more filesystem types other than ext4
+	addStr("fs_type", "ext4")
+	addStr("mount_point", "system")
+	addStr("use_dynamic_partition_size", "true")
+	addPath("ext_mkuserimg", ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs"))
+	// b/177813163 deps of the host tools have to be added. Remove this.
+	for _, t := range []string{"mke2fs", "e2fsdroid", "tune2fs"} {
+		deps = append(deps, ctx.Config().HostToolPath(ctx, t))
+	}
+
+	if proptools.Bool(f.properties.Use_avb) {
+		addStr("avb_hashtree_enable", "true")
+		addPath("avb_avbtool", ctx.Config().HostToolPath(ctx, "avbtool"))
+		algorithm := proptools.StringDefault(f.properties.Avb_algorithm, "SHA256_RSA4096")
+		addStr("avb_algorithm", algorithm)
+		key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key))
+		addPath("avb_key_path", key)
+		addStr("avb_add_hashtree_footer_args", "--do_not_generate_fec")
+		addStr("partition_name", f.Name())
+	}
+
+	propFile = android.PathForModuleOut(ctx, "prop").OutputPath
+	builder := android.NewRuleBuilder(pctx, ctx)
+	builder.Command().Text("rm").Flag("-rf").Output(propFile)
+	for _, p := range props {
+		builder.Command().
+			Text("echo").Flag("-e").
+			Flag(`"` + p.name + "=" + p.value + `"`).
+			Text(">>").Output(propFile)
+	}
+	builder.Build("build_filesystem_prop", fmt.Sprintf("Creating filesystem props for %s", f.BaseModuleName()))
+	return propFile, deps
+}
+
 var _ android.AndroidMkEntriesProvider = (*filesystem)(nil)
 
 // Implements android.AndroidMkEntriesProvider
diff --git a/java/androidmk.go b/java/androidmk.go
index aaad44f..cc454b0 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -196,6 +196,9 @@
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(entries *android.AndroidMkEntries) {
 				entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
+				if prebuilt.dexJarFile != nil {
+					entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile)
+				}
 				entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile)
 				entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
 				entries.SetString("LOCAL_SDK_VERSION", prebuilt.makeSdkVersion())
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 233e9d5..e2647cf 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -166,3 +166,25 @@
 		}
 	}
 }
+
+func TestImportSoongDexJar(t *testing.T) {
+	ctx, config := testJava(t, `
+		java_import {
+			name: "my-java-import",
+			jars: ["a.jar"],
+			prefer: true,
+			compile_dex: true,
+		}
+	`)
+
+	mod := ctx.ModuleForTests("my-java-import", "android_common").Module()
+	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+	expectedSoongDexJar := buildDir + "/.intermediates/my-java-import/android_common/dex/my-java-import.jar"
+	actualSoongDexJar := entries.EntryMap["LOCAL_SOONG_DEX_JAR"]
+
+	if len(actualSoongDexJar) != 1 {
+		t.Errorf("LOCAL_SOONG_DEX_JAR incorrect len %d", len(actualSoongDexJar))
+	} else if actualSoongDexJar[0] != expectedSoongDexJar {
+		t.Errorf("LOCAL_SOONG_DEX_JAR mismatch, actual: %s, expected: %s", actualSoongDexJar[0], expectedSoongDexJar)
+	}
+}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 80211fd..c8f9538 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -347,8 +347,8 @@
 	ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
 }
 
-func skipDexpreoptBootJars(ctx android.PathContext) bool {
-	return dexpreopt.GetGlobalConfig(ctx).DisablePreopt
+func SkipDexpreoptBootJars(ctx android.PathContext) bool {
+	return dexpreopt.GetGlobalConfig(ctx).DisablePreoptBootImages
 }
 
 // Singleton for generating boot image build rules.
@@ -371,7 +371,7 @@
 
 // Accessor function for the apex package. Returns nil if dexpreopt is disabled.
 func DexpreoptedArtApexJars(ctx android.BuilderContext) map[android.ArchType]android.OutputPaths {
-	if skipDexpreoptBootJars(ctx) {
+	if SkipDexpreoptBootJars(ctx) {
 		return nil
 	}
 	// Include dexpreopt files for the primary boot image.
@@ -387,7 +387,7 @@
 
 // Generate build rules for boot images.
 func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) {
-	if skipDexpreoptBootJars(ctx) {
+	if SkipDexpreoptBootJars(ctx) {
 		return
 	}
 	if dexpreopt.GetCachedGlobalSoongConfig(ctx) == nil {
@@ -625,8 +625,10 @@
 		cmd.FlagWithInput("--profile-file=", profile)
 	}
 
-	if global.DirtyImageObjects.Valid() {
-		cmd.FlagWithInput("--dirty-image-objects=", global.DirtyImageObjects.Path())
+	dirtyImageFile := "frameworks/base/config/dirty-image-objects"
+	dirtyImagePath := android.ExistentPathForSource(ctx, dirtyImageFile)
+	if dirtyImagePath.Valid() {
+		cmd.FlagWithInput("--dirty-image-objects=", dirtyImagePath.Path())
 	}
 
 	if image.extends != nil {
@@ -727,7 +729,7 @@
 	globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
 	global := dexpreopt.GetGlobalConfig(ctx)
 
-	if global.DisableGenerateProfile || ctx.Config().UnbundledBuild() {
+	if global.DisableGenerateProfile {
 		return nil
 	}
 	profile := ctx.Config().Once(bootImageProfileRuleKey, func() interface{} {
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index d302524..4bd255c 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -67,6 +67,19 @@
 
 	stubFlagsRule(ctx)
 
+	// If there is a prebuilt hiddenapi dir, generate rules to use the
+	// files within. Generally, we build the hiddenapi files from source
+	// during the build, ensuring consistency. It's possible, in a split
+	// build (framework and vendor) scenario, for the vendor build to use
+	// prebuilt hiddenapi files from the framework build. In this scenario,
+	// the framework and vendor builds must use the same source to ensure
+	// consistency.
+
+	if ctx.Config().PrebuiltHiddenApiDir(ctx) != "" {
+		h.flags = prebuiltFlagsRule(ctx)
+		return
+	}
+
 	// These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them.
 	if ctx.Config().FrameworksBaseDirExists(ctx) {
 		h.flags = flagsRule(ctx)
@@ -212,6 +225,19 @@
 	rule.Build("hiddenAPIStubFlagsFile", "hiddenapi stub flags")
 }
 
+func prebuiltFlagsRule(ctx android.SingletonContext) android.Path {
+	outputPath := hiddenAPISingletonPaths(ctx).flags
+	inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-flags.csv")
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   android.Cp,
+		Output: outputPath,
+		Input:  inputPath,
+	})
+
+	return outputPath
+}
+
 // flagsRule creates a rule to build hiddenapi-flags.csv out of flags.csv files generated for boot image modules and
 // the unsupported API.
 func flagsRule(ctx android.SingletonContext) android.Path {
@@ -391,6 +417,20 @@
 		return
 	}
 
+	if ctx.Config().PrebuiltHiddenApiDir(ctx) != "" {
+		outputPath := hiddenAPISingletonPaths(ctx).index
+		inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-index.csv")
+
+		ctx.Build(pctx, android.BuildParams{
+			Rule:   android.Cp,
+			Output: outputPath,
+			Input:  inputPath,
+		})
+
+		h.index = outputPath
+		return
+	}
+
 	indexes := android.Paths{}
 	ctx.VisitAllModules(func(module android.Module) {
 		if h, ok := module.(hiddenAPIIntf); ok {
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 955c739..0f9ef58 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -23,9 +23,10 @@
 	"github.com/google/blueprint/proptools"
 )
 
-func testConfigWithBootJars(bp string, bootJars []string) android.Config {
+func testConfigWithBootJars(bp string, bootJars []string, prebuiltHiddenApiDir *string) android.Config {
 	config := testConfig(nil, bp, nil)
 	config.TestProductVariables.BootJars = android.CreateTestConfiguredJarList(bootJars)
+	config.TestProductVariables.PrebuiltHiddenApiDir = prebuiltHiddenApiDir
 	return config
 }
 
@@ -44,8 +45,8 @@
 	return ctx
 }
 
-func testHiddenAPIBootJars(t *testing.T, bp string, bootJars []string) (*android.TestContext, android.Config) {
-	config := testConfigWithBootJars(bp, bootJars)
+func testHiddenAPIBootJars(t *testing.T, bp string, bootJars []string, prebuiltHiddenApiDir *string) (*android.TestContext, android.Config) {
+	config := testConfigWithBootJars(bp, bootJars, prebuiltHiddenApiDir)
 
 	return testHiddenAPIWithConfig(t, config), config
 }
@@ -64,7 +65,7 @@
 			srcs: ["a.java"],
 			compile_dex: true,
 	}
-	`, []string{":foo"})
+	`, []string{":foo"}, nil)
 
 	hiddenAPI := ctx.SingletonForTests("hiddenapi")
 	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -81,7 +82,7 @@
 			jars: ["a.jar"],
 			compile_dex: true,
 	}
-	`, []string{":foo"})
+	`, []string{":foo"}, nil)
 
 	hiddenAPI := ctx.SingletonForTests("hiddenapi")
 	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -105,7 +106,7 @@
 			compile_dex: true,
 			prefer: false,
 	}
-	`, []string{":foo"})
+	`, []string{":foo"}, nil)
 
 	hiddenAPI := ctx.SingletonForTests("hiddenapi")
 	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -134,7 +135,7 @@
 			compile_dex: true,
 			prefer: true,
 	}
-	`, []string{":foo"})
+	`, []string{":foo"}, nil)
 
 	hiddenAPI := ctx.SingletonForTests("hiddenapi")
 	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -217,3 +218,48 @@
 	}
 	return generateDexPath(module)
 }
+
+func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) {
+
+	// The idea behind this test is to ensure that when the build is
+	// confugured with a PrebuiltHiddenApiDir that the rules for the
+	// hiddenapi singleton copy the prebuilts to the typical output
+	// location, and then use that output location for the hiddenapi encode
+	// dex step.
+
+	// Where to find the prebuilt hiddenapi files:
+	prebuiltHiddenApiDir := "path/to/prebuilt/hiddenapi"
+
+	ctx, _ := testHiddenAPIBootJars(t, `
+		java_import {
+			name: "foo",
+			jars: ["a.jar"],
+			compile_dex: true,
+	}
+	`, []string{":foo"}, &prebuiltHiddenApiDir)
+
+	expectedCpInput := prebuiltHiddenApiDir + "/hiddenapi-flags.csv"
+	expectedCpOutput := buildDir + "/hiddenapi/hiddenapi-flags.csv"
+	expectedFlagsCsv := buildDir + "/hiddenapi/hiddenapi-flags.csv"
+
+	foo := ctx.ModuleForTests("foo", "android_common")
+
+	hiddenAPI := ctx.SingletonForTests("hiddenapi")
+	cpRule := hiddenAPI.Rule("Cp")
+	actualCpInput := cpRule.BuildParams.Input
+	actualCpOutput := cpRule.BuildParams.Output
+	encodeDexRule := foo.Rule("hiddenAPIEncodeDex")
+	actualFlagsCsv := encodeDexRule.BuildParams.Args["flagsCsv"]
+
+	if actualCpInput.String() != expectedCpInput {
+		t.Errorf("Prebuilt hiddenapi cp rule input mismatch, actual: %s, expected: %s", actualCpInput, expectedCpInput)
+	}
+
+	if actualCpOutput.String() != expectedCpOutput {
+		t.Errorf("Prebuilt hiddenapi cp rule output mismatch, actual: %s, expected: %s", actualCpOutput, expectedCpOutput)
+	}
+
+	if actualFlagsCsv != expectedFlagsCsv {
+		t.Errorf("Prebuilt hiddenapi encode dex rule flags csv mismatch, actual: %s, expected: %s", actualFlagsCsv, expectedFlagsCsv)
+	}
+}
diff --git a/java/java.go b/java/java.go
index 3c6146b..59ec94d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2831,6 +2831,10 @@
 	return nil
 }
 
+func (j *Import) LintDepSets() LintDepSets {
+	return LintDepSets{}
+}
+
 func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
 	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
 
diff --git a/licenses/Android.bp b/licenses/Android.bp
index 217792f..8032dc5 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -1052,6 +1052,11 @@
 }
 
 license_kind {
+	name: "legacy_permissive",
+	conditions: ["permissive"],
+}
+
+license_kind {
 	name: "legacy_notice",
 	conditions: ["notice"],
 }
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 06f6c63..a5986b2 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -117,6 +117,7 @@
 		productOut("misc_info.txt"),
 		productOut("apex"),
 		productOut("kernel"),
+		productOut("kernel-*"),
 		productOut("data"),
 		productOut("skin"),
 		productOut("obj/NOTICE_FILES"),