Merge "Update soong's go.mod to 1.15.6"
diff --git a/OWNERS b/OWNERS
index 3a5a8a7..e851bf7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -11,10 +11,8 @@
 joeo@google.com
 jungjw@google.com
 lberki@google.com
-patricearruda@google.com
 ruperts@google.com
 
 # To expedite LON reviews
 hansson@google.com
 paulduffin@google.com
-
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 357b99f..a00a54d 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -515,6 +515,6 @@
 		// build statement have later timestamps than the outputs.
 		rule.Restat()
 
-		rule.Build(fmt.Sprintf("bazel %s", index), buildStatement.Mnemonic)
+		rule.Build(fmt.Sprintf("bazel %d", index), buildStatement.Mnemonic)
 	}
 }
diff --git a/android/config.go b/android/config.go
index 89467d8..ddb2de3 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1053,6 +1053,10 @@
 	return String(c.config.productVariables.DeviceVndkVersion)
 }
 
+func (c *deviceConfig) RecoverySnapshotVersion() string {
+	return String(c.config.productVariables.RecoverySnapshotVersion)
+}
+
 func (c *deviceConfig) CurrentApiLevelForVendorModules() string {
 	return StringDefault(c.config.productVariables.DeviceCurrentApiLevelForVendorModules, "current")
 }
@@ -1272,6 +1276,10 @@
 	return Bool(c.productVariables.Flatten_apex)
 }
 
+func (c *config) ForceApexSymlinkOptimization() bool {
+	return Bool(c.productVariables.ForceApexSymlinkOptimization)
+}
+
 func (c *config) CompressedApex() bool {
 	return Bool(c.productVariables.CompressedApex)
 }
@@ -1360,6 +1368,18 @@
 	return Bool(c.config.productVariables.BoardMoveRecoveryResourcesToVendorBoot)
 }
 
+func (c *deviceConfig) PlatformSepolicyVersion() string {
+	return String(c.config.productVariables.PlatformSepolicyVersion)
+}
+
+func (c *deviceConfig) BoardSepolicyVers() string {
+	return String(c.config.productVariables.BoardSepolicyVers)
+}
+
+func (c *deviceConfig) BoardReqdMaskPolicy() []string {
+	return c.config.productVariables.BoardReqdMaskPolicy
+}
+
 // The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
 // Such lists are used in the build system for things like bootclasspath jars or system server jars.
 // The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index 5a6917e..9f3f804 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -541,12 +541,15 @@
 }
 
 func (s *valueVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
-	if !config.IsSet(s.variable) {
+	if !config.IsSet(s.variable) || !values.IsValid() {
 		return nil, nil
 	}
 	configValue := config.String(s.variable)
 
 	propStruct := values.Elem().Elem()
+	if !propStruct.IsValid() {
+		return nil, nil
+	}
 	for i := 0; i < propStruct.NumField(); i++ {
 		field := propStruct.Field(i)
 		kind := field.Kind()
diff --git a/android/variable.go b/android/variable.go
index 753ddd7..7532797 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -181,6 +181,8 @@
 	DeviceCurrentApiLevelForVendorModules *string  `json:",omitempty"`
 	DeviceSystemSdkVersions               []string `json:",omitempty"`
 
+	RecoverySnapshotVersion *string `json:",omitempty"`
+
 	DeviceSecondaryArch        *string  `json:",omitempty"`
 	DeviceSecondaryArchVariant *string  `json:",omitempty"`
 	DeviceSecondaryCpuVariant  *string  `json:",omitempty"`
@@ -311,18 +313,23 @@
 
 	BoardVendorSepolicyDirs      []string `json:",omitempty"`
 	BoardOdmSepolicyDirs         []string `json:",omitempty"`
+	BoardReqdMaskPolicy          []string `json:",omitempty"`
 	SystemExtPublicSepolicyDirs  []string `json:",omitempty"`
 	SystemExtPrivateSepolicyDirs []string `json:",omitempty"`
 	BoardSepolicyM4Defs          []string `json:",omitempty"`
 
+	BoardSepolicyVers       *string `json:",omitempty"`
+	PlatformSepolicyVersion *string `json:",omitempty"`
+
 	VendorVars map[string]map[string]string `json:",omitempty"`
 
 	Ndk_abis               *bool `json:",omitempty"`
 	Exclude_draft_ndk_apis *bool `json:",omitempty"`
 
-	Flatten_apex   *bool `json:",omitempty"`
-	CompressedApex *bool `json:",omitempty"`
-	Aml_abis       *bool `json:",omitempty"`
+	Flatten_apex                 *bool `json:",omitempty"`
+	ForceApexSymlinkOptimization *bool `json:",omitempty"`
+	CompressedApex               *bool `json:",omitempty"`
+	Aml_abis                     *bool `json:",omitempty"`
 
 	DexpreoptGlobalConfig *string `json:",omitempty"`
 
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index c5f2bf8..69bf64f 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -289,6 +289,7 @@
 libcutils(minSdkVersion:29)
 libcutils_headers(minSdkVersion:29)
 libcutils_sockets(minSdkVersion:29)
+libderive_sdk(minSdkVersion:30)
 libdiagnose_usb(minSdkVersion:(no version))
 libdl(minSdkVersion:(no version))
 libdmabufheap(minSdkVersion:29)
diff --git a/apex/apex.go b/apex/apex.go
index 9fb616d..2182069 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1913,9 +1913,11 @@
 		a.linkToSystemLib = false
 	}
 
+	forced := ctx.Config().ForceApexSymlinkOptimization()
+
 	// We don't need the optimization for updatable APEXes, as it might give false signal
-	// to the system health when the APEXes are still bundled (b/149805758)
-	if a.Updatable() && a.properties.ApexType == imageApex {
+	// to the system health when the APEXes are still bundled (b/149805758).
+	if !forced && a.Updatable() && a.properties.ApexType == imageApex {
 		a.linkToSystemLib = false
 	}
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 84a8356..9d43348 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3150,6 +3150,7 @@
 		"etc/vndkcore.libraries.VER.txt",
 		"etc/vndksp.libraries.VER.txt",
 		"etc/vndkprivate.libraries.VER.txt",
+		"etc/vndkproduct.libraries.VER.txt",
 	})
 }
 
@@ -3216,7 +3217,7 @@
 func vndkLibrariesTxtFiles(vers ...string) (result string) {
 	for _, v := range vers {
 		if v == "current" {
-			for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate"} {
+			for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
 				result += `
 					vndk_libraries_txt {
 						name: "` + txt + `.libraries.txt",
@@ -3224,7 +3225,7 @@
 				`
 			}
 		} else {
-			for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate"} {
+			for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
 				result += `
 					prebuilt_etc {
 						name: "` + txt + `.libraries.` + v + `.txt",
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index 27d93ee..ccf4e57 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -60,6 +60,7 @@
 		"etc/vndkcore.libraries.VER.txt",
 		"etc/vndksp.libraries.VER.txt",
 		"etc/vndkprivate.libraries.VER.txt",
+		"etc/vndkproduct.libraries.VER.txt",
 	})
 }
 
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 4ada55d..040aa0b 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -519,9 +519,7 @@
 		entries.SubName += ".cfi"
 	}
 
-	if c.androidMkVendorSuffix {
-		entries.SubName += vendorSuffix
-	}
+	entries.SubName += c.androidMkSuffix
 
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		c.libraryDecorator.androidMkWriteExportedFlags(entries)
@@ -548,12 +546,7 @@
 
 func (c *snapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
 	entries.Class = "EXECUTABLES"
-
-	if c.androidMkVendorSuffix {
-		entries.SubName = vendorSuffix
-	} else {
-		entries.SubName = ""
-	}
+	entries.SubName = c.androidMkSuffix
 
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		entries.AddStrings("LOCAL_MODULE_SYMLINKS", c.Properties.Symlinks...)
@@ -562,12 +555,7 @@
 
 func (c *snapshotObjectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
 	entries.Class = "STATIC_LIBRARIES"
-
-	if c.androidMkVendorSuffix {
-		entries.SubName = vendorSuffix
-	} else {
-		entries.SubName = ""
-	}
+	entries.SubName = c.androidMkSuffix
 
 	entries.ExtraFooters = append(entries.ExtraFooters,
 		func(w io.Writer, name, prefix, moduleDir string) {
diff --git a/cc/cc.go b/cc/cc.go
index b815268..0d0aec7 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -52,6 +52,8 @@
 		ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
 		ctx.BottomUp("vendor_snapshot", VendorSnapshotMutator).Parallel()
 		ctx.BottomUp("vendor_snapshot_source", VendorSnapshotSourceMutator).Parallel()
+		ctx.BottomUp("recovery_snapshot", RecoverySnapshotMutator).Parallel()
+		ctx.BottomUp("recovery_snapshot_source", RecoverySnapshotSourceMutator).Parallel()
 	})
 
 	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -334,10 +336,16 @@
 
 	// Normally Soong uses the directory structure to decide which modules
 	// should be included (framework) or excluded (non-framework) from the
-	// different snapshots (vendor, recovery, etc.), but these properties
-	// allow a partner to exclude a module normally thought of as a
-	// framework module from a snapshot.
-	Exclude_from_vendor_snapshot   *bool
+	// different snapshots (vendor, recovery, etc.), but this property
+	// allows a partner to exclude a module normally thought of as a
+	// framework module from the vendor snapshot.
+	Exclude_from_vendor_snapshot *bool
+
+	// Normally Soong uses the directory structure to decide which modules
+	// should be included (framework) or excluded (non-framework) from the
+	// different snapshots (vendor, recovery, etc.), but this property
+	// allows a partner to exclude a module normally thought of as a
+	// framework module from the recovery snapshot.
 	Exclude_from_recovery_snapshot *bool
 
 	// List of APEXes that this module has private access to for testing purpose. The module
@@ -1634,8 +1642,9 @@
 			// Note: this is still non-installable
 		}
 
-		// glob exported headers for snapshot, if BOARD_VNDK_VERSION is current.
-		if i, ok := c.linker.(snapshotLibraryInterface); ok && ctx.DeviceConfig().VndkVersion() == "current" {
+		// glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or
+		// RECOVERY_SNAPSHOT_VERSION is current.
+		if i, ok := c.linker.(snapshotLibraryInterface); ok {
 			if shouldCollectHeadersForSnapshot(ctx, c, apexInfo) {
 				i.collectHeadersForSnapshot(ctx)
 			}
@@ -1877,6 +1886,7 @@
 
 		vendorPublicLibraries := vendorPublicLibraries(actx.Config())
 		vendorSnapshotSharedLibs := vendorSnapshotSharedLibs(actx.Config())
+		recoverySnapshotSharedLibs := recoverySnapshotSharedLibs(actx.Config())
 
 		rewriteVendorLibs := func(lib string) string {
 			// only modules with BOARD_VNDK_VERSION uses snapshot.
@@ -1897,7 +1907,19 @@
 			for _, entry := range list {
 				// strip #version suffix out
 				name, _ := StubsLibNameAndVersion(entry)
-				if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
+				if c.InRecovery() {
+					recoverySnapshotVersion :=
+						actx.DeviceConfig().RecoverySnapshotVersion()
+					if recoverySnapshotVersion == "current" ||
+						recoverySnapshotVersion == "" {
+						nonvariantLibs = append(nonvariantLibs, name)
+					} else if snapshot, ok := recoverySnapshotSharedLibs.get(
+						name, actx.Arch().ArchType); ok {
+						nonvariantLibs = append(nonvariantLibs, snapshot)
+					} else {
+						nonvariantLibs = append(nonvariantLibs, name)
+					}
+				} else if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
 					variantLibs = append(variantLibs, name+ndkLibrarySuffix)
 				} else if ctx.useVndk() {
 					nonvariantLibs = append(nonvariantLibs, rewriteVendorLibs(entry))
@@ -1942,14 +1964,36 @@
 		return lib
 	}
 
-	vendorSnapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config())
+	snapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config())
+	snapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config())
+	snapshotObjects := vendorSnapshotObjects(actx.Config())
+
+	if c.InRecovery() {
+		rewriteSnapshotLibs = func(lib string, snapshotMap *snapshotMap) string {
+			recoverySnapshotVersion :=
+				actx.DeviceConfig().RecoverySnapshotVersion()
+			if recoverySnapshotVersion == "current" ||
+				recoverySnapshotVersion == "" {
+				return lib
+			} else if snapshot, ok := snapshotMap.get(lib, actx.Arch().ArchType); ok {
+				return snapshot
+			}
+
+			return lib
+		}
+
+		snapshotHeaderLibs = recoverySnapshotHeaderLibs(actx.Config())
+		snapshotStaticLibs = recoverySnapshotStaticLibs(actx.Config())
+		snapshotObjects = recoverySnapshotObjects(actx.Config())
+	}
+
 	for _, lib := range deps.HeaderLibs {
 		depTag := libraryDependencyTag{Kind: headerLibraryDependency}
 		if inList(lib, deps.ReexportHeaderLibHeaders) {
 			depTag.reexportFlags = true
 		}
 
-		lib = rewriteSnapshotLibs(lib, vendorSnapshotHeaderLibs)
+		lib = rewriteSnapshotLibs(lib, snapshotHeaderLibs)
 
 		if c.IsStubs() {
 			actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
@@ -1965,7 +2009,6 @@
 	// map from sysprop_library to implementation library; it will be used in whole_static_libs,
 	// static_libs, and shared_libs.
 	syspropImplLibraries := syspropImplLibraries(actx.Config())
-	vendorSnapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config())
 
 	for _, lib := range deps.WholeStaticLibs {
 		depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true, reexportFlags: true}
@@ -1973,7 +2016,7 @@
 			lib = impl
 		}
 
-		lib = rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)
+		lib = rewriteSnapshotLibs(lib, snapshotStaticLibs)
 
 		actx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
@@ -1993,7 +2036,7 @@
 			lib = impl
 		}
 
-		lib = rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)
+		lib = rewriteSnapshotLibs(lib, snapshotStaticLibs)
 
 		actx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
@@ -2007,14 +2050,14 @@
 		depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true}
 		actx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
-		}, depTag, rewriteSnapshotLibs(staticUnwinder(actx), vendorSnapshotStaticLibs))
+		}, depTag, rewriteSnapshotLibs(staticUnwinder(actx), snapshotStaticLibs))
 	}
 
 	for _, lib := range deps.LateStaticLibs {
 		depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
 		actx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
-		}, depTag, rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs))
+		}, depTag, rewriteSnapshotLibs(lib, snapshotStaticLibs))
 	}
 
 	// shared lib names without the #version suffix
@@ -2074,17 +2117,15 @@
 		actx.AddDependency(c, depTag, gen)
 	}
 
-	vendorSnapshotObjects := vendorSnapshotObjects(actx.Config())
-
 	crtVariations := GetCrtVariations(ctx, c)
 	actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
 	if deps.CrtBegin != "" {
 		actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
-			rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
+			rewriteSnapshotLibs(deps.CrtBegin, snapshotObjects))
 	}
 	if deps.CrtEnd != "" {
 		actx.AddVariationDependencies(crtVariations, CrtEndDepTag,
-			rewriteSnapshotLibs(deps.CrtEnd, vendorSnapshotObjects))
+			rewriteSnapshotLibs(deps.CrtEnd, snapshotObjects))
 	}
 	if deps.LinkerFlagsFile != "" {
 		actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
@@ -2796,6 +2837,7 @@
 
 func (c *Module) makeLibName(ctx android.ModuleContext, ccDep LinkableInterface, depName string) string {
 	vendorSuffixModules := vendorSuffixModules(ctx.Config())
+	recoverySuffixModules := recoverySuffixModules(ctx.Config())
 	vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
 
 	libName := baseLibName(depName)
@@ -2813,8 +2855,10 @@
 				return baseName + ".vendor"
 			}
 
-			if vendorSuffixModules[baseName] {
+			if c.inVendor() && vendorSuffixModules[baseName] {
 				return baseName + ".vendor"
+			} else if c.InRecovery() && recoverySuffixModules[baseName] {
+				return baseName + ".recovery"
 			} else {
 				return baseName
 			}
@@ -3096,6 +3140,12 @@
 		// We don't track beyond LLNDK or from an implementation library to its stubs.
 		return false
 	}
+	if depTag == staticVariantTag {
+		// This dependency is for optimization (reuse *.o from the static lib). It doesn't
+		// actually mean that the static lib (and its dependencies) are copied into the
+		// APEX.
+		return false
+	}
 	return true
 }
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index fb85336..2d02a6a 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -68,6 +68,7 @@
 	t.Helper()
 	config := TestConfig(buildDir, android.Android, nil, bp, nil)
 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.ProductVndkVersion = StringPtr("current")
 	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
 
 	return testCcWithConfig(t, config)
@@ -81,6 +82,15 @@
 	return testCcWithConfig(t, config)
 }
 
+func testCcNoProductVndk(t *testing.T, bp string) *android.TestContext {
+	t.Helper()
+	config := TestConfig(buildDir, android.Android, nil, bp, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+
+	return testCcWithConfig(t, config)
+}
+
 func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
 	t.Helper()
 
@@ -421,6 +431,9 @@
 			name: "vndkprivate.libraries.txt",
 		}
 		vndk_libraries_txt {
+			name: "vndkproduct.libraries.txt",
+		}
+		vndk_libraries_txt {
 			name: "vndkcorevariant.libraries.txt",
 		}
 	`
@@ -445,7 +458,6 @@
 	checkVndkModule(t, ctx, "libvndk_sp_product_private", "", true, "", productVariant)
 
 	// Check VNDK snapshot output.
-
 	snapshotDir := "vndk-snapshot"
 	snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
 
@@ -476,6 +488,7 @@
 	checkSnapshot(t, ctx, snapshotSingleton, "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
 	checkSnapshot(t, ctx, snapshotSingleton, "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
 	checkSnapshot(t, ctx, snapshotSingleton, "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
+	checkSnapshot(t, ctx, snapshotSingleton, "vndkproduct.libraries.txt", "vndkproduct.libraries.txt", snapshotConfigsPath, "")
 
 	checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
 		"LLNDK: libc.so",
@@ -493,11 +506,15 @@
 		"VNDK-private: libvndk-private.so",
 		"VNDK-private: libvndk_sp_private-x.so",
 		"VNDK-private: libvndk_sp_product_private-x.so",
+		"VNDK-product: libc++.so",
+		"VNDK-product: libvndk_product.so",
+		"VNDK-product: libvndk_sp_product_private-x.so",
 	})
 	checkVndkLibrariesOutput(t, ctx, "llndk.libraries.txt", []string{"libc.so", "libdl.so", "libft2.so", "libm.so"})
 	checkVndkLibrariesOutput(t, ctx, "vndkcore.libraries.txt", []string{"libvndk-private.so", "libvndk.so", "libvndk_product.so"})
 	checkVndkLibrariesOutput(t, ctx, "vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp-x.so", "libvndk_sp_private-x.so", "libvndk_sp_product_private-x.so"})
 	checkVndkLibrariesOutput(t, ctx, "vndkprivate.libraries.txt", []string{"libft2.so", "libvndk-private.so", "libvndk_sp_private-x.so", "libvndk_sp_product_private-x.so"})
+	checkVndkLibrariesOutput(t, ctx, "vndkproduct.libraries.txt", []string{"libc++.so", "libvndk_product.so", "libvndk_sp_product_private-x.so"})
 	checkVndkLibrariesOutput(t, ctx, "vndkcorevariant.libraries.txt", nil)
 }
 
@@ -711,6 +728,15 @@
 			},
 			nocrt: true,
 		}
+		cc_library {
+			name: "libvndk-private",
+			vendor_available: false,
+			product_available: false,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
 	`)
 
 	checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
@@ -719,8 +745,13 @@
 		"LLNDK: libft2.so",
 		"LLNDK: libm.so",
 		"VNDK-SP: libc++.so",
+		"VNDK-core: libvndk-private.so",
 		"VNDK-core: libvndk.so",
 		"VNDK-private: libft2.so",
+		"VNDK-private: libvndk-private.so",
+		"VNDK-product: libc++.so",
+		"VNDK-product: libvndk-private.so",
+		"VNDK-product: libvndk.so",
 	})
 }
 
@@ -1492,6 +1523,13 @@
 	}
 }
 
+func assertExcludeFromRecoverySnapshotIs(t *testing.T, c *Module, expected bool) {
+	t.Helper()
+	if c.ExcludeFromRecoverySnapshot() != expected {
+		t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", c.String(), expected)
+	}
+}
+
 func TestVendorSnapshotExclude(t *testing.T) {
 
 	// This test verifies that the exclude_from_vendor_snapshot property
@@ -1739,7 +1777,7 @@
 	}
 `
 	config := TestConfig(buildDir, android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
 	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
 	ctx := testCcWithConfig(t, config)
 
@@ -1810,6 +1848,111 @@
 	}
 }
 
+func TestRecoverySnapshotExclude(t *testing.T) {
+	// This test verifies that the exclude_from_recovery_snapshot property
+	// makes its way from the Android.bp source file into the module data
+	// structure. It also verifies that modules are correctly included or
+	// excluded in the recovery snapshot based on their path (framework or
+	// vendor) and the exclude_from_recovery_snapshot property.
+
+	frameworkBp := `
+		cc_library_shared {
+			name: "libinclude",
+			srcs: ["src/include.cpp"],
+                        recovery_available: true,
+		}
+		cc_library_shared {
+			name: "libexclude",
+			srcs: ["src/exclude.cpp"],
+			recovery: true,
+			exclude_from_recovery_snapshot: true,
+		}
+	`
+
+	vendorProprietaryBp := `
+		cc_library_shared {
+			name: "libvendor",
+			srcs: ["vendor.cpp"],
+			recovery: true,
+		}
+	`
+
+	depsBp := GatherRequiredDepsForTest(android.Android)
+
+	mockFS := map[string][]byte{
+		"deps/Android.bp":       []byte(depsBp),
+		"framework/Android.bp":  []byte(frameworkBp),
+		"framework/include.cpp": nil,
+		"framework/exclude.cpp": nil,
+		"device/Android.bp":     []byte(vendorProprietaryBp),
+		"device/vendor.cpp":     nil,
+	}
+
+	config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+	ctx := CreateTestContext(config)
+	ctx.Register()
+
+	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+
+	// Test an include and exclude framework module.
+	assertExcludeFromRecoverySnapshotIs(t, ctx.ModuleForTests("libinclude", coreVariant).Module().(*Module), false)
+	assertExcludeFromRecoverySnapshotIs(t, ctx.ModuleForTests("libinclude", recoveryVariant).Module().(*Module), false)
+	assertExcludeFromRecoverySnapshotIs(t, ctx.ModuleForTests("libexclude", recoveryVariant).Module().(*Module), true)
+
+	// A vendor module is excluded, but by its path, not the
+	// exclude_from_recovery_snapshot property.
+	assertExcludeFromRecoverySnapshotIs(t, ctx.ModuleForTests("libvendor", recoveryVariant).Module().(*Module), false)
+
+	// Verify the content of the recovery snapshot.
+
+	snapshotDir := "recovery-snapshot"
+	snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
+
+	var includeJsonFiles []string
+	var excludeJsonFiles []string
+
+	for _, arch := range [][]string{
+		[]string{"arm64", "armv8-a"},
+	} {
+		archType := arch[0]
+		archVariant := arch[1]
+		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
+		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+
+		// Included modules
+		checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
+
+		// Excluded modules
+		checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
+		checkSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
+	}
+
+	// Verify that each json file for an included module has a rule.
+	for _, jsonFile := range includeJsonFiles {
+		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+			t.Errorf("include json file %q not found", jsonFile)
+		}
+	}
+
+	// Verify that each json file for an excluded module has no rule.
+	for _, jsonFile := range excludeJsonFiles {
+		if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
+			t.Errorf("exclude json file %q found", jsonFile)
+		}
+	}
+}
+
 func TestDoubleLoadableDepError(t *testing.T) {
 	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
 	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
@@ -2088,7 +2231,7 @@
 
 func TestVndkExtWithoutProductVndkVersion(t *testing.T) {
 	// This test checks the VNDK-Ext properties when PRODUCT_PRODUCT_VNDK_VERSION is not set.
-	ctx := testCc(t, `
+	ctx := testCcNoProductVndk(t, `
 		cc_library {
 			name: "libvndk",
 			vendor_available: true,
@@ -3400,8 +3543,17 @@
 
 const runtimeLibAndroidBp = `
 	cc_library {
+		name: "liball_available",
+		vendor_available: true,
+		product_available: true,
+		no_libcrt : true,
+		nocrt : true,
+		system_shared_libs : [],
+	}
+	cc_library {
 		name: "libvendor_available1",
 		vendor_available: true,
+		runtime_libs: ["liball_available"],
 		no_libcrt : true,
 		nocrt : true,
 		system_shared_libs : [],
@@ -3409,18 +3561,10 @@
 	cc_library {
 		name: "libvendor_available2",
 		vendor_available: true,
-		runtime_libs: ["libvendor_available1"],
-		no_libcrt : true,
-		nocrt : true,
-		system_shared_libs : [],
-	}
-	cc_library {
-		name: "libvendor_available3",
-		vendor_available: true,
-		runtime_libs: ["libvendor_available1"],
+		runtime_libs: ["liball_available"],
 		target: {
 			vendor: {
-				exclude_runtime_libs: ["libvendor_available1"],
+				exclude_runtime_libs: ["liball_available"],
 			}
 		},
 		no_libcrt : true,
@@ -3429,7 +3573,7 @@
 	}
 	cc_library {
 		name: "libcore",
-		runtime_libs: ["libvendor_available1"],
+		runtime_libs: ["liball_available"],
 		no_libcrt : true,
 		nocrt : true,
 		system_shared_libs : [],
@@ -3444,7 +3588,30 @@
 	cc_library {
 		name: "libvendor2",
 		vendor: true,
-		runtime_libs: ["libvendor_available1", "libvendor1"],
+		runtime_libs: ["liball_available", "libvendor1"],
+		no_libcrt : true,
+		nocrt : true,
+		system_shared_libs : [],
+	}
+	cc_library {
+		name: "libproduct_available1",
+		product_available: true,
+		runtime_libs: ["liball_available"],
+		no_libcrt : true,
+		nocrt : true,
+		system_shared_libs : [],
+	}
+	cc_library {
+		name: "libproduct1",
+		product_specific: true,
+		no_libcrt : true,
+		nocrt : true,
+		system_shared_libs : [],
+	}
+	cc_library {
+		name: "libproduct2",
+		product_specific: true,
+		runtime_libs: ["liball_available", "libproduct1"],
 		no_libcrt : true,
 		nocrt : true,
 		system_shared_libs : [],
@@ -3457,32 +3624,45 @@
 	// runtime_libs for core variants use the module names without suffixes.
 	variant := "android_arm64_armv8-a_shared"
 
-	module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
+	module := ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
+	checkRuntimeLibs(t, []string{"liball_available"}, module)
+
+	module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
+	checkRuntimeLibs(t, []string{"liball_available"}, module)
 
 	module = ctx.ModuleForTests("libcore", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
+	checkRuntimeLibs(t, []string{"liball_available"}, module)
 
 	// runtime_libs for vendor variants have '.vendor' suffixes if the modules have both core
 	// and vendor variants.
 	variant = "android_vendor.VER_arm64_armv8-a_shared"
 
-	module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"libvendor_available1.vendor"}, module)
+	module = ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
+	checkRuntimeLibs(t, []string{"liball_available.vendor"}, module)
 
 	module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"libvendor_available1.vendor", "libvendor1"}, module)
+	checkRuntimeLibs(t, []string{"liball_available.vendor", "libvendor1"}, module)
+
+	// runtime_libs for product variants have '.product' suffixes if the modules have both core
+	// and product variants.
+	variant = "android_product.VER_arm64_armv8-a_shared"
+
+	module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
+	checkRuntimeLibs(t, []string{"liball_available.product"}, module)
+
+	module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
+	checkRuntimeLibs(t, []string{"liball_available.product", "libproduct1"}, module)
 }
 
 func TestExcludeRuntimeLibs(t *testing.T) {
 	ctx := testCc(t, runtimeLibAndroidBp)
 
 	variant := "android_arm64_armv8-a_shared"
-	module := ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
+	module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
+	checkRuntimeLibs(t, []string{"liball_available"}, module)
 
 	variant = "android_vendor.VER_arm64_armv8-a_shared"
-	module = ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
+	module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
 	checkRuntimeLibs(t, nil, module)
 }
 
@@ -3493,11 +3673,14 @@
 
 	variant := "android_arm64_armv8-a_shared"
 
-	module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
+	module := ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
+	checkRuntimeLibs(t, []string{"liball_available"}, module)
 
 	module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"libvendor_available1", "libvendor1"}, module)
+	checkRuntimeLibs(t, []string{"liball_available", "libvendor1"}, module)
+
+	module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
+	checkRuntimeLibs(t, []string{"liball_available", "libproduct1"}, module)
 }
 
 func checkStaticLibs(t *testing.T, expected []string, module *Module) {
@@ -4244,3 +4427,21 @@
 		t.Errorf("expected %q in cflags, got %q", "-Iinclude/libbar", cFlags)
 	}
 }
+
+func TestAidlFlagsPassedToTheAidlCompiler(t *testing.T) {
+	ctx := testCc(t, `
+		cc_library {
+			name: "libfoo",
+			srcs: ["a/Foo.aidl"],
+			aidl: { flags: ["-Werror"], },
+		}
+	`)
+
+	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
+	manifest := android.RuleBuilderSboxProtoForTests(t, libfoo.Output("aidl.sbox.textproto"))
+	aidlCommand := manifest.Commands[0].GetCommand()
+	expectedAidlFlag := "-Werror"
+	if !strings.Contains(aidlCommand, expectedAidlFlag) {
+		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
+	}
+}
diff --git a/cc/compiler.go b/cc/compiler.go
index 2c05899..eb2b566 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -123,6 +123,9 @@
 
 		// whether to generate traces (for systrace) for this interface
 		Generate_traces *bool
+
+		// list of flags that will be passed to the AIDL compiler
+		Flags []string
 	}
 
 	Renderscript struct {
@@ -521,6 +524,7 @@
 	}
 
 	if compiler.hasSrcExt(".aidl") {
+		flags.aidlFlags = append(flags.aidlFlags, compiler.Properties.Aidl.Flags...)
 		if len(compiler.Properties.Aidl.Local_include_dirs) > 0 {
 			localAidlIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Aidl.Local_include_dirs)
 			flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(localAidlIncludeDirs))
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 519a9e2..3282958 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -94,6 +94,7 @@
 // `modernize-*`.
 var ClangTidyDisableChecks = []string{
 	"misc-no-recursion",
+	"readability-function-cognitive-complexity", // http://b/175055536
 }
 
 func init() {
@@ -190,6 +191,8 @@
 		"-Wno-pessimizing-move",                     // http://b/154270751
 		// New warnings to be fixed after clang-r399163
 		"-Wno-non-c-typedef-for-linkage", // http://b/161304145
+		// New warnings to be fixed after clang-r407598
+		"-Wno-string-concatenation", // http://b/175068488
 	}, " "))
 
 	// Extra cflags for external third-party projects to disable warnings that
diff --git a/cc/config/global.go b/cc/config/global.go
index e5cb7ee..fa8e0fb 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -135,8 +135,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r399163b"
-	ClangDefaultShortVersion = "11.0.5"
+	ClangDefaultVersion      = "clang-r407598"
+	ClangDefaultShortVersion = "12.0.1"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
diff --git a/cc/genrule.go b/cc/genrule.go
index 9648869..1ce2169 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -75,7 +75,15 @@
 }
 
 func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
-	return Bool(g.Recovery_available)
+	// If the build is using a snapshot, the recovery variant under AOSP directories
+	// is not needed.
+	recoverySnapshotVersion := ctx.DeviceConfig().RecoverySnapshotVersion()
+	if recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" &&
+		!isRecoveryProprietaryModule(ctx) {
+		return false
+	} else {
+		return Bool(g.Recovery_available)
+	}
 }
 
 func (g *GenruleExtraProperties) ExtraImageVariations(ctx android.BaseModuleContext) []string {
diff --git a/cc/image.go b/cc/image.go
index 13d77cc..11ba55c 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -67,9 +67,8 @@
 )
 
 func (ctx *moduleContext) ProductSpecific() bool {
-	//TODO(b/150902910): Replace HasNonSystemVariants() with HasProductVariant()
 	return ctx.ModuleContext.ProductSpecific() ||
-		(ctx.mod.HasNonSystemVariants() && ctx.mod.InProduct())
+		(ctx.mod.HasProductVariant() && ctx.mod.InProduct())
 }
 
 func (ctx *moduleContext) SocSpecific() bool {
@@ -277,6 +276,9 @@
 	platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
 	boardVndkVersion := mctx.DeviceConfig().VndkVersion()
 	productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
+	recoverySnapshotVersion := mctx.DeviceConfig().RecoverySnapshotVersion()
+	usingRecoverySnapshot := recoverySnapshotVersion != "current" &&
+		recoverySnapshotVersion != ""
 	if boardVndkVersion == "current" {
 		boardVndkVersion = platformVndkVersion
 	}
@@ -315,7 +317,11 @@
 		if snapshot, ok := m.linker.(interface {
 			version() string
 		}); ok {
-			vendorVariants = append(vendorVariants, snapshot.version())
+			if m.InstallInRecovery() {
+				recoveryVariantNeeded = true
+			} else {
+				vendorVariants = append(vendorVariants, snapshot.version())
+			}
 		} else {
 			mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
 		}
@@ -421,6 +427,15 @@
 		coreVariantNeeded = false
 	}
 
+	// If using a snapshot, the recovery variant under AOSP directories is not needed,
+	// except for kernel headers, which needs all variants.
+	if _, ok := m.linker.(*kernelHeadersDecorator); !ok &&
+		!m.isSnapshotPrebuilt() &&
+		usingRecoverySnapshot &&
+		!isRecoveryProprietaryModule(mctx) {
+		recoveryVariantNeeded = false
+	}
+
 	for _, variant := range android.FirstUniqueStrings(vendorVariants) {
 		m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
 	}
@@ -433,6 +448,14 @@
 	m.Properties.VendorRamdiskVariantNeeded = vendorRamdiskVariantNeeded
 	m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
 	m.Properties.CoreVariantNeeded = coreVariantNeeded
+
+	// Disable the module if no variants are needed.
+	if !ramdiskVariantNeeded &&
+		!recoveryVariantNeeded &&
+		!coreVariantNeeded &&
+		len(m.Properties.ExtraVariants) == 0 {
+		m.Disable()
+	}
 }
 
 func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
diff --git a/cc/library.go b/cc/library.go
index 23556b0..bc6ff69 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1738,12 +1738,9 @@
 
 		isLLNDK := false
 		if m, ok := mctx.Module().(*Module); ok {
-			isLLNDK = m.IsLlndk()
 			// Don't count the vestigial llndk_library module as isLLNDK, it needs a static
 			// variant so that a cc_library_prebuilt can depend on it.
-			if _, ok := m.linker.(*llndkStubDecorator); ok {
-				isLLNDK = false
-			}
+			isLLNDK = m.IsLlndk() && !isVestigialLLNDKModule(m)
 		}
 		buildStatic := library.BuildStaticVariant() && !isLLNDK
 		buildShared := library.BuildSharedVariant()
@@ -1855,9 +1852,8 @@
 	Host() bool
 	InRamdisk() bool
 	InVendorRamdisk() bool
-	InRecovery() bool
 }) bool {
-	return !module.Host() && !module.InRamdisk() && !module.InVendorRamdisk() && !module.InRecovery()
+	return !module.Host() && !module.InRamdisk() && !module.InVendorRamdisk()
 }
 
 func CanBeVersionVariant(module interface {
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index d0fbc48..0c4bcfd 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -100,6 +100,11 @@
 	return name + llndkLibrarySuffix
 }
 
+func (stub *llndkStubDecorator) linkerProps() []interface{} {
+	props := stub.libraryDecorator.linkerProps()
+	return append(props, &stub.Properties)
+}
+
 func (stub *llndkStubDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
 	stub.libraryDecorator.libName = stub.implementationModuleName(ctx.ModuleName())
 	return stub.libraryDecorator.linkerFlags(ctx, flags)
@@ -137,12 +142,6 @@
 	module.installer = nil
 	module.library = stub
 
-	module.AddProperties(
-		&module.Properties,
-		&stub.Properties,
-		&library.MutatedProperties,
-		&library.flagExporter.Properties)
-
 	return module
 }
 
@@ -156,8 +155,14 @@
 //    }
 func LlndkLibraryFactory() android.Module {
 	module := NewLLndkStubLibrary()
-	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
-	return module
+	return module.Init()
+}
+
+// isVestigialLLNDKModule returns true if m is a vestigial llndk_library module used to provide
+// properties to the LLNDK variant of a cc_library.
+func isVestigialLLNDKModule(m *Module) bool {
+	_, ok := m.linker.(*llndkStubDecorator)
+	return ok
 }
 
 type llndkHeadersDecorator struct {
diff --git a/cc/makevars.go b/cc/makevars.go
index bd8aab5..8301c6b 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -99,6 +99,7 @@
 	ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "")
 
 	ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion())
+	ctx.Strict("RECOVERY_SNAPSHOT_VERSION", ctx.DeviceConfig().RecoverySnapshotVersion())
 
 	// Filter vendor_public_library that are exported to make
 	exportedVendorPublicLibraries := []string{}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 0e2d01a..bb92a88 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -458,6 +458,22 @@
 	return false
 }
 
+func toDisableUnsignedShiftBaseChange(flags []string) bool {
+	// Returns true if any flag is fsanitize*integer, and there is
+	// no explicit flag about sanitize=unsigned-shift-base.
+	for _, f := range flags {
+		if strings.Contains(f, "sanitize=unsigned-shift-base") {
+			return false
+		}
+	}
+	for _, f := range flags {
+		if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
+			return true
+		}
+	}
+	return false
+}
+
 func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
 	minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"
 	minimalRuntimePath := "${config.ClangAsanLibDir}/" + minimalRuntimeLib
@@ -614,6 +630,10 @@
 		if toDisableImplicitIntegerChange(flags.Local.CFlags) {
 			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=implicit-integer-sign-change")
 		}
+		// http://b/171275751, Android doesn't build with this sanitizer yet.
+		if toDisableUnsignedShiftBaseChange(flags.Local.CFlags) {
+			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=unsigned-shift-base")
+		}
 	}
 
 	if len(sanitize.Properties.DiagSanitizers) > 0 {
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 4c4e9b6..8c5d1a4 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -22,6 +22,8 @@
 	"sync"
 
 	"android/soong/android"
+
+	"github.com/google/blueprint/proptools"
 )
 
 // Defines the specifics of different images to which the snapshot process is applicable, e.g.,
@@ -30,6 +32,9 @@
 	// Used to register callbacks with the build system.
 	init()
 
+	// Returns true if a snapshot should be generated for this image.
+	shouldGenerateSnapshot(ctx android.SingletonContext) bool
+
 	// Function that returns true if the module is included in this image.
 	// Using a function return instead of a value to prevent early
 	// evalution of a function that may be not be defined.
@@ -55,6 +60,28 @@
 	// snapshot, e.g., using the exclude_from_vendor_snapshot or
 	// exclude_from_recovery_snapshot properties.
 	excludeFromSnapshot(m *Module) bool
+
+	// Returns the snapshotMap to be used for a given module and config, or nil if the
+	// module is not included in this image.
+	getSnapshotMap(m *Module, cfg android.Config) *snapshotMap
+
+	// Returns mutex used for mutual exclusion when updating the snapshot maps.
+	getMutex() *sync.Mutex
+
+	// For a given arch, a maps of which modules are included in this image.
+	suffixModules(config android.Config) map[string]bool
+
+	// Whether to add a given module to the suffix map.
+	shouldBeAddedToSuffixModules(m *Module) bool
+
+	// Returns true if the build is using a snapshot for this image.
+	isUsingSnapshot(cfg android.DeviceConfig) bool
+
+	// Whether to skip the module mutator for a module in a given context.
+	skipModuleMutator(ctx android.BottomUpMutatorContext) bool
+
+	// Whether to skip the source mutator for a given module.
+	skipSourceMutator(ctx android.BottomUpMutatorContext) bool
 }
 
 type vendorSnapshotImage struct{}
@@ -69,6 +96,11 @@
 	android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
 }
 
+func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
+	// BOARD_VNDK_VERSION must be set to 'current' in order to generate a snapshot.
+	return ctx.DeviceConfig().VndkVersion() == "current"
+}
+
 func (vendorSnapshotImage) inImage(m *Module) func() bool {
 	return m.inVendor
 }
@@ -90,6 +122,75 @@
 	return m.ExcludeFromVendorSnapshot()
 }
 
+func (vendorSnapshotImage) getSnapshotMap(m *Module, cfg android.Config) *snapshotMap {
+	if lib, ok := m.linker.(libraryInterface); ok {
+		if lib.static() {
+			return vendorSnapshotStaticLibs(cfg)
+		} else if lib.shared() {
+			return vendorSnapshotSharedLibs(cfg)
+		} else {
+			// header
+			return vendorSnapshotHeaderLibs(cfg)
+		}
+	} else if m.binary() {
+		return vendorSnapshotBinaries(cfg)
+	} else if m.object() {
+		return vendorSnapshotObjects(cfg)
+	} else {
+		return nil
+	}
+}
+
+func (vendorSnapshotImage) getMutex() *sync.Mutex {
+	return &vendorSnapshotsLock
+}
+
+func (vendorSnapshotImage) suffixModules(config android.Config) map[string]bool {
+	return vendorSuffixModules(config)
+}
+
+func (vendorSnapshotImage) shouldBeAddedToSuffixModules(module *Module) bool {
+	// vendor suffix should be added to snapshots if the source module isn't vendor: true.
+	if module.SocSpecific() {
+		return false
+	}
+
+	// But we can't just check SocSpecific() since we already passed the image mutator.
+	// Check ramdisk and recovery to see if we are real "vendor: true" module.
+	ramdiskAvailable := module.InRamdisk() && !module.OnlyInRamdisk()
+	vendorRamdiskAvailable := module.InVendorRamdisk() && !module.OnlyInVendorRamdisk()
+	recoveryAvailable := module.InRecovery() && !module.OnlyInRecovery()
+
+	return !ramdiskAvailable && !recoveryAvailable && !vendorRamdiskAvailable
+}
+
+func (vendorSnapshotImage) isUsingSnapshot(cfg android.DeviceConfig) bool {
+	vndkVersion := cfg.VndkVersion()
+	return vndkVersion != "current" && vndkVersion != ""
+}
+
+func (vendorSnapshotImage) skipModuleMutator(ctx android.BottomUpMutatorContext) bool {
+	vndkVersion := ctx.DeviceConfig().VndkVersion()
+	module, ok := ctx.Module().(*Module)
+	return !ok || module.VndkVersion() != vndkVersion
+}
+
+func (vendorSnapshotImage) skipSourceMutator(ctx android.BottomUpMutatorContext) bool {
+	vndkVersion := ctx.DeviceConfig().VndkVersion()
+	module, ok := ctx.Module().(*Module)
+	if !ok {
+		return true
+	}
+	if module.VndkVersion() != vndkVersion {
+		return true
+	}
+	// .. and also filter out llndk library
+	if module.IsLlndk() {
+		return true
+	}
+	return false
+}
+
 func (recoverySnapshotImage) init() {
 	android.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
 	android.RegisterModuleType("recovery_snapshot_shared", RecoverySnapshotSharedFactory)
@@ -99,6 +200,12 @@
 	android.RegisterModuleType("recovery_snapshot_object", RecoverySnapshotObjectFactory)
 }
 
+func (recoverySnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
+	// RECOVERY_SNAPSHOT_VERSION must be set to 'current' in order to generate a
+	// snapshot.
+	return ctx.DeviceConfig().RecoverySnapshotVersion() == "current"
+}
+
 func (recoverySnapshotImage) inImage(m *Module) func() bool {
 	return m.InRecovery
 }
@@ -120,6 +227,52 @@
 	return m.ExcludeFromRecoverySnapshot()
 }
 
+func (recoverySnapshotImage) getSnapshotMap(m *Module, cfg android.Config) *snapshotMap {
+	if lib, ok := m.linker.(libraryInterface); ok {
+		if lib.static() {
+			return recoverySnapshotStaticLibs(cfg)
+		} else if lib.shared() {
+			return recoverySnapshotSharedLibs(cfg)
+		} else {
+			// header
+			return recoverySnapshotHeaderLibs(cfg)
+		}
+	} else if m.binary() {
+		return recoverySnapshotBinaries(cfg)
+	} else if m.object() {
+		return recoverySnapshotObjects(cfg)
+	} else {
+		return nil
+	}
+}
+
+func (recoverySnapshotImage) getMutex() *sync.Mutex {
+	return &recoverySnapshotsLock
+}
+
+func (recoverySnapshotImage) suffixModules(config android.Config) map[string]bool {
+	return recoverySuffixModules(config)
+}
+
+func (recoverySnapshotImage) shouldBeAddedToSuffixModules(module *Module) bool {
+	return proptools.BoolDefault(module.Properties.Recovery_available, false)
+}
+
+func (recoverySnapshotImage) isUsingSnapshot(cfg android.DeviceConfig) bool {
+	recoverySnapshotVersion := cfg.RecoverySnapshotVersion()
+	return recoverySnapshotVersion != "current" && recoverySnapshotVersion != ""
+}
+
+func (recoverySnapshotImage) skipModuleMutator(ctx android.BottomUpMutatorContext) bool {
+	module, ok := ctx.Module().(*Module)
+	return !ok || !module.InRecovery()
+}
+
+func (recoverySnapshotImage) skipSourceMutator(ctx android.BottomUpMutatorContext) bool {
+	module, ok := ctx.Module().(*Module)
+	return !ok || !module.InRecovery()
+}
+
 var vendorSnapshotImageSingleton vendorSnapshotImage
 var recoverySnapshotImageSingleton recoverySnapshotImage
 
@@ -154,6 +307,16 @@
 	vendorSnapshotObjectsKey    = android.NewOnceKey("vendorSnapshotObjects")
 )
 
+var (
+	recoverySnapshotsLock         sync.Mutex
+	recoverySuffixModulesKey      = android.NewOnceKey("recoverySuffixModules")
+	recoverySnapshotHeaderLibsKey = android.NewOnceKey("recoverySnapshotHeaderLibs")
+	recoverySnapshotStaticLibsKey = android.NewOnceKey("recoverySnapshotStaticLibs")
+	recoverySnapshotSharedLibsKey = android.NewOnceKey("recoverySnapshotSharedLibs")
+	recoverySnapshotBinariesKey   = android.NewOnceKey("recoverySnapshotBinaries")
+	recoverySnapshotObjectsKey    = android.NewOnceKey("recoverySnapshotObjects")
+)
+
 // vendorSuffixModules holds names of modules whose vendor variants should have the vendor suffix.
 // This is determined by source modules, and then this will be used when exporting snapshot modules
 // to Makefile.
@@ -200,12 +363,52 @@
 	}).(*snapshotMap)
 }
 
+func recoverySuffixModules(config android.Config) map[string]bool {
+	return config.Once(recoverySuffixModulesKey, func() interface{} {
+		return make(map[string]bool)
+	}).(map[string]bool)
+}
+
+func recoverySnapshotHeaderLibs(config android.Config) *snapshotMap {
+	return config.Once(recoverySnapshotHeaderLibsKey, func() interface{} {
+		return newSnapshotMap()
+	}).(*snapshotMap)
+}
+
+func recoverySnapshotSharedLibs(config android.Config) *snapshotMap {
+	return config.Once(recoverySnapshotSharedLibsKey, func() interface{} {
+		return newSnapshotMap()
+	}).(*snapshotMap)
+}
+
+func recoverySnapshotStaticLibs(config android.Config) *snapshotMap {
+	return config.Once(recoverySnapshotStaticLibsKey, func() interface{} {
+		return newSnapshotMap()
+	}).(*snapshotMap)
+}
+
+func recoverySnapshotBinaries(config android.Config) *snapshotMap {
+	return config.Once(recoverySnapshotBinariesKey, func() interface{} {
+		return newSnapshotMap()
+	}).(*snapshotMap)
+}
+
+func recoverySnapshotObjects(config android.Config) *snapshotMap {
+	return config.Once(recoverySnapshotObjectsKey, func() interface{} {
+		return newSnapshotMap()
+	}).(*snapshotMap)
+}
+
 type baseSnapshotDecoratorProperties struct {
 	// snapshot version.
 	Version string
 
 	// Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
 	Target_arch string
+
+	// Suffix to be added to the module name, e.g., vendor_shared,
+	// recovery_shared, etc.
+	Module_suffix string
 }
 
 // baseSnapshotDecorator provides common basic functions for all snapshot modules, such as snapshot
@@ -222,7 +425,6 @@
 // will be seen as "libbase.vendor_static.30.arm64" by Soong.
 type baseSnapshotDecorator struct {
 	baseProperties baseSnapshotDecoratorProperties
-	moduleSuffix   string
 }
 
 func (p *baseSnapshotDecorator) Name(name string) string {
@@ -235,7 +437,7 @@
 		versionSuffix += "." + p.arch()
 	}
 
-	return p.moduleSuffix + versionSuffix
+	return p.baseProperties.Module_suffix + versionSuffix
 }
 
 func (p *baseSnapshotDecorator) version() string {
@@ -246,6 +448,10 @@
 	return p.baseProperties.Target_arch
 }
 
+func (p *baseSnapshotDecorator) module_suffix() string {
+	return p.baseProperties.Module_suffix
+}
+
 func (p *baseSnapshotDecorator) isSnapshotPrebuilt() bool {
 	return true
 }
@@ -253,7 +459,7 @@
 // Call this with a module suffix after creating a snapshot module, such as
 // vendorSnapshotSharedSuffix, recoverySnapshotBinarySuffix, etc.
 func (p *baseSnapshotDecorator) init(m *Module, suffix string) {
-	p.moduleSuffix = suffix
+	p.baseProperties.Module_suffix = suffix
 	m.AddProperties(&p.baseProperties)
 	android.AddLoadHook(m, func(ctx android.LoadHookContext) {
 		vendorSnapshotLoadHook(ctx, p)
@@ -313,7 +519,7 @@
 		// Library flags for cfi variant.
 		Cfi snapshotLibraryProperties `android:"arch_variant"`
 	}
-	androidMkVendorSuffix bool
+	androidMkSuffix string
 }
 
 func (p *snapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
@@ -337,7 +543,12 @@
 // done by normal library decorator, e.g. exporting flags.
 func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
 	m := ctx.Module().(*Module)
-	p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+
+	if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+		p.androidMkSuffix = vendorSuffix
+	} else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
+		p.androidMkSuffix = recoverySuffix
+	}
 
 	if p.header() {
 		return p.libraryDecorator.link(ctx, flags, deps, objs)
@@ -530,8 +741,8 @@
 type snapshotBinaryDecorator struct {
 	baseSnapshotDecorator
 	*binaryDecorator
-	properties            snapshotBinaryProperties
-	androidMkVendorSuffix bool
+	properties      snapshotBinaryProperties
+	androidMkSuffix string
 }
 
 func (p *snapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
@@ -556,7 +767,12 @@
 	binName := in.Base()
 
 	m := ctx.Module().(*Module)
-	p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+	if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+		p.androidMkSuffix = vendorSuffix
+	} else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
+		p.androidMkSuffix = recoverySuffix
+
+	}
 
 	// use cpExecutable to make it executable
 	outputFile := android.PathForModuleOut(ctx, binName)
@@ -627,8 +843,8 @@
 type snapshotObjectLinker struct {
 	baseSnapshotDecorator
 	objectLinker
-	properties            vendorSnapshotObjectProperties
-	androidMkVendorSuffix bool
+	properties      vendorSnapshotObjectProperties
+	androidMkSuffix string
 }
 
 func (p *snapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
@@ -649,7 +865,12 @@
 	}
 
 	m := ctx.Module().(*Module)
-	p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+
+	if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+		p.androidMkSuffix = vendorSuffix
+	} else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
+		p.androidMkSuffix = recoverySuffix
+	}
 
 	return android.PathForModuleSrc(ctx, *p.properties.Src)
 }
@@ -717,17 +938,24 @@
 //
 // TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
 func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) {
-	vndkVersion := ctx.DeviceConfig().VndkVersion()
-	// don't need snapshot if current
-	if vndkVersion == "current" || vndkVersion == "" {
+	snapshotMutator(ctx, vendorSnapshotImageSingleton)
+}
+
+func RecoverySnapshotMutator(ctx android.BottomUpMutatorContext) {
+	snapshotMutator(ctx, recoverySnapshotImageSingleton)
+}
+
+func snapshotMutator(ctx android.BottomUpMutatorContext, image snapshotImage) {
+	if !image.isUsingSnapshot(ctx.DeviceConfig()) {
 		return
 	}
-
 	module, ok := ctx.Module().(*Module)
-	if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion {
+	if !ok || !module.Enabled() {
 		return
 	}
-
+	if image.skipModuleMutator(ctx) {
+		return
+	}
 	if !module.isSnapshotPrebuilt() {
 		return
 	}
@@ -742,39 +970,31 @@
 		return
 	}
 
-	var snapshotMap *snapshotMap
-
-	if lib, ok := module.linker.(libraryInterface); ok {
-		if lib.static() {
-			snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
-		} else if lib.shared() {
-			snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
-		} else {
-			// header
-			snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
-		}
-	} else if _, ok := module.linker.(*snapshotBinaryDecorator); ok {
-		snapshotMap = vendorSnapshotBinaries(ctx.Config())
-	} else if _, ok := module.linker.(*snapshotObjectLinker); ok {
-		snapshotMap = vendorSnapshotObjects(ctx.Config())
-	} else {
+	var snapshotMap *snapshotMap = image.getSnapshotMap(module, ctx.Config())
+	if snapshotMap == nil {
 		return
 	}
 
-	vendorSnapshotsLock.Lock()
-	defer vendorSnapshotsLock.Unlock()
+	mutex := image.getMutex()
+	mutex.Lock()
+	defer mutex.Unlock()
 	snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName())
 }
 
 // VendorSnapshotSourceMutator disables source modules which have corresponding snapshots.
 func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
+	snapshotSourceMutator(ctx, vendorSnapshotImageSingleton)
+}
+
+func RecoverySnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
+	snapshotSourceMutator(ctx, recoverySnapshotImageSingleton)
+}
+
+func snapshotSourceMutator(ctx android.BottomUpMutatorContext, image snapshotImage) {
 	if !ctx.Device() {
 		return
 	}
-
-	vndkVersion := ctx.DeviceConfig().VndkVersion()
-	// don't need snapshot if current
-	if vndkVersion == "current" || vndkVersion == "" {
+	if !image.isUsingSnapshot(ctx.DeviceConfig()) {
 		return
 	}
 
@@ -783,48 +1003,23 @@
 		return
 	}
 
-	// vendor suffix should be added to snapshots if the source module isn't vendor: true.
-	if !module.SocSpecific() {
-		// But we can't just check SocSpecific() since we already passed the image mutator.
-		// Check ramdisk and recovery to see if we are real "vendor: true" module.
-		ramdiskAvailable := module.InRamdisk() && !module.OnlyInRamdisk()
-		vendorRamdiskAvailable := module.InVendorRamdisk() && !module.OnlyInVendorRamdisk()
-		recoveryAvailable := module.InRecovery() && !module.OnlyInRecovery()
+	if image.shouldBeAddedToSuffixModules(module) {
+		mutex := image.getMutex()
+		mutex.Lock()
+		defer mutex.Unlock()
 
-		if !ramdiskAvailable && !recoveryAvailable && !vendorRamdiskAvailable {
-			vendorSnapshotsLock.Lock()
-			defer vendorSnapshotsLock.Unlock()
-
-			vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true
-		}
+		image.suffixModules(ctx.Config())[ctx.ModuleName()] = true
 	}
 
-	if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() {
-		// only non-snapshot modules with BOARD_VNDK_VERSION
+	if module.isSnapshotPrebuilt() {
+		return
+	}
+	if image.skipSourceMutator(ctx) {
 		return
 	}
 
-	// .. and also filter out llndk library
-	if module.IsLlndk() {
-		return
-	}
-
-	var snapshotMap *snapshotMap
-
-	if lib, ok := module.linker.(libraryInterface); ok {
-		if lib.static() {
-			snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
-		} else if lib.shared() {
-			snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
-		} else {
-			// header
-			snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
-		}
-	} else if module.binary() {
-		snapshotMap = vendorSnapshotBinaries(ctx.Config())
-	} else if module.object() {
-		snapshotMap = vendorSnapshotObjects(ctx.Config())
-	} else {
+	var snapshotMap *snapshotMap = image.getSnapshotMap(module, ctx.Config())
+	if snapshotMap == nil {
 		return
 	}
 
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index e841a54..77d82f1 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -71,6 +71,10 @@
 // shouldCollectHeadersForSnapshot determines if the module is a possible candidate for snapshot.
 // If it's true, collectHeadersForSnapshot will be called in GenerateAndroidBuildActions.
 func shouldCollectHeadersForSnapshot(ctx android.ModuleContext, m *Module, apexInfo android.ApexInfo) bool {
+	if ctx.DeviceConfig().VndkVersion() != "current" &&
+		ctx.DeviceConfig().RecoverySnapshotVersion() != "current" {
+		return false
+	}
 	if _, _, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo); ok {
 		return ctx.Config().VndkSnapshotBuildArtifacts()
 	} else if isVendorSnapshotAware(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) ||
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index d2c29d6..417516b 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -85,7 +85,6 @@
 	// Modules under following directories are ignored. They are OEM's and vendor's
 	// proprietary modules(device/, kernel/, vendor/, and hardware/).
 	recoveryProprietaryDirs = []string{
-		"bootable/recovery",
 		"device",
 		"hardware",
 		"kernel",
@@ -156,6 +155,28 @@
 	return false
 }
 
+func isRecoveryProprietaryModule(ctx android.BaseModuleContext) bool {
+
+	// Any module in a vendor proprietary path is a vendor proprietary
+	// module.
+	if isRecoveryProprietaryPath(ctx.ModuleDir()) {
+		return true
+	}
+
+	// However if the module is not in a vendor proprietary path, it may
+	// still be a vendor proprietary module. This happens for cc modules
+	// that are excluded from the vendor snapshot, and it means that the
+	// vendor has assumed control of the framework-provided module.
+
+	if c, ok := ctx.Module().(*Module); ok {
+		if c.ExcludeFromRecoverySnapshot() {
+			return true
+		}
+	}
+
+	return false
+}
+
 // Determine if a module is going to be included in vendor snapshot or not.
 //
 // Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in
@@ -192,7 +213,7 @@
 	}
 	// If the module would be included based on its path, check to see if
 	// the module is marked to be excluded. If so, skip it.
-	if m.ExcludeFromVendorSnapshot() {
+	if image.excludeFromSnapshot(m) {
 		return false
 	}
 	if m.Target().Os.Class != android.Device {
@@ -290,8 +311,7 @@
 }
 
 func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
-	// BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot.
-	if ctx.DeviceConfig().VndkVersion() != "current" {
+	if !c.image.shouldGenerateSnapshot(ctx) {
 		return
 	}
 
@@ -480,7 +500,7 @@
 		inProprietaryPath := c.image.isProprietaryPath(moduleDir)
 		apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
 
-		if m.ExcludeFromVendorSnapshot() {
+		if c.image.excludeFromSnapshot(m) {
 			if inProprietaryPath {
 				// Error: exclude_from_vendor_snapshot applies
 				// to framework-path modules only.
diff --git a/cc/vndk.go b/cc/vndk.go
index 6bc7131..2071a03 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -35,6 +35,7 @@
 	vndkCoreLibrariesTxt             = "vndkcore.libraries.txt"
 	vndkSpLibrariesTxt               = "vndksp.libraries.txt"
 	vndkPrivateLibrariesTxt          = "vndkprivate.libraries.txt"
+	vndkProductLibrariesTxt          = "vndkproduct.libraries.txt"
 	vndkUsingCoreVariantLibrariesTxt = "vndkcorevariant.libraries.txt"
 )
 
@@ -45,6 +46,7 @@
 			vndkCoreLibrariesTxt,
 			vndkSpLibrariesTxt,
 			vndkPrivateLibrariesTxt,
+			vndkProductLibrariesTxt,
 		}
 	}
 	// Snapshot vndks have their own *.libraries.VER.txt files.
@@ -54,6 +56,7 @@
 		insertVndkVersion(vndkCoreLibrariesTxt, vndkVersion),
 		insertVndkVersion(vndkSpLibrariesTxt, vndkVersion),
 		insertVndkVersion(vndkPrivateLibrariesTxt, vndkVersion),
+		insertVndkVersion(vndkProductLibrariesTxt, vndkVersion),
 	}
 }
 
@@ -229,10 +232,11 @@
 }
 
 var (
-	vndkCoreLibrariesKey             = android.NewOnceKey("vndkCoreLibrarires")
-	vndkSpLibrariesKey               = android.NewOnceKey("vndkSpLibrarires")
-	llndkLibrariesKey                = android.NewOnceKey("llndkLibrarires")
-	vndkPrivateLibrariesKey          = android.NewOnceKey("vndkPrivateLibrarires")
+	vndkCoreLibrariesKey             = android.NewOnceKey("vndkCoreLibraries")
+	vndkSpLibrariesKey               = android.NewOnceKey("vndkSpLibraries")
+	llndkLibrariesKey                = android.NewOnceKey("llndkLibraries")
+	vndkPrivateLibrariesKey          = android.NewOnceKey("vndkPrivateLibraries")
+	vndkProductLibrariesKey          = android.NewOnceKey("vndkProductLibraries")
 	vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibraries")
 	vndkMustUseVendorVariantListKey  = android.NewOnceKey("vndkMustUseVendorVariantListKey")
 	vndkLibrariesLock                sync.Mutex
@@ -262,6 +266,12 @@
 	}).(map[string]string)
 }
 
+func vndkProductLibraries(config android.Config) map[string]string {
+	return config.Once(vndkProductLibrariesKey, func() interface{} {
+		return make(map[string]string)
+	}).(map[string]string)
+}
+
 func vndkUsingCoreVariantLibraries(config android.Config) map[string]string {
 	return config.Once(vndkUsingCoreVariantLibrariesKey, func() interface{} {
 		return make(map[string]string)
@@ -299,6 +309,12 @@
 }
 
 func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
+	if m.InProduct() {
+		// We may skip the steps for the product variants because they
+		// are already covered by the vendor variants.
+		return
+	}
+
 	name := m.BaseModuleName()
 	filename, err := getVndkFileName(m)
 	if err != nil {
@@ -318,12 +334,6 @@
 	vndkLibrariesLock.Lock()
 	defer vndkLibrariesLock.Unlock()
 
-	if m.InProduct() {
-		// We may skip the other steps for the product variants because they
-		// are already covered by the vendor variants.
-		return
-	}
-
 	if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
 		m.Properties.MustUseVendorVariant = true
 	}
@@ -339,6 +349,9 @@
 	if m.IsVndkPrivate() {
 		vndkPrivateLibraries(mctx.Config())[name] = filename
 	}
+	if m.VendorProperties.Product_available != nil {
+		vndkProductLibraries(mctx.Config())[name] = filename
+	}
 }
 
 // Check for modules that mustn't be VNDK
@@ -453,6 +466,7 @@
 // - vndkcore.libraries.txt
 // - vndksp.libraries.txt
 // - vndkprivate.libraries.txt
+// - vndkproduct.libraries.txt
 // - vndkcorevariant.libraries.txt
 // A module behaves like a prebuilt_etc but its content is generated by soong.
 // By being a soong module, these files can be referenced by other soong modules.
@@ -486,6 +500,8 @@
 		list = android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
 	case vndkPrivateLibrariesTxt:
 		list = android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
+	case vndkProductLibrariesTxt:
+		list = android.SortedStringMapValues(vndkProductLibraries(ctx.Config()))
 	case vndkUsingCoreVariantLibrariesTxt:
 		list = android.SortedStringMapValues(vndkUsingCoreVariantLibraries(ctx.Config()))
 	default:
@@ -807,6 +823,7 @@
 	vndkcore := android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
 	vndksp := android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
 	vndkprivate := android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
+	vndkproduct := android.SortedStringMapValues(vndkProductLibraries(ctx.Config()))
 
 	// Build list of vndk libs as merged & tagged & filter-out(libclang_rt):
 	// Since each target have different set of libclang_rt.* files,
@@ -824,6 +841,7 @@
 	merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
 	merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...)
 	merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
+	merged = append(merged, addPrefix(filterOutLibClangRt(vndkproduct), "VNDK-product: ")...)
 	c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt")
 	android.WriteFileRule(ctx, c.vndkLibrariesFile, strings.Join(merged, "\n"))
 }
diff --git a/java/app.go b/java/app.go
index 249313c..574472c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -905,6 +905,8 @@
 		&module.appProperties,
 		&module.overridableAppProperties)
 
+	module.usesLibrary.enforce = true
+
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	android.InitOverridableModule(module, &module.appProperties.Overrides)
@@ -1175,6 +1177,9 @@
 // with knowledge of their shared libraries.
 type usesLibrary struct {
 	usesLibraryProperties UsesLibraryProperties
+
+	// Whether to enforce verify_uses_library check.
+	enforce bool
 }
 
 func (u *usesLibrary) addLib(lib string, optional bool) {
@@ -1241,7 +1246,7 @@
 func (u *usesLibrary) enforceUsesLibraries() bool {
 	defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs) > 0 ||
 		len(u.usesLibraryProperties.Optional_uses_libs) > 0
-	return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, defaultEnforceUsesLibs)
+	return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, u.enforce || defaultEnforceUsesLibs)
 }
 
 // Freeze the value of `enforce_uses_libs` based on the current values of `uses_libs` and `optional_uses_libs`.
diff --git a/java/app_import.go b/java/app_import.go
index 2054785..df940f1 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -430,6 +430,8 @@
 	android.InitDefaultableModule(module)
 	android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
 
+	module.usesLibrary.enforce = true
+
 	return module
 }
 
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 3b55c81..344d23b 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -182,31 +182,31 @@
 			name:                "no preferred",
 			aaptPreferredConfig: nil,
 			aaptPrebuiltDPI:     []string{},
-			expected:            "prebuilts/apk/app.apk",
+			expected:            "verify_uses_libraries/apk/app.apk",
 		},
 		{
 			name:                "AAPTPreferredConfig matches",
 			aaptPreferredConfig: proptools.StringPtr("xhdpi"),
 			aaptPrebuiltDPI:     []string{"xxhdpi", "ldpi"},
-			expected:            "prebuilts/apk/app_xhdpi.apk",
+			expected:            "verify_uses_libraries/apk/app_xhdpi.apk",
 		},
 		{
 			name:                "AAPTPrebuiltDPI matches",
 			aaptPreferredConfig: proptools.StringPtr("mdpi"),
 			aaptPrebuiltDPI:     []string{"xxhdpi", "xhdpi"},
-			expected:            "prebuilts/apk/app_xxhdpi.apk",
+			expected:            "verify_uses_libraries/apk/app_xxhdpi.apk",
 		},
 		{
 			name:                "non-first AAPTPrebuiltDPI matches",
 			aaptPreferredConfig: proptools.StringPtr("mdpi"),
 			aaptPrebuiltDPI:     []string{"ldpi", "xhdpi"},
-			expected:            "prebuilts/apk/app_xhdpi.apk",
+			expected:            "verify_uses_libraries/apk/app_xhdpi.apk",
 		},
 		{
 			name:                "no matches",
 			aaptPreferredConfig: proptools.StringPtr("mdpi"),
 			aaptPrebuiltDPI:     []string{"ldpi", "xxxhdpi"},
-			expected:            "prebuilts/apk/app.apk",
+			expected:            "verify_uses_libraries/apk/app.apk",
 		},
 	}
 
@@ -225,7 +225,7 @@
 		if len(matches) != 2 {
 			t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
 		}
-		if test.expected != matches[1] {
+		if strings.HasSuffix(matches[1], test.expected) {
 			t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
 		}
 	}
@@ -302,7 +302,7 @@
 					},
 				}
 			`,
-			expected: "prebuilts/apk/app_arm64.apk",
+			expected: "verify_uses_libraries/apk/app_arm64.apk",
 		},
 		{
 			name: "no matching arch",
@@ -321,7 +321,7 @@
 					},
 				}
 			`,
-			expected: "prebuilts/apk/app.apk",
+			expected: "verify_uses_libraries/apk/app.apk",
 		},
 		{
 			name: "no matching arch without default",
@@ -359,7 +359,7 @@
 		if len(matches) != 2 {
 			t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
 		}
-		if test.expected != matches[1] {
+		if strings.HasSuffix(matches[1], test.expected) {
 			t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
 		}
 	}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index f54b517..c74009e 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -192,24 +192,6 @@
 
 		Current ApiToCheck
 
-		// The java_sdk_library module generates references to modules (i.e. filegroups)
-		// from which information about the latest API version can be obtained. As those
-		// modules may not exist (e.g. because a previous version has not been released) it
-		// sets ignore_missing_latest_api=true on the droidstubs modules it creates so
-		// that droidstubs can ignore those references if the modules do not yet exist.
-		//
-		// If true then this will ignore module references for modules that do not exist
-		// in properties that supply the previous version of the API.
-		//
-		// There are two sets of those:
-		// * Api_file, Removed_api_file in check_api.last_released
-		// * New_since in check_api.api_lint.new_since
-		//
-		// The first two must be set as a pair, so either they should both exist or neither
-		// should exist - in which case when this property is true they are ignored. If one
-		// exists and the other does not then it is an error.
-		Ignore_missing_latest_api *bool `blueprint:"mutated"`
-
 		Api_lint struct {
 			Enabled *bool
 
@@ -304,25 +286,6 @@
 	return false
 }
 
-func ignoreMissingModules(ctx android.BottomUpMutatorContext, apiToCheck *ApiToCheck) {
-	apiFile := String(apiToCheck.Api_file)
-	removedApiFile := String(apiToCheck.Removed_api_file)
-
-	apiModule := android.SrcIsModule(apiFile)
-	removedApiModule := android.SrcIsModule(removedApiFile)
-
-	if apiModule == "" || removedApiModule == "" {
-		return
-	}
-
-	if ctx.OtherModuleExists(apiModule) || ctx.OtherModuleExists(removedApiModule) {
-		return
-	}
-
-	apiToCheck.Api_file = nil
-	apiToCheck.Removed_api_file = nil
-}
-
 // Used by xsd_config
 type ApiFilePath interface {
 	ApiFilePath() android.Path
@@ -1079,24 +1042,6 @@
 func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
 	d.Javadoc.addDeps(ctx)
 
-	// If requested clear any properties that provide information about the latest version
-	// of an API and which reference non-existent modules.
-	if Bool(d.properties.Check_api.Ignore_missing_latest_api) {
-		previousApi := android.SrcIsModule(String(d.properties.Previous_api))
-		if previousApi != "" && !ctx.OtherModuleExists(previousApi) {
-			d.properties.Previous_api = nil
-		}
-		ignoreMissingModules(ctx, &d.properties.Check_api.Last_released)
-
-		// If the new_since references a module, e.g. :module-latest-api and the module
-		// does not exist then clear it.
-		newSinceSrc := d.properties.Check_api.Api_lint.New_since
-		newSinceSrcModule := android.SrcIsModule(proptools.String(newSinceSrc))
-		if newSinceSrcModule != "" && !ctx.OtherModuleExists(newSinceSrcModule) {
-			d.properties.Check_api.Api_lint.New_since = nil
-		}
-	}
-
 	if len(d.properties.Merge_annotations_dirs) != 0 {
 		for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
 			ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
diff --git a/java/java.go b/java/java.go
index 18dd9bd..82b53be 100644
--- a/java/java.go
+++ b/java/java.go
@@ -304,6 +304,9 @@
 
 		// whether to generate Binder#GetTransaction name method.
 		Generate_get_transaction_name *bool
+
+		// list of flags that will be passed to the AIDL compiler
+		Flags []string
 	}
 
 	// If true, export a copy of the module as a -hostdex module for host testing.
@@ -872,6 +875,8 @@
 	var flags []string
 	var deps android.Paths
 
+	flags = append(flags, j.deviceProperties.Aidl.Flags...)
+
 	if aidlPreprocess.Valid() {
 		flags = append(flags, "-p"+aidlPreprocess.String())
 		deps = append(deps, aidlPreprocess.Path())
diff --git a/java/java_test.go b/java/java_test.go
index d1ba3db..a2466f9 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2424,6 +2424,22 @@
 	}
 }
 
+func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_library {
+			name: "foo",
+			srcs: ["aidl/foo/IFoo.aidl"],
+			aidl: { flags: ["-Werror"], },
+		}
+	`)
+
+	aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+	expectedAidlFlag := "-Werror"
+	if !strings.Contains(aidlCommand, expectedAidlFlag) {
+		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
+	}
+}
+
 func TestDataNativeBinaries(t *testing.T) {
 	ctx, config := testJava(t, `
 		java_test_host {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 4f3c22f..1a655a6 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1273,9 +1273,8 @@
 		Generate_stubs                   *bool
 		Previous_api                     *string
 		Check_api                        struct {
-			Current                   ApiToCheck
-			Last_released             ApiToCheck
-			Ignore_missing_latest_api *bool
+			Current       ApiToCheck
+			Last_released ApiToCheck
 
 			Api_lint struct {
 				Enabled       *bool
@@ -1358,9 +1357,8 @@
 	// check against the not-yet-release API
 	props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
 	props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
-	props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api)
 
-	if !apiScope.unstable {
+	if !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api) {
 		// check against the latest released API
 		latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
 		props.Previous_api = latestApiFilegroupName
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 35a807b..56d660e 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -31,12 +31,19 @@
 	// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
 	bindgenClangVersion = "clang-r399163b"
 
+	_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
+		if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
+			return override
+		}
+		return bindgenClangVersion
+	})
+
 	//TODO(b/160803703) Use a prebuilt bindgen instead of the built bindgen.
 	_ = pctx.HostBinToolVariable("bindgenCmd", "bindgen")
 	_ = pctx.SourcePathVariable("bindgenClang",
-		"${cc_config.ClangBase}/${config.HostPrebuiltTag}/"+bindgenClangVersion+"/bin/clang")
+		"${cc_config.ClangBase}/${config.HostPrebuiltTag}/${bindgenClangVersion}/bin/clang")
 	_ = pctx.SourcePathVariable("bindgenLibClang",
-		"${cc_config.ClangBase}/${config.HostPrebuiltTag}/"+bindgenClangVersion+"/lib64/")
+		"${cc_config.ClangBase}/${config.HostPrebuiltTag}/${bindgenClangVersion}/lib64/")
 
 	//TODO(ivanlozano) Switch this to RuleBuilder
 	bindgen = pctx.AndroidStaticRule("bindgen",
diff --git a/ui/build/config.go b/ui/build/config.go
index 1152cd7..15da1bc 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -56,6 +56,7 @@
 	katiSuffix      string
 	targetDevice    string
 	targetDeviceDir string
+	fullBuild       bool
 
 	// Autodetected
 	totalRAM uint64
@@ -791,6 +792,14 @@
 	c.targetDevice = device
 }
 
+func (c *configImpl) FullBuild() bool {
+	return c.fullBuild
+}
+
+func (c *configImpl) SetFullBuild(fullBuild bool) {
+	c.fullBuild = fullBuild
+}
+
 func (c *configImpl) TargetBuildVariant() string {
 	if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
 		return v
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index fe0aca9..be6f00a 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -214,6 +214,9 @@
 		// So that later Kati runs can find BoardConfig.mk faster
 		"TARGET_DEVICE_DIR",
 
+		// To decide whether to skip the old installed cleanup step.
+		"FULL_BUILD",
+
 		// Whether --werror_overriding_commands will work
 		"BUILD_BROKEN_DUP_RULES",
 
@@ -278,6 +281,7 @@
 	config.SetNinjaArgs(strings.Fields(makeVars["NINJA_GOALS"]))
 	config.SetTargetDevice(makeVars["TARGET_DEVICE"])
 	config.SetTargetDeviceDir(makeVars["TARGET_DEVICE_DIR"])
+	config.SetFullBuild(makeVars["FULL_BUILD"] == "true")
 
 	config.SetBuildBrokenDupRules(makeVars["BUILD_BROKEN_DUP_RULES"] == "true")
 	config.SetBuildBrokenUsesNetwork(makeVars["BUILD_BROKEN_USES_NETWORK"] == "true")
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 06ec646..668b20e 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -229,7 +229,11 @@
 
 	// Cleanup steps.
 	cleanCopyHeaders(ctx, config)
-	cleanOldInstalledFiles(ctx, config)
+	// Skip the old installed file cleanup step for few non-full build goals as we don't create
+	// an installed file list for them.
+	if config.FullBuild() {
+		cleanOldInstalledFiles(ctx, config)
+	}
 }
 
 // Clean out obsolete header files on the disk that were *not copied* during the