Merge "Add test_module_config_host" into main
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 392e819..d29e312 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -137,18 +137,22 @@
 	inputFiles := make([]android.Path, len(declarationFiles))
 	copy(inputFiles, declarationFiles)
 	inputFiles = append(inputFiles, valuesFiles...)
+	args := map[string]string{
+		"release_version":    ctx.Config().ReleaseVersion(),
+		"package":            module.properties.Package,
+		"declarations":       android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
+		"values":             joinAndPrefix(" --values ", module.properties.Values),
+		"default-permission": optionalVariable(" --default-permission ", defaultPermission),
+	}
+	if len(module.properties.Container) > 0 {
+		args["container"] = "--container " + module.properties.Container
+	}
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        aconfigRule,
 		Output:      intermediateCacheFilePath,
 		Inputs:      inputFiles,
 		Description: "aconfig_declarations",
-		Args: map[string]string{
-			"release_version":    ctx.Config().ReleaseVersion(),
-			"package":            module.properties.Package,
-			"declarations":       android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
-			"values":             joinAndPrefix(" --values ", module.properties.Values),
-			"default-permission": optionalVariable(" --default-permission ", defaultPermission),
-		},
+		Args:        args,
 	})
 
 	intermediateDumpFilePath := android.PathForModuleOut(ctx, "intermediate.txt")
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index 1fe3c86..5201fed 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -69,3 +69,38 @@
 	depData, _ := android.SingletonModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
 	android.AssertBoolEquals(t, "exportable", depData.Exportable, false)
 }
+
+func TestAconfigDeclarationsWithContainer(t *testing.T) {
+	bp := `
+		aconfig_declarations {
+			name: "module_name",
+			package: "com.example.package",
+			container: "com.android.foo",
+			srcs: [
+				"foo.aconfig",
+			],
+		}
+	`
+	result := runTest(t, android.FixtureExpectsNoErrors, bp)
+
+	module := result.ModuleForTests("module_name", "")
+	rule := module.Rule("aconfig")
+	android.AssertStringEquals(t, "rule must contain container", rule.Args["container"], "--container com.android.foo")
+}
+
+func TestAconfigDeclarationsWithoutContainer(t *testing.T) {
+	bp := `
+		aconfig_declarations {
+			name: "module_name",
+			package: "com.example.package",
+			srcs: [
+				"foo.aconfig",
+			],
+		}
+	`
+	result := runTest(t, android.FixtureExpectsNoErrors, bp)
+
+	module := result.ModuleForTests("module_name", "")
+	rule := module.Rule("aconfig")
+	android.AssertIntEquals(t, "rule must not contain container", len(rule.Args["container"]), 0)
+}
diff --git a/aconfig/codegen/rust_aconfig_library.go b/aconfig/codegen/rust_aconfig_library.go
index 3f7495b..a0a2a54 100644
--- a/aconfig/codegen/rust_aconfig_library.go
+++ b/aconfig/codegen/rust_aconfig_library.go
@@ -101,6 +101,7 @@
 	deps = a.BaseSourceProvider.SourceProviderDeps(ctx, deps)
 	deps.Rustlibs = append(deps.Rustlibs, "libflags_rust")
 	deps.Rustlibs = append(deps.Rustlibs, "liblazy_static")
+	deps.Rustlibs = append(deps.Rustlibs, "libaconfig_storage_read_api")
 	ctx.AddDependency(ctx.Module(), rustDeclarationsTag, a.Properties.Aconfig_declarations)
 	return deps
 }
diff --git a/aconfig/codegen/rust_aconfig_library_test.go b/aconfig/codegen/rust_aconfig_library_test.go
index 60bc9f7..330cecd 100644
--- a/aconfig/codegen/rust_aconfig_library_test.go
+++ b/aconfig/codegen/rust_aconfig_library_test.go
@@ -28,6 +28,11 @@
 				crate_name: "lazy_static",
 				srcs: ["src/lib.rs"],
 			}
+			rust_library {
+				name: "libaconfig_storage_read_api", // test mock
+				crate_name: "aconfig_storage_read_api",
+				srcs: ["lib.rs"],
+                        }
 			aconfig_declarations {
 				name: "my_aconfig_declarations",
 				package: "com.example.package",
@@ -98,6 +103,11 @@
 				crate_name: "lazy_static",
 				srcs: ["src/lib.rs"],
 			}
+			rust_library {
+				name: "libaconfig_storage_read_api", // test mock
+				crate_name: "aconfig_storage_read_api",
+				srcs: ["lib.rs"],
+                        }
 			aconfig_declarations {
 				name: "my_aconfig_declarations",
 				package: "com.example.package",
@@ -145,6 +155,11 @@
 				crate_name: "lazy_static",
 				srcs: ["src/lib.rs"],
 			}
+			rust_library {
+				name: "libaconfig_storage_read_api", // test mock
+				crate_name: "aconfig_storage_read_api",
+				srcs: ["lib.rs"],
+                        }
 			aconfig_declarations {
 				name: "my_aconfig_declarations",
 				package: "com.example.package",
diff --git a/aconfig/init.go b/aconfig/init.go
index 4625128..4655467 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -28,6 +28,7 @@
 		blueprint.RuleParams{
 			Command: `${aconfig} create-cache` +
 				` --package ${package}` +
+				` ${container}` +
 				` ${declarations}` +
 				` ${values}` +
 				` ${default-permission}` +
@@ -38,7 +39,7 @@
 				"${aconfig}",
 			},
 			Restat: true,
-		}, "release_version", "package", "declarations", "values", "default-permission")
+		}, "release_version", "package", "container", "declarations", "values", "default-permission")
 
 	// For create-device-config-sysprops: Generate aconfig flag value map text file
 	aconfigTextRule = pctx.AndroidStaticRule("aconfig_text",
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index fcc57e1..4c1782b 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -105,7 +105,8 @@
 		}
 	})
 
-	for container, aconfigFiles := range *mergedAconfigFiles {
+	for _, container := range SortedKeys(*mergedAconfigFiles) {
+		aconfigFiles := (*mergedAconfigFiles)[container]
 		(*mergedAconfigFiles)[container] = mergeAconfigFiles(ctx, container, aconfigFiles, false)
 	}
 
@@ -172,7 +173,8 @@
 	})
 	// We only need to set the provider if we have aconfig files.
 	if len(mergedAconfigFiles) > 0 {
-		for container, aconfigFiles := range mergedAconfigFiles {
+		for _, container := range SortedKeys(mergedAconfigFiles) {
+			aconfigFiles := mergedAconfigFiles[container]
 			mergedAconfigFiles[container] = mergeAconfigFiles(ctx, container, aconfigFiles, true)
 		}
 
diff --git a/android/api_levels.go b/android/api_levels.go
index 1130c3e..fab5fc7 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -289,6 +289,8 @@
 
 var ApiLevelR = uncheckedFinalApiLevel(30)
 
+var ApiLevelUpsideDownCake = uncheckedFinalApiLevel(34)
+
 // ReplaceFinalizedCodenames returns the API level number associated with that API level
 // if the `raw` input is the codename of an API level has been finalized.
 // If the input is *not* a finalized codename, the input is returned unmodified.
diff --git a/android/arch.go b/android/arch.go
index 4fe4345..9e79e31 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -693,6 +693,7 @@
 	m.base().commonProperties.CompileTarget = target
 	m.base().commonProperties.CompileMultiTargets = multiTargets
 	m.base().commonProperties.CompilePrimary = primaryTarget
+	m.base().commonProperties.ArchReady = true
 }
 
 // decodeMultilib returns the appropriate compile_multilib property for the module, or the default
diff --git a/android/arch_module_context.go b/android/arch_module_context.go
index 3cf4b41..a3a03af 100644
--- a/android/arch_module_context.go
+++ b/android/arch_module_context.go
@@ -35,6 +35,7 @@
 type archModuleContext struct {
 	// TODO: these should eventually go through a (possibly cached) provider like any other configuration instead
 	//  of being special cased.
+	ready         bool
 	os            OsType
 	target        Target
 	targetPrimary bool
@@ -42,6 +43,13 @@
 	primaryArch   bool
 }
 
+// ArchReady returns true if the arch mutator has run on the module. Before this returns
+// true, the module essentially doesn't have an arch and cannot make decisions based on
+// architecture.
+func (a *archModuleContext) ArchReady() bool {
+	return a.ready
+}
+
 func (a *archModuleContext) Target() Target {
 	return a.target
 }
diff --git a/android/base_module_context.go b/android/base_module_context.go
index dd38a4e..c4922f4 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -219,7 +219,7 @@
 
 	// EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
 	// can be used to evaluate the final value of Configurable properties.
-	EvaluateConfiguration(parser.SelectType, string) (string, bool)
+	EvaluateConfiguration(parser.SelectType, string, string) (string, bool)
 }
 
 type baseModuleContext struct {
@@ -305,6 +305,12 @@
 	AllowDisabledModuleDependency(target Module) bool
 }
 
+type AlwaysAllowDisabledModuleDependencyTag struct{}
+
+func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
+	return true
+}
+
 func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool, ignoreBlueprint bool) Module {
 	aModule, _ := module.(Module)
 
@@ -571,31 +577,6 @@
 	return sb.String()
 }
 
-func (m *baseModuleContext) EvaluateConfiguration(ty parser.SelectType, condition string) (string, bool) {
-	switch ty {
-	case parser.SelectTypeReleaseVariable:
-		if v, ok := m.Config().productVariables.BuildFlags[condition]; ok {
-			return v, true
-		}
-		return "", false
-	case parser.SelectTypeProductVariable:
-		// TODO(b/323382414): Might add these on a case-by-case basis
-		m.ModuleErrorf("TODO(b/323382414): Product variables are not yet supported in selects")
-		return "", false
-	case parser.SelectTypeSoongConfigVariable:
-		parts := strings.Split(condition, ":")
-		namespace := parts[0]
-		variable := parts[1]
-		if n, ok := m.Config().productVariables.VendorVars[namespace]; ok {
-			if v, ok := n[variable]; ok {
-				return v, true
-			}
-		}
-		return "", false
-	case parser.SelectTypeVariant:
-		m.ModuleErrorf("TODO(b/323382414): Variants are not yet supported in selects")
-		return "", false
-	default:
-		panic("Should be unreachable")
-	}
+func (m *baseModuleContext) EvaluateConfiguration(ty parser.SelectType, property, condition string) (string, bool) {
+	return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(ty, property, condition)
 }
diff --git a/android/buildinfo_prop.go b/android/buildinfo_prop.go
index 8e19ad5..8288fc5 100644
--- a/android/buildinfo_prop.go
+++ b/android/buildinfo_prop.go
@@ -54,6 +54,39 @@
 	return Paths{p.outputFilePath}, nil
 }
 
+func getBuildVariant(config Config) string {
+	if config.Eng() {
+		return "eng"
+	} else if config.Debuggable() {
+		return "userdebug"
+	} else {
+		return "user"
+	}
+}
+
+func getBuildFlavor(config Config) string {
+	buildFlavor := config.DeviceProduct() + "-" + getBuildVariant(config)
+	if InList("address", config.SanitizeDevice()) && !strings.Contains(buildFlavor, "_asan") {
+		buildFlavor += "_asan"
+	}
+	return buildFlavor
+}
+
+func shouldAddBuildThumbprint(config Config) bool {
+	knownOemProperties := []string{
+		"ro.product.brand",
+		"ro.product.name",
+		"ro.product.device",
+	}
+
+	for _, knownProp := range knownOemProperties {
+		if InList(knownProp, config.OemProperties()) {
+			return true
+		}
+	}
+	return false
+}
+
 func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
 	p.outputFilePath = PathForModuleOut(ctx, p.Name()).OutputPath
 	if !ctx.Config().KatiEnabled() {
@@ -61,87 +94,66 @@
 		return
 	}
 
-	lines := make([]string, 0)
-
-	writeString := func(str string) {
-		lines = append(lines, str)
-	}
-
-	writeString("# begin build properties")
-	writeString("# autogenerated by build/soong/android/buildinfo_prop.go")
-
-	writeProp := func(key, value string) {
-		if strings.Contains(key, "=") {
-			panic(fmt.Errorf("wrong property key %q: key must not contain '='", key))
-		}
-		writeString(key + "=" + value)
-	}
+	rule := NewRuleBuilder(pctx, ctx)
 
 	config := ctx.Config()
+	buildVariant := getBuildVariant(config)
+	buildFlavor := getBuildFlavor(config)
 
-	writeProp("ro.build.version.sdk", config.PlatformSdkVersion().String())
-	writeProp("ro.build.version.preview_sdk", config.PlatformPreviewSdkVersion())
-	writeProp("ro.build.version.codename", config.PlatformSdkCodename())
-	writeProp("ro.build.version.all_codenames", strings.Join(config.PlatformVersionActiveCodenames(), ","))
-	writeProp("ro.build.version.release", config.PlatformVersionLastStable())
-	writeProp("ro.build.version.release_or_codename", config.PlatformVersionName())
-	writeProp("ro.build.version.security_patch", config.PlatformSecurityPatch())
-	writeProp("ro.build.version.base_os", config.PlatformBaseOS())
-	writeProp("ro.build.version.min_supported_target_sdk", config.PlatformMinSupportedTargetSdkVersion())
-	writeProp("ro.build.version.known_codenames", config.PlatformVersionKnownCodenames())
+	cmd := rule.Command().BuiltTool("buildinfo")
 
-	if config.Eng() {
-		writeProp("ro.build.type", "eng")
-	} else if config.Debuggable() {
-		writeProp("ro.build.type", "userdebug")
-	} else {
-		writeProp("ro.build.type", "user")
+	if config.BoardUseVbmetaDigestInFingerprint() {
+		cmd.Flag("--use-vbmeta-digest-in-fingerprint")
 	}
 
-	// Currently, only a few properties are implemented to unblock microdroid use case.
-	// TODO(b/189164487): support below properties as well and replace build/make/tools/buildinfo.sh
-	/*
-		if $BOARD_USE_VBMETA_DIGTEST_IN_FINGERPRINT {
-			writeProp("ro.build.legacy.id", config.BuildID())
-		} else {
-			writeProp("ro.build.id", config.BuildId())
-		}
-		writeProp("ro.build.display.id", $BUILD_DISPLAY_ID)
-		writeProp("ro.build.version.incremental", $BUILD_NUMBER)
-		writeProp("ro.build.version.preview_sdk_fingerprint", $PLATFORM_PREVIEW_SDK_FINGERPRINT)
-		writeProp("ro.build.version.release_or_preview_display", $PLATFORM_DISPLAY_VERSION)
-		writeProp("ro.build.date", `$DATE`)
-		writeProp("ro.build.date.utc", `$DATE +%s`)
-		writeProp("ro.build.user", $BUILD_USERNAME)
-		writeProp("ro.build.host", $BUILD_HOSTNAME)
-		writeProp("ro.build.tags", $BUILD_VERSION_TAGS)
-		writeProp("ro.build.flavor", $TARGET_BUILD_FLAVOR)
-		// These values are deprecated, use "ro.product.cpu.abilist"
-		// instead (see below).
-		writeString("# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,")
-		writeString("# use ro.product.cpu.abilist instead.")
-		writeProp("ro.product.cpu.abi", $TARGET_CPU_ABI)
-		if [ -n "$TARGET_CPU_ABI2" ] {
-			writeProp("ro.product.cpu.abi2", $TARGET_CPU_ABI2)
-		}
+	cmd.FlagWithArg("--build-flavor=", buildFlavor)
+	cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx))
+	cmd.FlagWithArg("--build-id=", config.BuildId())
+	cmd.FlagWithArg("--build-keys=", config.BuildKeys())
 
-		if [ -n "$PRODUCT_DEFAULT_LOCALE" ] {
-			writeProp("ro.product.locale", $PRODUCT_DEFAULT_LOCALE)
-		}
-		writeProp("ro.wifi.channels", $PRODUCT_DEFAULT_WIFI_CHANNELS)
-		writeString("# ro.build.product is obsolete; use ro.product.device")
-		writeProp("ro.build.product", $TARGET_DEVICE)
+	// shouldn't depend on BuildNumberFile and BuildThumbprintFile to prevent from rebuilding
+	// on every incremental build.
+	cmd.FlagWithArg("--build-number-file=", config.BuildNumberFile(ctx).String())
+	if shouldAddBuildThumbprint(config) {
+		cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String())
+	}
 
-		writeString("# Do not try to parse description or thumbprint")
-		writeProp("ro.build.description", $PRIVATE_BUILD_DESC)
-		if [ -n "$BUILD_THUMBPRINT" ] {
-			writeProp("ro.build.thumbprint", $BUILD_THUMBPRINT)
-		}
-	*/
+	cmd.FlagWithArg("--build-type=", config.BuildType())
+	cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME"))
+	cmd.FlagWithArg("--build-variant=", buildVariant)
+	cmd.FlagForEachArg("--cpu-abis=", config.DeviceAbi())
 
-	writeString("# end build properties")
+	// shouldn't depend on BUILD_DATETIME_FILE to prevent from rebuilding on every incremental
+	// build.
+	cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE"))
 
-	WriteFileRule(ctx, p.outputFilePath, strings.Join(lines, "\n"))
+	if len(config.ProductLocales()) > 0 {
+		cmd.FlagWithArg("--default-locale=", config.ProductLocales()[0])
+	}
+
+	cmd.FlagForEachArg("--default-wifi-channels=", config.ProductDefaultWifiChannels())
+	cmd.FlagWithArg("--device=", config.DeviceName())
+	if config.DisplayBuildNumber() {
+		cmd.Flag("--display-build-number")
+	}
+
+	cmd.FlagWithArg("--platform-base-os=", config.PlatformBaseOS())
+	cmd.FlagWithArg("--platform-display-version=", config.PlatformDisplayVersionName())
+	cmd.FlagWithArg("--platform-min-supported-target-sdk-version=", config.PlatformMinSupportedTargetSdkVersion())
+	cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx))
+	cmd.FlagWithArg("--platform-preview-sdk-version=", config.PlatformPreviewSdkVersion())
+	cmd.FlagWithArg("--platform-sdk-version=", config.PlatformSdkVersion().String())
+	cmd.FlagWithArg("--platform-security-patch=", config.PlatformSecurityPatch())
+	cmd.FlagWithArg("--platform-version=", config.PlatformVersionName())
+	cmd.FlagWithArg("--platform-version-codename=", config.PlatformSdkCodename())
+	cmd.FlagForEachArg("--platform-version-all-codenames=", config.PlatformVersionActiveCodenames())
+	cmd.FlagWithArg("--platform-version-known-codenames=", config.PlatformVersionKnownCodenames())
+	cmd.FlagWithArg("--platform-version-last-stable=", config.PlatformVersionLastStable())
+	cmd.FlagWithArg("--product=", config.DeviceProduct())
+
+	cmd.FlagWithOutput("--out=", p.outputFilePath)
+
+	rule.Build(ctx.ModuleName(), "generating buildinfo props")
 
 	if !p.installable() {
 		p.SkipInstall()
diff --git a/android/config.go b/android/config.go
index 567ebd8..2ee3b93 100644
--- a/android/config.go
+++ b/android/config.go
@@ -114,6 +114,8 @@
 	GenerateDocFile
 )
 
+const testKeyDir = "build/make/target/product/security"
+
 // SoongOutDir returns the build output directory for the configuration.
 func (c Config) SoongOutDir() string {
 	return c.soongOutDir
@@ -168,7 +170,10 @@
 // Thus, verify_overlaps is disabled when RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE is set to false.
 // TODO(b/308174018): Re-enable verify_overlaps for both builr from source/mainline prebuilts.
 func (c Config) DisableVerifyOverlaps() bool {
-	return c.IsEnvTrue("DISABLE_VERIFY_OVERLAPS") || !c.ReleaseDefaultModuleBuildFromSource()
+	if c.IsEnvFalse("DISABLE_VERIFY_OVERLAPS") && c.ReleaseDisableVerifyOverlaps() {
+		panic("The current release configuration does not support verify_overlaps. DISABLE_VERIFY_OVERLAPS cannot be set to false")
+	}
+	return c.IsEnvTrue("DISABLE_VERIFY_OVERLAPS") || c.ReleaseDisableVerifyOverlaps() || !c.ReleaseDefaultModuleBuildFromSource()
 }
 
 // MaxPageSizeSupported returns the max page size supported by the device. This
@@ -209,6 +214,10 @@
 		Bool(c.config.productVariables.ReleaseDefaultModuleBuildFromSource)
 }
 
+func (c Config) ReleaseDisableVerifyOverlaps() bool {
+	return c.config.productVariables.GetBuildFlagBool("RELEASE_DISABLE_VERIFY_OVERLAPS_CHECK")
+}
+
 // Enables flagged apis annotated with READ_WRITE aconfig flags to be included in the stubs
 // and hiddenapi flags so that they are accessible at runtime
 func (c Config) ReleaseExportRuntimeApis() bool {
@@ -834,6 +843,10 @@
 	return String(c.productVariables.BuildId)
 }
 
+func (c *config) DisplayBuildNumber() bool {
+	return Bool(c.productVariables.DisplayBuildNumber)
+}
+
 // BuildNumberFile returns the path to a text file containing metadata
 // representing the current build's number.
 //
@@ -845,6 +858,23 @@
 	return PathForOutput(ctx, String(c.productVariables.BuildNumberFile))
 }
 
+// BuildHostnameFile returns the path to a text file containing metadata
+// representing the current build's host name.
+func (c *config) BuildHostnameFile(ctx PathContext) Path {
+	return PathForOutput(ctx, String(c.productVariables.BuildHostnameFile))
+}
+
+// BuildThumbprintFile returns the path to a text file containing metadata
+// representing the current build's thumbprint.
+//
+// Rules that want to reference the build thumbprint should read from this file
+// without depending on it. They will run whenever their other dependencies
+// require them to run and get the current build thumbprint. This ensures they
+// don't rebuild on every incremental build when the build thumbprint changes.
+func (c *config) BuildThumbprintFile(ctx PathContext) Path {
+	return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildThumbprintFile))
+}
+
 // DeviceName returns the name of the current device target.
 // TODO: take an AndroidModuleContext to select the device name for multi-device builds
 func (c *config) DeviceName() string {
@@ -866,6 +896,10 @@
 	return c.productVariables.DeviceProduct != nil
 }
 
+func (c *config) DeviceAbi() []string {
+	return c.productVariables.DeviceAbi
+}
+
 func (c *config) DeviceResourceOverlays() []string {
 	return c.productVariables.DeviceResourceOverlays
 }
@@ -874,6 +908,10 @@
 	return c.productVariables.ProductResourceOverlays
 }
 
+func (c *config) PlatformDisplayVersionName() string {
+	return String(c.productVariables.Platform_display_version_name)
+}
+
 func (c *config) PlatformVersionName() string {
 	return String(c.productVariables.Platform_version_name)
 }
@@ -1031,7 +1069,7 @@
 	if defaultCert != "" {
 		return PathForSource(ctx, filepath.Dir(defaultCert))
 	}
-	return PathForSource(ctx, "build/make/target/product/security")
+	return PathForSource(ctx, testKeyDir)
 }
 
 func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) {
@@ -1043,10 +1081,18 @@
 	return defaultDir.Join(ctx, "testkey.x509.pem"), defaultDir.Join(ctx, "testkey.pk8")
 }
 
+func (c *config) BuildKeys() string {
+	defaultCert := String(c.productVariables.DefaultAppCertificate)
+	if defaultCert == "" || defaultCert == filepath.Join(testKeyDir, "testkey") {
+		return "test-keys"
+	}
+	return "dev-keys"
+}
+
 func (c *config) ApexKeyDir(ctx ModuleContext) SourcePath {
 	// TODO(b/121224311): define another variable such as TARGET_APEX_KEY_OVERRIDE
 	defaultCert := String(c.productVariables.DefaultAppCertificate)
-	if defaultCert == "" || filepath.Dir(defaultCert) == "build/make/target/product/security" {
+	if defaultCert == "" || filepath.Dir(defaultCert) == testKeyDir {
 		// When defaultCert is unset or is set to the testkeys path, use the APEX keys
 		// that is under the module dir
 		return pathForModuleSrc(ctx)
@@ -1105,6 +1151,10 @@
 	return Bool(c.productVariables.Eng)
 }
 
+func (c *config) BuildType() string {
+	return String(c.productVariables.BuildType)
+}
+
 // DevicePrimaryArchType returns the ArchType for the first configured device architecture, or
 // Common if there are no device architectures.
 func (c *config) DevicePrimaryArchType() ArchType {
@@ -2079,3 +2129,19 @@
 func (c *config) BuildIgnoreApexContributionContents() []string {
 	return c.productVariables.BuildIgnoreApexContributionContents
 }
+
+func (c *config) ProductLocales() []string {
+	return c.productVariables.ProductLocales
+}
+
+func (c *config) ProductDefaultWifiChannels() []string {
+	return c.productVariables.ProductDefaultWifiChannels
+}
+
+func (c *config) BoardUseVbmetaDigestInFingerprint() bool {
+	return Bool(c.productVariables.BoardUseVbmetaDigestInFingerprint)
+}
+
+func (c *config) OemProperties() []string {
+	return c.productVariables.OemProperties
+}
diff --git a/android/early_module_context.go b/android/early_module_context.go
index 8f75773..cf1b5fc 100644
--- a/android/early_module_context.go
+++ b/android/early_module_context.go
@@ -15,9 +15,10 @@
 package android
 
 import (
-	"github.com/google/blueprint"
 	"os"
 	"text/scanner"
+
+	"github.com/google/blueprint"
 )
 
 // EarlyModuleContext provides methods that can be called early, as soon as the properties have
@@ -54,6 +55,9 @@
 	// PropertyErrorf reports an error at the line number of a property in the module definition.
 	PropertyErrorf(property, fmt string, args ...interface{})
 
+	// OtherModulePropertyErrorf reports an error at the line number of a property in the given module definition.
+	OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{})
+
 	// Failed returns true if any errors have been reported.  In most cases the module can continue with generating
 	// build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
 	// has prevented the module from creating necessary data it can return early when Failed returns true.
@@ -167,3 +171,7 @@
 func (e *earlyModuleContext) Namespace() *Namespace {
 	return e.EarlyModuleContext.Namespace().(*Namespace)
 }
+
+func (e *earlyModuleContext) OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) {
+	e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args)
+}
diff --git a/android/filegroup.go b/android/filegroup.go
index bc881ed..86d7b4b 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -15,6 +15,7 @@
 package android
 
 import (
+	"maps"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -97,6 +98,25 @@
 	}
 	SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: fg.srcs.Strings()})
 	CollectDependencyAconfigFiles(ctx, &fg.mergedAconfigFiles)
+
+	var aconfigDeclarations []string
+	var intermediateCacheOutputPaths Paths
+	var srcjars Paths
+	modeInfos := make(map[string]ModeInfo)
+	ctx.VisitDirectDeps(func(module Module) {
+		if dep, ok := OtherModuleProvider(ctx, module, CodegenInfoProvider); ok {
+			aconfigDeclarations = append(aconfigDeclarations, dep.AconfigDeclarations...)
+			intermediateCacheOutputPaths = append(intermediateCacheOutputPaths, dep.IntermediateCacheOutputPaths...)
+			srcjars = append(srcjars, dep.Srcjars...)
+			maps.Copy(modeInfos, dep.ModeInfos)
+		}
+	})
+	SetProvider(ctx, CodegenInfoProvider, CodegenInfo{
+		AconfigDeclarations:          aconfigDeclarations,
+		IntermediateCacheOutputPaths: intermediateCacheOutputPaths,
+		Srcjars:                      srcjars,
+		ModeInfos:                    modeInfos,
+	})
 }
 
 func (fg *fileGroup) Srcs() Paths {
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 463fd07..eabb1b1 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -77,6 +77,11 @@
 		if ctx.OtherModuleDependencyTag(dep) == DefaultsDepTag {
 			return
 		}
+		// The required dependencies just say modules A and B should be installed together.
+		// It doesn't mean that one is built using the other.
+		if ctx.OtherModuleDependencyTag(dep) == RequiredDepTag {
+			return
+		}
 
 		if info, ok := OtherModuleProvider(ctx, dep, LicenseMetadataProvider); ok {
 			allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
diff --git a/android/module.go b/android/module.go
index 000476c..9f1d5ef 100644
--- a/android/module.go
+++ b/android/module.go
@@ -29,6 +29,7 @@
 	"android/soong/bazel"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/parser"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -123,6 +124,8 @@
 	// TransitivePackagingSpecs returns the PackagingSpecs for this module and any transitive
 	// dependencies with dependency tags for which IsInstallDepNeeded() returns true.
 	TransitivePackagingSpecs() []PackagingSpec
+
+	ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator
 }
 
 // Qualified id for a module
@@ -433,6 +436,10 @@
 	// Set by osMutator
 	CompileOS OsType `blueprint:"mutated"`
 
+	// Set to true after the arch mutator has run on this module and set CompileTarget,
+	// CompileMultiTargets, and CompilePrimary
+	ArchReady bool `blueprint:"mutated"`
+
 	// The Target of artifacts that this module variant is responsible for creating.
 	//
 	// Set by archMutator
@@ -542,6 +549,15 @@
 
 var teamDepTag = TeamDepTagType{}
 
+// Dependency tag for required, host_required, and target_required modules.
+var RequiredDepTag = struct {
+	blueprint.BaseDependencyTag
+	InstallAlwaysNeededDependencyTag
+	// Requiring disabled module has been supported (as a side effect of this being implemented
+	// in Make). We may want to make it an error, but for now, let's keep the existing behavior.
+	AlwaysAllowDisabledModuleDependencyTag
+}{}
+
 // CommonTestOptions represents the common `test_options` properties in
 // Android.bp.
 type CommonTestOptions struct {
@@ -1007,6 +1023,87 @@
 	if m.Team() != "" {
 		ctx.AddDependency(ctx.Module(), teamDepTag, m.Team())
 	}
+
+	// TODO(jiyong): remove below case. This is to work around build errors happening
+	// on branches with reduced manifest like aosp_kernel-build-tools.
+	// In the branch, a build error occurs as follows.
+	// 1. aosp_kernel-build-tools is a reduced manifest branch. It doesn't have some git
+	// projects like external/bouncycastle
+	// 2. `boot_signer` is `required` by modules like `build_image` which is explicitly list as
+	// the top-level build goal (in the shell file that invokes Soong).
+	// 3. `boot_signer` depends on `bouncycastle-unbundled` which is in the missing git project.
+	// 4. aosp_kernel-build-tools invokes soong with `--skip-make`. Therefore, the absence of
+	// ALLOW_MISSING_DEPENDENCIES didn't cause a problem.
+	// 5. Now, since Soong understands `required` deps, it tries to build `boot_signer` and the
+	// absence of external/bouncycastle fails the build.
+	//
+	// Unfortunately, there's no way for Soong to correctly determine if it's running in a
+	// reduced manifest branch. Instead, here, we use the absence of DeviceArch or DeviceName as
+	// a strong signal, because that's very common across reduced manifest branches.
+	pv := ctx.Config().productVariables
+	fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil
+	if fullManifest {
+		m.addRequiredDeps(ctx)
+	}
+}
+
+// addRequiredDeps adds required, target_required, and host_required as dependencies.
+func (m *ModuleBase) addRequiredDeps(ctx BottomUpMutatorContext) {
+	addDep := func(target Target, depName string) {
+		if !ctx.OtherModuleExists(depName) {
+			if ctx.Config().AllowMissingDependencies() {
+				return
+			}
+		}
+
+		// If Android native module requires another Android native module, ensure that
+		// they have the same bitness. This mimics the policy in select-bitness-of-required-modules
+		// in build/make/core/main.mk.
+		// TODO(jiyong): the Make-side does this only when the required module is a shared
+		// library or a native test.
+		bothInAndroid := m.Device() && target.Os.Class == Device
+		nativeArch := m.Arch().ArchType.Multilib != string(MultilibCommon)
+		sameBitness := m.Arch().ArchType.Multilib == target.Arch.ArchType.Multilib
+		if bothInAndroid && nativeArch && !sameBitness {
+			return
+		}
+
+		variation := target.Variations()
+		if ctx.OtherModuleFarDependencyVariantExists(variation, depName) {
+			ctx.AddFarVariationDependencies(variation, RequiredDepTag, depName)
+		}
+	}
+
+	if m.Device() {
+		for _, depName := range m.RequiredModuleNames() {
+			for _, target := range ctx.Config().Targets[Android] {
+				addDep(target, depName)
+			}
+		}
+		for _, depName := range m.HostRequiredModuleNames() {
+			for _, target := range ctx.Config().Targets[ctx.Config().BuildOS] {
+				addDep(target, depName)
+			}
+		}
+	}
+
+	if m.Host() {
+		for _, depName := range m.RequiredModuleNames() {
+			for _, target := range ctx.Config().Targets[ctx.Config().BuildOS] {
+				// When a host module requires another host module, don't make a
+				// dependency if they have different OSes (i.e. hostcross).
+				if m.Target().HostCross != target.HostCross {
+					continue
+				}
+				addDep(target, depName)
+			}
+		}
+		for _, depName := range m.TargetRequiredModuleNames() {
+			for _, target := range ctx.Config().Targets[Android] {
+				addDep(target, depName)
+			}
+		}
+	}
 }
 
 // AddProperties "registers" the provided props
@@ -1136,6 +1233,10 @@
 	return distFiles
 }
 
+func (m *ModuleBase) ArchReady() bool {
+	return m.commonProperties.ArchReady
+}
+
 func (m *ModuleBase) Target() Target {
 	return m.commonProperties.CompileTarget
 }
@@ -1659,6 +1760,7 @@
 	}
 
 	return archModuleContext{
+		ready:         m.commonProperties.ArchReady,
 		os:            m.commonProperties.CompileOS,
 		target:        m.commonProperties.CompileTarget,
 		targetPrimary: m.commonProperties.CompilePrimary,
@@ -2009,6 +2111,65 @@
 	return proptools.Bool(m.commonProperties.Native_bridge_supported)
 }
 
+type ConfigAndErrorContext interface {
+	Config() Config
+	OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+}
+
+type configurationEvalutor struct {
+	ctx ConfigAndErrorContext
+	m   Module
+}
+
+func (m *ModuleBase) ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator {
+	return configurationEvalutor{
+		ctx: ctx,
+		m:   m.module,
+	}
+}
+
+func (e configurationEvalutor) PropertyErrorf(property string, fmt string, args ...interface{}) {
+	e.ctx.OtherModulePropertyErrorf(e.m, property, fmt, args)
+}
+
+func (e configurationEvalutor) EvaluateConfiguration(ty parser.SelectType, property, condition string) (string, bool) {
+	ctx := e.ctx
+	m := e.m
+	switch ty {
+	case parser.SelectTypeReleaseVariable:
+		if v, ok := ctx.Config().productVariables.BuildFlags[condition]; ok {
+			return v, true
+		}
+		return "", false
+	case parser.SelectTypeProductVariable:
+		// TODO(b/323382414): Might add these on a case-by-case basis
+		ctx.OtherModulePropertyErrorf(m, property, "TODO(b/323382414): Product variables are not yet supported in selects")
+		return "", false
+	case parser.SelectTypeSoongConfigVariable:
+		parts := strings.Split(condition, ":")
+		namespace := parts[0]
+		variable := parts[1]
+		if n, ok := ctx.Config().productVariables.VendorVars[namespace]; ok {
+			if v, ok := n[variable]; ok {
+				return v, true
+			}
+		}
+		return "", false
+	case parser.SelectTypeVariant:
+		if condition == "arch" {
+			if !m.base().ArchReady() {
+				ctx.OtherModulePropertyErrorf(m, property, "A select on arch was attempted before the arch mutator ran")
+				return "", false
+			}
+			return m.base().Arch().ArchType.Name, true
+		}
+		ctx.OtherModulePropertyErrorf(m, property, "Unknown variant %s", condition)
+		return "", false
+	default:
+		panic("Should be unreachable")
+	}
+}
+
 // ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current
 // variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
 // or if this variant is not overridden.
diff --git a/android/module_context.go b/android/module_context.go
index 1cab630..d3e2770 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -234,6 +234,8 @@
 	variables   map[string]string
 }
 
+var _ ModuleContext = &moduleContext{}
+
 func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
 	return pctx, BuildParams{
 		Rule:            ErrorRule,
diff --git a/android/sdk.go b/android/sdk.go
index 6d5293e..121470d 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -868,3 +868,11 @@
 }
 
 var AdditionalSdkInfoProvider = blueprint.NewProvider[AdditionalSdkInfo]()
+
+var apiFingerprintPathKey = NewOnceKey("apiFingerprintPathKey")
+
+func ApiFingerprintPath(ctx PathContext) OutputPath {
+	return ctx.Config().Once(apiFingerprintPathKey, func() interface{} {
+		return PathForOutput(ctx, "api_fingerprint.txt")
+	}).(OutputPath)
+}
diff --git a/android/selects_test.go b/android/selects_test.go
index aa9c521..b4e226f 100644
--- a/android/selects_test.go
+++ b/android/selects_test.go
@@ -231,11 +231,30 @@
 				my_string: proptools.StringPtr("c.cpp"),
 			},
 		},
+		{
+			name: "Select on variant",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_string: select(variant("arch"), {
+					"x86": "my_x86",
+					"x86_64": "my_x86_64",
+					"arm": "my_arm",
+					"arm64": "my_arm64",
+					_: "my_default",
+				}),
+			}
+			`,
+			provider: selectsTestProvider{
+				my_string: proptools.StringPtr("my_arm64"),
+			},
+		},
 	}
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
 			fixtures := GroupFixturePreparers(
+				PrepareForTestWithArchMutator,
 				FixtureRegisterWithContext(func(ctx RegistrationContext) {
 					ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
 				}),
@@ -249,8 +268,8 @@
 			result := fixtures.RunTestWithBp(t, tc.bp)
 
 			if tc.expectedError == "" {
-				m := result.ModuleForTests("foo", "")
-				p, _ := OtherModuleProvider[selectsTestProvider](result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
+				m := result.ModuleForTests("foo", "android_arm64_armv8-a")
+				p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
 				if !reflect.DeepEqual(p, tc.provider) {
 					t.Errorf("Expected:\n  %q\ngot:\n  %q", tc.provider.String(), p.String())
 				}
@@ -310,7 +329,7 @@
 func newSelectsMockModule() Module {
 	m := &selectsMockModule{}
 	m.AddProperties(&m.properties)
-	InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
+	InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst)
 	InitDefaultableModule(m)
 	return m
 }
diff --git a/android/singleton.go b/android/singleton.go
index ccddeaf..76df1eb 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -87,6 +87,9 @@
 	// builder whenever a file matching the pattern as added or removed, without rerunning if a
 	// file that does not match the pattern is added to a searched directory.
 	GlobWithDeps(pattern string, excludes []string) ([]string, error)
+
+	// OtherModulePropertyErrorf reports an error on the line number of the given property of the given module
+	OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{})
 }
 
 type singletonAdaptor struct {
@@ -251,7 +254,7 @@
 
 func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name string) []Module {
 	// get module reference for visibility enforcement
-	qualified := createVisibilityModuleReference(s.ModuleName(referer), s.ModuleDir(referer), s.ModuleType(referer))
+	qualified := createVisibilityModuleReference(s.ModuleName(referer), s.ModuleDir(referer), referer)
 
 	modules := s.SingletonContext.ModuleVariantsFromName(referer, name)
 	result := make([]Module, 0, len(modules))
@@ -279,3 +282,7 @@
 func (s *singletonContextAdaptor) moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
 	return s.SingletonContext.ModuleProvider(module, provider)
 }
+
+func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) {
+	s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args)
+}
diff --git a/android/variable.go b/android/variable.go
index 73f5bfd..9b630c0 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -193,9 +193,13 @@
 	// Suffix to add to generated Makefiles
 	Make_suffix *string `json:",omitempty"`
 
-	BuildId         *string `json:",omitempty"`
-	BuildNumberFile *string `json:",omitempty"`
+	BuildId             *string `json:",omitempty"`
+	BuildNumberFile     *string `json:",omitempty"`
+	BuildHostnameFile   *string `json:",omitempty"`
+	BuildThumbprintFile *string `json:",omitempty"`
+	DisplayBuildNumber  *bool   `json:",omitempty"`
 
+	Platform_display_version_name             *string  `json:",omitempty"`
 	Platform_version_name                     *string  `json:",omitempty"`
 	Platform_sdk_version                      *int     `json:",omitempty"`
 	Platform_sdk_codename                     *string  `json:",omitempty"`
@@ -296,6 +300,8 @@
 	MinimizeJavaDebugInfo        *bool    `json:",omitempty"`
 	Build_from_text_stub         *bool    `json:",omitempty"`
 
+	BuildType *string `json:",omitempty"`
+
 	Check_elf_files *bool `json:",omitempty"`
 
 	UncompressPrivAppDex             *bool    `json:",omitempty"`
@@ -472,9 +478,8 @@
 
 	AfdoProfiles []string `json:",omitempty"`
 
-	ProductManufacturer string   `json:",omitempty"`
-	ProductBrand        string   `json:",omitempty"`
-	BuildVersionTags    []string `json:",omitempty"`
+	ProductManufacturer string `json:",omitempty"`
+	ProductBrand        string `json:",omitempty"`
 
 	ReleaseVersion          string   `json:",omitempty"`
 	ReleaseAconfigValueSets []string `json:",omitempty"`
@@ -502,6 +507,14 @@
 	ExportRuntimeApis *bool `json:",omitempty"`
 
 	AconfigContainerValidation string `json:",omitempty"`
+
+	ProductLocales []string `json:",omitempty"`
+
+	ProductDefaultWifiChannels []string `json:",omitempty"`
+
+	BoardUseVbmetaDigestInFingerprint *bool `json:",omitempty"`
+
+	OemProperties []string `json:",omitempty"`
 }
 
 type PartitionQualifiedVariablesType struct {
diff --git a/android/visibility.go b/android/visibility.go
index 79a534f..89c0adc 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -58,19 +58,14 @@
 var visibilityRuleRegexp = regexp.MustCompile(visibilityRulePattern)
 
 type visibilityModuleReference struct {
-	name              qualifiedModuleName
-	isPartitionModule bool
+	name   qualifiedModuleName
+	module Module
 }
 
-func createVisibilityModuleReference(name, dir, typ string) visibilityModuleReference {
-	isPartitionModule := false
-	switch typ {
-	case "android_filesystem", "android_system_image":
-		isPartitionModule = true
-	}
+func createVisibilityModuleReference(name, dir string, module Module) visibilityModuleReference {
 	return visibilityModuleReference{
-		name:              createQualifiedModuleName(name, dir),
-		isPartitionModule: isPartitionModule,
+		name:   createQualifiedModuleName(name, dir),
+		module: module,
 	}
 }
 
@@ -214,21 +209,37 @@
 	return "//visibility:private"
 }
 
+var anyPartitionRegex = regexp.MustCompile("^any_(system|system_ext|vendor|product|data|odm)_partition$")
+
 // visibilityRule for //visibility:any_partition
-type anyPartitionRule struct{}
+type anyPartitionRule struct {
+	partitionType string
+}
 
 var _ visibilityRule = anyPartitionRule{}
 
+type PartitionTypeInterface interface {
+	PartitionType() string
+}
+
 func (r anyPartitionRule) matches(m visibilityModuleReference) bool {
-	return m.isPartitionModule
+	if m2, ok := m.module.(PartitionTypeInterface); ok {
+		return m2.PartitionType() == r.partitionType
+	}
+	return false
 }
 
 func (r anyPartitionRule) String() string {
-	return "//visibility:any_partition"
+	return "//visibility:any_" + r.partitionType + "_partition"
 }
 
 var visibilityRuleMap = NewOnceKey("visibilityRuleMap")
 
+type visibilityRulesForModule struct {
+	rule                   compositeRule
+	implicitPartitionRules compositeRule
+}
+
 // The map from qualifiedModuleName to visibilityRule.
 func moduleToVisibilityRuleMap(config Config) *sync.Map {
 	return config.Once(visibilityRuleMap, func() interface{} {
@@ -304,9 +315,6 @@
 		if pkg == "visibility" {
 			switch name {
 			case "private", "public":
-			case "any_partition":
-				// any_partition can be used with another visibility fields
-				continue
 			case "legacy_public":
 				ctx.PropertyErrorf(property, "//visibility:legacy_public must not be used")
 				continue
@@ -314,6 +322,10 @@
 				// This keyword does not create a rule so pretend it does not exist.
 				ruleCount -= 1
 			default:
+				if anyPartitionRegex.MatchString(name) {
+					// any_*_partition can be used with another visibility fields
+					continue
+				}
 				ctx.PropertyErrorf(property, "unrecognized visibility rule %q", v)
 				continue
 			}
@@ -352,15 +364,20 @@
 
 	// Parse the visibility rules that control access to the module and store them by id
 	// for use when enforcing the rules.
+	var rule compositeRule
 	primaryProperty := m.base().primaryVisibilityProperty
 	if primaryProperty != nil {
 		if visibility := primaryProperty.getStrings(); visibility != nil {
-			rule := parseRules(ctx, currentPkg, primaryProperty.getName(), visibility)
-			if rule != nil {
-				moduleToVisibilityRuleMap(ctx.Config()).Store(qualifiedModuleId, rule)
-			}
+			rule = parseRules(ctx, currentPkg, primaryProperty.getName(), visibility)
 		}
 	}
+	ipr := implicitPartitionRules(ctx)
+	if rule != nil || ipr != nil {
+		moduleToVisibilityRuleMap(ctx.Config()).Store(qualifiedModuleId, visibilityRulesForModule{
+			rule:                   rule,
+			implicitPartitionRules: ipr,
+		})
+	}
 }
 
 func parseRules(ctx BaseModuleContext, currentPkg, property string, visibility []string) compositeRule {
@@ -392,8 +409,13 @@
 				hasNonPrivateRule = false
 				// This does not actually create a rule so continue onto the next rule.
 				continue
-			case "any_partition":
-				r = anyPartitionRule{}
+			default:
+				match := anyPartitionRegex.FindStringSubmatch(name)
+				if match != nil {
+					r = anyPartitionRule{
+						partitionType: match[1],
+					}
+				}
 			}
 		} else {
 			switch name {
@@ -432,6 +454,22 @@
 	return rules
 }
 
+func implicitPartitionRules(ctx BaseModuleContext) compositeRule {
+	var result compositeRule
+	if ctx.SocSpecific() {
+		result = append(result, anyPartitionRule{partitionType: "vendor"})
+	} else if ctx.ProductSpecific() {
+		result = append(result, anyPartitionRule{partitionType: "product"})
+	} else if ctx.Module().InstallInData() {
+		result = append(result, anyPartitionRule{partitionType: "data"})
+	} else if ctx.SystemExtSpecific() {
+		result = append(result, anyPartitionRule{partitionType: "system_ext"})
+	} else if ctx.DeviceSpecific() {
+		result = append(result, anyPartitionRule{partitionType: "odm"})
+	}
+	return result
+}
+
 func isAllowedFromOutsideVendor(pkg string, name string) bool {
 	if pkg == "vendor" {
 		return name == "__subpackages__"
@@ -470,7 +508,7 @@
 }
 
 func visibilityRuleEnforcer(ctx TopDownMutatorContext) {
-	qualified := createVisibilityModuleReference(ctx.ModuleName(), ctx.ModuleDir(), ctx.ModuleType())
+	qualified := createVisibilityModuleReference(ctx.ModuleName(), ctx.ModuleDir(), ctx.Module())
 
 	// Visit all the dependencies making sure that this module has access to them all.
 	ctx.VisitDirectDeps(func(dep Module) {
@@ -505,10 +543,13 @@
 // which is currently //visibility:public.
 func effectiveVisibilityRules(config Config, qualified qualifiedModuleName) compositeRule {
 	moduleToVisibilityRule := moduleToVisibilityRuleMap(config)
-	value, ok := moduleToVisibilityRule.Load(qualified)
+	value := visibilityRulesForModule{}
+	if valueRaw, ok := moduleToVisibilityRule.Load(qualified); ok {
+		value = valueRaw.(visibilityRulesForModule)
+	}
 	var rule compositeRule
-	if ok {
-		rule = value.(compositeRule)
+	if value.rule != nil {
+		rule = value.rule
 	} else {
 		rule = packageDefaultVisibility(moduleToVisibilityRule, qualified)
 	}
@@ -518,6 +559,20 @@
 	if rule == nil {
 		rule = defaultVisibility
 	}
+
+	// If a partition rule wasn't specified, add implicit partition visibility
+	// rules based on the partition properties like vendor: true.
+	foundPartitionRule := false
+	for _, r := range rule {
+		if _, ok := r.(anyPartitionRule); ok {
+			foundPartitionRule = true
+			break
+		}
+	}
+	if !foundPartitionRule {
+		rule = append(rule, value.implicitPartitionRules...)
+	}
+
 	return rule
 }
 
@@ -531,7 +586,7 @@
 	for {
 		value, ok := moduleToVisibilityRule.Load(packageQualifiedId)
 		if ok {
-			return value.(compositeRule)
+			return value.(visibilityRulesForModule).rule
 		}
 
 		if packageQualifiedId.isRootPackage() {
@@ -605,7 +660,7 @@
 
 	rule := effectiveVisibilityRules(ctx.Config(), qualified)
 
-	currentModule := createVisibilityModuleReference(moduleName, dir, ctx.OtherModuleType(module))
+	currentModule := createVisibilityModuleReference(moduleName, dir, module)
 
 	// Modules are implicitly visible to other modules in the same package,
 	// without checking the visibility rules. Here we need to add that visibility
diff --git a/android/visibility_test.go b/android/visibility_test.go
index bb43b1f..1a2eeca 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1905,7 +1905,7 @@
 		},
 	},
 	{
-		name: "any_partition visibility works",
+		name: "any_system_partition visibility works",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
 				android_filesystem {
@@ -1916,12 +1916,12 @@
 				package(default_visibility=["//visibility:private"])
 				mock_library {
 					name: "bar",
-					visibility: ["//visibility:any_partition"],
+					visibility: ["//visibility:any_system_partition"],
 				}`),
 		},
 	},
 	{
-		name: "any_partition visibility works with the other visibility",
+		name: "any_system_partition visibility works with the other visibility",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
 				android_filesystem {
@@ -1935,13 +1935,13 @@
 					name: "bar",
 					visibility: [
 						"//top2",
-						"//visibility:any_partition"
+						"//visibility:any_system_partition"
 					],
 				}`),
 		},
 	},
 	{
-		name: "any_partition visibility doesn't work for non-partitions",
+		name: "any_system_partition visibility doesn't work for non-partitions",
 		fs: MockFS{
 			"top/Android.bp": []byte(`
 				mock_library {
@@ -1951,11 +1951,77 @@
 			"top/nested/Android.bp": []byte(`
 				mock_library {
 					name: "bar",
-					visibility: ["//visibility:any_partition"],
+					visibility: ["//visibility:any_system_partition"],
 				}`),
 		},
 		expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
 	},
+	{
+		name: "any_system_partition visibility doesn't work for vendor partitions",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				android_filesystem {
+					name: "foo",
+					partition_type: "vendor",
+					deps: ["bar"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				package(default_visibility=["//visibility:private"])
+				mock_library {
+					name: "bar",
+					visibility: ["//visibility:any_system_partition"],
+				}`),
+		},
+		expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
+	},
+	{
+		name: "Vendor modules are visible to any vendor partition by default",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				android_filesystem {
+					name: "foo",
+					partition_type: "vendor",
+					deps: ["bar"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				package(default_visibility=["//visibility:private"])
+				mock_library {
+					name: "bar",
+					vendor: true,
+				}`),
+		},
+	},
+	{
+		name: "Not visible to vendor partitions when using any_system_partiton, even if vendor: true",
+		fs: MockFS{
+			"top/Android.bp": []byte(`
+				android_filesystem {
+					name: "foo",
+					partition_type: "vendor",
+					deps: ["bar"],
+				}`),
+			"top/nested/Android.bp": []byte(`
+				package(default_visibility=["//visibility:private"])
+				mock_library {
+					name: "bar",
+					vendor: true,
+					visibility: ["//visibility:any_system_partition"],
+				}`),
+		},
+		expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
+	},
+	{
+		name: "unknown any_partition specs throw errors",
+		fs: MockFS{
+			"top/nested/Android.bp": []byte(`
+				package(default_visibility=["//visibility:private"])
+				mock_library {
+					name: "bar",
+					visibility: ["//visibility:any_unknown_partition"],
+				}`),
+		},
+		expectedErrors: []string{`unrecognized visibility rule "//visibility:any_unknown_partition"`},
+	},
 }
 
 func TestVisibility(t *testing.T) {
@@ -1977,8 +2043,7 @@
 					ctx.RegisterModuleType("mock_library", newMockLibraryModule)
 					ctx.RegisterModuleType("mock_parent", newMockParentFactory)
 					ctx.RegisterModuleType("mock_defaults", defaultsFactory)
-					// For testing //visibility:any_partition. The module type doesn't matter, just that it's registered under the name "android_filesystem"
-					ctx.RegisterModuleType("android_filesystem", newMockLibraryModule)
+					ctx.RegisterModuleType("android_filesystem", newMockFilesystemModule)
 				}),
 				prepareForTestWithFakePrebuiltModules,
 				// Add additional files to the mock filesystem
@@ -2032,6 +2097,37 @@
 func (p *mockLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
 }
 
+type mockFilesystemModuleProperties struct {
+	Partition_type *string
+	Deps           []string
+}
+
+type mockFilesystemModule struct {
+	ModuleBase
+	properties mockFilesystemModuleProperties
+}
+
+func (j *mockFilesystemModule) DepsMutator(ctx BottomUpMutatorContext) {
+	ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...)
+}
+
+func (p *mockFilesystemModule) GenerateAndroidBuildActions(ModuleContext) {
+}
+
+func (p *mockFilesystemModule) PartitionType() string {
+	if p.properties.Partition_type == nil {
+		return "system"
+	}
+	return *p.properties.Partition_type
+}
+
+func newMockFilesystemModule() Module {
+	m := &mockFilesystemModule{}
+	m.AddProperties(&m.properties)
+	InitAndroidArchModule(m, DeviceSupported, MultilibCommon)
+	return m
+}
+
 type mockDefaults struct {
 	ModuleBase
 	DefaultsModuleBase
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 460f1ff..1dd479c 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -511,6 +511,22 @@
 		`,
 	},
 	{
+		// Unsupported function case because that doesn't work in bp
+		desc: "error for unsupported functions",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(filter-out filter-out-file.java ,$(call all-java-files-under, src))
+LOCAL_PACKAGE_NAME := foo
+include $(BUILD_PACKAGE)
+`,
+		expected: `
+android_app {
+	name: "foo",
+	srcs: ["UNSUPPORTED FUNCTION:filter-out filter-out-file.java  src/**/*.java"],
+}
+		`,
+	},
+	{
 		desc: "ignore all-makefiles-under",
 		in: `
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/androidmk/parser/parser.go b/androidmk/parser/parser.go
index fb6be38..8a20bb0 100644
--- a/androidmk/parser/parser.go
+++ b/androidmk/parser/parser.go
@@ -413,6 +413,9 @@
 				p.accept('\t')
 				newLine = false
 				continue loop
+			} else if p.tok == '\n' {
+				p.accept('\n')
+				continue loop
 			} else if p.parseDirective() {
 				newLine = false
 				continue
diff --git a/androidmk/parser/parser_test.go b/androidmk/parser/parser_test.go
index 9efebf8..db3313d 100644
--- a/androidmk/parser/parser_test.go
+++ b/androidmk/parser/parser_test.go
@@ -84,6 +84,22 @@
 			},
 		},
 	},
+	{
+		name: "Blank line in rule's command",
+		in:   `all:
+	echo first line
+
+	echo second line`,
+		out: []Node{
+			&Rule{
+				Target: SimpleMakeString("all", NoPos),
+				RecipePos: NoPos,
+				Recipe: "echo first line\necho second line",
+				Prerequisites: SimpleMakeString("", NoPos),
+			},
+		},
+	},
+
 }
 
 func TestParse(t *testing.T) {
diff --git a/androidmk/parser/scope.go b/androidmk/parser/scope.go
index 8111c89..e1a523a 100644
--- a/androidmk/parser/scope.go
+++ b/androidmk/parser/scope.go
@@ -14,9 +14,7 @@
 
 package parser
 
-import (
-	"strings"
-)
+import "strings"
 
 type Scope interface {
 	Get(name string) string
@@ -88,7 +86,7 @@
 			if fname == "call" {
 				return scope.Call(argVals[0], argVals[1:]), true
 			} else {
-				return []string{"__builtin_func:" + fname + " " + strings.Join(argVals, " ")}, true
+				return []string{"UNSUPPORTED FUNCTION:" + fname + " " + strings.Join(argVals, " ")}, true
 			}
 		}
 	}
diff --git a/apex/Android.bp b/apex/Android.bp
index 27017ae..abae9e2 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -40,7 +40,6 @@
         "dexpreopt_bootjars_test.go",
         "platform_bootclasspath_test.go",
         "systemserver_classpath_fragment_test.go",
-        "vndk_test.go",
     ],
     pluginFor: ["soong_build"],
 }
diff --git a/apex/aconfig_test.go b/apex/aconfig_test.go
index a179dbf..515b2fd 100644
--- a/apex/aconfig_test.go
+++ b/apex/aconfig_test.go
@@ -217,6 +217,12 @@
 				srcs: ["src/lib.rs"],
 				apex_available: ["myapex"],
 			}
+			rust_library {
+				name: "libaconfig_storage_read_api", // test mock
+				crate_name: "aconfig_storage_read_api",
+				srcs: ["src/lib.rs"],
+				apex_available: ["myapex"],
+			}
 			rust_ffi_shared {
 				name: "libmy_rust_library",
 				srcs: ["src/lib.rs"],
@@ -480,6 +486,12 @@
 				srcs: ["src/lib.rs"],
 				apex_available: ["myapex"],
 			}
+			rust_library {
+				name: "libaconfig_storage_read_api", // test mock
+				crate_name: "aconfig_storage_read_api",
+				srcs: ["src/lib.rs"],
+				apex_available: ["myapex"],
+			}
 			rust_ffi_shared {
 				name: "libmy_rust_library",
 				srcs: ["src/lib.rs"],
@@ -524,6 +536,12 @@
 				srcs: ["src/lib.rs"],
 				apex_available: ["myapex"],
 			}
+			rust_library {
+				name: "libaconfig_storage_read_api", // test mock
+				crate_name: "aconfig_storage_read_api",
+				srcs: ["src/lib.rs"],
+				apex_available: ["myapex"],
+			}
 			rust_binary {
 				name: "my_rust_binary",
 				srcs: ["foo/bar/MyClass.rs"],
diff --git a/apex/apex.go b/apex/apex.go
index 32a3638..bc91407 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1648,10 +1648,9 @@
 	return af
 }
 
-func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, depName string) apexFile {
+func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, outputFile android.Path) apexFile {
 	dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir())
-	fileToCopy := prebuilt.OutputFile()
-	return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt)
+	return newApexFile(ctx, outputFile, outputFile.Base(), dirInApex, etc, prebuilt)
 }
 
 func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
@@ -1821,6 +1820,9 @@
 		if dt, ok := depTag.(*dependencyTag); ok && !dt.payload {
 			return false
 		}
+		if depTag == android.RequiredDepTag {
+			return false
+		}
 
 		ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
 		externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
@@ -2120,7 +2122,10 @@
 			}
 		case prebuiltTag:
 			if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
-				vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
+				filesToCopy, _ := prebuilt.OutputFiles("")
+				for _, etcFile := range filesToCopy {
+					vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
+				}
 				addAconfigFiles(vctx, ctx, child)
 			} else {
 				ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
@@ -2263,7 +2268,10 @@
 		// Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
 	} else if java.IsXmlPermissionsFileDepTag(depTag) {
 		if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
-			vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
+			filesToCopy, _ := prebuilt.OutputFiles("")
+			for _, etcFile := range filesToCopy {
+				vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
+			}
 		}
 	} else if rust.IsDylibDepTag(depTag) {
 		if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
@@ -2314,6 +2322,8 @@
 		// nothing
 	} else if depTag == android.DarwinUniversalVariantTag {
 		// nothing
+	} else if depTag == android.RequiredDepTag {
+		// nothing
 	} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
 		ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
 	}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index add6083..3e9f246 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -218,7 +218,6 @@
 	),
 
 	android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
-		variables.DeviceVndkVersion = proptools.StringPtr("current")
 		variables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
 		variables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
 		variables.Platform_sdk_codename = proptools.StringPtr("Q")
@@ -226,7 +225,6 @@
 		// "Tiramisu" needs to be in the next line for compatibility with soong code,
 		// not because of these tests specifically (it's not used by the tests)
 		variables.Platform_version_active_codenames = []string{"Q", "Tiramisu"}
-		variables.Platform_vndk_version = proptools.StringPtr("29")
 		variables.BuildId = proptools.StringPtr("TEST.BUILD_ID")
 	}),
 )
@@ -2062,9 +2060,9 @@
 		}
 	`)
 
-	vendorVariant := "android_vendor.29_arm64_armv8-a"
+	vendorVariant := "android_vendor_arm64_armv8-a"
 
-	mylib := ctx.ModuleForTests("mylib", vendorVariant+"_shared_myapex")
+	mylib := ctx.ModuleForTests("mylib", vendorVariant+"_shared_apex29")
 
 	// Ensure that mylib links with "current" LLNDK
 	libFlags := names(mylib.Rule("ld").Args["libFlags"])
@@ -3025,158 +3023,6 @@
 	ensureListNotContains(t, requireNativeLibs, ":vndk")
 }
 
-func TestVendorApex_use_vndk_as_stable_TryingToIncludeVNDKLib(t *testing.T) {
-	testApexError(t, `Trying to include a VNDK library`, `
-		apex {
-			name: "myapex",
-			key: "myapex.key",
-			native_shared_libs: ["libc++"], // libc++ is a VNDK lib
-			vendor: true,
-			use_vndk_as_stable: true,
-			updatable: false,
-		}
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}`)
-}
-
-func TestVendorApex_use_vndk_as_stable(t *testing.T) {
-	//   myapex                  myapex2
-	//    |                       |
-	//  mybin ------.           mybin2
-	//   \           \          /  |
-	// (stable)   .---\--------`   |
-	//     \     /     \           |
-	//      \   /       \         /
-	//      libvndk       libvendor
-	//      (vndk)
-	ctx := testApex(t, `
-		apex {
-			name: "myapex",
-			key: "myapex.key",
-			binaries: ["mybin"],
-			vendor: true,
-			use_vndk_as_stable: true,
-			updatable: false,
-		}
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-		cc_binary {
-			name: "mybin",
-			vendor: true,
-			shared_libs: ["libvndk", "libvendor"],
-		}
-		cc_library {
-			name: "libvndk",
-			vndk: {
-				enabled: true,
-			},
-			vendor_available: true,
-			product_available: true,
-		}
-		cc_library {
-			name: "libvendor",
-			vendor: true,
-			stl: "none",
-		}
-		apex {
-			name: "myapex2",
-			key: "myapex.key",
-			binaries: ["mybin2"],
-			vendor: true,
-			use_vndk_as_stable: false,
-			updatable: false,
-		}
-		cc_binary {
-			name: "mybin2",
-			vendor: true,
-			shared_libs: ["libvndk", "libvendor"],
-		}
-	`,
-		android.FixtureModifyConfig(func(config android.Config) {
-			config.TestProductVariables.KeepVndk = proptools.BoolPtr(true)
-		}),
-	)
-
-	vendorVariant := "android_vendor.29_arm64_armv8-a"
-
-	for _, tc := range []struct {
-		name                 string
-		apexName             string
-		moduleName           string
-		moduleVariant        string
-		libs                 []string
-		contents             []string
-		requireVndkNamespace bool
-	}{
-		{
-			name:          "use_vndk_as_stable",
-			apexName:      "myapex",
-			moduleName:    "mybin",
-			moduleVariant: vendorVariant + "_apex10000",
-			libs: []string{
-				// should link with vendor variants of VNDK libs(libvndk/libc++)
-				"out/soong/.intermediates/libvndk/" + vendorVariant + "_shared/libvndk.so",
-				"out/soong/.intermediates/" + cc.DefaultCcCommonTestModulesDir + "libc++/" + vendorVariant + "_shared/libc++.so",
-				// unstable Vendor libs as APEX variant
-				"out/soong/.intermediates/libvendor/" + vendorVariant + "_shared_apex10000/libvendor.so",
-			},
-			contents: []string{
-				"bin/mybin",
-				"lib64/libvendor.so",
-				// VNDK libs (libvndk/libc++) are not included
-			},
-			requireVndkNamespace: true,
-		},
-		{
-			name:          "!use_vndk_as_stable",
-			apexName:      "myapex2",
-			moduleName:    "mybin2",
-			moduleVariant: vendorVariant + "_myapex2",
-			libs: []string{
-				// should link with "unique" APEX(myapex2) variant of VNDK libs(libvndk/libc++)
-				"out/soong/.intermediates/libvndk/" + vendorVariant + "_shared_myapex2/libvndk.so",
-				"out/soong/.intermediates/" + cc.DefaultCcCommonTestModulesDir + "libc++/" + vendorVariant + "_shared_myapex2/libc++.so",
-				// unstable vendor libs have "merged" APEX variants
-				"out/soong/.intermediates/libvendor/" + vendorVariant + "_shared_apex10000/libvendor.so",
-			},
-			contents: []string{
-				"bin/mybin2",
-				"lib64/libvendor.so",
-				// VNDK libs are included as well
-				"lib64/libvndk.so",
-				"lib64/libc++.so",
-			},
-			requireVndkNamespace: false,
-		},
-	} {
-		t.Run(tc.name, func(t *testing.T) {
-			// Check linked libs
-			ldRule := ctx.ModuleForTests(tc.moduleName, tc.moduleVariant).Rule("ld")
-			libs := names(ldRule.Args["libFlags"])
-			for _, lib := range tc.libs {
-				ensureListContains(t, libs, lib)
-			}
-			// Check apex contents
-			ensureExactContents(t, ctx, tc.apexName, "android_common_"+tc.apexName, tc.contents)
-
-			// Check "requireNativeLibs"
-			apexManifestRule := ctx.ModuleForTests(tc.apexName, "android_common_"+tc.apexName).Rule("apexManifestRule")
-			requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
-			if tc.requireVndkNamespace {
-				ensureListContains(t, requireNativeLibs, ":vndk")
-			} else {
-				ensureListNotContains(t, requireNativeLibs, ":vndk")
-			}
-		})
-	}
-}
-
 func TestProductVariant(t *testing.T) {
 	ctx := testApex(t, `
 		apex {
@@ -3202,7 +3048,7 @@
 	`)
 
 	cflags := strings.Fields(
-		ctx.ModuleForTests("foo", "android_product.29_arm64_armv8-a_myapex").Rule("cc").Args["cFlags"])
+		ctx.ModuleForTests("foo", "android_product_arm64_armv8-a_apex10000").Rule("cc").Args["cFlags"])
 	ensureListContains(t, cflags, "-D__ANDROID_VNDK__")
 	ensureListContains(t, cflags, "-D__ANDROID_APEX__")
 	ensureListContains(t, cflags, "-D__ANDROID_PRODUCT__")
@@ -3823,166 +3669,6 @@
 	assertFileListEquals(t, files, actualFiles)
 }
 
-func TestVndkApexCurrent(t *testing.T) {
-	commonFiles := []string{
-		"lib/libc++.so",
-		"lib64/libc++.so",
-		"etc/llndk.libraries.29.txt",
-		"etc/vndkcore.libraries.29.txt",
-		"etc/vndksp.libraries.29.txt",
-		"etc/vndkprivate.libraries.29.txt",
-		"etc/vndkproduct.libraries.29.txt",
-	}
-	testCases := []struct {
-		vndkVersion   string
-		expectedFiles []string
-	}{
-		{
-			vndkVersion: "current",
-			expectedFiles: append(commonFiles,
-				"lib/libvndk.so",
-				"lib/libvndksp.so",
-				"lib64/libvndk.so",
-				"lib64/libvndksp.so"),
-		},
-	}
-	for _, tc := range testCases {
-		t.Run("VNDK.current with DeviceVndkVersion="+tc.vndkVersion, func(t *testing.T) {
-			ctx := testApex(t, `
-			apex_vndk {
-				name: "com.android.vndk.current",
-				key: "com.android.vndk.current.key",
-				updatable: false,
-			}
-
-			apex_key {
-				name: "com.android.vndk.current.key",
-				public_key: "testkey.avbpubkey",
-				private_key: "testkey.pem",
-			}
-
-			cc_library {
-				name: "libvndk",
-				srcs: ["mylib.cpp"],
-				vendor_available: true,
-				product_available: true,
-				vndk: {
-					enabled: true,
-				},
-				system_shared_libs: [],
-				stl: "none",
-				apex_available: [ "com.android.vndk.current" ],
-			}
-
-			cc_library {
-				name: "libvndksp",
-				srcs: ["mylib.cpp"],
-				vendor_available: true,
-				product_available: true,
-				vndk: {
-					enabled: true,
-					support_system_process: true,
-				},
-				system_shared_libs: [],
-				stl: "none",
-				apex_available: [ "com.android.vndk.current" ],
-			}
-
-			// VNDK-Ext should not cause any problems
-
-			cc_library {
-				name: "libvndk.ext",
-				srcs: ["mylib2.cpp"],
-				vendor: true,
-				vndk: {
-					enabled: true,
-					extends: "libvndk",
-				},
-				system_shared_libs: [],
-				stl: "none",
-			}
-
-			cc_library {
-				name: "libvndksp.ext",
-				srcs: ["mylib2.cpp"],
-				vendor: true,
-				vndk: {
-					enabled: true,
-					support_system_process: true,
-					extends: "libvndksp",
-				},
-				system_shared_libs: [],
-				stl: "none",
-			}
-		`+vndkLibrariesTxtFiles("current"), android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
-				variables.DeviceVndkVersion = proptools.StringPtr(tc.vndkVersion)
-				variables.KeepVndk = proptools.BoolPtr(true)
-			}))
-			ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", tc.expectedFiles)
-		})
-	}
-}
-
-func TestVndkApexWithPrebuilt(t *testing.T) {
-	ctx := testApex(t, `
-		apex_vndk {
-			name: "com.android.vndk.current",
-			key: "com.android.vndk.current.key",
-			updatable: false,
-		}
-
-		apex_key {
-			name: "com.android.vndk.current.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_prebuilt_library_shared {
-			name: "libvndk",
-			srcs: ["libvndk.so"],
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			system_shared_libs: [],
-			stl: "none",
-			apex_available: [ "com.android.vndk.current" ],
-		}
-
-		cc_prebuilt_library_shared {
-			name: "libvndk.arm",
-			srcs: ["libvndk.arm.so"],
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			enabled: false,
-			arch: {
-				arm: {
-					enabled: true,
-				},
-			},
-			system_shared_libs: [],
-			stl: "none",
-			apex_available: [ "com.android.vndk.current" ],
-		}
-		`+vndkLibrariesTxtFiles("current"),
-		withFiles(map[string][]byte{
-			"libvndk.so":     nil,
-			"libvndk.arm.so": nil,
-		}))
-	ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", []string{
-		"lib/libvndk.so",
-		"lib/libvndk.arm.so",
-		"lib64/libvndk.so",
-		"lib/libc++.so",
-		"lib64/libc++.so",
-		"etc/*",
-	})
-}
-
 func vndkLibrariesTxtFiles(vers ...string) (result string) {
 	for _, v := range vers {
 		if v == "current" {
@@ -4090,9 +3776,10 @@
 func TestVndkApexNameRule(t *testing.T) {
 	ctx := testApex(t, `
 		apex_vndk {
-			name: "com.android.vndk.current",
+			name: "com.android.vndk.v29",
 			key: "myapex.key",
 			file_contexts: ":myapex-file_contexts",
+			vndk_version: "29",
 			updatable: false,
 		}
 		apex_vndk {
@@ -4106,7 +3793,7 @@
 			name: "myapex.key",
 			public_key: "testkey.avbpubkey",
 			private_key: "testkey.pem",
-		}`+vndkLibrariesTxtFiles("28", "current"))
+		}`+vndkLibrariesTxtFiles("28", "29"))
 
 	assertApexName := func(expected, moduleName string) {
 		module := ctx.ModuleForTests(moduleName, "android_common")
@@ -4114,51 +3801,10 @@
 		ensureContains(t, apexManifestRule.Args["opt"], "-v name "+expected)
 	}
 
-	assertApexName("com.android.vndk.v29", "com.android.vndk.current")
+	assertApexName("com.android.vndk.v29", "com.android.vndk.v29")
 	assertApexName("com.android.vndk.v28", "com.android.vndk.v28")
 }
 
-func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
-	ctx := testApex(t, `
-		apex_vndk {
-			name: "com.android.vndk.current",
-			key: "com.android.vndk.current.key",
-			file_contexts: ":myapex-file_contexts",
-			updatable: false,
-		}
-
-		apex_key {
-			name: "com.android.vndk.current.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_library {
-			name: "libvndk",
-			srcs: ["mylib.cpp"],
-			vendor_available: true,
-			product_available: true,
-			native_bridge_supported: true,
-			host_supported: true,
-			vndk: {
-				enabled: true,
-			},
-			system_shared_libs: [],
-			stl: "none",
-			apex_available: [ "com.android.vndk.current" ],
-		}
-		`+vndkLibrariesTxtFiles("current"),
-		withNativeBridgeEnabled)
-
-	ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", []string{
-		"lib/libvndk.so",
-		"lib64/libvndk.so",
-		"lib/libc++.so",
-		"lib64/libc++.so",
-		"etc/*",
-	})
-}
-
 func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
 	testApexError(t, `module "com.android.vndk.current" .*: native_bridge_supported: .* doesn't support native bridge binary`, `
 		apex_vndk {
@@ -4259,47 +3905,6 @@
 	})
 }
 
-func TestVndkApexShouldNotProvideNativeLibs(t *testing.T) {
-	ctx := testApex(t, `
-		apex_vndk {
-			name: "com.android.vndk.current",
-			key: "com.android.vndk.current.key",
-			file_contexts: ":myapex-file_contexts",
-			updatable: false,
-		}
-
-		apex_key {
-			name: "com.android.vndk.current.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_library {
-			name: "libz",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			stubs: {
-				symbol_file: "libz.map.txt",
-				versions: ["30"],
-			}
-		}
-	`+vndkLibrariesTxtFiles("current"), withFiles(map[string][]byte{
-		"libz.map.txt": nil,
-	}))
-
-	apexManifestRule := ctx.ModuleForTests("com.android.vndk.current", "android_common").Rule("apexManifestRule")
-	provideNativeLibs := names(apexManifestRule.Args["provideNativeLibs"])
-	ensureListEmpty(t, provideNativeLibs)
-	ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", []string{
-		"out/soong/.intermediates/libz/android_vendor.29_arm64_armv8-a_shared/libz.so:lib64/libz.so",
-		"out/soong/.intermediates/libz/android_vendor.29_arm_armv7-a-neon_shared/libz.so:lib/libz.so",
-		"*/*",
-	})
-}
-
 func TestVendorApexWithVndkPrebuilts(t *testing.T) {
 	ctx := testApex(t, "",
 		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -10047,7 +9652,6 @@
 			key: "myapex.key",
 			updatable: false,
 			java_libs: ["foo"],
-			required: ["otherapex"],
 		}
 
 		apex_key {
@@ -11297,6 +10901,15 @@
 			],
 		}
 
+		rust_library {
+			name: "libaconfig_storage_read_api", // test mock
+			crate_name: "aconfig_storage_read_api",
+			srcs: ["src/lib.rs"],
+			apex_available: [
+				"myapex",
+			],
+		}
+
 		rust_ffi_shared {
 			name: "libmy_rust_library",
 			srcs: ["src/lib.rs"],
@@ -11381,14 +10994,14 @@
 	mod := ctx.ModuleForTests("myapex", "android_common_myapex")
 	s := mod.Rule("apexRule").Args["copy_commands"]
 	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
-	if len(copyCmds) != 26 {
-		t.Fatalf("Expected 26 commands, got %d in:\n%s", len(copyCmds), s)
+	if len(copyCmds) != 28 {
+		t.Fatalf("Expected 28 commands, got %d in:\n%s", len(copyCmds), s)
 	}
 
-	ensureMatches(t, copyCmds[22], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
-	ensureMatches(t, copyCmds[23], "^cp -f .*/package.map .*/image.apex/etc$")
-	ensureMatches(t, copyCmds[24], "^cp -f .*/flag.map .*/image.apex/etc$")
-	ensureMatches(t, copyCmds[25], "^cp -f .*/flag.val .*/image.apex/etc$")
+	ensureMatches(t, copyCmds[24], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
+	ensureMatches(t, copyCmds[25], "^cp -f .*/package.map .*/image.apex/etc$")
+	ensureMatches(t, copyCmds[26], "^cp -f .*/flag.map .*/image.apex/etc$")
+	ensureMatches(t, copyCmds[27], "^cp -f .*/flag.val .*/image.apex/etc$")
 
 	inputs := []string{
 		"my_aconfig_declarations_foo/intermediate.pb",
diff --git a/apex/builder.go b/apex/builder.go
index 6ad282a..50db631 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -485,7 +485,7 @@
 }
 
 func isVintfFragment(fi apexFile) bool {
-	isVintfFragment, _ := path.Match("etc/vintf/*.xml", fi.path())
+	isVintfFragment, _ := path.Match("etc/vintf/*", fi.path())
 	return isVintfFragment
 }
 
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
deleted file mode 100644
index 894aece..0000000
--- a/apex/vndk_test.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package apex
-
-import (
-	"testing"
-
-	"github.com/google/blueprint/proptools"
-
-	"android/soong/android"
-)
-
-func TestVndkApexUsesVendorVariant(t *testing.T) {
-	bp := `
-		apex_vndk {
-			name: "com.android.vndk.current",
-			key: "mykey",
-			updatable: false,
-		}
-		apex_key {
-			name: "mykey",
-		}
-		cc_library {
-			name: "libfoo",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			system_shared_libs: [],
-			stl: "none",
-		}
-		` + vndkLibrariesTxtFiles("current")
-
-	ensureFileSrc := func(t *testing.T, files []fileInApex, path, src string) {
-		t.Helper()
-		for _, f := range files {
-			if f.path == path {
-				ensureContains(t, f.src, src)
-				return
-			}
-		}
-		t.Errorf("expected path %q not found", path)
-	}
-
-	t.Run("VNDK lib doesn't have an apex variant", func(t *testing.T) {
-		ctx := testApex(t, bp)
-
-		// libfoo doesn't have apex variants
-		for _, variant := range ctx.ModuleVariantsForTests("libfoo") {
-			ensureNotContains(t, variant, "_myapex")
-		}
-
-		// VNDK APEX doesn't create apex variant
-		files := getFiles(t, ctx, "com.android.vndk.current", "android_common")
-		ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.29_arm_armv7-a-neon_shared/libfoo.so")
-	})
-
-	t.Run("VNDK APEX gathers only vendor variants even if product variants are available", func(t *testing.T) {
-		ctx := testApex(t, bp)
-
-		files := getFiles(t, ctx, "com.android.vndk.current", "android_common")
-		ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.29_arm_armv7-a-neon_shared/libfoo.so")
-	})
-
-	t.Run("VNDK APEX supports coverage variants", func(t *testing.T) {
-		ctx := testApex(t, bp,
-			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
-				variables.GcovCoverage = proptools.BoolPtr(true)
-				variables.Native_coverage = proptools.BoolPtr(true)
-			}),
-		)
-
-		files := getFiles(t, ctx, "com.android.vndk.current", "android_common")
-		ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.29_arm_armv7-a-neon_shared/libfoo.so")
-
-		files = getFiles(t, ctx, "com.android.vndk.current", "android_common_cov")
-		ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.29_arm_armv7-a-neon_shared_cov/libfoo.so")
-	})
-}
diff --git a/cc/Android.bp b/cc/Android.bp
index 9e4b763..93d9aa2 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -111,7 +111,6 @@
         "test_data_test.go",
         "tidy_test.go",
         "vendor_public_library_test.go",
-        "vendor_snapshot_test.go",
     ],
     pluginFor: ["soong_build"],
 }
diff --git a/cc/cc.go b/cc/cc.go
index 0fa3457..90185ea 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2980,6 +2980,9 @@
 		if depTag == stubImplDepTag {
 			return false
 		}
+		if depTag == android.RequiredDepTag {
+			return false
+		}
 
 		// Even if target lib has no vendor variant, keep checking dependency
 		// graph in case it depends on vendor_available or product_available
@@ -3157,6 +3160,10 @@
 			return
 		}
 
+		if depTag == android.RequiredDepTag {
+			return
+		}
+
 		if dep.Target().Os != ctx.Os() {
 			ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
 			return
diff --git a/cc/cc_test.go b/cc/cc_test.go
index d1b728e..74fae04 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -17,7 +17,6 @@
 import (
 	"fmt"
 	"os"
-	"path/filepath"
 	"reflect"
 	"regexp"
 	"runtime"
@@ -39,17 +38,6 @@
 }
 
 var prepareForCcTest = android.GroupFixturePreparers(
-	PrepareForTestWithCcIncludeVndk,
-	android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
-		variables.VendorApiLevel = StringPtr("202404")
-		variables.DeviceVndkVersion = StringPtr("current")
-		variables.KeepVndk = BoolPtr(true)
-		variables.Platform_vndk_version = StringPtr("29")
-	}),
-)
-
-// TODO(b/316829758) Update prepareForCcTest with this configuration and remove prepareForCcTestWithoutVndk
-var prepareForCcTestWithoutVndk = android.GroupFixturePreparers(
 	PrepareForIntegrationTestWithCc,
 	android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
 		variables.VendorApiLevel = StringPtr("202404")
@@ -123,30 +111,14 @@
 func testCcError(t *testing.T, pattern string, bp string) {
 	t.Helper()
 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	testCcErrorWithConfig(t, pattern, config)
-	return
-}
-
-// testCcErrorProductVndk runs tests using the prepareForCcTest
-//
-// See testCc for an explanation as to how to stop using this deprecated method.
-//
-// deprecated
-func testCcErrorProductVndk(t *testing.T, pattern string, bp string) {
-	t.Helper()
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
 	testCcErrorWithConfig(t, pattern, config)
 	return
 }
 
 const (
 	coreVariant     = "android_arm64_armv8-a_shared"
-	vendorVariant   = "android_vendor.29_arm64_armv8-a_shared"
-	productVariant  = "android_product.29_arm64_armv8-a_shared"
+	vendorVariant   = "android_vendor_arm64_armv8-a_shared"
+	productVariant  = "android_product_arm64_armv8-a_shared"
 	recoveryVariant = "android_recovery_arm64_armv8-a_shared"
 )
 
@@ -302,44 +274,6 @@
 	checkInstallPartition(t, ctx, "libproduct_odmavailable", vendorVariant, "odm")
 }
 
-func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string,
-	isVndkSp bool, extends string, variant string) {
-
-	t.Helper()
-
-	mod := ctx.ModuleForTests(name, variant).Module().(*Module)
-
-	// Check library properties.
-	lib, ok := mod.compiler.(*libraryDecorator)
-	if !ok {
-		t.Errorf("%q must have libraryDecorator", name)
-	} else if lib.baseInstaller.subDir != subDir {
-		t.Errorf("%q must use %q as subdir but it is using %q", name, subDir,
-			lib.baseInstaller.subDir)
-	}
-
-	// Check VNDK properties.
-	if mod.vndkdep == nil {
-		t.Fatalf("%q must have `vndkdep`", name)
-	}
-	if !mod.IsVndk() {
-		t.Errorf("%q IsVndk() must equal to true", name)
-	}
-	if mod.IsVndkSp() != isVndkSp {
-		t.Errorf("%q IsVndkSp() must equal to %t", name, isVndkSp)
-	}
-
-	// Check VNDK extension properties.
-	isVndkExt := extends != ""
-	if mod.IsVndkExt() != isVndkExt {
-		t.Errorf("%q IsVndkExt() must equal to %t", name, isVndkExt)
-	}
-
-	if actualExtends := mod.getVndkExtendsModuleName(); actualExtends != extends {
-		t.Errorf("%q must extend from %q but get %q", name, extends, actualExtends)
-	}
-}
-
 func checkWriteFileOutput(t *testing.T, ctx *android.TestContext, params android.TestingBuildParams, expected []string) {
 	t.Helper()
 	content := android.ContentFromFileRuleForTests(t, ctx, params)
@@ -347,344 +281,6 @@
 	assertArrayString(t, actual, expected)
 }
 
-func checkVndkOutput(t *testing.T, ctx *android.TestContext, output string, expected []string) {
-	t.Helper()
-	vndkSnapshot := ctx.SingletonForTests("vndk-snapshot")
-	checkWriteFileOutput(t, ctx, vndkSnapshot.Output(output), expected)
-}
-
-func checkVndkLibrariesOutput(t *testing.T, ctx *android.TestContext, module string, expected []string) {
-	t.Helper()
-	got := ctx.ModuleForTests(module, "android_common").Module().(*vndkLibrariesTxt).fileNames
-	assertArrayString(t, got, expected)
-}
-
-func TestVndk(t *testing.T) {
-	t.Parallel()
-	bp := `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_private",
-			vendor_available: true,
-			vndk: {
-				enabled: true,
-				private: true,
-			},
-			nocrt: true,
-			stem: "libvndk-private",
-		}
-
-		cc_library {
-			name: "libvndk_product",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-			target: {
-				vendor: {
-					cflags: ["-DTEST"],
-				},
-				product: {
-					cflags: ["-DTEST"],
-				},
-			},
-		}
-
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-			suffix: "-x",
-		}
-
-		cc_library {
-			name: "libvndk_sp_private",
-			vendor_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-				private: true,
-			},
-			nocrt: true,
-			target: {
-				vendor: {
-					suffix: "-x",
-				},
-			},
-		}
-
-		cc_library {
-			name: "libvndk_sp_product_private",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-				private: true,
-			},
-			nocrt: true,
-			target: {
-				vendor: {
-					suffix: "-x",
-				},
-				product: {
-					suffix: "-x",
-				},
-			},
-		}
-
-		cc_library {
-			name: "libllndk",
-			llndk: {
-				symbol_file: "libllndk.map.txt",
-				export_llndk_headers: ["libllndk_headers"],
-			}
-		}
-
-		cc_library {
-			name: "libclang_rt.hwasan-llndk",
-			llndk: {
-				symbol_file: "libclang_rt.hwasan.map.txt",
-			}
-		}
-
-		cc_library_headers {
-			name: "libllndk_headers",
-			llndk: {
-				llndk_headers: true,
-			},
-			export_include_dirs: ["include"],
-		}
-
-		llndk_libraries_txt {
-			name: "llndk.libraries.txt",
-		}
-		vndkcore_libraries_txt {
-			name: "vndkcore.libraries.txt",
-		}
-		vndksp_libraries_txt {
-			name: "vndksp.libraries.txt",
-		}
-		vndkprivate_libraries_txt {
-			name: "vndkprivate.libraries.txt",
-		}
-		vndkproduct_libraries_txt {
-			name: "vndkproduct.libraries.txt",
-		}
-		vndkcorevariant_libraries_txt {
-			name: "vndkcorevariant.libraries.txt",
-			insert_vndk_version: false,
-		}
-	`
-
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-
-	ctx := testCcWithConfig(t, config)
-
-	// subdir == "" because VNDK libs are not supposed to be installed separately.
-	// They are installed as part of VNDK APEX instead.
-	checkVndkModule(t, ctx, "libvndk", "", false, "", vendorVariant)
-	checkVndkModule(t, ctx, "libvndk_private", "", false, "", vendorVariant)
-	checkVndkModule(t, ctx, "libvndk_product", "", false, "", vendorVariant)
-	checkVndkModule(t, ctx, "libvndk_sp", "", true, "", vendorVariant)
-	checkVndkModule(t, ctx, "libvndk_sp_private", "", true, "", vendorVariant)
-	checkVndkModule(t, ctx, "libvndk_sp_product_private", "", true, "", vendorVariant)
-
-	checkVndkModule(t, ctx, "libvndk_product", "", false, "", productVariant)
-	checkVndkModule(t, ctx, "libvndk_sp_product_private", "", true, "", productVariant)
-
-	// Check VNDK snapshot output.
-	snapshotDir := "vndk-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-
-	vndkLibPath := filepath.Join(snapshotVariantPath, fmt.Sprintf("arch-%s-%s",
-		"arm64", "armv8-a"))
-	vndkLib2ndPath := filepath.Join(snapshotVariantPath, fmt.Sprintf("arch-%s-%s",
-		"arm", "armv7-a-neon"))
-
-	vndkCoreLibPath := filepath.Join(vndkLibPath, "shared", "vndk-core")
-	vndkSpLibPath := filepath.Join(vndkLibPath, "shared", "vndk-sp")
-	llndkLibPath := filepath.Join(vndkLibPath, "shared", "llndk-stub")
-
-	vndkCoreLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-core")
-	vndkSpLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-sp")
-	llndkLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "llndk-stub")
-
-	variant := "android_vendor.29_arm64_armv8-a_shared"
-	variant2nd := "android_vendor.29_arm_armv7-a-neon_shared"
-
-	snapshotSingleton := ctx.SingletonForTests("vndk-snapshot")
-
-	CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLibPath, variant)
-	CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
-	CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLibPath, variant)
-	CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLib2ndPath, variant2nd)
-	CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
-	CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
-	CheckSnapshot(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", llndkLibPath, variant)
-	CheckSnapshot(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", llndkLib2ndPath, variant2nd)
-
-	snapshotConfigsPath := filepath.Join(snapshotVariantPath, "configs")
-	CheckSnapshot(t, ctx, snapshotSingleton, "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "android_common")
-	CheckSnapshot(t, ctx, snapshotSingleton, "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "android_common")
-	CheckSnapshot(t, ctx, snapshotSingleton, "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "android_common")
-	CheckSnapshot(t, ctx, snapshotSingleton, "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "android_common")
-	CheckSnapshot(t, ctx, snapshotSingleton, "vndkproduct.libraries.txt", "vndkproduct.libraries.txt", snapshotConfigsPath, "android_common")
-
-	checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
-		"LLNDK: libc.so",
-		"LLNDK: libdl.so",
-		"LLNDK: libft2.so",
-		"LLNDK: libllndk.so",
-		"LLNDK: libm.so",
-		"VNDK-SP: libc++.so",
-		"VNDK-SP: libvndk_sp-x.so",
-		"VNDK-SP: libvndk_sp_private-x.so",
-		"VNDK-SP: libvndk_sp_product_private-x.so",
-		"VNDK-core: libvndk-private.so",
-		"VNDK-core: libvndk.so",
-		"VNDK-core: libvndk_product.so",
-		"VNDK-private: libft2.so",
-		"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", "libclang_rt.hwasan-llndk.so", "libdl.so", "libft2.so", "libllndk.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)
-}
-
-func TestVndkWithHostSupported(t *testing.T) {
-	t.Parallel()
-	ctx := testCc(t, `
-		cc_library {
-			name: "libvndk_host_supported",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			host_supported: true,
-		}
-
-		cc_library {
-			name: "libvndk_host_supported_but_disabled_on_device",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			host_supported: true,
-			enabled: false,
-			target: {
-				host: {
-					enabled: true,
-				}
-			}
-		}
-
-		vndkcore_libraries_txt {
-			name: "vndkcore.libraries.txt",
-		}
-	`)
-
-	checkVndkLibrariesOutput(t, ctx, "vndkcore.libraries.txt", []string{"libvndk_host_supported.so"})
-}
-
-func TestVndkLibrariesTxtAndroidMk(t *testing.T) {
-	t.Parallel()
-	bp := `
-		llndk_libraries_txt {
-			name: "llndk.libraries.txt",
-			insert_vndk_version: true,
-		}`
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	config.TestProductVariables.KeepVndk = BoolPtr(true)
-	ctx := testCcWithConfig(t, config)
-
-	module := ctx.ModuleForTests("llndk.libraries.txt", "android_common")
-	entries := android.AndroidMkEntriesForTest(t, ctx, module.Module())[0]
-	assertArrayString(t, entries.EntryMap["LOCAL_MODULE_STEM"], []string{"llndk.libraries.29.txt"})
-}
-
-func TestVndkUsingCoreVariant(t *testing.T) {
-	t.Parallel()
-	bp := `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk2",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				private: true,
-			},
-			nocrt: true,
-		}
-
-		vndkcorevariant_libraries_txt {
-			name: "vndkcorevariant.libraries.txt",
-			insert_vndk_version: false,
-		}
-	`
-
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
-	config.TestProductVariables.KeepVndk = BoolPtr(true)
-
-	setVndkMustUseVendorVariantListForTest(config, []string{"libvndk"})
-
-	ctx := testCcWithConfig(t, config)
-
-	checkVndkLibrariesOutput(t, ctx, "vndkcorevariant.libraries.txt", []string{"libc++.so", "libvndk2.so", "libvndk_sp.so"})
-}
-
 func TestDataLibs(t *testing.T) {
 	t.Parallel()
 	bp := `
@@ -702,9 +298,6 @@
  `
 
 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
 
 	ctx := testCcWithConfig(t, config)
 	module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
@@ -761,9 +354,6 @@
  `
 
 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
 
 	ctx := testCcWithConfig(t, config)
 	module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
@@ -859,247 +449,9 @@
 	}
 }
 
-func TestVndkModuleError(t *testing.T) {
-	t.Parallel()
-	// Check the error message for vendor_available and product_available properties.
-	testCcErrorProductVndk(t, "vndk: vendor_available must be set to true when `vndk: {enabled: true}`", `
-		cc_library {
-			name: "libvndk",
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-	`)
-
-	testCcErrorProductVndk(t, "vndk: vendor_available must be set to true when `vndk: {enabled: true}`", `
-		cc_library {
-			name: "libvndk",
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-	`)
-
-	testCcErrorProductVndk(t, "product properties must have the same values with the vendor properties for VNDK modules", `
-		cc_library {
-			name: "libvndkprop",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-			target: {
-				vendor: {
-					cflags: ["-DTEST",],
-				},
-			},
-		}
-	`)
-}
-
-func TestVndkDepError(t *testing.T) {
-	t.Parallel()
-	// Check whether an error is emitted when a VNDK lib depends on a system lib.
-	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			shared_libs: ["libfwk"],  // Cause error
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libfwk",
-			nocrt: true,
-		}
-	`)
-
-	// Check whether an error is emitted when a VNDK lib depends on a vendor lib.
-	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			shared_libs: ["libvendor"],  // Cause error
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvendor",
-			vendor: true,
-			nocrt: true,
-		}
-	`)
-
-	// Check whether an error is emitted when a VNDK-SP lib depends on a system lib.
-	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			shared_libs: ["libfwk"],  // Cause error
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libfwk",
-			nocrt: true,
-		}
-	`)
-
-	// Check whether an error is emitted when a VNDK-SP lib depends on a vendor lib.
-	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			shared_libs: ["libvendor"],  // Cause error
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvendor",
-			vendor: true,
-			nocrt: true,
-		}
-	`)
-
-	// Check whether an error is emitted when a VNDK-SP lib depends on a VNDK lib.
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			shared_libs: ["libvndk"],  // Cause error
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-	`)
-
-	// Check whether an error is emitted when a VNDK lib depends on a non-VNDK lib.
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			shared_libs: ["libnonvndk"],
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libnonvndk",
-			vendor_available: true,
-			product_available: true,
-			nocrt: true,
-		}
-	`)
-
-	// Check whether an error is emitted when a VNDK-private lib depends on a non-VNDK lib.
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
-		cc_library {
-			name: "libvndkprivate",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				private: true,
-			},
-			shared_libs: ["libnonvndk"],
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libnonvndk",
-			vendor_available: true,
-			product_available: true,
-			nocrt: true,
-		}
-	`)
-
-	// Check whether an error is emitted when a VNDK-sp lib depends on a non-VNDK lib.
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
-		cc_library {
-			name: "libvndksp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			shared_libs: ["libnonvndk"],
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libnonvndk",
-			vendor_available: true,
-			product_available: true,
-			nocrt: true,
-		}
-	`)
-
-	// Check whether an error is emitted when a VNDK-sp-private lib depends on a non-VNDK lib.
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
-		cc_library {
-			name: "libvndkspprivate",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-				private: true,
-			},
-			shared_libs: ["libnonvndk"],
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libnonvndk",
-			vendor_available: true,
-			product_available: true,
-			nocrt: true,
-		}
-	`)
-}
-
 func TestDoubleLoadbleDep(t *testing.T) {
 	t.Parallel()
-	// okay to link : LLNDK -> double_loadable VNDK
+	// okay to link : LLNDK -> double_loadable
 	testCc(t, `
 		cc_library {
 			name: "libllndk",
@@ -1113,32 +465,9 @@
 			name: "libdoubleloadable",
 			vendor_available: true,
 			product_available: true,
-			vndk: {
-				enabled: true,
-			},
 			double_loadable: true,
 		}
 	`)
-	// okay to link : LLNDK -> VNDK-SP
-	testCc(t, `
-		cc_library {
-			name: "libllndk",
-			shared_libs: ["libvndksp"],
-			llndk: {
-				symbol_file: "libllndk.map.txt",
-			}
-		}
-
-		cc_library {
-			name: "libvndksp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-		}
-	`)
 	// okay to link : double_loadable -> double_loadable
 	testCc(t, `
 		cc_library {
@@ -1154,15 +483,12 @@
 			double_loadable: true,
 		}
 	`)
-	// okay to link : double_loadable VNDK -> double_loadable VNDK private
+	// okay to link : double_loadable -> double_loadable
 	testCc(t, `
 		cc_library {
 			name: "libdoubleloadable",
 			vendor_available: true,
 			product_available: true,
-			vndk: {
-				enabled: true,
-			},
 			double_loadable: true,
 			shared_libs: ["libnondoubleloadable"],
 		}
@@ -1171,10 +497,6 @@
 			name: "libnondoubleloadable",
 			vendor_available: true,
 			product_available: true,
-			vndk: {
-				enabled: true,
-				private: true,
-			},
 			double_loadable: true,
 		}
 	`)
@@ -1204,7 +526,7 @@
 
 func TestDoubleLoadableDepError(t *testing.T) {
 	t.Parallel()
-	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
+	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable lib.
 	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
 		cc_library {
 			name: "libllndk",
@@ -1218,9 +540,6 @@
 			name: "libnondoubleloadable",
 			vendor_available: true,
 			product_available: true,
-			vndk: {
-				enabled: true,
-			},
 		}
 	`)
 
@@ -1285,999 +604,13 @@
 	`)
 }
 
-func TestCheckVndkMembershipBeforeDoubleLoadable(t *testing.T) {
-	t.Parallel()
-	testCcError(t, "module \"libvndksp\" variant .*: .*: VNDK-SP must only depend on VNDK-SP", `
-		cc_library {
-			name: "libvndksp",
-			shared_libs: ["libanothervndksp"],
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			}
-		}
-
-		cc_library {
-			name: "libllndk",
-			shared_libs: ["libanothervndksp"],
-		}
-
-		cc_library {
-			name: "libanothervndksp",
-			vendor_available: true,
-			product_available: true,
-		}
-	`)
-}
-
-func TestVndkExt(t *testing.T) {
-	t.Parallel()
-	// This test checks the VNDK-Ext properties.
-	bp := `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-		cc_library {
-			name: "libvndk2",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			target: {
-				vendor: {
-					suffix: "-suffix",
-				},
-				product: {
-					suffix: "-suffix",
-				},
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk2_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk2",
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext_product",
-			product_specific: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk2_ext_product",
-			product_specific: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk2",
-			},
-			nocrt: true,
-		}
-	`
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-
-	ctx := testCcWithConfig(t, config)
-
-	checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk", vendorVariant)
-	checkVndkModule(t, ctx, "libvndk_ext_product", "vndk", false, "libvndk", productVariant)
-
-	mod_vendor := ctx.ModuleForTests("libvndk2_ext", vendorVariant).Module().(*Module)
-	assertString(t, mod_vendor.outputFile.Path().Base(), "libvndk2-suffix.so")
-
-	mod_product := ctx.ModuleForTests("libvndk2_ext_product", productVariant).Module().(*Module)
-	assertString(t, mod_product.outputFile.Path().Base(), "libvndk2-suffix.so")
-}
-
-func TestVndkExtError(t *testing.T) {
-	t.Parallel()
-	// This test ensures an error is emitted in ill-formed vndk-ext definition.
-	testCcError(t, "must set `vendor: true` or `product_specific: true` to set `extends: \".*\"`", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-	`)
-
-	testCcError(t, "must set `extends: \"\\.\\.\\.\"` to vndk extension", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-	`)
-
-	testCcErrorProductVndk(t, "must set `extends: \"\\.\\.\\.\"` to vndk extension", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext_product",
-			product_specific: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-	`)
-
-	testCcErrorProductVndk(t, "must not set at the same time as `vndk: {extends: \"\\.\\.\\.\"}`", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext_product",
-			product_specific: true,
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-	`)
-}
-
-func TestVndkExtInconsistentSupportSystemProcessError(t *testing.T) {
-	t.Parallel()
-	// This test ensures an error is emitted for inconsistent support_system_process.
-	testCcError(t, "module \".*\" with mismatched support_system_process", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-	`)
-
-	testCcError(t, "module \".*\" with mismatched support_system_process", `
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk_sp",
-			},
-			nocrt: true,
-		}
-	`)
-}
-
-func TestVndkExtVendorAvailableFalseError(t *testing.T) {
-	t.Parallel()
-	// This test ensures an error is emitted when a VNDK-Ext library extends a VNDK library
-	// with `private: true`.
-	testCcError(t, "`extends` refers module \".*\" which has `private: true`", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				private: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-	`)
-
-	testCcErrorProductVndk(t, "`extends` refers module \".*\" which has `private: true`", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				private: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext_product",
-			product_specific: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-	`)
-}
-
-func TestVendorModuleUseVndkExt(t *testing.T) {
-	t.Parallel()
-	// This test ensures a vendor module can depend on a VNDK-Ext library.
-	testCc(t, `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk_sp",
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvendor",
-			vendor: true,
-			shared_libs: ["libvndk_ext", "libvndk_sp_ext"],
-			nocrt: true,
-		}
-	`)
-}
-
-func TestVndkExtUseVendorLib(t *testing.T) {
-	t.Parallel()
-	// This test ensures a VNDK-Ext library can depend on a vendor library.
-	testCc(t, `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			shared_libs: ["libvendor"],
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvendor",
-			vendor: true,
-			nocrt: true,
-		}
-	`)
-
-	// This test ensures a VNDK-SP-Ext library can depend on a vendor library.
-	testCc(t, `
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk_sp",
-				support_system_process: true,
-			},
-			shared_libs: ["libvendor"],  // Cause an error
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvendor",
-			vendor: true,
-			nocrt: true,
-		}
-	`)
-}
-
-func TestProductVndkExtDependency(t *testing.T) {
-	t.Parallel()
-	bp := `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext_product",
-			product_specific: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			shared_libs: ["libproduct_for_vndklibs"],
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp_ext_product",
-			product_specific: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk_sp",
-				support_system_process: true,
-			},
-			shared_libs: ["libproduct_for_vndklibs"],
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libproduct",
-			product_specific: true,
-			shared_libs: ["libvndk_ext_product", "libvndk_sp_ext_product"],
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libproduct_for_vndklibs",
-			product_specific: true,
-			nocrt: true,
-		}
-	`
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-
-	testCcWithConfig(t, config)
-}
-
-func TestVndkSpExtUseVndkError(t *testing.T) {
-	t.Parallel()
-	// This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK
-	// library.
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk_sp",
-				support_system_process: true,
-			},
-			shared_libs: ["libvndk"],  // Cause an error
-			nocrt: true,
-		}
-	`)
-
-	// This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK-Ext
-	// library.
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk_sp",
-				support_system_process: true,
-			},
-			shared_libs: ["libvndk_ext"],  // Cause an error
-			nocrt: true,
-		}
-	`)
-}
-
-func TestVndkUseVndkExtError(t *testing.T) {
-	t.Parallel()
-	// This test ensures an error is emitted if a VNDK/VNDK-SP library depends on a
-	// VNDK-Ext/VNDK-SP-Ext library.
-	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk2",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			shared_libs: ["libvndk_ext"],
-			nocrt: true,
-		}
-	`)
-
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk2",
-			vendor_available: true,
-			vndk: {
-				enabled: true,
-			},
-			target: {
-				vendor: {
-					shared_libs: ["libvndk_ext"],
-				},
-			},
-			nocrt: true,
-		}
-	`)
-
-	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk_sp",
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp_2",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			shared_libs: ["libvndk_sp_ext"],
-			nocrt: true,
-		}
-	`)
-
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp_ext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk_sp",
-			},
-			nocrt: true,
-		}
-
-		cc_library {
-			name: "libvndk_sp2",
-			vendor_available: true,
-			vndk: {
-				enabled: true,
-			},
-			target: {
-				vendor: {
-					shared_libs: ["libvndk_sp_ext"],
-				},
-			},
-			nocrt: true,
-		}
-	`)
-}
-
-func TestEnforceProductVndkVersion(t *testing.T) {
-	t.Parallel()
-	bp := `
-		cc_library {
-			name: "libllndk",
-			llndk: {
-				symbol_file: "libllndk.map.txt",
-			}
-		}
-		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-		cc_library {
-			name: "libvndk_sp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-			nocrt: true,
-		}
-		cc_library {
-			name: "libva",
-			vendor_available: true,
-			nocrt: true,
-		}
-		cc_library {
-			name: "libpa",
-			product_available: true,
-			nocrt: true,
-		}
-		cc_library {
-			name: "libboth_available",
-			vendor_available: true,
-			product_available: true,
-			nocrt: true,
-			srcs: ["foo.c"],
-			target: {
-				vendor: {
-					suffix: "-vendor",
-				},
-				product: {
-					suffix: "-product",
-				},
-			}
-		}
-		cc_library {
-			name: "libproduct_va",
-			product_specific: true,
-			vendor_available: true,
-			nocrt: true,
-		}
-		cc_library {
-			name: "libprod",
-			product_specific: true,
-			shared_libs: [
-				"libllndk",
-				"libvndk",
-				"libvndk_sp",
-				"libpa",
-				"libboth_available",
-				"libproduct_va",
-			],
-			nocrt: true,
-		}
-		cc_library {
-			name: "libvendor",
-			vendor: true,
-			shared_libs: [
-				"libllndk",
-				"libvndk",
-				"libvndk_sp",
-				"libva",
-				"libboth_available",
-				"libproduct_va",
-			],
-			nocrt: true,
-		}
-	`
-
-	ctx := prepareForCcTest.RunTestWithBp(t, bp).TestContext
-
-	checkVndkModule(t, ctx, "libvndk", "", false, "", productVariant)
-	checkVndkModule(t, ctx, "libvndk_sp", "", true, "", productVariant)
-
-	mod_vendor := ctx.ModuleForTests("libboth_available", vendorVariant).Module().(*Module)
-	assertString(t, mod_vendor.outputFile.Path().Base(), "libboth_available-vendor.so")
-
-	mod_product := ctx.ModuleForTests("libboth_available", productVariant).Module().(*Module)
-	assertString(t, mod_product.outputFile.Path().Base(), "libboth_available-product.so")
-
-	ensureStringContains := func(t *testing.T, str string, substr string) {
-		t.Helper()
-		if !strings.Contains(str, substr) {
-			t.Errorf("%q is not found in %v", substr, str)
-		}
-	}
-	ensureStringNotContains := func(t *testing.T, str string, substr string) {
-		t.Helper()
-		if strings.Contains(str, substr) {
-			t.Errorf("%q is found in %v", substr, str)
-		}
-	}
-
-	// _static variant is used since _shared reuses *.o from the static variant
-	vendor_static := ctx.ModuleForTests("libboth_available", strings.Replace(vendorVariant, "_shared", "_static", 1))
-	product_static := ctx.ModuleForTests("libboth_available", strings.Replace(productVariant, "_shared", "_static", 1))
-
-	vendor_cflags := vendor_static.Rule("cc").Args["cFlags"]
-	ensureStringContains(t, vendor_cflags, "-D__ANDROID_VNDK__")
-	ensureStringContains(t, vendor_cflags, "-D__ANDROID_VENDOR__")
-	ensureStringNotContains(t, vendor_cflags, "-D__ANDROID_PRODUCT__")
-	ensureStringContains(t, vendor_cflags, "-D__ANDROID_VENDOR_API__=202404")
-
-	product_cflags := product_static.Rule("cc").Args["cFlags"]
-	ensureStringContains(t, product_cflags, "-D__ANDROID_VNDK__")
-	ensureStringContains(t, product_cflags, "-D__ANDROID_PRODUCT__")
-	ensureStringNotContains(t, product_cflags, "-D__ANDROID_VENDOR__")
-	ensureStringNotContains(t, product_cflags, "-D__ANDROID_VENDOR_API__=202404")
-}
-
-func TestEnforceProductVndkVersionErrors(t *testing.T) {
-	t.Parallel()
-	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.29", `
-		cc_library {
-			name: "libprod",
-			product_specific: true,
-			shared_libs: [
-				"libvendor",
-			],
-			nocrt: true,
-		}
-		cc_library {
-			name: "libvendor",
-			vendor: true,
-			nocrt: true,
-		}
-	`)
-	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.29", `
-		cc_library {
-			name: "libprod",
-			product_specific: true,
-			shared_libs: [
-				"libsystem",
-			],
-			nocrt: true,
-		}
-		cc_library {
-			name: "libsystem",
-			nocrt: true,
-		}
-	`)
-	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.29", `
-		cc_library {
-			name: "libprod",
-			product_specific: true,
-			shared_libs: [
-				"libva",
-			],
-			nocrt: true,
-		}
-		cc_library {
-			name: "libva",
-			vendor_available: true,
-			nocrt: true,
-		}
-	`)
-	testCcErrorProductVndk(t, "non-VNDK module should not link to \".*\" which has `private: true`", `
-		cc_library {
-			name: "libprod",
-			product_specific: true,
-			shared_libs: [
-				"libvndk_private",
-			],
-			nocrt: true,
-		}
-		cc_library {
-			name: "libvndk_private",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				private: true,
-			},
-			nocrt: true,
-		}
-	`)
-	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.29", `
-		cc_library {
-			name: "libprod",
-			product_specific: true,
-			shared_libs: [
-				"libsystem_ext",
-			],
-			nocrt: true,
-		}
-		cc_library {
-			name: "libsystem_ext",
-			system_ext_specific: true,
-			nocrt: true,
-		}
-	`)
-	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:", `
-		cc_library {
-			name: "libsystem",
-			shared_libs: [
-				"libproduct_va",
-			],
-			nocrt: true,
-		}
-		cc_library {
-			name: "libproduct_va",
-			product_specific: true,
-			vendor_available: true,
-			nocrt: true,
-		}
-	`)
-}
-
 func TestMakeLinkType(t *testing.T) {
 	t.Parallel()
 	bp := `
 		cc_library {
-			name: "libvndk",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-			},
-		}
-		cc_library {
-			name: "libvndksp",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-		}
-		cc_library {
-			name: "libvndkprivate",
-			vendor_available: true,
-			product_available: true,
-			vndk: {
-				enabled: true,
-				private: true,
-			},
-		}
-		cc_library {
 			name: "libvendor",
 			vendor: true,
 		}
-		cc_library {
-			name: "libvndkext",
-			vendor: true,
-			vndk: {
-				enabled: true,
-				extends: "libvndk",
-			},
-		}
 		vndk_prebuilt_shared {
 			name: "prevndk",
 			version: "27",
@@ -2307,40 +640,15 @@
 				private: true,
 			}
 		}
-
 		llndk_libraries_txt {
 			name: "llndk.libraries.txt",
 		}
-		vndkcore_libraries_txt {
-			name: "vndkcore.libraries.txt",
-		}
-		vndksp_libraries_txt {
-			name: "vndksp.libraries.txt",
-		}
-		vndkprivate_libraries_txt {
-			name: "vndkprivate.libraries.txt",
-		}
-		vndkcorevariant_libraries_txt {
-			name: "vndkcorevariant.libraries.txt",
-			insert_vndk_version: false,
-		}
 	`
 
 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
 	// native:vndk
 	ctx := testCcWithConfig(t, config)
 
-	checkVndkLibrariesOutput(t, ctx, "vndkcore.libraries.txt",
-		[]string{"libvndk.so", "libvndkprivate.so"})
-	checkVndkLibrariesOutput(t, ctx, "vndksp.libraries.txt",
-		[]string{"libc++.so", "libvndksp.so"})
-	checkVndkLibrariesOutput(t, ctx, "llndk.libraries.txt",
-		[]string{"libc.so", "libdl.so", "libft2.so", "libllndk.so", "libllndkprivate.so", "libm.so"})
-	checkVndkLibrariesOutput(t, ctx, "vndkprivate.libraries.txt",
-		[]string{"libft2.so", "libllndkprivate.so", "libvndkprivate.so"})
-
 	vendorVariant27 := "android_vendor.27_arm64_armv8-a_shared"
 
 	tests := []struct {
@@ -2348,15 +656,9 @@
 		name     string
 		expected string
 	}{
-		{vendorVariant, "libvndk", "native:vndk"},
-		{vendorVariant, "libvndksp", "native:vndk"},
-		{vendorVariant, "libvndkprivate", "native:vndk_private"},
 		{vendorVariant, "libvendor", "native:vendor"},
-		{vendorVariant, "libvndkext", "native:vendor"},
 		{vendorVariant, "libllndk", "native:vndk"},
 		{vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vndk"},
-		{coreVariant, "libvndk", "native:platform"},
-		{coreVariant, "libvndkprivate", "native:platform"},
 		{coreVariant, "libllndk", "native:platform"},
 	}
 	for _, test := range tests {
@@ -2674,18 +976,18 @@
 	`)
 	actual := result.ModuleVariantsForTests("libllndk")
 	for i := 0; i < len(actual); i++ {
-		if !strings.HasPrefix(actual[i], "android_vendor.29_") {
+		if !strings.HasPrefix(actual[i], "android_vendor_") {
 			actual = append(actual[:i], actual[i+1:]...)
 			i--
 		}
 	}
 	expected := []string{
-		"android_vendor.29_arm64_armv8-a_shared",
-		"android_vendor.29_arm_armv7-a-neon_shared",
+		"android_vendor_arm64_armv8-a_shared",
+		"android_vendor_arm_armv7-a-neon_shared",
 	}
 	android.AssertArrayString(t, "variants for llndk stubs", expected, actual)
 
-	params := result.ModuleForTests("libllndk", "android_vendor.29_arm_armv7-a-neon_shared").Description("generate stub")
+	params := result.ModuleForTests("libllndk", "android_vendor_arm_armv7-a-neon_shared").Description("generate stub")
 	android.AssertSame(t, "use Vendor API level for default stubs", "202404", params.Args["apiLevel"])
 
 	checkExportedIncludeDirs := func(module, variant string, expectedDirs ...string) {
@@ -2697,11 +999,11 @@
 	}
 
 	checkExportedIncludeDirs("libllndk", "android_arm64_armv8-a_shared", "include")
-	checkExportedIncludeDirs("libllndk", "android_vendor.29_arm64_armv8-a_shared", "include")
+	checkExportedIncludeDirs("libllndk", "android_vendor_arm64_armv8-a_shared", "include")
 	checkExportedIncludeDirs("libllndk_with_external_headers", "android_arm64_armv8-a_shared", "include")
-	checkExportedIncludeDirs("libllndk_with_external_headers", "android_vendor.29_arm64_armv8-a_shared", "include_llndk")
+	checkExportedIncludeDirs("libllndk_with_external_headers", "android_vendor_arm64_armv8-a_shared", "include_llndk")
 	checkExportedIncludeDirs("libllndk_with_override_headers", "android_arm64_armv8-a_shared", "include")
-	checkExportedIncludeDirs("libllndk_with_override_headers", "android_vendor.29_arm64_armv8-a_shared", "include_llndk")
+	checkExportedIncludeDirs("libllndk_with_override_headers", "android_vendor_arm64_armv8-a_shared", "include_llndk")
 }
 
 func TestLlndkHeaders(t *testing.T) {
@@ -2733,7 +1035,7 @@
 	`)
 
 	// _static variant is used since _shared reuses *.o from the static variant
-	cc := ctx.ModuleForTests("libvendor", "android_vendor.29_arm_armv7-a-neon_static").Rule("cc")
+	cc := ctx.ModuleForTests("libvendor", "android_vendor_arm_armv7-a-neon_static").Rule("cc")
 	cflags := cc.Args["cFlags"]
 	if !strings.Contains(cflags, "-Imy_include") {
 		t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
@@ -2855,7 +1157,7 @@
 
 	// runtime_libs for vendor variants have '.vendor' suffixes if the modules have both core
 	// and vendor variants.
-	variant = "android_vendor.29_arm64_armv8-a_shared"
+	variant = "android_vendor_arm64_armv8-a_shared"
 
 	module = ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
 	checkRuntimeLibs(t, []string{"liball_available.vendor"}, module)
@@ -2865,7 +1167,7 @@
 
 	// runtime_libs for product variants have '.product' suffixes if the modules have both core
 	// and product variants.
-	variant = "android_product.29_arm64_armv8-a_shared"
+	variant = "android_product_arm64_armv8-a_shared"
 
 	module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
 	checkRuntimeLibs(t, []string{"liball_available.product"}, module)
@@ -2882,7 +1184,7 @@
 	module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
 	checkRuntimeLibs(t, []string{"liball_available"}, module)
 
-	variant = "android_vendor.29_arm64_armv8-a_shared"
+	variant = "android_vendor_arm64_armv8-a_shared"
 	module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
 	checkRuntimeLibs(t, nil, module)
 }
@@ -3065,9 +1367,6 @@
  `
 
 	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
 
 	ctx := testCcWithConfig(t, config)
 	module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
@@ -4795,8 +3094,7 @@
 	}
 }
 
-// TODO(b/316829758) Remove this test and do not set VNDK version from other tests
-func TestImageVariantsWithoutVndk(t *testing.T) {
+func TestImageVariants(t *testing.T) {
 	t.Parallel()
 
 	bp := `
@@ -4815,7 +3113,7 @@
 	}
 	`
 
-	ctx := prepareForCcTestWithoutVndk.RunTestWithBp(t, bp)
+	ctx := prepareForCcTest.RunTestWithBp(t, bp)
 
 	hasDep := func(m android.Module, wantDep android.Module) bool {
 		t.Helper()
@@ -4843,7 +3141,7 @@
 	testDepWithVariant("product")
 }
 
-func TestVendorSdkVersionWithoutVndk(t *testing.T) {
+func TestVendorSdkVersion(t *testing.T) {
 	t.Parallel()
 
 	bp := `
@@ -4861,7 +3159,7 @@
 		}
 	`
 
-	ctx := prepareForCcTestWithoutVndk.RunTestWithBp(t, bp)
+	ctx := prepareForCcTest.RunTestWithBp(t, bp)
 	testSdkVersionFlag := func(module, version string) {
 		flags := ctx.ModuleForTests(module, "android_vendor_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
 		android.AssertStringDoesContain(t, "min sdk version", flags, "-target aarch64-linux-android"+version)
@@ -4871,7 +3169,7 @@
 	testSdkVersionFlag("libbar", "29")
 
 	ctx = android.GroupFixturePreparers(
-		prepareForCcTestWithoutVndk,
+		prepareForCcTest,
 		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
 			if variables.BuildFlags == nil {
 				variables.BuildFlags = make(map[string]string)
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 0de9e05..10342a3 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -49,7 +49,6 @@
 	}
 
 	arm64Ldflags = []string{
-		"-Wl,--hash-style=gnu",
 		"-Wl,-z,separate-code",
 		"-Wl,-z,separate-loadable-segments",
 	}
diff --git a/cc/config/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index 335ad56..f7d190b 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -42,7 +42,6 @@
 		"-Wl,-z,now",
 		"-Wl,--build-id=md5",
 		"-Wl,--fatal-warnings",
-		"-Wl,--hash-style=gnu",
 		"-Wl,--no-undefined-version",
 	}
 
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 603bc6d..3284e4b 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -38,7 +38,6 @@
   }
 
 	armLdflags = []string{
-		"-Wl,--hash-style=gnu",
 		"-Wl,-m,armelf",
 		// Revert this after b/322359235 is fixed
 		"-Wl,-mllvm", "-Wl,-enable-shrink-wrap=false",
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 6a84fee..47f0de1 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -23,24 +23,29 @@
 
 var (
 	riscv64Cflags = []string{
-		// Help catch common 32/64-bit errors.
+		// Help catch common 32/64-bit errors. (This is duplicated in all 64-bit
+		// architectures' cflags.)
 		"-Werror=implicit-function-declaration",
+		// This is already the driver's Android default, but duplicated here (and
+		// below) for ease of experimentation with additional extensions.
 		"-march=rv64gcv_zba_zbb_zbs",
-		"-munaligned-access",
-		// Until https://gitlab.com/qemu-project/qemu/-/issues/1976 is fixed...
+		// TODO: move to driver (https://github.com/google/android-riscv64/issues/111)
+		"-mno-strict-align",
+		// TODO: remove when qemu V works (https://gitlab.com/qemu-project/qemu/-/issues/1976)
+		// (Note that we'll probably want to wait for berberis to be good enough
+		// that most people don't care about qemu's V performance either!)
 		"-mno-implicit-float",
-		// (https://github.com/google/android-riscv64/issues/124)
+		// TODO: remove when clang default changed (https://github.com/google/android-riscv64/issues/124)
 		"-mllvm -jump-is-expensive=false",
 	}
 
 	riscv64ArchVariantCflags = map[string][]string{}
 
 	riscv64Ldflags = []string{
-		"-Wl,--hash-style=gnu",
+		// This is already the driver's Android default, but duplicated here (and
+		// above) for ease of experimentation with additional extensions.
 		"-march=rv64gcv_zba_zbb_zbs",
-		"-munaligned-access",
-		// We should change the default for this in clang, but for now...
-		// (https://github.com/google/android-riscv64/issues/124)
+		// TODO: remove when clang default changed (https://github.com/google/android-riscv64/issues/124)
 		"-Wl,-mllvm -Wl,-jump-is-expensive=false",
 	}
 
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 12119a7..ca2c2b7 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -30,7 +30,6 @@
 	x86_64Cppflags = []string{}
 
 	x86_64Ldflags = []string{
-		"-Wl,--hash-style=gnu",
 		"-Wl,-z,separate-loadable-segments",
 	}
 
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 2faa670..60b8339 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -33,9 +33,7 @@
 
 	x86Cppflags = []string{}
 
-	x86Ldflags = []string{
-		"-Wl,--hash-style=gnu",
-	}
+	x86Ldflags = []string{}
 
 	x86ArchVariantCflags = map[string][]string{
 		"": []string{
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index f80be99..99d4ebb 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -46,7 +46,6 @@
 		"-Wl,-z,now",
 		"-Wl,--build-id=md5",
 		"-Wl,--fatal-warnings",
-		"-Wl,--hash-style=gnu",
 		"-Wl,--no-undefined-version",
 
 		// Use the device gcc toolchain
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index 05c644f..b3d5116 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -200,7 +200,7 @@
 	}
 	`
 	t.Helper()
-	ctx := PrepareForTestWithCcIncludeVndk.RunTestWithBp(t, bp)
+	ctx := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
 
 	variants := ctx.ModuleVariantsForTests("gen")
 	if !slices.Contains(variants, "android_vendor_arm64_armv8-a") {
@@ -210,3 +210,47 @@
 		t.Errorf(`expected product variant, but does not exist in %v`, variants)
 	}
 }
+
+// cc_genrule is initialized to android.InitAndroidArchModule
+// that is an architecture-specific Android module.
+// So testing properties tagged with `android:"arch_variant"`
+// for cc_genrule.
+func TestMultilibGenruleOut(t *testing.T) {
+	bp := `
+	cc_genrule {
+		name: "gen",
+		cmd: "cp $(in) $(out)",
+		srcs: ["foo"],
+		multilib: {
+			lib32: {
+				out: [
+					"subdir32/external-module32",
+				],
+			},
+			lib64: {
+				out: [
+					"subdir64/external-module64",
+				],
+			},
+		},
+	}
+	`
+	result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
+	gen_32bit := result.ModuleForTests("gen", "android_arm_armv7-a-neon").OutputFiles(t, "")
+	android.AssertPathsEndWith(t,
+		"genrule_out",
+		[]string{
+			"subdir32/external-module32",
+		},
+		gen_32bit,
+	)
+
+	gen_64bit := result.ModuleForTests("gen", "android_arm64_armv8-a").OutputFiles(t, "")
+	android.AssertPathsEndWith(t,
+		"genrule_out",
+		[]string{
+			"subdir64/external-module64",
+		},
+		gen_64bit,
+	)
+}
diff --git a/cc/library_stub.go b/cc/library_stub.go
index aab6664..cddb1b5 100644
--- a/cc/library_stub.go
+++ b/cc/library_stub.go
@@ -496,11 +496,10 @@
 func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool      { return false }
 func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string {
 	var variations []string
-	platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
 
 	if String(v.properties.Variant) == "llndk" {
-		variations = append(variations, VendorVariationPrefix+platformVndkVersion)
-		variations = append(variations, ProductVariationPrefix+platformVndkVersion)
+		variations = append(variations, VendorVariation)
+		variations = append(variations, ProductVariation)
 	}
 
 	return variations
diff --git a/cc/library_stub_test.go b/cc/library_stub_test.go
index 528577a..4df0a41 100644
--- a/cc/library_stub_test.go
+++ b/cc/library_stub_test.go
@@ -71,8 +71,8 @@
 	android.AssertBoolEquals(t, "original library should be linked with non-stub variant", true, hasDirectDependency(t, ctx, libfoo, libbar))
 	android.AssertBoolEquals(t, "Stub library from API surface should be not linked with non-stub variant", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
 
-	libfooVendor := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
-	libbarApiImportVendor := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+	libfooVendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Module()
+	libbarApiImportVendor := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
 
 	android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfooVendor, libbar))
 	android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfooVendor, libbarApiImportVendor))
@@ -102,8 +102,8 @@
 
 	ctx := prepareForCcTest.RunTestWithBp(t, bp)
 
-	libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
-	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+	libfoo := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Module()
+	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
 
 	android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
 }
@@ -135,9 +135,9 @@
 
 	ctx := prepareForCcTest.RunTestWithBp(t, bp)
 
-	libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
-	libbar := ctx.ModuleForTests("libbar", "android_vendor.29_arm64_armv8-a_shared").Module()
-	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+	libfoo := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Module()
+	libbar := ctx.ModuleForTests("libbar", "android_vendor_arm64_armv8-a_shared").Module()
+	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
 
 	android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar))
 	android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
@@ -174,13 +174,13 @@
 		}
 	`
 	ctx := prepareForCcTest.RunTestWithBp(t, bp)
-	vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
+	vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"]
 	android.AssertStringDoesContain(t, "Vendor binary should compile using headers provided by stub", vendorCFlags, "-Istub_include_dir")
 	android.AssertStringDoesNotContain(t, "Vendor binary should not compile using headers of source", vendorCFlags, "-Isource_include_dir")
 	android.AssertStringDoesContain(t, "Vendor binary should compile using system headers provided by stub", vendorCFlags, "-isystem stub_system_include_dir")
 	android.AssertStringDoesNotContain(t, "Vendor binary should not compile using system headers of source", vendorCFlags, "-isystem source_system_include_dir")
 
-	vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").OrderOnly.Strings()
+	vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor_arm64_armv8-a").Rule("cc").OrderOnly.Strings()
 	// Building the stub.so file first assembles its .h files in multi-tree out.
 	// These header files are required for compiling the other API domain (vendor in this case)
 	android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so")
@@ -223,17 +223,17 @@
 
 	ctx := prepareForCcTest.RunTestWithBp(t, bp)
 
-	binfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
-	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
-	libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module()
+	binfoo := ctx.ModuleForTests("binfoo", "android_vendor_arm64_armv8-a").Module()
+	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
+	libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor_arm64_armv8-a").Module()
 
 	android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, binfoo, libbarApiImport))
 	android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
 
-	binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
+	binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor_arm64_armv8-a").Rule("ld").Args["libFlags"]
 	android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", binFooLibFlags, "libbar.llndk.apiimport.so")
 
-	binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
+	binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"]
 	android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", binFooCFlags, "-Ilibbar_llndk_include")
 }
 
@@ -446,12 +446,12 @@
 
 	binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
 	libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
-	libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+	libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
 
 	android.AssertBoolEquals(t, "Binary using SDK should be linked with API library from NDK variant", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
 	android.AssertBoolEquals(t, "Binary using SDK should not be linked with API library from LLNDK variant", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportLlndk))
 
-	binbaz := ctx.ModuleForTests("binbaz", "android_vendor.29_arm64_armv8-a").Module()
+	binbaz := ctx.ModuleForTests("binbaz", "android_vendor_arm64_armv8-a").Module()
 
 	android.AssertBoolEquals(t, "Vendor binary should be linked with API library from LLNDK variant", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportLlndk))
 	android.AssertBoolEquals(t, "Vendor binary should not be linked with API library from NDK variant", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
diff --git a/cc/linker.go b/cc/linker.go
index 2c50db2..9686697 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -530,13 +530,6 @@
 		flags.Global.LdFlags = append(flags.Global.LdFlags, RpathFlags(ctx)...)
 	}
 
-	if ctx.useSdk() {
-		// The bionic linker now has support gnu style hashes (which are much faster!), but shipping
-		// to older devices requires the old style hash. Fortunately, we can build with both and
-		// it'll work anywhere.
-		flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--hash-style=both")
-	}
-
 	flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ToolchainLdflags())
 
 	// Version_script is not needed when linking stubs lib where the version
diff --git a/cc/lto.go b/cc/lto.go
index 05fa8ee..a084db7 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -90,10 +90,6 @@
 	} else if ctx.testBinary() || ctx.testLibrary() {
 		// Do not enable LTO for tests for better debugging.
 		ltoEnabled = false
-	} else if ctx.isVndk() {
-		// FIXME: ThinLTO for VNDK produces different output.
-		// b/169217596
-		ltoEnabled = false
 	}
 
 	lto.Properties.LtoDefault = ltoDefault
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 183e818..64193b1 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -325,13 +325,6 @@
 	if runtime.GOOS == "darwin" {
 		return false
 	}
-	// abidw doesn't currently handle top-byte-ignore correctly. Disable ABI
-	// dumping for those configs while we wait for a fix. We'll still have ABI
-	// checking coverage from non-hwasan builds.
-	// http://b/190554910
-	if android.InList("hwaddress", config.SanitizeDevice()) {
-		return false
-	}
 	// http://b/156513478
 	return config.ReleaseNdkAbiMonitored()
 }
diff --git a/cc/object_test.go b/cc/object_test.go
index c0d1331..004dfd3 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -41,7 +41,7 @@
 		{"android_arm64_armv8-a_sdk_29", "29"},
 		{"android_arm64_armv8-a_sdk_30", "30"},
 		{"android_arm64_armv8-a_sdk_current", "10000"},
-		{"android_vendor.29_arm64_armv8-a", "29"},
+		{"android_vendor_arm64_armv8-a", "10000"},
 	}
 
 	ctx := prepareForCcTest.RunTestWithBp(t, bp)
@@ -50,7 +50,7 @@
 		expected := "-target aarch64-linux-android" + v.num + " "
 		android.AssertStringDoesContain(t, "cflag", cflags, expected)
 	}
-	ctx = prepareForCcTestWithoutVndk.RunTestWithBp(t, bp)
+	ctx = prepareForCcTest.RunTestWithBp(t, bp)
 	android.AssertStringDoesContain(t, "cflag",
 		ctx.ModuleForTests("crt_foo", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"],
 		"-target aarch64-linux-android10000 ")
diff --git a/cc/testing.go b/cc/testing.go
index 9c2900c..3bdc383 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -305,10 +305,7 @@
 			recovery_available: true,
 			host_supported: true,
 			min_sdk_version: "29",
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
+			double_loadable: true,
 			apex_available: [
 				"//apex_available:platform",
 				"//apex_available:anyapex",
@@ -624,19 +621,6 @@
 	android.FixtureOverrideTextFile(linuxBionicDefaultsPath, withLinuxBionic()),
 )
 
-// This adds some additional modules and singletons which might negatively impact the performance
-// of tests so they are not included in the PrepareForIntegrationTestWithCc.
-var PrepareForTestWithCcIncludeVndk = android.GroupFixturePreparers(
-	PrepareForIntegrationTestWithCc,
-	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
-		snapshot.VendorSnapshotImageSingleton.Init(ctx)
-		snapshot.RecoverySnapshotImageSingleton.Init(ctx)
-		RegisterVendorSnapshotModules(ctx)
-		RegisterRecoverySnapshotModules(ctx)
-		ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
-	}),
-)
-
 // PrepareForTestWithHostMusl sets the host configuration to musl libc instead of glibc.  It also disables the test
 // on mac, which doesn't support musl libc, and adds musl modules.
 var PrepareForTestWithHostMusl = android.GroupFixturePreparers(
@@ -722,7 +706,6 @@
 	snapshot.RecoverySnapshotImageSingleton.Init(ctx)
 	RegisterVendorSnapshotModules(ctx)
 	RegisterRecoverySnapshotModules(ctx)
-	ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
 	RegisterVndkLibraryTxtTypes(ctx)
 
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
diff --git a/cc/vendor_public_library_test.go b/cc/vendor_public_library_test.go
index 769be09..7385f2b 100644
--- a/cc/vendor_public_library_test.go
+++ b/cc/vendor_public_library_test.go
@@ -65,8 +65,8 @@
 	`)
 
 	coreVariant := "android_arm64_armv8-a_shared"
-	vendorVariant := "android_vendor.29_arm64_armv8-a_shared"
-	productVariant := "android_product.29_arm64_armv8-a_shared"
+	vendorVariant := "android_vendor_arm64_armv8-a_shared"
+	productVariant := "android_product_arm64_armv8-a_shared"
 
 	// test if header search paths are correctly added
 	// _static variant is used since _shared reuses *.o from the static variant
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
deleted file mode 100644
index 0a55431..0000000
--- a/cc/vendor_snapshot_test.go
+++ /dev/null
@@ -1,1751 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cc
-
-import (
-	"android/soong/android"
-	"fmt"
-	"path/filepath"
-	"reflect"
-	"strings"
-	"testing"
-)
-
-func checkJsonContents(t *testing.T, ctx *android.TestContext, snapshotSingleton android.TestingSingleton, jsonPath string, key string, value string) {
-	jsonOut := snapshotSingleton.MaybeOutput(jsonPath)
-	if jsonOut.Rule == nil {
-		t.Errorf("%q expected but not found", jsonPath)
-		return
-	}
-	content := android.ContentFromFileRuleForTests(t, ctx, jsonOut)
-	if !strings.Contains(content, fmt.Sprintf("%q:%q", key, value)) {
-		t.Errorf("%q must include %q:%q but it only has %v", jsonPath, key, value, jsonOut.Args["content"])
-	}
-}
-
-func TestVendorSnapshotCapture(t *testing.T) {
-	bp := `
-	cc_library {
-		name: "libvndk",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		nocrt: true,
-	}
-
-	cc_library {
-		name: "libvendor",
-		vendor: true,
-		nocrt: true,
-	}
-
-	cc_library {
-		name: "libvendor_override",
-		vendor: true,
-		nocrt: true,
-		overrides: ["libvendor"],
-	}
-
-	cc_library {
-		name: "libvendor_available",
-		vendor_available: true,
-		nocrt: true,
-		min_sdk_version: "29",
-	}
-
-	cc_library_headers {
-		name: "libvendor_headers",
-		vendor_available: true,
-		nocrt: true,
-	}
-
-	cc_binary {
-		name: "vendor_bin",
-		vendor: true,
-		nocrt: true,
-	}
-
-	cc_binary {
-		name: "vendor_available_bin",
-		vendor_available: true,
-		nocrt: true,
-	}
-
-	cc_binary {
-		name: "vendor_bin_override",
-		vendor: true,
-		nocrt: true,
-		overrides: ["vendor_bin"],
-	}
-
-	cc_prebuilt_library_static {
-		name: "libb",
-		vendor_available: true,
-		srcs: ["libb.a"],
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-	}
-
-	cc_object {
-		name: "obj",
-		vendor_available: true,
-	}
-
-	cc_library {
-		name: "libllndk",
-		llndk: {
-			symbol_file: "libllndk.map.txt",
-		},
-	}
-`
-
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	ctx := testCcWithConfig(t, config)
-
-	// Check Vendor snapshot output.
-
-	snapshotDir := "vendor-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
-	var jsonFiles []string
-
-	for _, arch := range [][]string{
-		[]string{"arm64", "armv8-a"},
-		[]string{"arm", "armv7-a-neon"},
-	} {
-		archType := arch[0]
-		archVariant := arch[1]
-		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
-		// For shared libraries, only non-VNDK vendor_available modules are captured
-		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(sharedDir, "libvendor.so.json"),
-			filepath.Join(sharedDir, "libvendor_available.so.json"))
-
-		// LLNDK modules are not captured
-		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant)
-
-		// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
-		// Also cfi variants are captured, except for prebuilts like toolchain_library
-		staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant)
-		staticCfiVariant := fmt.Sprintf("android_vendor.29_%s_%s_static_cfi", archType, archVariant)
-		staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
-		CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(staticDir, "libb.a.json"),
-			filepath.Join(staticDir, "libvndk.a.json"),
-			filepath.Join(staticDir, "libvndk.cfi.a.json"),
-			filepath.Join(staticDir, "libvendor.a.json"),
-			filepath.Join(staticDir, "libvendor.cfi.a.json"),
-			filepath.Join(staticDir, "libvendor_available.a.json"),
-			filepath.Join(staticDir, "libvendor_available.cfi.a.json"))
-
-		checkJsonContents(t, ctx, snapshotSingleton, filepath.Join(staticDir, "libb.a.json"), "MinSdkVersion", "apex_inherit")
-		checkJsonContents(t, ctx, snapshotSingleton, filepath.Join(staticDir, "libvendor_available.a.json"), "MinSdkVersion", "29")
-
-		// For binary executables, all vendor:true and vendor_available modules are captured.
-		if archType == "arm64" {
-			binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
-			binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
-			CheckSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
-			CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
-			jsonFiles = append(jsonFiles,
-				filepath.Join(binaryDir, "vendor_bin.json"),
-				filepath.Join(binaryDir, "vendor_available_bin.json"))
-
-			checkOverrides(t, ctx, snapshotSingleton, filepath.Join(binaryDir, "vendor_bin_override.json"), []string{"vendor_bin"})
-		}
-
-		// For header libraries, all vendor:true and vendor_available modules are captured.
-		headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
-		jsonFiles = append(jsonFiles, filepath.Join(headerDir, "libvendor_headers.json"))
-
-		// For object modules, all vendor:true and vendor_available modules are captured.
-		objectVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
-		objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
-		CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
-		jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
-
-		checkOverrides(t, ctx, snapshotSingleton, filepath.Join(sharedDir, "libvendor_override.so.json"), []string{"libvendor"})
-	}
-
-	for _, jsonFile := range jsonFiles {
-		// verify all json files exist
-		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
-			t.Errorf("%q expected but not found", jsonFile)
-		}
-	}
-
-	// fake snapshot should have all outputs in the normal snapshot.
-	fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
-	for _, output := range snapshotSingleton.AllOutputs() {
-		fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
-		if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
-			t.Errorf("%q expected but not found", fakeOutput)
-		}
-	}
-}
-
-func TestVendorSnapshotDirected(t *testing.T) {
-	bp := `
-	cc_library_shared {
-		name: "libvendor",
-		vendor: true,
-		nocrt: true,
-	}
-
-	cc_library_shared {
-		name: "libvendor_available",
-		vendor_available: true,
-		nocrt: true,
-	}
-
-	genrule {
-		name: "libfoo_gen",
-		cmd: "",
-		out: ["libfoo.so"],
-	}
-
-	cc_prebuilt_library_shared {
-		name: "libfoo",
-		vendor: true,
-		prefer: true,
-		srcs: [":libfoo_gen"],
-	}
-
-	cc_library_shared {
-		name: "libfoo",
-		vendor: true,
-		nocrt: true,
-	}
-`
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	config.TestProductVariables.DirectedVendorSnapshot = true
-	config.TestProductVariables.VendorSnapshotModules = make(map[string]bool)
-	config.TestProductVariables.VendorSnapshotModules["libvendor"] = true
-	config.TestProductVariables.VendorSnapshotModules["libfoo"] = true
-	ctx := testCcWithConfig(t, config)
-
-	// Check Vendor snapshot output.
-
-	snapshotDir := "vendor-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
-	var includeJsonFiles []string
-
-	for _, arch := range [][]string{
-		[]string{"arm64", "armv8-a"},
-		[]string{"arm", "armv7-a-neon"},
-	} {
-		archType := arch[0]
-		archVariant := arch[1]
-		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
-		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-
-		// Included modules
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
-		// Check that snapshot captures "prefer: true" prebuilt
-		CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
-
-		// Excluded modules. Modules not included in the directed vendor snapshot
-		// are still include as fake modules.
-		CheckSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor_available.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)
-		}
-	}
-}
-
-func TestVendorSnapshotUse(t *testing.T) {
-	frameworkBp := `
-	cc_library {
-		name: "libvndk",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		nocrt: true,
-	}
-
-	cc_library {
-		name: "libvendor",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		system_shared_libs: [],
-	}
-
-	cc_library {
-		name: "libvendor_available",
-		vendor_available: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		system_shared_libs: [],
-	}
-
-	cc_library {
-		name: "lib32",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		system_shared_libs: [],
-		compile_multilib: "32",
-	}
-
-	cc_library {
-		name: "lib64",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		no_crt_pad_segment: true,
-		stl: "none",
-		system_shared_libs: [],
-		compile_multilib: "64",
-	}
-
-	cc_library {
-		name: "libllndk",
-		llndk: {
-			symbol_file: "libllndk.map.txt",
-		},
-	}
-
-	cc_binary {
-		name: "bin",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		system_shared_libs: [],
-	}
-
-	cc_binary {
-		name: "bin32",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		system_shared_libs: [],
-		compile_multilib: "32",
-	}
-`
-
-	vndkBp := `
-	vndk_prebuilt_shared {
-		name: "libvndk",
-		version: "31",
-		target_arch: "arm64",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		arch: {
-			arm64: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-			arm: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-		},
-	}
-
-	// old snapshot module which has to be ignored
-	vndk_prebuilt_shared {
-		name: "libvndk",
-		version: "26",
-		target_arch: "arm64",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		arch: {
-			arm64: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-			arm: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-		},
-	}
-
-	// different arch snapshot which has to be ignored
-	vndk_prebuilt_shared {
-		name: "libvndk",
-		version: "31",
-		target_arch: "arm",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		arch: {
-			arm: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-		},
-	}
-
-	vndk_prebuilt_shared {
-		name: "libllndk",
-		version: "31",
-		target_arch: "arm64",
-		vendor_available: true,
-		product_available: true,
-		arch: {
-			arm64: {
-				srcs: ["libllndk.so"],
-			},
-			arm: {
-				srcs: ["libllndk.so"],
-			},
-		},
-	}
-`
-
-	vendorProprietaryBp := `
-	cc_library {
-		name: "libvendor_without_snapshot",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		no_crt_pad_segment: true,
-		stl: "none",
-		system_shared_libs: [],
-	}
-
-	cc_library_shared {
-		name: "libclient",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		no_crt_pad_segment: true,
-		stl: "none",
-		system_shared_libs: [],
-		shared_libs: ["libvndk", "libvendor_available", "libllndk"],
-		static_libs: ["libvendor", "libvendor_without_snapshot"],
-		arch: {
-			arm64: {
-				shared_libs: ["lib64"],
-			},
-			arm: {
-				shared_libs: ["lib32"],
-			},
-		},
-		srcs: ["client.cpp"],
-	}
-
-	cc_library_shared {
-		name: "libclient_cfi",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		no_crt_pad_segment: true,
-		stl: "none",
-		system_shared_libs: [],
-		static_libs: ["libvendor"],
-		sanitize: {
-			cfi: true,
-		},
-		srcs: ["client.cpp"],
-	}
-
-	cc_library_shared {
-		name: "libvndkext",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		no_crt_pad_segment: true,
-		stl: "none",
-		system_shared_libs: [],
-		vndk: {
-			extends: "libvndk",
-			enabled: true,
-		}
-	}
-
-	cc_binary {
-		name: "bin_without_snapshot",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "libc++_static",
-		system_shared_libs: [],
-		static_libs: ["libvndk"],
-		srcs: ["bin.cpp"],
-	}
-
-	vendor_snapshot {
-		name: "vendor_snapshot",
-		version: "31",
-		arch: {
-			arm64: {
-				vndk_libs: [
-					"libvndk",
-					"libllndk",
-				],
-				static_libs: [
-					"libc++_static",
-					"libc++demangle",
-					"libunwind",
-					"libvendor",
-					"libvendor_available",
-					"libvndk",
-					"lib64",
-				],
-				shared_libs: [
-					"libvendor",
-					"libvendor_override",
-					"libvendor_available",
-					"lib64",
-				],
-				binaries: [
-					"bin",
-					"bin_override",
-				],
-			},
-			arm: {
-				vndk_libs: [
-					"libvndk",
-					"libllndk",
-				],
-				static_libs: [
-					"libvendor",
-					"libvendor_available",
-					"libvndk",
-					"lib32",
-				],
-				shared_libs: [
-					"libvendor",
-					"libvendor_override",
-					"libvendor_available",
-					"lib32",
-				],
-				binaries: [
-					"bin32",
-				],
-			},
-		}
-	}
-
-	vendor_snapshot_static {
-		name: "libvndk",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "both",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "libvndk.a",
-			},
-			arm: {
-				src: "libvndk.a",
-			},
-		},
-		shared_libs: ["libvndk"],
-		export_shared_lib_headers: ["libvndk"],
-	}
-
-	vendor_snapshot_shared {
-		name: "libvendor",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "both",
-		vendor: true,
-		no_crt_pad_segment: true,
-		shared_libs: [
-			"libvendor_without_snapshot",
-			"libvendor_available",
-			"libvndk",
-		],
-		arch: {
-			arm64: {
-				src: "libvendor.so",
-				export_include_dirs: ["include/libvendor"],
-			},
-			arm: {
-				src: "libvendor.so",
-				export_include_dirs: ["include/libvendor"],
-			},
-		},
-	}
-
-	vendor_snapshot_shared {
-		name: "libvendor_override",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "both",
-		vendor: true,
-		no_crt_pad_segment: true,
-		overrides: ["libvendor"],
-		shared_libs: [
-			"libvendor_without_snapshot",
-			"libvendor_available",
-			"libvndk",
-		],
-		arch: {
-			arm64: {
-				src: "override/libvendor.so",
-				export_include_dirs: ["include/libvendor"],
-			},
-			arm: {
-				src: "override/libvendor.so",
-				export_include_dirs: ["include/libvendor"],
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "lib32",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "32",
-		vendor: true,
-		arch: {
-			arm: {
-				src: "lib32.a",
-			},
-		},
-	}
-
-	vendor_snapshot_shared {
-		name: "lib32",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "32",
-		vendor: true,
-		no_crt_pad_segment: true,
-		arch: {
-			arm: {
-				src: "lib32.so",
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "lib64",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "lib64.a",
-			},
-		},
-	}
-
-	vendor_snapshot_shared {
-		name: "lib64",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		no_crt_pad_segment: true,
-		arch: {
-			arm64: {
-				src: "lib64.so",
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "libvendor",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "both",
-		vendor: true,
-		arch: {
-			arm64: {
-				cfi: {
-					src: "libvendor.cfi.a",
-					export_include_dirs: ["include/libvendor_cfi"],
-				},
-				src: "libvendor.a",
-				export_include_dirs: ["include/libvendor"],
-			},
-			arm: {
-				cfi: {
-					src: "libvendor.cfi.a",
-					export_include_dirs: ["include/libvendor_cfi"],
-				},
-				src: "libvendor.a",
-				export_include_dirs: ["include/libvendor"],
-			},
-		},
-	}
-
-	vendor_snapshot_shared {
-		name: "libvendor_available",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "both",
-		vendor: true,
-		no_crt_pad_segment: true,
-		arch: {
-			arm64: {
-				src: "libvendor_available.so",
-				export_include_dirs: ["include/libvendor"],
-			},
-			arm: {
-				src: "libvendor_available.so",
-				export_include_dirs: ["include/libvendor"],
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "libvendor_available",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "both",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "libvendor_available.a",
-				export_include_dirs: ["include/libvendor"],
-			},
-			arm: {
-				src: "libvendor_available.so",
-				export_include_dirs: ["include/libvendor"],
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "libc++_static",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "libc++_static.a",
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "libc++demangle",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "libc++demangle.a",
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "libunwind",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "libunwind.a",
-			},
-		},
-	}
-
-	vendor_snapshot_binary {
-		name: "bin",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "bin",
-			},
-		},
-		symlinks: ["binfoo", "binbar"],
-	}
-
-	vendor_snapshot_binary {
-		name: "bin_override",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		overrides: ["bin"],
-		arch: {
-			arm64: {
-				src: "override/bin",
-			},
-		},
-		symlinks: ["binfoo", "binbar"],
-	}
-
-	vendor_snapshot_binary {
-		name: "bin32",
-		version: "31",
-		target_arch: "arm64",
-		compile_multilib: "32",
-		vendor: true,
-		arch: {
-			arm: {
-				src: "bin32",
-			},
-		},
-	}
-
-	// old snapshot module which has to be ignored
-	vendor_snapshot_binary {
-		name: "bin",
-		version: "26",
-		target_arch: "arm64",
-		compile_multilib: "first",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "bin",
-			},
-		},
-	}
-
-	// different arch snapshot which has to be ignored
-	vendor_snapshot_binary {
-		name: "bin",
-		version: "31",
-		target_arch: "arm",
-		compile_multilib: "first",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "bin",
-			},
-		},
-	}
-`
-	depsBp := GatherRequiredDepsForTest(android.Android)
-
-	mockFS := map[string][]byte{
-		"deps/Android.bp":                  []byte(depsBp),
-		"framework/Android.bp":             []byte(frameworkBp),
-		"framework/symbol.txt":             nil,
-		"vendor/Android.bp":                []byte(vendorProprietaryBp),
-		"vendor/bin":                       nil,
-		"vendor/override/bin":              nil,
-		"vendor/bin32":                     nil,
-		"vendor/bin.cpp":                   nil,
-		"vendor/client.cpp":                nil,
-		"vendor/include/libvndk/a.h":       nil,
-		"vendor/include/libvendor/b.h":     nil,
-		"vendor/include/libvendor_cfi/c.h": nil,
-		"vendor/libc++_static.a":           nil,
-		"vendor/libc++demangle.a":          nil,
-		"vendor/libunwind.a":               nil,
-		"vendor/libvndk.a":                 nil,
-		"vendor/libvendor.a":               nil,
-		"vendor/libvendor.cfi.a":           nil,
-		"vendor/libvendor.so":              nil,
-		"vendor/override/libvendor.so":     nil,
-		"vendor/lib32.a":                   nil,
-		"vendor/lib32.so":                  nil,
-		"vendor/lib64.a":                   nil,
-		"vendor/lib64.so":                  nil,
-		"vndk/Android.bp":                  []byte(vndkBp),
-		"vndk/include/libvndk/a.h":         nil,
-		"vndk/libvndk.so":                  nil,
-		"vndk/libllndk.so":                 nil,
-	}
-
-	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("31")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("32")
-	ctx := CreateTestContext(config)
-	ctx.Register()
-
-	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "vendor/Android.bp", "vndk/Android.bp"})
-	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	android.FailIfErrored(t, errs)
-
-	sharedVariant := "android_vendor.31_arm64_armv8-a_shared"
-	staticVariant := "android_vendor.31_arm64_armv8-a_static"
-	binaryVariant := "android_vendor.31_arm64_armv8-a"
-
-	sharedCfiVariant := "android_vendor.31_arm64_armv8-a_shared_cfi"
-	staticCfiVariant := "android_vendor.31_arm64_armv8-a_static_cfi"
-
-	shared32Variant := "android_vendor.31_arm_armv7-a-neon_shared"
-	binary32Variant := "android_vendor.31_arm_armv7-a-neon"
-
-	// libclient uses libvndk.vndk.31.arm64, libvendor.vendor_static.31.arm64, libvendor_without_snapshot
-	libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"]
-	for _, includeFlags := range []string{
-		"-Ivndk/include/libvndk",     // libvndk
-		"-Ivendor/include/libvendor", // libvendor
-	} {
-		if !strings.Contains(libclientCcFlags, includeFlags) {
-			t.Errorf("flags for libclient must contain %#v, but was %#v.",
-				includeFlags, libclientCcFlags)
-		}
-	}
-
-	libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"]
-	for _, input := range [][]string{
-		[]string{sharedVariant, "libvndk.vndk.31.arm64"},
-		[]string{sharedVariant, "libllndk.vndk.31.arm64"},
-		[]string{staticVariant, "libvendor.vendor_static.31.arm64"},
-		[]string{staticVariant, "libvendor_without_snapshot"},
-	} {
-		outputPaths := GetOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
-		if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
-			t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
-		}
-
-	}
-
-	libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs
-	if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib64"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
-	}
-
-	libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs
-	if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
-	}
-
-	libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs
-	if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib32"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g)
-	}
-
-	// libclient_cfi uses libvendor.vendor_static.31.arm64's cfi variant
-	libclientCfiCcFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("cc").Args["cFlags"]
-	if !strings.Contains(libclientCfiCcFlags, "-Ivendor/include/libvendor_cfi") {
-		t.Errorf("flags for libclient_cfi must contain %#v, but was %#v.",
-			"-Ivendor/include/libvendor_cfi", libclientCfiCcFlags)
-	}
-
-	libclientCfiLdFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("ld").Args["libFlags"]
-	libvendorCfiOutputPaths := GetOutputPaths(ctx, staticCfiVariant, []string{"libvendor.vendor_static.31.arm64"})
-	if !strings.Contains(libclientCfiLdFlags, libvendorCfiOutputPaths[0].String()) {
-		t.Errorf("libflags for libclientCfi must contain %#v, but was %#v", libvendorCfiOutputPaths[0], libclientCfiLdFlags)
-	}
-
-	// bin_without_snapshot uses libvndk.vendor_static.31.arm64 (which reexports vndk's exported headers)
-	binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"]
-	if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivndk/include/libvndk") {
-		t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.",
-			"-Ivendor/include/libvndk", binWithoutSnapshotCcFlags)
-	}
-
-	binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"]
-	libVndkStaticOutputPaths := GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.31.arm64"})
-	if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
-		t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
-			libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
-	}
-
-	// libvendor.so is installed by libvendor.vendor_shared.31.arm64
-	ctx.ModuleForTests("libvendor.vendor_shared.31.arm64", sharedVariant).Output("libvendor.so")
-
-	// lib64.so is installed by lib64.vendor_shared.31.arm64
-	ctx.ModuleForTests("lib64.vendor_shared.31.arm64", sharedVariant).Output("lib64.so")
-
-	// lib32.so is installed by lib32.vendor_shared.31.arm64
-	ctx.ModuleForTests("lib32.vendor_shared.31.arm64", shared32Variant).Output("lib32.so")
-
-	// libvendor_available.so is installed by libvendor_available.vendor_shared.31.arm64
-	ctx.ModuleForTests("libvendor_available.vendor_shared.31.arm64", sharedVariant).Output("libvendor_available.so")
-
-	// libvendor_without_snapshot.so is installed by libvendor_without_snapshot
-	ctx.ModuleForTests("libvendor_without_snapshot", sharedVariant).Output("libvendor_without_snapshot.so")
-
-	// bin is installed by bin.vendor_binary.31.arm64
-	bin64Module := ctx.ModuleForTests("bin.vendor_binary.31.arm64", binaryVariant)
-	bin64Module.Output("bin")
-
-	// also test symlinks
-	bin64MkEntries := android.AndroidMkEntriesForTest(t, ctx, bin64Module.Module())
-	bin64KatiSymlinks := bin64MkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"]
-
-	// Either AndroidMk entries contain symlinks, or symlinks should be installed by Soong
-	for _, symlink := range []string{"binfoo", "binbar"} {
-		if inList(symlink, bin64KatiSymlinks) {
-			continue
-		}
-
-		bin64Module.Output(symlink)
-	}
-
-	// bin32 is installed by bin32.vendor_binary.31.arm64
-	ctx.ModuleForTests("bin32.vendor_binary.31.arm64", binary32Variant).Output("bin32")
-
-	// bin_without_snapshot is installed by bin_without_snapshot
-	ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
-
-	// libvendor, libvendor_available and bin don't have vendor.31 variant
-	libvendorVariants := ctx.ModuleVariantsForTests("libvendor")
-	if inList(sharedVariant, libvendorVariants) {
-		t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant)
-	}
-
-	libvendorAvailableVariants := ctx.ModuleVariantsForTests("libvendor_available")
-	if inList(sharedVariant, libvendorAvailableVariants) {
-		t.Errorf("libvendor_available must not have variant %#v, but it does", sharedVariant)
-	}
-
-	binVariants := ctx.ModuleVariantsForTests("bin")
-	if inList(binaryVariant, binVariants) {
-		t.Errorf("bin must not have variant %#v, but it does", sharedVariant)
-	}
-
-	// test overrides property
-	binOverrideModule := ctx.ModuleForTests("bin_override.vendor_binary.31.arm64", binaryVariant)
-	binOverrideModule.Output("bin")
-	binOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, binOverrideModule.Module())
-	binOverrideEntry := binOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
-	if !inList("bin", binOverrideEntry) {
-		t.Errorf("bin_override must override bin but was %q\n", binOverrideEntry)
-	}
-
-	libvendorOverrideModule := ctx.ModuleForTests("libvendor_override.vendor_shared.31.arm64", sharedVariant)
-	libvendorOverrideModule.Output("libvendor.so")
-	libvendorOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, libvendorOverrideModule.Module())
-	libvendorOverrideEntry := libvendorOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
-	if !inList("libvendor", libvendorOverrideEntry) {
-		t.Errorf("libvendor_override must override libvendor but was %q\n", libvendorOverrideEntry)
-	}
-}
-
-func TestVendorSnapshotSanitizer(t *testing.T) {
-	bp := `
-	vendor_snapshot {
-		name: "vendor_snapshot",
-		version: "28",
-		arch: {
-			arm64: {
-				static_libs: [
-					"libsnapshot",
-					"note_memtag_heap_sync",
-				],
-				objects: [
-					"snapshot_object",
-				],
-				vndk_libs: [
-					"libclang_rt.hwasan",
-				],
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "libsnapshot",
-		vendor: true,
-		target_arch: "arm64",
-		version: "28",
-		arch: {
-			arm64: {
-				src: "libsnapshot.a",
-				cfi: {
-					src: "libsnapshot.cfi.a",
-				},
-				hwasan: {
-					src: "libsnapshot.hwasan.a",
-				},
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "note_memtag_heap_sync",
-		vendor: true,
-		target_arch: "arm64",
-		version: "28",
-		arch: {
-			arm64: {
-				src: "note_memtag_heap_sync.a",
-			},
-		},
-	}
-
-	vndk_prebuilt_shared {
-		name: "libclang_rt.hwasan",
-		version: "28",
-		target_arch: "arm64",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		arch: {
-			arm64: {
-				srcs: ["libclang_rt.hwasan.so"],
-			},
-		},
-	}
-
-	vendor_snapshot_object {
-		name: "snapshot_object",
-		vendor: true,
-		target_arch: "arm64",
-		version: "28",
-		arch: {
-			arm64: {
-				src: "snapshot_object.o",
-			},
-		},
-		stl: "none",
-	}
-
-	cc_test {
-		name: "vstest",
-		gtest: false,
-		vendor: true,
-		compile_multilib: "64",
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		static_libs: ["libsnapshot"],
-		system_shared_libs: [],
-	}
-`
-
-	mockFS := map[string][]byte{
-		"vendor/Android.bp":              []byte(bp),
-		"vendor/libc++demangle.a":        nil,
-		"vendor/libclang_rt.hwasan.so":   nil,
-		"vendor/libsnapshot.a":           nil,
-		"vendor/libsnapshot.cfi.a":       nil,
-		"vendor/libsnapshot.hwasan.a":    nil,
-		"vendor/note_memtag_heap_sync.a": nil,
-		"vendor/snapshot_object.o":       nil,
-	}
-
-	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("28")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
-	ctx := testCcWithConfig(t, config)
-
-	// Check non-cfi, cfi and hwasan variant.
-	staticVariant := "android_vendor.28_arm64_armv8-a_static"
-	staticCfiVariant := "android_vendor.28_arm64_armv8-a_static_cfi"
-	staticHwasanVariant := "android_vendor.28_arm64_armv8-a_static_hwasan"
-	staticHwasanCfiVariant := "android_vendor.28_arm64_armv8-a_static_hwasan_cfi"
-
-	staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticVariant).Module().(*Module)
-	assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a")
-
-	staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticCfiVariant).Module().(*Module)
-	assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
-
-	staticHwasanModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanVariant).Module().(*Module)
-	assertString(t, staticHwasanModule.outputFile.Path().Base(), "libsnapshot.hwasan.a")
-
-	staticHwasanCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanCfiVariant).Module().(*Module)
-	if !staticHwasanCfiModule.HiddenFromMake() || !staticHwasanCfiModule.PreventInstall() {
-		t.Errorf("Hwasan and Cfi cannot enabled at the same time.")
-	}
-
-	snapshotObjModule := ctx.ModuleForTests("snapshot_object.vendor_object.28.arm64", "android_vendor.28_arm64_armv8-a").Module()
-	snapshotObjMkEntries := android.AndroidMkEntriesForTest(t, ctx, snapshotObjModule)
-	// snapshot object must not add ".hwasan" suffix
-	assertString(t, snapshotObjMkEntries[0].EntryMap["LOCAL_MODULE"][0], "snapshot_object")
-}
-
-func TestVendorSnapshotExclude(t *testing.T) {
-
-	// This test verifies that the exclude_from_vendor_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 vendor snapshot based on their path (framework or
-	// vendor) and the exclude_from_vendor_snapshot property.
-
-	frameworkBp := `
-		cc_library_shared {
-			name: "libinclude",
-			srcs: ["src/include.cpp"],
-			vendor_available: true,
-		}
-		cc_library_shared {
-			name: "libexclude",
-			srcs: ["src/exclude.cpp"],
-			vendor: true,
-			exclude_from_vendor_snapshot: true,
-		}
-		cc_library_shared {
-			name: "libavailable_exclude",
-			srcs: ["src/exclude.cpp"],
-			vendor_available: true,
-			exclude_from_vendor_snapshot: true,
-		}
-	`
-
-	vendorProprietaryBp := `
-		cc_library_shared {
-			name: "libvendor",
-			srcs: ["vendor.cpp"],
-			vendor: 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(t.TempDir(), android.Android, nil, "", mockFS)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	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.
-	AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, vendorVariant)
-	AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, vendorVariant)
-	AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, vendorVariant)
-
-	// A vendor module is excluded, but by its path, not the
-	// exclude_from_vendor_snapshot property.
-	AssertExcludeFromVendorSnapshotIs(t, ctx, "libvendor", false, vendorVariant)
-
-	// Verify the content of the vendor snapshot.
-
-	snapshotDir := "vendor-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
-	var includeJsonFiles []string
-	var excludeJsonFiles []string
-
-	for _, arch := range [][]string{
-		[]string{"arm64", "armv8-a"},
-		[]string{"arm", "armv7-a-neon"},
-	} {
-		archType := arch[0]
-		archVariant := arch[1]
-		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
-		sharedVariant := fmt.Sprintf("android_vendor.29_%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"))
-		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.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 TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) {
-
-	// This test verifies that using the exclude_from_vendor_snapshot
-	// property on a module in a vendor proprietary path generates an
-	// error. These modules are already excluded, so we prohibit using the
-	// property in this way, which could add to confusion.
-
-	vendorProprietaryBp := `
-		cc_library_shared {
-			name: "libvendor",
-			srcs: ["vendor.cpp"],
-			vendor: true,
-			exclude_from_vendor_snapshot: true,
-		}
-	`
-
-	depsBp := GatherRequiredDepsForTest(android.Android)
-
-	mockFS := map[string][]byte{
-		"deps/Android.bp":   []byte(depsBp),
-		"device/Android.bp": []byte(vendorProprietaryBp),
-		"device/vendor.cpp": nil,
-	}
-
-	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	ctx := CreateTestContext(config)
-	ctx.Register()
-
-	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "device/Android.bp"})
-	android.FailIfErrored(t, errs)
-
-	_, errs = ctx.PrepareBuildActions(config)
-	android.CheckErrorsAgainstExpectations(t, errs, []string{
-		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
-		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
-		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
-		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
-		`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
-		`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
-	})
-}
-
-func TestRecoverySnapshotCapture(t *testing.T) {
-	bp := `
-	cc_library {
-		name: "libvndk",
-		vendor_available: true,
-		recovery_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		nocrt: true,
-	}
-
-	cc_library {
-		name: "librecovery",
-		recovery: true,
-		nocrt: true,
-	}
-
-	cc_library {
-		name: "librecovery_available",
-		recovery_available: true,
-		nocrt: true,
-	}
-
-	cc_library_headers {
-		name: "librecovery_headers",
-		recovery_available: true,
-		nocrt: true,
-	}
-
-	cc_binary {
-		name: "recovery_bin",
-		recovery: true,
-		nocrt: true,
-	}
-
-	cc_binary {
-		name: "recovery_available_bin",
-		recovery_available: true,
-		nocrt: true,
-	}
-
-	cc_prebuilt_library_static {
-		name: "libb",
-		recovery_available: true,
-		srcs: ["libb.a"],
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-	}
-
-	cc_object {
-		name: "obj",
-		recovery_available: true,
-	}
-`
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	ctx := testCcWithConfig(t, config)
-
-	// Check Recovery snapshot output.
-
-	snapshotDir := "recovery-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
-	var jsonFiles []string
-
-	for _, arch := range [][]string{
-		[]string{"arm64", "armv8-a"},
-	} {
-		archType := arch[0]
-		archVariant := arch[1]
-		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
-		// For shared libraries, only recovery_available modules are captured.
-		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(sharedDir, "libvndk.so.json"),
-			filepath.Join(sharedDir, "librecovery.so.json"),
-			filepath.Join(sharedDir, "librecovery_available.so.json"))
-
-		// For static libraries, all recovery:true and recovery_available modules are captured.
-		staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant)
-		staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
-		CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(staticDir, "libb.a.json"),
-			filepath.Join(staticDir, "librecovery.a.json"),
-			filepath.Join(staticDir, "librecovery_available.a.json"))
-
-		// For binary executables, all recovery:true and recovery_available modules are captured.
-		if archType == "arm64" {
-			binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
-			binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
-			CheckSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
-			CheckSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
-			jsonFiles = append(jsonFiles,
-				filepath.Join(binaryDir, "recovery_bin.json"),
-				filepath.Join(binaryDir, "recovery_available_bin.json"))
-		}
-
-		// For header libraries, all vendor:true and vendor_available modules are captured.
-		headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
-		jsonFiles = append(jsonFiles, filepath.Join(headerDir, "librecovery_headers.json"))
-
-		// For object modules, all vendor:true and vendor_available modules are captured.
-		objectVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
-		objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
-		CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
-		jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
-	}
-
-	for _, jsonFile := range jsonFiles {
-		// verify all json files exist
-		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
-			t.Errorf("%q expected but not found", jsonFile)
-		}
-	}
-}
-
-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,
-		}
-		cc_library_shared {
-			name: "libavailable_exclude",
-			srcs: ["src/exclude.cpp"],
-			recovery_available: true,
-			exclude_from_recovery_snapshot: true,
-		}
-	`
-
-	vendorProprietaryBp := `
-		cc_library_shared {
-			name: "librecovery",
-			srcs: ["recovery.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/recovery.cpp":   nil,
-	}
-
-	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
-	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	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, "libinclude", false, recoveryVariant)
-	AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, recoveryVariant)
-	AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, recoveryVariant)
-
-	// A recovery module is excluded, but by its path, not the
-	// exclude_from_recovery_snapshot property.
-	AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, recoveryVariant)
-
-	// Verify the content of the recovery snapshot.
-
-	snapshotDir := "recovery-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", 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, "librecovery", "librecovery.so", sharedDir, sharedVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
-		CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.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 TestRecoverySnapshotDirected(t *testing.T) {
-	bp := `
-	cc_library_shared {
-		name: "librecovery",
-		recovery: true,
-		nocrt: true,
-	}
-
-	cc_library_shared {
-		name: "librecovery_available",
-		recovery_available: true,
-		nocrt: true,
-	}
-
-	genrule {
-		name: "libfoo_gen",
-		cmd: "",
-		out: ["libfoo.so"],
-	}
-
-	cc_prebuilt_library_shared {
-		name: "libfoo",
-		recovery: true,
-		prefer: true,
-		srcs: [":libfoo_gen"],
-	}
-
-	cc_library_shared {
-		name: "libfoo",
-		recovery: true,
-		nocrt: true,
-	}
-`
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	config.TestProductVariables.DirectedRecoverySnapshot = true
-	config.TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
-	config.TestProductVariables.RecoverySnapshotModules["librecovery"] = true
-	config.TestProductVariables.RecoverySnapshotModules["libfoo"] = true
-	ctx := testCcWithConfig(t, config)
-
-	// Check recovery snapshot output.
-
-	snapshotDir := "recovery-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
-	var includeJsonFiles []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, "librecovery", "librecovery.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
-		// Check that snapshot captures "prefer: true" prebuilt
-		CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
-
-		// Excluded modules. Modules not included in the directed recovery snapshot
-		// are still include as fake modules.
-		CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.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)
-		}
-	}
-}
-
-func TestSnapshotInRelativeInstallPath(t *testing.T) {
-	bp := `
-	cc_library {
-		name: "libvendor_available",
-		vendor_available: true,
-		nocrt: true,
-	}
-
-	cc_library {
-		name: "libvendor_available_var",
-		vendor_available: true,
-		stem: "libvendor_available",
-		relative_install_path: "var",
-		nocrt: true,
-	}
-`
-
-	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-	ctx := testCcWithConfig(t, config)
-
-	// Check Vendor snapshot output.
-
-	snapshotDir := "vendor-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
-	var jsonFiles []string
-
-	for _, arch := range [][]string{
-		[]string{"arm64", "armv8-a"},
-		[]string{"arm", "armv7-a-neon"},
-	} {
-		archType := arch[0]
-		archVariant := arch[1]
-		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
-		// For shared libraries, only non-VNDK vendor_available modules are captured
-		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-		sharedDirVar := filepath.Join(sharedDir, "var")
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
-		CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available_var", "libvendor_available.so", sharedDirVar, sharedVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(sharedDir, "libvendor_available.so.json"),
-			filepath.Join(sharedDirVar, "libvendor_available.so.json"))
-	}
-
-	for _, jsonFile := range jsonFiles {
-		// verify all json files exist
-		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
-			t.Errorf("%q expected but not found", jsonFile)
-		}
-	}
-
-	// fake snapshot should have all outputs in the normal snapshot.
-	fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
-	for _, output := range snapshotSingleton.AllOutputs() {
-		fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
-		if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
-			t.Errorf("%q expected but not found", fakeOutput)
-		}
-	}
-}
diff --git a/cmd/symbols_map/Android.bp b/cmd/symbols_map/Android.bp
index 0ba3b07..e3ae6ed 100644
--- a/cmd/symbols_map/Android.bp
+++ b/cmd/symbols_map/Android.bp
@@ -5,17 +5,16 @@
 blueprint_go_binary {
     name: "symbols_map",
     srcs: [
-        "elf.go",
         "r8.go",
         "symbols_map.go",
     ],
     testSrcs: [
-        "elf_test.go",
         "r8_test.go",
     ],
     deps: [
         "blueprint-pathtools",
         "golang-protobuf-encoding-prototext",
+        "soong-elf",
         "soong-response",
         "symbols_map_proto",
     ],
diff --git a/cmd/symbols_map/symbols_map.go b/cmd/symbols_map/symbols_map.go
index 938446d..c56cf93 100644
--- a/cmd/symbols_map/symbols_map.go
+++ b/cmd/symbols_map/symbols_map.go
@@ -22,6 +22,7 @@
 	"strings"
 
 	"android/soong/cmd/symbols_map/symbols_map_proto"
+	"android/soong/elf"
 	"android/soong/response"
 
 	"github.com/google/blueprint/pathtools"
@@ -116,7 +117,7 @@
 	if *elfFile != "" {
 		typ = symbols_map_proto.Mapping_ELF
 		location = *elfFile
-		identifier, err = elfIdentifier(*elfFile, true)
+		identifier, err = elf.Identifier(*elfFile, true)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "error reading elf identifier: %s\n", err)
 			os.Exit(1)
diff --git a/elf/Android.bp b/elf/Android.bp
new file mode 100644
index 0000000..6450be1
--- /dev/null
+++ b/elf/Android.bp
@@ -0,0 +1,28 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+    name: "soong-elf",
+    pkgPath: "android/soong/elf",
+    srcs: [
+        "elf.go",
+    ],
+    testSrcs: [
+        "elf_test.go",
+    ],
+}
diff --git a/cmd/symbols_map/elf.go b/elf/elf.go
similarity index 94%
rename from cmd/symbols_map/elf.go
rename to elf/elf.go
index 950e3b2..e84a8ae 100644
--- a/cmd/symbols_map/elf.go
+++ b/elf/elf.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package elf
 
 import (
 	"debug/elf"
@@ -26,9 +26,9 @@
 
 const gnuBuildID = "GNU\x00"
 
-// elfIdentifier extracts the elf build ID from an elf file.  If allowMissing is true it returns
+// Identifier extracts the elf build ID from an elf file.  If allowMissing is true it returns
 // an empty identifier if the file exists but the build ID note does not.
-func elfIdentifier(filename string, allowMissing bool) (string, error) {
+func Identifier(filename string, allowMissing bool) (string, error) {
 	f, err := os.Open(filename)
 	if err != nil {
 		return "", fmt.Errorf("failed to open %s: %w", filename, err)
diff --git a/cmd/symbols_map/elf_test.go b/elf/elf_test.go
similarity index 99%
rename from cmd/symbols_map/elf_test.go
rename to elf/elf_test.go
index a94c87f..a220770 100644
--- a/cmd/symbols_map/elf_test.go
+++ b/elf/elf_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package elf
 
 import (
 	"bytes"
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 7642378..21a18df 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -57,6 +57,7 @@
 	ctx.RegisterModuleType("prebuilt_root_host", PrebuiltRootHostFactory)
 	ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
 	ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
+	ctx.RegisterModuleType("prebuilt_usr_hyphendata", PrebuiltUserHyphenDataFactory)
 	ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
 	ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
 	ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
@@ -71,10 +72,15 @@
 
 type prebuiltEtcProperties struct {
 	// Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax.
+	// Mutually exclusive with srcs.
 	Src *string `android:"path,arch_variant"`
 
+	// Source files of this prebuilt. Can reference a genrule type module with the ":module" syntax.
+	// Mutually exclusive with src. When used, filename_from_src is set to true.
+	Srcs []string `android:"path,arch_variant"`
+
 	// Optional name for the installed file. If unspecified, name of the module is used as the file
-	// name.
+	// name. Only available when using a single source (src).
 	Filename *string `android:"arch_variant"`
 
 	// When set to true, and filename property is not set, the name for the installed file
@@ -127,9 +133,9 @@
 	// Returns the sub install directory relative to BaseDir().
 	SubDir() string
 
-	// Returns an android.OutputPath to the intermeidate file, which is the renamed prebuilt source
+	// Returns an android.OutputPath to the intermediate file, which is the renamed prebuilt source
 	// file.
-	OutputFile() android.OutputPath
+	OutputFiles(tag string) (android.Paths, error)
 }
 
 type PrebuiltEtc struct {
@@ -142,8 +148,8 @@
 	properties       prebuiltEtcProperties
 	subdirProperties prebuiltSubdirProperties
 
-	sourceFilePath android.Path
-	outputFilePath android.OutputPath
+	sourceFilePaths android.Paths
+	outputFilePaths android.OutputPaths
 	// The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share.
 	installDirBase               string
 	installDirBase64             string
@@ -246,6 +252,9 @@
 }
 
 func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path {
+	if len(p.properties.Srcs) > 0 {
+		panic(fmt.Errorf("SourceFilePath not available on multi-source prebuilt %q", p.Name()))
+	}
 	return android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
 }
 
@@ -260,7 +269,10 @@
 }
 
 func (p *PrebuiltEtc) OutputFile() android.OutputPath {
-	return p.outputFilePath
+	if len(p.properties.Srcs) > 0 {
+		panic(fmt.Errorf("OutputFile not available on multi-source prebuilt %q", p.Name()))
+	}
+	return p.outputFilePaths[0]
 }
 
 var _ android.OutputFileProducer = (*PrebuiltEtc)(nil)
@@ -268,7 +280,7 @@
 func (p *PrebuiltEtc) OutputFiles(tag string) (android.Paths, error) {
 	switch tag {
 	case "":
-		return android.Paths{p.outputFilePath}, nil
+		return p.outputFilePaths.Paths(), nil
 	default:
 		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
 	}
@@ -301,50 +313,7 @@
 	return false
 }
 
-func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	filename := proptools.String(p.properties.Filename)
-	filenameFromSrc := proptools.Bool(p.properties.Filename_from_src)
-	if p.properties.Src != nil {
-		p.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
-
-		// Determine the output file basename.
-		// If Filename is set, use the name specified by the property.
-		// If Filename_from_src is set, use the source file name.
-		// Otherwise use the module name.
-		if filename != "" {
-			if filenameFromSrc {
-				ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
-				return
-			}
-		} else if filenameFromSrc {
-			filename = p.sourceFilePath.Base()
-		} else {
-			filename = ctx.ModuleName()
-		}
-	} else if ctx.Config().AllowMissingDependencies() {
-		// If no srcs was set and AllowMissingDependencies is enabled then
-		// mark the module as missing dependencies and set a fake source path
-		// and file name.
-		ctx.AddMissingDependencies([]string{"MISSING_PREBUILT_SRC_FILE"})
-		p.sourceFilePath = android.PathForModuleSrc(ctx)
-		if filename == "" {
-			filename = ctx.ModuleName()
-		}
-	} else {
-		ctx.PropertyErrorf("src", "missing prebuilt source file")
-		return
-	}
-
-	if strings.Contains(filename, "/") {
-		ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
-		return
-	}
-
-	// Check that `sub_dir` and `relative_install_path` are not set at the same time.
-	if p.subdirProperties.Sub_dir != nil && p.subdirProperties.Relative_install_path != nil {
-		ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir")
-	}
-
+func (p *PrebuiltEtc) installBaseDir(ctx android.ModuleContext) string {
 	// If soc install dir was specified and SOC specific is set, set the installDirPath to the
 	// specified socInstallDirBase.
 	installBaseDir := p.installDirBase
@@ -357,47 +326,138 @@
 	if p.installAvoidMultilibConflict && !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
 		installBaseDir = filepath.Join(installBaseDir, ctx.Arch().ArchType.String())
 	}
+	return installBaseDir
+}
 
-	p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir())
+func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	var installs []installProperties
 
-	// Call InstallFile even when uninstallable to make the module included in the package
-	ip := installProperties{
-		installable:    p.Installable(),
-		filename:       filename,
-		sourceFilePath: p.sourceFilePath,
-		symlinks:       p.properties.Symlinks,
+	if p.properties.Src != nil && len(p.properties.Srcs) > 0 {
+		ctx.PropertyErrorf("src", "src is set. Cannot set srcs")
 	}
-	p.addInstallRules(ctx, ip)
+
+	// Check that `sub_dir` and `relative_install_path` are not set at the same time.
+	if p.subdirProperties.Sub_dir != nil && p.subdirProperties.Relative_install_path != nil {
+		ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir")
+	}
+	p.installDirPath = android.PathForModuleInstall(ctx, p.installBaseDir(ctx), p.SubDir())
+
+	filename := proptools.String(p.properties.Filename)
+	filenameFromSrc := proptools.Bool(p.properties.Filename_from_src)
+	if p.properties.Src != nil {
+		p.sourceFilePaths = android.PathsForModuleSrc(ctx, []string{proptools.String(p.properties.Src)})
+		// If the source was not found, set a fake source path to
+		// support AllowMissingDependencies executions.
+		if len(p.sourceFilePaths) == 0 {
+			p.sourceFilePaths = android.Paths{android.PathForModuleSrc(ctx)}
+		}
+
+		// Determine the output file basename.
+		// If Filename is set, use the name specified by the property.
+		// If Filename_from_src is set, use the source file name.
+		// Otherwise use the module name.
+		if filename != "" {
+			if filenameFromSrc {
+				ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
+				return
+			}
+		} else if filenameFromSrc {
+			filename = p.sourceFilePaths[0].Base()
+		} else {
+			filename = ctx.ModuleName()
+		}
+		if strings.Contains(filename, "/") {
+			ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
+			return
+		}
+		p.outputFilePaths = android.OutputPaths{android.PathForModuleOut(ctx, filename).OutputPath}
+
+		ip := installProperties{
+			filename:       filename,
+			sourceFilePath: p.sourceFilePaths[0],
+			outputFilePath: p.outputFilePaths[0],
+			installDirPath: p.installDirPath,
+			symlinks:       p.properties.Symlinks,
+		}
+		installs = append(installs, ip)
+	} else if len(p.properties.Srcs) > 0 {
+		if filename != "" {
+			ctx.PropertyErrorf("filename", "filename cannot be set when using srcs")
+		}
+		if len(p.properties.Symlinks) > 0 {
+			ctx.PropertyErrorf("symlinks", "symlinks cannot be set when using srcs")
+		}
+		if p.properties.Filename_from_src != nil {
+			ctx.PropertyErrorf("filename_from_src", "filename_from_src is implicitly set to true when using srcs")
+		}
+		p.sourceFilePaths = android.PathsForModuleSrc(ctx, p.properties.Srcs)
+		for _, src := range p.sourceFilePaths {
+			filename := src.Base()
+			output := android.PathForModuleOut(ctx, filename).OutputPath
+			ip := installProperties{
+				filename:       filename,
+				sourceFilePath: src,
+				outputFilePath: output,
+				installDirPath: p.installDirPath,
+			}
+			p.outputFilePaths = append(p.outputFilePaths, output)
+			installs = append(installs, ip)
+		}
+	} else if ctx.Config().AllowMissingDependencies() {
+		// If no srcs was set and AllowMissingDependencies is enabled then
+		// mark the module as missing dependencies and set a fake source path
+		// and file name.
+		ctx.AddMissingDependencies([]string{"MISSING_PREBUILT_SRC_FILE"})
+		p.sourceFilePaths = android.Paths{android.PathForModuleSrc(ctx)}
+		if filename == "" {
+			filename = ctx.ModuleName()
+		}
+		p.outputFilePaths = android.OutputPaths{android.PathForModuleOut(ctx, filename).OutputPath}
+		ip := installProperties{
+			filename:       filename,
+			sourceFilePath: p.sourceFilePaths[0],
+			outputFilePath: p.outputFilePaths[0],
+			installDirPath: p.installDirPath,
+		}
+		installs = append(installs, ip)
+	} else {
+		ctx.PropertyErrorf("src", "missing prebuilt source file")
+		return
+	}
+
+	// Call InstallFile even when uninstallable to make the module included in the package.
+	if !p.Installable() {
+		p.SkipInstall()
+	}
+	for _, ip := range installs {
+		ip.addInstallRules(ctx)
+	}
 	android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
 }
 
 type installProperties struct {
-	installable    bool
 	filename       string
 	sourceFilePath android.Path
+	outputFilePath android.OutputPath
+	installDirPath android.InstallPath
 	symlinks       []string
 }
 
 // utility function to add install rules to the build graph.
 // Reduces code duplication between Soong and Mixed build analysis
-func (p *PrebuiltEtc) addInstallRules(ctx android.ModuleContext, ip installProperties) {
-	if !ip.installable {
-		p.SkipInstall()
-	}
-
+func (ip *installProperties) addInstallRules(ctx android.ModuleContext) {
 	// Copy the file from src to a location in out/ with the correct `filename`
 	// This ensures that outputFilePath has the correct name for others to
 	// use, as the source file may have a different name.
-	p.outputFilePath = android.PathForModuleOut(ctx, ip.filename).OutputPath
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   android.Cp,
-		Output: p.outputFilePath,
+		Output: ip.outputFilePath,
 		Input:  ip.sourceFilePath,
 	})
 
-	installPath := ctx.InstallFile(p.installDirPath, ip.filename, p.outputFilePath)
+	installPath := ctx.InstallFile(ip.installDirPath, ip.filename, ip.outputFilePath)
 	for _, sl := range ip.symlinks {
-		ctx.InstallSymlink(p.installDirPath, sl, installPath)
+		ctx.InstallSymlink(ip.installDirPath, sl, installPath)
 	}
 }
 
@@ -421,15 +481,15 @@
 		class = "ETC"
 	}
 
-	return []android.AndroidMkEntries{android.AndroidMkEntries{
+	return []android.AndroidMkEntries{{
 		Class:      class,
 		SubName:    nameSuffix,
-		OutputFile: android.OptionalPathForPath(p.outputFilePath),
+		OutputFile: android.OptionalPathForPath(p.outputFilePaths[0]),
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_TAGS", "optional")
 				entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.String())
-				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
+				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePaths[0].Base())
 				if len(p.properties.Symlinks) > 0 {
 					entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...)
 				}
@@ -552,6 +612,17 @@
 	return module
 }
 
+// prebuilt_usr_hyphendata is for a prebuilt artifact that is installed in
+// <partition>/usr/hyphen-data/<sub_dir> directory.
+func PrebuiltUserHyphenDataFactory() android.Module {
+	module := &PrebuiltEtc{}
+	InitPrebuiltEtcModule(module, "usr/hyphen-data")
+	// This module is device-only
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	android.InitDefaultableModule(module)
+	return module
+}
+
 // prebuilt_font installs a font in <partition>/fonts directory.
 func PrebuiltFontFactory() android.Module {
 	module := &PrebuiltEtc{}
@@ -700,7 +771,11 @@
 		targetArch := "arch-" + m.Target().Arch.ArchType.String()
 
 		snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "etc", m.BaseModuleName())
-		snapshotOutputs = append(snapshotOutputs, copyFile(ctx, m.OutputFile(), snapshotLibOut, s.Fake))
+		outputs, _ := m.OutputFiles("")
+		for _, output := range outputs {
+			cp := copyFile(ctx, output, snapshotLibOut, s.Fake)
+			snapshotOutputs = append(snapshotOutputs, cp)
+		}
 
 		prop := snapshot.SnapshotJsonFlags{}
 		propOut := snapshotLibOut + ".json"
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index df11709..e346bd7 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -96,7 +96,7 @@
 	`)
 
 	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
-	android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePath.Base())
+	android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePaths[0].Base())
 }
 
 func TestPrebuiltEtcGlob(t *testing.T) {
@@ -113,10 +113,24 @@
 	`)
 
 	p := result.Module("my_foo", "android_arm64_armv8-a").(*PrebuiltEtc)
-	android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePath.Base())
+	android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePaths[0].Base())
 
 	p = result.Module("my_bar", "android_arm64_armv8-a").(*PrebuiltEtc)
-	android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePath.Base())
+	android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePaths[0].Base())
+}
+
+func TestPrebuiltEtcMultipleSrcs(t *testing.T) {
+	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+		prebuilt_etc {
+			name: "foo",
+			srcs: ["*.conf"],
+		}
+	`)
+
+	p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
+	android.AssertStringEquals(t, "output file path", "bar.conf", p.outputFilePaths[0].Base())
+	android.AssertStringEquals(t, "output file path", "baz.conf", p.outputFilePaths[1].Base())
+	android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[2].Base())
 }
 
 func TestPrebuiltEtcAndroidMk(t *testing.T) {
@@ -273,6 +287,20 @@
 	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
 }
 
+func TestPrebuiltPrebuiltUserHyphenDataInstallDirPath(t *testing.T) {
+	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+	prebuilt_usr_hyphendata {
+			name: "foo.conf",
+			src: "foo.conf",
+			sub_dir: "bar",
+		}
+	`)
+
+	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+	expected := "out/soong/target/product/test_device/system/usr/hyphen-data/bar"
+	android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+}
+
 func TestPrebuiltFontInstallDirPath(t *testing.T) {
 	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
 		prebuilt_font {
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 64a2e23..efc889c 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -88,6 +88,10 @@
 	// is ext4.
 	Type *string
 
+	// Identifies which partition this is for //visibility:any_system_image (and others) visibility
+	// checks, and will be used in the future for API surface checks.
+	Partition_type *string
+
 	// file_contexts file to make image. Currently, only ext4 is supported.
 	File_contexts *string `android:"path"`
 
@@ -175,6 +179,9 @@
 var pctx = android.NewPackageContext("android/soong/filesystem")
 
 func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if !android.InList(f.PartitionType(), validPartitions) {
+		ctx.PropertyErrorf("partition_type", "partition_type must be one of %s, found: %s", validPartitions, f.PartitionType())
+	}
 	switch f.fsType(ctx) {
 	case ext4Type:
 		f.output = f.buildImageUsingBuildImage(ctx)
@@ -441,6 +448,10 @@
 		Text(android.PathForArbitraryOutput(ctx, stagingDir).String())
 }
 
+func (f *filesystem) PartitionType() string {
+	return proptools.StringDefault(f.properties.Partition_type, "system")
+}
+
 var _ android.AndroidMkEntriesProvider = (*filesystem)(nil)
 
 // Implements android.AndroidMkEntriesProvider
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 6d62746..74c79e3 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -76,6 +76,11 @@
 
 		cc_library {
 			name: "libbar",
+			required: ["libbaz"],
+		}
+
+		cc_library {
+			name: "libbaz",
 		}
 	`)
 
@@ -87,6 +92,7 @@
 		"bin/foo",
 		"lib/libbar.so",
 		"lib64/libbar.so",
+		"lib64/libbaz.so",
 		"etc/bpf/bpf.o",
 	}
 	for _, e := range expected {
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 34f4ffb..5028a49 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -43,6 +43,9 @@
 }
 
 func (s *systemImage) buildExtraFiles(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths {
+	if s.filesystem.properties.Partition_type != nil {
+		ctx.PropertyErrorf("partition_type", "partition_type must be unset on an android_system_image module. It is assumed to be 'system'.")
+	}
 	lc := s.buildLinkerConfigFile(ctx, root)
 	// Add more files if needed
 	return []android.OutputPath{lc}
@@ -53,19 +56,40 @@
 	output := root.Join(ctx, "system", "etc", "linker.config.pb")
 
 	// we need "Module"s for packaging items
-	var otherModules []android.Module
+	modulesInPackageByModule := make(map[android.Module]bool)
+	modulesInPackageByName := make(map[string]bool)
+
 	deps := s.gatherFilteredPackagingSpecs(ctx)
 	ctx.WalkDeps(func(child, parent android.Module) bool {
 		for _, ps := range child.PackagingSpecs() {
 			if _, ok := deps[ps.RelPathInPackage()]; ok {
-				otherModules = append(otherModules, child)
+				modulesInPackageByModule[child] = true
+				modulesInPackageByName[child.Name()] = true
+				return true
 			}
 		}
 		return true
 	})
 
+	provideModules := make([]android.Module, 0, len(modulesInPackageByModule))
+	for mod := range modulesInPackageByModule {
+		provideModules = append(provideModules, mod)
+	}
+
+	var requireModules []android.Module
+	ctx.WalkDeps(func(child, parent android.Module) bool {
+		_, parentInPackage := modulesInPackageByModule[parent]
+		_, childInPackageName := modulesInPackageByName[child.Name()]
+
+		// When parent is in the package, and child (or its variant) is not, this can be from an interface.
+		if parentInPackage && !childInPackageName {
+			requireModules = append(requireModules, child)
+		}
+		return true
+	})
+
 	builder := android.NewRuleBuilder(pctx, ctx)
-	linkerconfig.BuildLinkerConfig(ctx, builder, input, otherModules, output)
+	linkerconfig.BuildLinkerConfig(ctx, builder, input, provideModules, requireModules, output)
 	builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String())
 	return output
 }
diff --git a/genrule/genrule.go b/genrule/genrule.go
index a2a3f75..43f4fe5 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -317,7 +317,17 @@
 						// required relative locations of the tool and its dependencies, use those
 						// instead.  They will be copied to those relative locations in the sbox
 						// sandbox.
-						packagedTools = append(packagedTools, specs...)
+						// Care must be taken since TransitivePackagingSpec may return device-side
+						// paths via the required property. Filter them out.
+						for i, ps := range specs {
+							if ps.Partition() != "" {
+								if i == 0 {
+									panic("first PackagingSpec is assumed to be the host-side tool")
+								}
+								continue
+							}
+							packagedTools = append(packagedTools, ps)
+						}
 						// Assume that the first PackagingSpec of the module is the tool.
 						addLocationLabel(tag.label, packagedToolLocation{specs[0]})
 					} else {
@@ -808,7 +818,7 @@
 
 type genRuleProperties struct {
 	// names of the output files that will be generated
-	Out []string
+	Out []string `android:"arch_variant"`
 }
 
 var Bool = proptools.Bool
diff --git a/java/aar.go b/java/aar.go
index 27dd38b..3ac77fa 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -104,6 +104,9 @@
 
 	// Filter only specified product and ignore other products
 	Filter_product *string `blueprint:"mutated"`
+
+	// Names of aconfig_declarations modules that specify aconfig flags that the module depends on.
+	Flags_packages []string
 }
 
 type aapt struct {
@@ -161,7 +164,9 @@
 }
 
 func (a *aapt) useResourceProcessorBusyBox(ctx android.BaseModuleContext) bool {
-	return BoolDefault(a.aaptProperties.Use_resource_processor, ctx.Config().UseResourceProcessorByDefault())
+	return BoolDefault(a.aaptProperties.Use_resource_processor, ctx.Config().UseResourceProcessorByDefault()) &&
+		// TODO(b/331641946): remove this when ResourceProcessorBusyBox supports generating shared libraries.
+		!slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib")
 }
 
 func (a *aapt) filterProduct() string {
@@ -348,6 +353,7 @@
 	classLoaderContexts            dexpreopt.ClassLoaderContextMap
 	excludedLibs                   []string
 	enforceDefaultTargetSdkVersion bool
+	forceNonFinalResourceIDs       bool
 	extraLinkFlags                 []string
 	aconfigTextFiles               android.Paths
 }
@@ -383,11 +389,6 @@
 	// Add additional manifest files to transitive manifests.
 	additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
 	transitiveManifestPaths := append(android.Paths{manifestPath}, additionalManifests...)
-	// TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import
-	// modules.  Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies
-	// of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of
-	// android_library_import modules.  If this is fixed, staticManifestsDepSet can be dropped completely in favor of
-	// staticResourcesNodesDepSet.manifests()
 	transitiveManifestPaths = append(transitiveManifestPaths, staticManifestsDepSet.ToList()...)
 
 	if len(transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) {
@@ -541,7 +542,8 @@
 
 	if a.useResourceProcessorBusyBox(ctx) {
 		rJar := android.PathForModuleOut(ctx, "busybox/R.jar")
-		resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary, a.aaptProperties.Aaptflags)
+		resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary, a.aaptProperties.Aaptflags,
+			opts.forceNonFinalResourceIDs)
 		aapt2ExtractExtraPackages(ctx, extraPackages, rJar)
 		transitiveRJars = append(transitiveRJars, rJar)
 		a.rJar = rJar
@@ -605,7 +607,8 @@
 // using Bazel's ResourceProcessorBusyBox tool, which is faster than compiling the R.java files and
 // supports producing classes for static dependencies that only include resources from that dependency.
 func resourceProcessorBusyBoxGenerateBinaryR(ctx android.ModuleContext, rTxt, manifest android.Path,
-	rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool, aaptFlags []string) {
+	rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool, aaptFlags []string,
+	forceNonFinalIds bool) {
 
 	var args []string
 	var deps android.Paths
@@ -615,6 +618,9 @@
 		// to ResourceProcessorBusyBox so that it can regenerate R.class files with the final resource IDs for each
 		// package.
 		args, deps = transitiveDeps.resourceProcessorDeps()
+		if forceNonFinalIds {
+			args = append(args, "--finalFields=false")
+		}
 	} else {
 		// When compiling a library don't pass any dependencies as it only needs to generate an R.class file for this
 		// library.  Pass --finalFields=false so that the R.class file contains non-final fields so they don't get
@@ -754,7 +760,8 @@
 	// reverse later.
 	// NOTE: this is legacy and probably incorrect behavior, for most other cases (e.g. conflicting classes in
 	// dependencies) the highest priority dependency is listed first, but for resources the highest priority
-	// dependency has to be listed last.
+	// dependency has to be listed last.  This is also inconsistent with the way manifests from the same
+	// transitive dependencies are merged.
 	staticResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil,
 		android.ReverseSliceInPlace(staticResourcesNodeDepSets))
 	sharedResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil,
@@ -804,6 +811,10 @@
 		a.aapt.deps(ctx, sdkDep)
 	}
 	a.usesLibrary.deps(ctx, false)
+
+	for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
+		ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+	}
 }
 
 func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -817,13 +828,14 @@
 			sdkContext:                     android.SdkContext(a),
 			classLoaderContexts:            a.classLoaderContexts,
 			enforceDefaultTargetSdkVersion: false,
+			aconfigTextFiles:               getAconfigFilePaths(ctx),
 		},
 	)
 
 	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
 	a.hideApexVariantFromMake = !apexInfo.IsForPlatform()
 
-	a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName())
+	a.stem = proptools.StringDefault(a.overridableProperties.Stem, ctx.ModuleName())
 
 	ctx.CheckbuildFile(a.aapt.proguardOptionsFile)
 	ctx.CheckbuildFile(a.aapt.exportPackage)
@@ -964,7 +976,8 @@
 
 	properties AARImportProperties
 
-	classpathFile                      android.WritablePath
+	headerJarFile                      android.WritablePath
+	implementationJarFile              android.WritablePath
 	proguardFlags                      android.WritablePath
 	exportPackage                      android.WritablePath
 	transitiveAaptResourcePackagesFile android.Path
@@ -985,6 +998,9 @@
 	sdkVersion    android.SdkSpec
 	minSdkVersion android.ApiLevel
 
+	usesLibrary
+	classLoaderContexts dexpreopt.ClassLoaderContextMap
+
 	// Single aconfig "cache file" merged from this module and all dependencies.
 	mergedAconfigFiles map[string]android.Paths
 }
@@ -997,7 +1013,7 @@
 	case ".aar":
 		return []android.Path{a.aarPath}, nil
 	case "":
-		return []android.Path{a.classpathFile}, nil
+		return []android.Path{a.implementationJarFile}, nil
 	default:
 		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
 	}
@@ -1080,6 +1096,8 @@
 
 	ctx.AddVariationDependencies(nil, libTag, a.properties.Libs...)
 	ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...)
+
+	a.usesLibrary.deps(ctx, false)
 }
 
 type JniPackageInfo struct {
@@ -1138,27 +1156,33 @@
 	}
 
 	extractedAARDir := android.PathForModuleOut(ctx, "aar")
-	a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar")
+	classpathFile := extractedAARDir.Join(ctx, "classes-combined.jar")
 	a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml")
 	a.rTxt = extractedAARDir.Join(ctx, "R.txt")
 	a.assetsPackage = android.PathForModuleOut(ctx, "assets.zip")
 	a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
+	transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx)
 	android.SetProvider(ctx, ProguardSpecInfoProvider, ProguardSpecInfo{
 		ProguardFlagsFiles: android.NewDepSet[android.Path](
 			android.POSTORDER,
 			android.Paths{a.proguardFlags},
+			transitiveProguardFlags,
+		),
+		UnconditionallyExportedProguardFlags: android.NewDepSet[android.Path](
+			android.POSTORDER,
 			nil,
+			transitiveUnconditionalExportedFlags,
 		),
 	})
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        unzipAAR,
 		Input:       a.aarPath,
-		Outputs:     android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest, a.assetsPackage, a.rTxt},
+		Outputs:     android.WritablePaths{classpathFile, a.proguardFlags, a.manifest, a.assetsPackage, a.rTxt},
 		Description: "unzip AAR",
 		Args: map[string]string{
 			"outDir":             extractedAARDir.String(),
-			"combinedClassesJar": a.classpathFile.String(),
+			"combinedClassesJar": classpathFile.String(),
 			"assetsPackage":      a.assetsPackage.String(),
 		},
 	})
@@ -1213,7 +1237,7 @@
 		linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil, nil)
 
 	a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar")
-	resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true, nil)
+	resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true, nil, false)
 
 	aapt2ExtractExtraPackages(ctx, a.extraAaptPackagesFile, a.rJar)
 
@@ -1231,13 +1255,7 @@
 	a.resourcesNodesDepSet = resourcesNodesDepSetBuilder.Build()
 
 	manifestDepSetBuilder := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(a.manifest)
-	// TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import
-	// modules.  Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies
-	// of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of
-	// android_library_import modules.  If this is fixed, AndroidLibraryDependency.ManifestsDepSet can be dropped
-	// completely in favor of AndroidLibraryDependency.ResourceNodesDepSet.manifest
-	//manifestDepSetBuilder.Transitive(transitiveStaticDeps.manifests)
-	_ = staticManifestsDepSet
+	manifestDepSetBuilder.Transitive(staticManifestsDepSet)
 	a.manifestsDepSet = manifestDepSetBuilder.Build()
 
 	transitiveAaptResourcePackages := staticDeps.resPackages().Strings()
@@ -1249,12 +1267,45 @@
 	a.transitiveAaptResourcePackagesFile = transitiveAaptResourcePackagesFile
 
 	a.collectTransitiveHeaderJars(ctx)
+
+	a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+
+	var staticJars android.Paths
+	var staticHeaderJars android.Paths
+	ctx.VisitDirectDeps(func(module android.Module) {
+		if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+			tag := ctx.OtherModuleDependencyTag(module)
+			switch tag {
+			case staticLibTag:
+				staticJars = append(staticJars, dep.ImplementationJars...)
+				staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
+			}
+		}
+		addCLCFromDep(ctx, module, a.classLoaderContexts)
+	})
+
+	if len(staticJars) > 0 {
+		combineJars := append(android.Paths{classpathFile}, staticJars...)
+		a.implementationJarFile = android.PathForModuleOut(ctx, "combined", ctx.ModuleName()+".jar")
+		TransformJarsToJar(ctx, a.implementationJarFile, "combine", combineJars, android.OptionalPath{}, false, nil, nil)
+	} else {
+		a.implementationJarFile = classpathFile
+	}
+
+	if len(staticHeaderJars) > 0 {
+		combineJars := append(android.Paths{classpathFile}, staticHeaderJars...)
+		a.headerJarFile = android.PathForModuleOut(ctx, "turbine-combined", ctx.ModuleName()+".jar")
+		TransformJarsToJar(ctx, a.headerJarFile, "combine header jars", combineJars, android.OptionalPath{}, false, nil, nil)
+	} else {
+		a.headerJarFile = classpathFile
+	}
+
 	android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
-		HeaderJars:                     android.PathsIfNonNil(a.classpathFile),
+		HeaderJars:                     android.PathsIfNonNil(a.headerJarFile),
 		TransitiveLibsHeaderJars:       a.transitiveLibsHeaderJars,
 		TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
-		ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
-		ImplementationJars:             android.PathsIfNonNil(a.classpathFile),
+		ImplementationAndResourcesJars: android.PathsIfNonNil(a.implementationJarFile),
+		ImplementationJars:             android.PathsIfNonNil(a.implementationJarFile),
 		StubsLinkType:                  Implementation,
 		// TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
 	})
@@ -1287,15 +1338,15 @@
 }
 
 func (a *AARImport) HeaderJars() android.Paths {
-	return android.Paths{a.classpathFile}
+	return android.Paths{a.headerJarFile}
 }
 
 func (a *AARImport) ImplementationAndResourcesJars() android.Paths {
-	return android.Paths{a.classpathFile}
+	return android.Paths{a.implementationJarFile}
 }
 
-func (a *AARImport) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path {
-	return nil
+func (a *AARImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+	return OptionalDexJarPath{}
 }
 
 func (a *AARImport) DexJarInstallPath() android.Path {
@@ -1303,9 +1354,11 @@
 }
 
 func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
-	return nil
+	return a.classLoaderContexts
 }
 
+var _ UsesLibraryDependency = (*AARImport)(nil)
+
 var _ android.ApexModule = (*AARImport)(nil)
 
 // Implements android.ApexModule
@@ -1314,7 +1367,7 @@
 }
 
 // Implements android.ApexModule
-func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+func (a *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
 	sdkVersion android.ApiLevel) error {
 	return nil
 }
@@ -1328,7 +1381,10 @@
 func AARImportFactory() android.Module {
 	module := &AARImport{}
 
-	module.AddProperties(&module.properties)
+	module.AddProperties(
+		&module.properties,
+		&module.usesLibrary.usesLibraryProperties,
+	)
 
 	android.InitPrebuiltModule(module, &module.properties.Aars)
 	android.InitApexModule(module)
diff --git a/java/aar_test.go b/java/aar_test.go
index 4d4e5d0..6bd53f2 100644
--- a/java/aar_test.go
+++ b/java/aar_test.go
@@ -81,3 +81,50 @@
 		})
 	}
 }
+
+func TestLibraryFlagsPackages(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForJavaTest,
+	).RunTestWithBp(t, `
+		android_library {
+			name: "foo",
+			srcs: ["a.java"],
+			sdk_version: "current",
+			flags_packages: [
+				"bar",
+				"baz",
+			],
+		}
+		aconfig_declarations {
+			name: "bar",
+			package: "com.example.package.bar",
+			srcs: [
+				"bar.aconfig",
+			],
+		}
+		aconfig_declarations {
+			name: "baz",
+			package: "com.example.package.baz",
+			srcs: [
+				"baz.aconfig",
+			],
+		}
+	`)
+
+	foo := result.ModuleForTests("foo", "android_common")
+
+	// android_library module depends on aconfig_declarations listed in flags_packages
+	android.AssertBoolEquals(t, "foo expected to depend on bar", true,
+		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"))
+
+	android.AssertBoolEquals(t, "foo expected to depend on baz", true,
+		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "baz"))
+
+	aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
+	linkInFlags := aapt2LinkRule.Args["inFlags"]
+	android.AssertStringDoesContain(t,
+		"aapt2 link command expected to pass feature flags arguments",
+		linkInFlags,
+		"--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+	)
+}
diff --git a/java/android_manifest_test.go b/java/android_manifest_test.go
index 5909b1e..7c91884 100644
--- a/java/android_manifest_test.go
+++ b/java/android_manifest_test.go
@@ -92,10 +92,9 @@
 			"out/soong/.intermediates/transitive/android_common/manifest_fixer/AndroidManifest.xml",
 			"transitive/AndroidManifest2.xml",
 			"out/soong/.intermediates/transitive_import/android_common/aar/AndroidManifest.xml",
+			"out/soong/.intermediates/transitive_import_dep/android_common/aar/AndroidManifest.xml",
 			"out/soong/.intermediates/direct_import/android_common/aar/AndroidManifest.xml",
-			// TODO(b/288358614): Soong has historically not merged manifests from dependencies of
-			// android_library_import modules.
-
+			"out/soong/.intermediates/direct_import_dep/android_common/aar/AndroidManifest.xml",
 		},
 		manifestMergerRule.Implicits)
 }
diff --git a/java/androidmk.go b/java/androidmk.go
index 498962f..a52d439 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -211,7 +211,7 @@
 	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:        "JAVA_LIBRARIES",
 		OverrideName: prebuilt.BaseModuleName(),
-		OutputFile:   android.OptionalPathForPath(prebuilt.combinedClasspathFile),
+		OutputFile:   android.OptionalPathForPath(prebuilt.combinedImplementationFile),
 		Include:      "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
@@ -219,8 +219,8 @@
 				if prebuilt.dexJarFile.IsSet() {
 					entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile.Path())
 				}
-				entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile)
-				entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
+				entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedHeaderFile)
+				entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedImplementationFile)
 				entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion.String())
 				entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
 				// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
@@ -262,13 +262,13 @@
 	}
 	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "JAVA_LIBRARIES",
-		OutputFile: android.OptionalPathForPath(prebuilt.classpathFile),
+		OutputFile: android.OptionalPathForPath(prebuilt.implementationJarFile),
 		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
-				entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.classpathFile)
-				entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.classpathFile)
+				entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.headerJarFile)
+				entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.implementationJarFile)
 				entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", prebuilt.exportPackage)
 				entries.SetPath("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", prebuilt.transitiveAaptResourcePackagesFile)
 				entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", prebuilt.proguardFlags)
diff --git a/java/app.go b/java/app.go
index 57d3490..7b25775 100755
--- a/java/app.go
+++ b/java/app.go
@@ -169,9 +169,6 @@
 	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
 	// from PRODUCT_PACKAGES.
 	Overrides []string
-
-	// Names of aconfig_declarations modules that specify aconfig flags that the app depends on.
-	Flags_packages []string
 }
 
 type AndroidApp struct {
@@ -290,6 +287,10 @@
 	}
 
 	a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
+
+	for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
+		ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+	}
 }
 
 func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -317,10 +318,6 @@
 				`must be names of android_app_certificate modules in the form ":module"`)
 		}
 	}
-
-	for _, aconfig_declaration := range a.overridableAppProperties.Flags_packages {
-		ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
-	}
 }
 
 func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -457,6 +454,21 @@
 	return proptools.BoolDefault(a.overridableAppProperties.Rename_resources_package, true)
 }
 
+func getAconfigFilePaths(ctx android.ModuleContext) (aconfigTextFilePaths android.Paths) {
+	ctx.VisitDirectDepsWithTag(aconfigDeclarationTag, func(dep android.Module) {
+		if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
+			aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath)
+		} else {
+			ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
+				"flags_packages property, but %s is not aconfig_declarations module type",
+				dep.Name(),
+			)
+		}
+	})
+
+	return aconfigTextFilePaths
+}
+
 func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
 	usePlatformAPI := proptools.Bool(a.Module.deviceProperties.Platform_apis)
 	if ctx.Module().(android.SdkContext).SdkVersion(ctx).Kind == android.SdkModule {
@@ -507,26 +519,17 @@
 		a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion
 	}
 
-	var aconfigTextFilePaths android.Paths
-	ctx.VisitDirectDepsWithTag(aconfigDeclarationTag, func(dep android.Module) {
-		if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
-			aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath)
-		} else {
-			ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
-				"flags_packages property, but %s is not aconfig_declarations module type",
-				dep.Name(),
-			)
-		}
-	})
-
+	// Use non final ids if we are doing optimized shrinking and are using R8.
+	nonFinalIds := Bool(a.dexProperties.Optimize.Optimized_shrink_resources) && a.dexer.effectiveOptimizeEnabled()
 	a.aapt.buildActions(ctx,
 		aaptBuildActionOptions{
 			sdkContext:                     android.SdkContext(a),
 			classLoaderContexts:            a.classLoaderContexts,
 			excludedLibs:                   a.usesLibraryProperties.Exclude_uses_libs,
 			enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(),
+			forceNonFinalResourceIDs:       nonFinalIds,
 			extraLinkFlags:                 aaptLinkFlags,
-			aconfigTextFiles:               aconfigTextFilePaths,
+			aconfigTextFiles:               getAconfigFilePaths(ctx),
 		},
 	)
 
@@ -547,7 +550,13 @@
 	staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
 
 	a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...)
-	a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile)
+	if !Bool(a.dexProperties.Optimize.Optimized_shrink_resources) {
+		// When using the optimized shrinking the R8 enqueuer will traverse the xml files that become
+		// live for code references and (transitively) mark these as live.
+		// In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now
+		// dead code alive)
+		a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile)
+	}
 }
 
 func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath {
@@ -580,7 +589,7 @@
 	var packageResources = a.exportPackage
 
 	if ctx.ModuleName() != "framework-res" {
-		if Bool(a.dexProperties.Optimize.Shrink_resources) {
+		if a.dexProperties.resourceShrinkingEnabled() {
 			protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk")
 			aapt2Convert(ctx, protoFile, packageResources, "proto")
 			a.dexer.resourcesInput = android.OptionalPathForPath(protoFile)
@@ -603,7 +612,7 @@
 		}
 
 		a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
-		if Bool(a.dexProperties.Optimize.Shrink_resources) {
+		if a.dexProperties.resourceShrinkingEnabled() {
 			binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk")
 			aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary")
 			packageResources = binaryResources
@@ -755,7 +764,7 @@
 
 	// Unlike installApkName, a.stem should respect base module name for override_android_app.
 	// Therefore, use ctx.ModuleName() instead of a.Name().
-	a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName())
+	a.stem = proptools.StringDefault(a.overridableProperties.Stem, ctx.ModuleName())
 
 	// Check if the install APK name needs to be overridden.
 	// Both android_app and override_android_app module are expected to possess
@@ -763,7 +772,7 @@
 	// from the base module. Therefore, use a.Name() which represents
 	// the module name for both android_app and override_android_app.
 	a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(
-		proptools.StringDefault(a.overridableDeviceProperties.Stem, a.Name()))
+		proptools.StringDefault(a.overridableProperties.Stem, a.Name()))
 
 	if ctx.ModuleName() == "framework-res" {
 		// framework-res.apk is installed as system/framework/framework-res.apk
@@ -1509,7 +1518,7 @@
 func OverrideAndroidAppModuleFactory() android.Module {
 	m := &OverrideAndroidApp{}
 	m.AddProperties(
-		&OverridableDeviceProperties{},
+		&OverridableProperties{},
 		&overridableAppProperties{},
 	)
 
diff --git a/java/app_test.go b/java/app_test.go
index 5d7b048..8262777 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -829,12 +829,12 @@
 				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
 				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
 				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
 			},
 			appCombined: []string{
 				"out/soong/.intermediates/app/android_common/javac/app.jar",
 				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
 			},
 
 			directResources: nil,
@@ -849,12 +849,12 @@
 			directClasspath: []string{
 				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
 				"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
-				"out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
 			},
 			directCombined: []string{
 				"out/soong/.intermediates/direct/android_common/javac/direct.jar",
 				"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
-				"out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
 			},
 
 			transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
@@ -928,13 +928,13 @@
 				"out/soong/.intermediates/app/android_common/busybox/R.jar",
 				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
 				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
 			},
 			appCombined: []string{
 				"out/soong/.intermediates/app/android_common/javac/app.jar",
 				"out/soong/.intermediates/app/android_common/busybox/R.jar",
 				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
 			},
 
 			directResources: nil,
@@ -953,12 +953,12 @@
 				"out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
 				"out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
 				"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
-				"out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
 			},
 			directCombined: []string{
 				"out/soong/.intermediates/direct/android_common/javac/direct.jar",
 				"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
-				"out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
 			},
 
 			transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
@@ -1034,13 +1034,13 @@
 				"out/soong/.intermediates/app/android_common/busybox/R.jar",
 				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
 				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
 			},
 			appCombined: []string{
 				"out/soong/.intermediates/app/android_common/javac/app.jar",
 				"out/soong/.intermediates/app/android_common/busybox/R.jar",
 				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
 			},
 
 			dontVerifyDirect:           true,
@@ -1075,12 +1075,12 @@
 				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
 				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
 				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
 			},
 			appCombined: []string{
 				"out/soong/.intermediates/app/android_common/javac/app.jar",
 				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
 			},
 
 			directResources: nil,
@@ -1098,12 +1098,12 @@
 				"out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
 				"out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
 				"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
-				"out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
 			},
 			directCombined: []string{
 				"out/soong/.intermediates/direct/android_common/javac/direct.jar",
 				"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
-				"out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
 			},
 
 			dontVerifyTransitive:       true,
@@ -1137,12 +1137,12 @@
 				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
 				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
 				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
 			},
 			appCombined: []string{
 				"out/soong/.intermediates/app/android_common/javac/app.jar",
 				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
-				"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
 			},
 
 			directResources: nil,
@@ -1157,12 +1157,12 @@
 			directClasspath: []string{
 				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
 				"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
-				"out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
 			},
 			directCombined: []string{
 				"out/soong/.intermediates/direct/android_common/javac/direct.jar",
 				"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
-				"out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+				"out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
 			},
 
 			transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
@@ -3625,7 +3625,10 @@
 		android_app {
 			name: "foo",
 			sdk_version: "current",
-			static_libs: ["lib1"],
+			static_libs: [
+				"lib1",
+				"lib3",
+			],
 		}
 
 		android_library {
@@ -3633,22 +3636,49 @@
 			sdk_version: "current",
 			optimize: {
 				proguard_flags_files: ["lib1proguard.cfg"],
+			},
+			static_libs: ["lib2"],
+		}
+
+		android_library {
+			name: "lib2",
+			sdk_version: "current",
+			optimize: {
+				proguard_flags_files: ["lib2proguard.cfg"],
 			}
 		}
+
+		android_library_import {
+			name: "lib3",
+			sdk_version: "current",
+			aars: ["lib3.aar"],
+			static_libs: ["lib4"],
+		}
+
+		android_library {
+			name: "lib4",
+			sdk_version: "current",
+			optimize: {
+				proguard_flags_files: ["lib4proguard.cfg"],
+			}
+		}
+
+
 	`)
 
 	m := ctx.ModuleForTests("foo", "android_common")
-	hasLib1Proguard := false
-	for _, s := range m.Rule("java.r8").Implicits.Strings() {
-		if s == "lib1proguard.cfg" {
-			hasLib1Proguard = true
-			break
-		}
-	}
+	r8 := m.Rule("java.r8")
+	implicits := r8.Implicits.RelativeToTop().Strings()
+	android.AssertStringListContains(t, "r8 implicits", implicits, "lib1proguard.cfg")
+	android.AssertStringListContains(t, "r8 implicits", implicits, "lib2proguard.cfg")
+	android.AssertStringListContains(t, "r8 implicits", implicits, "lib4proguard.cfg")
+	android.AssertStringListContains(t, "r8 implicits", implicits, "out/soong/.intermediates/lib3/android_common/aar/proguard.txt")
 
-	if !hasLib1Proguard {
-		t.Errorf("App does not use library proguard config")
-	}
+	flags := r8.Args["r8Flags"]
+	android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib1proguard.cfg")
+	android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib2proguard.cfg")
+	android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib4proguard.cfg")
+	android.AssertStringDoesContain(t, "r8 flags", flags, "-include out/soong/.intermediates/lib3/android_common/aar/proguard.txt")
 }
 
 func TestTargetSdkVersionManifestFixer(t *testing.T) {
@@ -4401,3 +4431,20 @@
 	dexpreopt := result.ModuleForTests("app", "android_common").MaybeRule("dexpreopt").Rule
 	android.AssertBoolEquals(t, "dexpreopt should be disabled if optional_uses_libs does not have an implementation", true, dexpreopt == nil)
 }
+
+func TestAppStem(t *testing.T) {
+	ctx := testApp(t, `
+				android_app {
+					name: "foo",
+					srcs: ["a.java"],
+					stem: "foo-new",
+					sdk_version: "current",
+				}`)
+
+	foo := ctx.ModuleForTests("foo", "android_common")
+
+	outputs := fmt.Sprint(foo.AllOutputs())
+	if !strings.Contains(outputs, "foo-new.apk") {
+		t.Errorf("Module output does not contain expected apk %s", "foo-new.apk")
+	}
+}
diff --git a/java/base.go b/java/base.go
index 69f88be..9bb133d 100644
--- a/java/base.go
+++ b/java/base.go
@@ -305,8 +305,8 @@
 	HiddenAPIFlagFileProperties
 }
 
-// Device properties that can be overridden by overriding module (e.g. override_android_app)
-type OverridableDeviceProperties struct {
+// Properties that can be overridden by overriding module (e.g. override_android_app)
+type OverridableProperties struct {
 	// set the name of the output. If not set, `name` is used.
 	// To override a module with this property set, overriding module might need to set this as well.
 	// Otherwise, both the overridden and the overriding modules will have the same output name, which
@@ -434,7 +434,7 @@
 	protoProperties  android.ProtoProperties
 	deviceProperties DeviceProperties
 
-	overridableDeviceProperties OverridableDeviceProperties
+	overridableProperties OverridableProperties
 
 	// jar file containing header classes including static library dependencies, suitable for
 	// inserting into the bootclasspath/classpath of another compile
@@ -616,6 +616,7 @@
 func (j *Module) addHostProperties() {
 	j.AddProperties(
 		&j.properties,
+		&j.overridableProperties,
 		&j.protoProperties,
 		&j.usesLibraryProperties,
 	)
@@ -625,7 +626,6 @@
 	j.addHostProperties()
 	j.AddProperties(
 		&j.deviceProperties,
-		&j.overridableDeviceProperties,
 		&j.dexer.dexProperties,
 		&j.dexpreoptProperties,
 		&j.linter.properties,
@@ -804,7 +804,7 @@
 	// Add dependency on libraries that provide additional hidden api annotations.
 	ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
 
-	if ctx.DeviceConfig().VndkVersion() != "" && ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
+	if ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
 		// Require java_sdk_library at inter-partition java dependency to ensure stable
 		// interface between partitions. If inter-partition java_library dependency is detected,
 		// raise build error because java_library doesn't have a stable interface.
@@ -1219,14 +1219,15 @@
 		}
 
 		android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
-			HeaderJars:                     android.PathsIfNonNil(j.headerJarFile),
-			TransitiveLibsHeaderJars:       j.transitiveLibsHeaderJars,
-			TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
-			AidlIncludeDirs:                j.exportAidlIncludeDirs,
-			ExportedPlugins:                j.exportedPluginJars,
-			ExportedPluginClasses:          j.exportedPluginClasses,
-			ExportedPluginDisableTurbine:   j.exportedDisableTurbine,
-			StubsLinkType:                  j.stubsLinkType,
+			HeaderJars:                          android.PathsIfNonNil(j.headerJarFile),
+			TransitiveLibsHeaderJars:            j.transitiveLibsHeaderJars,
+			TransitiveStaticLibsHeaderJars:      j.transitiveStaticLibsHeaderJars,
+			AidlIncludeDirs:                     j.exportAidlIncludeDirs,
+			ExportedPlugins:                     j.exportedPluginJars,
+			ExportedPluginClasses:               j.exportedPluginClasses,
+			ExportedPluginDisableTurbine:        j.exportedDisableTurbine,
+			StubsLinkType:                       j.stubsLinkType,
+			AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
 		})
 
 		j.outputFile = j.headerJarFile
@@ -1729,22 +1730,23 @@
 	android.CollectDependencyAconfigFiles(ctx, &j.mergedAconfigFiles)
 
 	android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
-		HeaderJars:                     android.PathsIfNonNil(j.headerJarFile),
-		RepackagedHeaderJars:           android.PathsIfNonNil(j.repackagedHeaderJarFile),
-		TransitiveLibsHeaderJars:       j.transitiveLibsHeaderJars,
-		TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
-		ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
-		ImplementationJars:             android.PathsIfNonNil(j.implementationJarFile),
-		ResourceJars:                   android.PathsIfNonNil(j.resourceJar),
-		AidlIncludeDirs:                j.exportAidlIncludeDirs,
-		SrcJarArgs:                     j.srcJarArgs,
-		SrcJarDeps:                     j.srcJarDeps,
-		TransitiveSrcFiles:             j.transitiveSrcFiles,
-		ExportedPlugins:                j.exportedPluginJars,
-		ExportedPluginClasses:          j.exportedPluginClasses,
-		ExportedPluginDisableTurbine:   j.exportedDisableTurbine,
-		JacocoReportClassesFile:        j.jacocoReportClassesFile,
-		StubsLinkType:                  j.stubsLinkType,
+		HeaderJars:                          android.PathsIfNonNil(j.headerJarFile),
+		RepackagedHeaderJars:                android.PathsIfNonNil(j.repackagedHeaderJarFile),
+		TransitiveLibsHeaderJars:            j.transitiveLibsHeaderJars,
+		TransitiveStaticLibsHeaderJars:      j.transitiveStaticLibsHeaderJars,
+		ImplementationAndResourcesJars:      android.PathsIfNonNil(j.implementationAndResourcesJar),
+		ImplementationJars:                  android.PathsIfNonNil(j.implementationJarFile),
+		ResourceJars:                        android.PathsIfNonNil(j.resourceJar),
+		AidlIncludeDirs:                     j.exportAidlIncludeDirs,
+		SrcJarArgs:                          j.srcJarArgs,
+		SrcJarDeps:                          j.srcJarDeps,
+		TransitiveSrcFiles:                  j.transitiveSrcFiles,
+		ExportedPlugins:                     j.exportedPluginJars,
+		ExportedPluginClasses:               j.exportedPluginClasses,
+		ExportedPluginDisableTurbine:        j.exportedDisableTurbine,
+		JacocoReportClassesFile:             j.jacocoReportClassesFile,
+		StubsLinkType:                       j.stubsLinkType,
+		AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
 	})
 
 	// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
@@ -1755,10 +1757,7 @@
 	return android.InList("androidx.compose.runtime_runtime", j.properties.Static_libs)
 }
 
-func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo {
-	transitiveUnconditionalExportedFlags := []*android.DepSet[android.Path]{}
-	transitiveProguardFlags := []*android.DepSet[android.Path]{}
-
+func collectDepProguardSpecInfo(ctx android.ModuleContext) (transitiveProguardFlags, transitiveUnconditionalExportedFlags []*android.DepSet[android.Path]) {
 	ctx.VisitDirectDeps(func(m android.Module) {
 		depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
 		depTag := ctx.OtherModuleDependencyTag(m)
@@ -1773,6 +1772,12 @@
 		}
 	})
 
+	return transitiveProguardFlags, transitiveUnconditionalExportedFlags
+}
+
+func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo {
+	transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx)
+
 	directUnconditionalExportedFlags := android.Paths{}
 	proguardFlagsForThisModule := android.PathsForModuleSrc(ctx, j.dexProperties.Optimize.Proguard_flags_files)
 	exportUnconditionally := proptools.Bool(j.dexProperties.Optimize.Export_proguard_flags_files)
@@ -2295,6 +2300,7 @@
 				// annotation processor that generates API is incompatible with the turbine
 				// optimization.
 				deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
+				deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
 			case pluginTag:
 				if plugin, ok := module.(*Plugin); ok {
 					if plugin.pluginProperties.Processor_class != nil {
@@ -2353,6 +2359,8 @@
 				deps.staticJars = append(deps.staticJars, dep.Srcs()...)
 				deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
 			}
+		} else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok {
+			deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
 		} else {
 			switch tag {
 			case bootClasspathTag:
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 7c45d30..cc3da76 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -77,7 +77,7 @@
 		return javaSdkLibrarySdkMemberType
 	}
 
-	return javaBootLibsSdkMemberType
+	return JavaBootLibsSdkMemberType
 }
 
 func (b bootclasspathFragmentContentDependencyTag) ExportMember() bool {
diff --git a/java/dex.go b/java/dex.go
index 4474c63..6caaa7f 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -66,6 +66,12 @@
 		// If true, optimize for size by removing unused resources. Defaults to false.
 		Shrink_resources *bool
 
+		// If true, use optimized resource shrinking in R8, overriding the
+		// Shrink_resources setting. Defaults to false.
+		// Optimized shrinking means that R8 will trace and treeshake resources together with code
+		// and apply additional optimizations. This implies non final fields in the R classes.
+		Optimized_shrink_resources *bool
+
 		// Flags to pass to proguard.
 		Proguard_flags []string
 
@@ -105,6 +111,10 @@
 	return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
 }
 
+func (d *DexProperties) resourceShrinkingEnabled() bool {
+	return BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources))
+}
+
 var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
 	blueprint.RuleParams{
 		Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -351,10 +361,14 @@
 		r8Flags = append(r8Flags, "-ignorewarnings")
 	}
 
+	// resourcesInput is empty when we don't use resource shrinking, if on, pass these to R8
 	if d.resourcesInput.Valid() {
 		r8Flags = append(r8Flags, "--resource-input", d.resourcesInput.Path().String())
 		r8Deps = append(r8Deps, d.resourcesInput.Path())
 		r8Flags = append(r8Flags, "--resource-output", d.resourcesOutput.Path().String())
+		if Bool(opt.Optimized_shrink_resources) {
+			r8Flags = append(r8Flags, "--optimized-resource-shrinking")
+		}
 	}
 
 	return r8Flags, r8Deps
diff --git a/java/java.go b/java/java.go
index d5a85f7..c5bdf9d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -21,6 +21,7 @@
 import (
 	"fmt"
 	"path/filepath"
+	"slices"
 	"sort"
 	"strings"
 
@@ -82,8 +83,8 @@
 	// Register sdk member types.
 	android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
 	android.RegisterSdkMemberType(javaLibsSdkMemberType)
-	android.RegisterSdkMemberType(javaBootLibsSdkMemberType)
-	android.RegisterSdkMemberType(javaSystemserverLibsSdkMemberType)
+	android.RegisterSdkMemberType(JavaBootLibsSdkMemberType)
+	android.RegisterSdkMemberType(JavaSystemserverLibsSdkMemberType)
 	android.RegisterSdkMemberType(javaTestSdkMemberType)
 }
 
@@ -154,7 +155,7 @@
 	// either java_libs, or java_header_libs would end up exporting more information than was strictly
 	// necessary. The java_boot_libs property to allow those modules to be exported as part of the
 	// sdk/module_exports without exposing any unnecessary information.
-	javaBootLibsSdkMemberType = &librarySdkMemberType{
+	JavaBootLibsSdkMemberType = &librarySdkMemberType{
 		android.SdkMemberTypeBase{
 			PropertyName: "java_boot_libs",
 			SupportsSdk:  true,
@@ -193,7 +194,7 @@
 	// either java_libs, or java_header_libs would end up exporting more information than was strictly
 	// necessary. The java_systemserver_libs property to allow those modules to be exported as part of
 	// the sdk/module_exports without exposing any unnecessary information.
-	javaSystemserverLibsSdkMemberType = &librarySdkMemberType{
+	JavaSystemserverLibsSdkMemberType = &librarySdkMemberType{
 		android.SdkMemberTypeBase{
 			PropertyName: "java_systemserver_libs",
 			SupportsSdk:  true,
@@ -309,6 +310,10 @@
 	// implementation jars. If the provider is set by java_sdk_library, the link type is "unknown"
 	// and selection between the stub jar vs implementation jar is deferred to SdkLibrary.sdkJars(...)
 	StubsLinkType StubsLinkType
+
+	// AconfigIntermediateCacheOutputPaths is a path to the cache files collected from the
+	// java_aconfig_library modules that are statically linked to this module.
+	AconfigIntermediateCacheOutputPaths android.Paths
 }
 
 var JavaInfoProvider = blueprint.NewProvider[JavaInfo]()
@@ -897,7 +902,7 @@
 		}
 	}
 
-	j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
+	j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
 
 	proguardSpecInfo := j.collectProguardSpecInfo(ctx)
 	android.SetProvider(ctx, ProguardSpecInfoProvider, proguardSpecInfo)
@@ -1702,7 +1707,7 @@
 }
 
 func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
+	j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
 
 	if ctx.Arch().ArchType == android.Common {
 		// Compile the jar
@@ -2341,6 +2346,9 @@
 	// List of shared java libs that this module has dependencies to
 	Libs []string
 
+	// List of static java libs that this module has dependencies to
+	Static_libs []string
+
 	// List of files to remove from the jar file(s)
 	Exclude_files []string
 
@@ -2393,9 +2401,10 @@
 	dexJarFileErr     error
 	dexJarInstallFile android.Path
 
-	combinedClasspathFile android.Path
-	classLoaderContexts   dexpreopt.ClassLoaderContextMap
-	exportAidlIncludeDirs android.Paths
+	combinedImplementationFile android.Path
+	combinedHeaderFile         android.Path
+	classLoaderContexts        dexpreopt.ClassLoaderContextMap
+	exportAidlIncludeDirs      android.Paths
 
 	hideApexVariantFromMake bool
 
@@ -2479,6 +2488,7 @@
 
 func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
 	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+	ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
 
 	if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
 		sdkDeps(ctx, android.SdkContext(j), j.dexer)
@@ -2508,23 +2518,13 @@
 func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	j.commonBuildActions(ctx)
 
-	jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
-
-	jarName := j.Stem() + ".jar"
-	outputFile := android.PathForModuleOut(ctx, "combined", jarName)
-	TransformJarsToJar(ctx, outputFile, "for prebuilts", jars, android.OptionalPath{},
-		false, j.properties.Exclude_files, j.properties.Exclude_dirs)
-	if Bool(j.properties.Jetifier) {
-		inputFile := outputFile
-		outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
-		TransformJetifier(ctx, outputFile, inputFile)
-	}
-	j.combinedClasspathFile = outputFile
 	j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
 
 	var flags javaBuilderFlags
 
 	j.collectTransitiveHeaderJars(ctx)
+	var staticJars android.Paths
+	var staticHeaderJars android.Paths
 	ctx.VisitDirectDeps(func(module android.Module) {
 		tag := ctx.OtherModuleDependencyTag(module)
 		if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
@@ -2534,6 +2534,8 @@
 				flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
 			case staticLibTag:
 				flags.classpath = append(flags.classpath, dep.HeaderJars...)
+				staticJars = append(staticJars, dep.ImplementationAndResourcesJars...)
+				staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
 			case bootClasspathTag:
 				flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...)
 			}
@@ -2547,6 +2549,46 @@
 		addCLCFromDep(ctx, module, j.classLoaderContexts)
 	})
 
+	jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
+	jarName := j.Stem() + ".jar"
+
+	// Always pass the input jars to TransformJarsToJar, even if there is only a single jar, we need the output
+	// file of the module to be named jarName.
+	outputFile := android.PathForModuleOut(ctx, "combined", jarName)
+	implementationJars := append(slices.Clone(jars), staticJars...)
+	TransformJarsToJar(ctx, outputFile, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{},
+		false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+
+	// If no dependencies have separate header jars then there is no need to create a separate
+	// header jar for this module.
+	reuseImplementationJarAsHeaderJar := slices.Equal(staticJars, staticHeaderJars)
+
+	var headerOutputFile android.WritablePath
+	if reuseImplementationJarAsHeaderJar {
+		headerOutputFile = outputFile
+	} else {
+		headerJars := append(slices.Clone(jars), staticHeaderJars...)
+		headerOutputFile = android.PathForModuleOut(ctx, "turbine-combined", jarName)
+		TransformJarsToJar(ctx, headerOutputFile, "combine prebuilt header jars", headerJars, android.OptionalPath{},
+			false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+	}
+
+	if Bool(j.properties.Jetifier) {
+		inputFile := outputFile
+		outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
+		TransformJetifier(ctx, outputFile, inputFile)
+
+		if !reuseImplementationJarAsHeaderJar {
+			headerInputFile := headerOutputFile
+			headerOutputFile = android.PathForModuleOut(ctx, "jetifier-headers", jarName)
+			TransformJetifier(ctx, headerOutputFile, headerInputFile)
+		} else {
+			headerOutputFile = outputFile
+		}
+	}
+	j.combinedHeaderFile = headerOutputFile
+	j.combinedImplementationFile = outputFile
+
 	j.maybeInstall(ctx, jarName, outputFile)
 
 	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
@@ -2630,11 +2672,11 @@
 	}
 
 	android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
-		HeaderJars:                     android.PathsIfNonNil(j.combinedClasspathFile),
+		HeaderJars:                     android.PathsIfNonNil(j.combinedHeaderFile),
 		TransitiveLibsHeaderJars:       j.transitiveLibsHeaderJars,
 		TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
-		ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile),
-		ImplementationJars:             android.PathsIfNonNil(j.combinedClasspathFile),
+		ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedImplementationFile),
+		ImplementationJars:             android.PathsIfNonNil(j.combinedImplementationFile),
 		AidlIncludeDirs:                j.exportAidlIncludeDirs,
 		StubsLinkType:                  j.stubsLinkType,
 		// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
@@ -2662,7 +2704,7 @@
 func (j *Import) OutputFiles(tag string) (android.Paths, error) {
 	switch tag {
 	case "", ".jar":
-		return android.Paths{j.combinedClasspathFile}, nil
+		return android.Paths{j.combinedImplementationFile}, nil
 	default:
 		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
 	}
@@ -2671,17 +2713,11 @@
 var _ android.OutputFileProducer = (*Import)(nil)
 
 func (j *Import) HeaderJars() android.Paths {
-	if j.combinedClasspathFile == nil {
-		return nil
-	}
-	return android.Paths{j.combinedClasspathFile}
+	return android.PathsIfNonNil(j.combinedHeaderFile)
 }
 
 func (j *Import) ImplementationAndResourcesJars() android.Paths {
-	if j.combinedClasspathFile == nil {
-		return nil
-	}
-	return android.Paths{j.combinedClasspathFile}
+	return android.PathsIfNonNil(j.combinedImplementationFile)
 }
 
 func (j *Import) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
@@ -3013,7 +3049,7 @@
 	module.AddProperties(
 		&CommonProperties{},
 		&DeviceProperties{},
-		&OverridableDeviceProperties{},
+		&OverridableProperties{},
 		&DexProperties{},
 		&DexpreoptProperties{},
 		&android.ProtoProperties{},
diff --git a/java/java_test.go b/java/java_test.go
index 9a4f085..2676aa5 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -588,10 +588,11 @@
 	javac := fooModule.Rule("javac")
 	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
 	barModule := ctx.ModuleForTests("bar", "android_common")
-	barJar := barModule.Rule("combineJar").Output
+	barJar := barModule.Output("combined/bar.jar").Output
 	bazModule := ctx.ModuleForTests("baz", "android_common")
 	bazJar := bazModule.Rule("combineJar").Output
-	sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output
+	sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").
+		Output("combined/sdklib.stubs.jar").Output
 
 	fooLibrary := fooModule.Module().(*Library)
 	assertDeepEquals(t, "foo unique sources incorrect",
@@ -1035,7 +1036,7 @@
 	}
 }
 
-func TestJavaLibrary(t *testing.T) {
+func TestJavaLibraryOutputFiles(t *testing.T) {
 	testJavaWithFS(t, "", map[string][]byte{
 		"libcore/Android.bp": []byte(`
 				java_library {
@@ -1052,7 +1053,7 @@
 	})
 }
 
-func TestJavaImport(t *testing.T) {
+func TestJavaImportOutputFiles(t *testing.T) {
 	testJavaWithFS(t, "", map[string][]byte{
 		"libcore/Android.bp": []byte(`
 				java_import {
@@ -1068,6 +1069,85 @@
 	})
 }
 
+func TestJavaImport(t *testing.T) {
+	bp := `
+		java_library {
+			name: "source_library",
+			srcs: ["source.java"],
+		}
+
+		java_import {
+			name: "import_with_no_deps",
+			jars: ["no_deps.jar"],
+		}
+
+		java_import {
+			name: "import_with_source_deps",
+			jars: ["source_deps.jar"],
+			static_libs: ["source_library"],
+		}
+
+		java_import {
+			name: "import_with_import_deps",
+			jars: ["import_deps.jar"],
+			static_libs: ["import_with_no_deps"],
+		}
+	`
+	ctx := android.GroupFixturePreparers(
+		PrepareForTestWithJavaDefaultModules,
+	).RunTestWithBp(t, bp)
+
+	source := ctx.ModuleForTests("source_library", "android_common")
+	sourceJar := source.Output("javac/source_library.jar")
+	sourceHeaderJar := source.Output("turbine-combined/source_library.jar")
+	sourceJavaInfo, _ := android.SingletonModuleProvider(ctx, source.Module(), JavaInfoProvider)
+
+	// The source library produces separate implementation and header jars
+	android.AssertPathsRelativeToTopEquals(t, "source library implementation jar",
+		[]string{sourceJar.Output.String()}, sourceJavaInfo.ImplementationAndResourcesJars)
+	android.AssertPathsRelativeToTopEquals(t, "source library header jar",
+		[]string{sourceHeaderJar.Output.String()}, sourceJavaInfo.HeaderJars)
+
+	importWithNoDeps := ctx.ModuleForTests("import_with_no_deps", "android_common")
+	importWithNoDepsJar := importWithNoDeps.Output("combined/import_with_no_deps.jar")
+	importWithNoDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider)
+
+	// An import with no deps produces a single jar used as both the header and implementation jar.
+	android.AssertPathsRelativeToTopEquals(t, "import with no deps implementation jar",
+		[]string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.ImplementationAndResourcesJars)
+	android.AssertPathsRelativeToTopEquals(t, "import with no deps header jar",
+		[]string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.HeaderJars)
+	android.AssertPathsRelativeToTopEquals(t, "import with no deps combined inputs",
+		[]string{"no_deps.jar"}, importWithNoDepsJar.Inputs)
+
+	importWithSourceDeps := ctx.ModuleForTests("import_with_source_deps", "android_common")
+	importWithSourceDepsJar := importWithSourceDeps.Output("combined/import_with_source_deps.jar")
+	importWithSourceDepsHeaderJar := importWithSourceDeps.Output("turbine-combined/import_with_source_deps.jar")
+	importWithSourceDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider)
+
+	// An import with source deps produces separate header and implementation jars.
+	android.AssertPathsRelativeToTopEquals(t, "import with source deps implementation jar",
+		[]string{importWithSourceDepsJar.Output.String()}, importWithSourceDepsJavaInfo.ImplementationAndResourcesJars)
+	android.AssertPathsRelativeToTopEquals(t, "import with source deps header jar",
+		[]string{importWithSourceDepsHeaderJar.Output.String()}, importWithSourceDepsJavaInfo.HeaderJars)
+	android.AssertPathsRelativeToTopEquals(t, "import with source deps combined implementation jar inputs",
+		[]string{"source_deps.jar", sourceJar.Output.String()}, importWithSourceDepsJar.Inputs)
+	android.AssertPathsRelativeToTopEquals(t, "import with source deps combined header jar inputs",
+		[]string{"source_deps.jar", sourceHeaderJar.Output.String()}, importWithSourceDepsHeaderJar.Inputs)
+
+	importWithImportDeps := ctx.ModuleForTests("import_with_import_deps", "android_common")
+	importWithImportDepsJar := importWithImportDeps.Output("combined/import_with_import_deps.jar")
+	importWithImportDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider)
+
+	// An import with only import deps produces a single jar used as both the header and implementation jar.
+	android.AssertPathsRelativeToTopEquals(t, "import with import deps implementation jar",
+		[]string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.ImplementationAndResourcesJars)
+	android.AssertPathsRelativeToTopEquals(t, "import with import deps header jar",
+		[]string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.HeaderJars)
+	android.AssertPathsRelativeToTopEquals(t, "import with import deps combined implementation jar inputs",
+		[]string{"import_deps.jar", importWithNoDepsJar.Output.String()}, importWithImportDepsJar.Inputs)
+}
+
 var compilerFlagsTestCases = []struct {
 	in  string
 	out bool
@@ -2757,3 +2837,38 @@
 	cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
 	android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
 }
+
+func TestJavaLibHostWithStem(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_library_host {
+			name: "foo",
+			srcs: ["a.java"],
+			stem: "foo-new",
+		}
+	`)
+
+	buildOS := ctx.Config().BuildOS.String()
+	foo := ctx.ModuleForTests("foo", buildOS+"_common")
+
+	outputs := fmt.Sprint(foo.AllOutputs())
+	if !strings.Contains(outputs, "foo-new.jar") {
+		t.Errorf("Module output does not contain expected jar %s", "foo-new.jar")
+	}
+}
+
+func TestJavaLibWithStem(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			stem: "foo-new",
+		}
+	`)
+
+	foo := ctx.ModuleForTests("foo", "android_common")
+
+	outputs := fmt.Sprint(foo.AllOutputs())
+	if !strings.Contains(outputs, "foo-new.jar") {
+		t.Errorf("Module output does not contain expected jar %s", "foo-new.jar")
+	}
+}
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 94e9c6c..6a79e58 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -158,6 +158,21 @@
 	mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
 }
 
+func createCombinedApiFilegroupModule(mctx android.LoadHookContext, name string, srcs []string) {
+	filegroupProps := struct {
+		Name *string
+		Srcs []string
+	}{}
+	filegroupProps.Name = proptools.StringPtr(name)
+
+	var transformedSrcs []string
+	for _, src := range srcs {
+		transformedSrcs = append(transformedSrcs, ":"+src)
+	}
+	filegroupProps.Srcs = transformedSrcs
+	mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
+}
+
 func createLatestApiModuleExtensionVersionFile(mctx android.LoadHookContext, name string, version string) {
 	genruleProps := struct {
 		Name *string
@@ -252,6 +267,10 @@
 	return module + ".api." + scope + "." + version
 }
 
+func PrebuiltApiCombinedModuleName(module, scope, version string) string {
+	return module + ".api.combined." + scope + "." + version
+}
+
 func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
 	// <apiver>/<scope>/api/<module>.txt
 	apiLevelFiles := globApiDirs(mctx, p, "api/*.txt")
@@ -307,7 +326,9 @@
 	}
 
 	// Sort the keys in order to make build.ninja stable
-	for _, k := range android.SortedKeys(latest) {
+	sortedLatestKeys := android.SortedKeys(latest)
+
+	for _, k := range sortedLatestKeys {
 		info := latest[k]
 		name := PrebuiltApiModuleName(info.module, info.scope, "latest")
 		latestExtensionVersionModuleName := PrebuiltApiModuleName(info.module, info.scope, "latest.extension_version")
@@ -333,11 +354,25 @@
 		}
 	}
 	// Create empty incompatibilities files for remaining modules
-	for _, k := range android.SortedKeys(latest) {
+	// If the incompatibility module has been created, create a corresponding combined module
+	for _, k := range sortedLatestKeys {
 		if _, ok := incompatibilities[k]; !ok {
 			createEmptyFile(mctx, PrebuiltApiModuleName(latest[k].module+"-incompatibilities", latest[k].scope, "latest"))
 		}
 	}
+
+	// Create combined latest api and removed api files modules.
+	// The combined modules list all api files of the api scope and its subset api scopes.
+	for _, k := range sortedLatestKeys {
+		info := latest[k]
+		name := PrebuiltApiCombinedModuleName(info.module, info.scope, "latest")
+
+		var srcs []string
+		currentApiScope := scopeByName[info.scope]
+		srcs = append(srcs, PrebuiltApiModuleName(info.module, currentApiScope.name, "latest"))
+
+		createCombinedApiFilegroupModule(mctx, name, srcs)
+	}
 }
 
 func createPrebuiltApiModules(mctx android.LoadHookContext) {
diff --git a/java/rro.go b/java/rro.go
index 3e0f8e9..72170fc 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -122,6 +122,10 @@
 
 	ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs...)
 	ctx.AddVariationDependencies(nil, libTag, r.properties.Resource_libs...)
+
+	for _, aconfig_declaration := range r.aaptProperties.Flags_packages {
+		ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+	}
 }
 
 func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -151,6 +155,7 @@
 			sdkContext:                     r,
 			enforceDefaultTargetSdkVersion: false,
 			extraLinkFlags:                 aaptLinkFlags,
+			aconfigTextFiles:               getAconfigFilePaths(ctx),
 		},
 	)
 
diff --git a/java/rro_test.go b/java/rro_test.go
index c4a4d04..d697ec6 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -405,3 +405,49 @@
 		android.AssertPathRelativeToTopEquals(t, "Install dir is not correct for "+testCase.name, testCase.expectedPath, mod.installDir)
 	}
 }
+
+func TestRuntimeResourceOverlayFlagsPackages(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForJavaTest,
+	).RunTestWithBp(t, `
+		runtime_resource_overlay {
+			name: "foo",
+			sdk_version: "current",
+			flags_packages: [
+				"bar",
+				"baz",
+			],
+		}
+		aconfig_declarations {
+			name: "bar",
+			package: "com.example.package.bar",
+			srcs: [
+				"bar.aconfig",
+			],
+		}
+		aconfig_declarations {
+			name: "baz",
+			package: "com.example.package.baz",
+			srcs: [
+				"baz.aconfig",
+			],
+		}
+	`)
+
+	foo := result.ModuleForTests("foo", "android_common")
+
+	// runtime_resource_overlay module depends on aconfig_declarations listed in flags_packages
+	android.AssertBoolEquals(t, "foo expected to depend on bar", true,
+		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"))
+
+	android.AssertBoolEquals(t, "foo expected to depend on baz", true,
+		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "baz"))
+
+	aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
+	linkInFlags := aapt2LinkRule.Args["inFlags"]
+	android.AssertStringDoesContain(t,
+		"aapt2 link command expected to pass feature flags arguments",
+		linkInFlags,
+		"--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+	)
+}
diff --git a/java/sdk.go b/java/sdk.go
index 3591ccd..d972c19 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -31,7 +31,6 @@
 
 var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey")
 var nonUpdatableFrameworkAidlPathKey = android.NewOnceKey("nonUpdatableFrameworkAidlPathKey")
-var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey")
 
 func UseApiFingerprint(ctx android.BaseModuleContext) (useApiFingerprint bool, fingerprintSdkVersion string, fingerprintDeps android.OutputPath) {
 	if ctx.Config().UnbundledBuild() && !ctx.Config().AlwaysUsePrebuiltSdks() {
@@ -45,8 +44,8 @@
 
 		useApiFingerprint = apiFingerprintTrue || dessertShaIsSet
 		if apiFingerprintTrue {
-			fingerprintSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
-			fingerprintDeps = ApiFingerprintPath(ctx)
+			fingerprintSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", android.ApiFingerprintPath(ctx).String())
+			fingerprintDeps = android.ApiFingerprintPath(ctx)
 		}
 		if dessertShaIsSet {
 			fingerprintSdkVersion = ctx.Config().Getenv("UNBUNDLED_BUILD_TARGET_SDK_WITH_DESSERT_SHA")
@@ -337,7 +336,7 @@
 
 // Create api_fingerprint.txt
 func createAPIFingerprint(ctx android.SingletonContext) {
-	out := ApiFingerprintPath(ctx)
+	out := android.ApiFingerprintPath(ctx)
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 
@@ -378,17 +377,11 @@
 	rule.Build("api_fingerprint", "generate api_fingerprint.txt")
 }
 
-func ApiFingerprintPath(ctx android.PathContext) android.OutputPath {
-	return ctx.Config().Once(apiFingerprintPathKey, func() interface{} {
-		return android.PathForOutput(ctx, "api_fingerprint.txt")
-	}).(android.OutputPath)
-}
-
 func sdkMakeVars(ctx android.MakeVarsContext) {
 	if ctx.Config().AlwaysUsePrebuiltSdks() {
 		return
 	}
 
 	ctx.Strict("FRAMEWORK_AIDL", sdkFrameworkAidlPath(ctx).String())
-	ctx.Strict("API_FINGERPRINT", ApiFingerprintPath(ctx).String())
+	ctx.Strict("API_FINGERPRINT", android.ApiFingerprintPath(ctx).String())
 }
diff --git a/java/sdk_library.go b/java/sdk_library.go
index cdd0448..5ddc675 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -30,6 +30,7 @@
 
 	"android/soong/android"
 	"android/soong/dexpreopt"
+	"android/soong/etc"
 )
 
 const (
@@ -1672,12 +1673,16 @@
 	return PrebuiltApiModuleName(name, apiScope.name, "latest")
 }
 
+func latestPrebuiltApiCombinedModuleName(name string, apiScope *apiScope) string {
+	return PrebuiltApiCombinedModuleName(name, apiScope.name, "latest")
+}
+
 func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string {
 	return ":" + module.latestApiModuleName(apiScope)
 }
 
 func (module *SdkLibrary) latestApiModuleName(apiScope *apiScope) string {
-	return latestPrebuiltApiModuleName(module.distStem(), apiScope)
+	return latestPrebuiltApiCombinedModuleName(module.distStem(), apiScope)
 }
 
 func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) string {
@@ -1685,7 +1690,7 @@
 }
 
 func (module *SdkLibrary) latestRemovedApiModuleName(apiScope *apiScope) string {
-	return latestPrebuiltApiModuleName(module.distStem()+"-removed", apiScope)
+	return latestPrebuiltApiCombinedModuleName(module.distStem()+"-removed", apiScope)
 }
 
 func (module *SdkLibrary) latestIncompatibilitiesFilegroupName(apiScope *apiScope) string {
@@ -1993,20 +1998,25 @@
 	if !Bool(module.sdkLibraryProperties.No_dist) {
 		// Dist the api txt and removed api txt artifacts for sdk builds.
 		distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
+		stubsTypeTagPrefix := ""
+		if mctx.Config().ReleaseHiddenApiExportableStubs() {
+			stubsTypeTagPrefix = ".exportable"
+		}
 		for _, p := range []struct {
 			tag     string
 			pattern string
 		}{
 			// "exportable" api files are copied to the dist directory instead of the
-			// "everything" api files.
-			{tag: ".exportable.api.txt", pattern: "%s.txt"},
-			{tag: ".exportable.removed-api.txt", pattern: "%s-removed.txt"},
+			// "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag
+			// is set. Otherwise, the "everything" api files are copied to the dist directory.
+			{tag: "%s.api.txt", pattern: "%s.txt"},
+			{tag: "%s.removed-api.txt", pattern: "%s-removed.txt"},
 		} {
 			props.Dists = append(props.Dists, android.Dist{
 				Targets: []string{"sdk", "win_sdk"},
 				Dir:     distDir,
 				Dest:    proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
-				Tag:     proptools.StringPtr(p.tag),
+				Tag:     proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)),
 			})
 		}
 	}
@@ -2079,7 +2089,7 @@
 	mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
 }
 
-func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
+func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties {
 	props := libraryProperties{}
 
 	props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
@@ -2095,13 +2105,22 @@
 	}
 	props.Compile_dex = compileDex
 
+	if !Bool(module.sdkLibraryProperties.No_dist) && doDist {
+		props.Dist.Targets = []string{"sdk", "win_sdk"}
+		props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
+		props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
+		props.Dist.Tag = proptools.StringPtr(".jar")
+	}
+
 	return props
 }
 
 func (module *SdkLibrary) createTopLevelStubsLibrary(
 	mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) {
 
-	props := module.topLevelStubsLibraryProps(mctx, apiScope)
+	// Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false
+	doDist := !mctx.Config().ReleaseHiddenApiExportableStubs()
+	props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
 	props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
 
 	// Add the stub compiling java_library/java_api_library as static lib based on build config
@@ -2117,18 +2136,11 @@
 func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
 	mctx android.DefaultableHookContext, apiScope *apiScope) {
 
-	props := module.topLevelStubsLibraryProps(mctx, apiScope)
+	// Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true
+	doDist := mctx.Config().ReleaseHiddenApiExportableStubs()
+	props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
 	props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))
 
-	// Dist the class jar artifact for sdk builds.
-	// "exportable" stubs are copied to dist for sdk builds instead of the "everything" stubs.
-	if !Bool(module.sdkLibraryProperties.No_dist) {
-		props.Dist.Targets = []string{"sdk", "win_sdk"}
-		props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
-		props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
-		props.Dist.Tag = proptools.StringPtr(".jar")
-	}
-
 	staticLib := module.exportableSourceStubsLibraryModuleName(apiScope)
 	props.Static_libs = append(props.Static_libs, staticLib)
 
@@ -3163,10 +3175,12 @@
 }
 
 // from android.PrebuiltEtcModule
-func (module *sdkLibraryXml) OutputFile() android.OutputPath {
-	return module.outputFilePath
+func (module *sdkLibraryXml) OutputFiles(tag string) (android.Paths, error) {
+	return android.OutputPaths{module.outputFilePath}.Paths(), nil
 }
 
+var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)
+
 // from android.ApexModule
 func (module *sdkLibraryXml) AvailableFor(what string) bool {
 	return true
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 93ef408..a19d382 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -139,10 +139,10 @@
 
 	exportedComponentsInfo, _ := android.SingletonModuleProvider(result, foo.Module(), android.ExportedComponentsInfoProvider)
 	expectedFooExportedComponents := []string{
-		"foo-removed.api.public.latest",
-		"foo-removed.api.system.latest",
-		"foo.api.public.latest",
-		"foo.api.system.latest",
+		"foo-removed.api.combined.public.latest",
+		"foo-removed.api.combined.system.latest",
+		"foo.api.combined.public.latest",
+		"foo.api.combined.system.latest",
 		"foo.stubs",
 		"foo.stubs.exportable",
 		"foo.stubs.exportable.system",
@@ -556,8 +556,8 @@
 
 	CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
 		`dex2oatd`,
-		`sdklib-removed.api.public.latest`,
-		`sdklib.api.public.latest`,
+		`sdklib-removed.api.combined.public.latest`,
+		`sdklib.api.combined.public.latest`,
 		`sdklib.impl`,
 		`sdklib.stubs`,
 		`sdklib.stubs.exportable`,
@@ -960,8 +960,8 @@
 	CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
 		`dex2oatd`,
 		`prebuilt_sdklib`,
-		`sdklib-removed.api.public.latest`,
-		`sdklib.api.public.latest`,
+		`sdklib-removed.api.combined.public.latest`,
+		`sdklib.api.combined.public.latest`,
 		`sdklib.impl`,
 		`sdklib.stubs`,
 		`sdklib.stubs.exportable`,
@@ -1039,8 +1039,8 @@
 
 	CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
 		`prebuilt_sdklib`,
-		`sdklib-removed.api.public.latest`,
-		`sdklib.api.public.latest`,
+		`sdklib-removed.api.combined.public.latest`,
+		`sdklib.api.combined.public.latest`,
 		`sdklib.impl`,
 		`sdklib.stubs`,
 		`sdklib.stubs.exportable`,
@@ -1239,7 +1239,6 @@
 		libraryType                string
 		fromPartition              string
 		toPartition                string
-		enforceVendorInterface     bool
 		enforceProductInterface    bool
 		enforceJavaSdkLibraryCheck bool
 		allowList                  []string
@@ -1274,9 +1273,6 @@
 			android.FixtureWithRootAndroidBp(bpFile),
 			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
 				variables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
-				if info.enforceVendorInterface {
-					variables.DeviceVndkVersion = proptools.StringPtr("current")
-				}
 				variables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
 				variables.InterPartitionJavaLibraryAllowList = info.allowList
 			}),
@@ -1304,7 +1300,6 @@
 		libraryType:                "java_library",
 		fromPartition:              "product",
 		toPartition:                "system",
-		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: false,
 	}, "")
@@ -1313,7 +1308,6 @@
 		libraryType:                "java_library",
 		fromPartition:              "product",
 		toPartition:                "system",
-		enforceVendorInterface:     true,
 		enforceProductInterface:    false,
 		enforceJavaSdkLibraryCheck: true,
 	}, "")
@@ -1322,7 +1316,6 @@
 		libraryType:                "java_library",
 		fromPartition:              "product",
 		toPartition:                "system",
-		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
 	}, errorMessage)
@@ -1331,7 +1324,6 @@
 		libraryType:                "java_library",
 		fromPartition:              "vendor",
 		toPartition:                "system",
-		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
 	}, errorMessage)
@@ -1340,7 +1332,6 @@
 		libraryType:                "java_library",
 		fromPartition:              "vendor",
 		toPartition:                "system",
-		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
 		allowList:                  []string{"bar"},
@@ -1350,7 +1341,6 @@
 		libraryType:                "java_library",
 		fromPartition:              "vendor",
 		toPartition:                "product",
-		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
 	}, errorMessage)
@@ -1359,7 +1349,6 @@
 		libraryType:                "java_sdk_library",
 		fromPartition:              "product",
 		toPartition:                "system",
-		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
 	}, "")
@@ -1368,7 +1357,6 @@
 		libraryType:                "java_sdk_library",
 		fromPartition:              "vendor",
 		toPartition:                "system",
-		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
 	}, "")
@@ -1377,7 +1365,6 @@
 		libraryType:                "java_sdk_library",
 		fromPartition:              "vendor",
 		toPartition:                "product",
-		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
 	}, "")
@@ -1393,6 +1380,11 @@
 			"sdklib_group_foo",
 			"sdklib_owner_foo",
 			"foo"),
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.BuildFlags = map[string]string{
+				"RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+			}
+		}),
 	).RunTestWithBp(t, `
 		java_sdk_library {
 			name: "sdklib_no_group",
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 59c5466..b291e70 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -189,7 +189,7 @@
 		return javaSdkLibrarySdkMemberType
 	}
 
-	return javaSystemserverLibsSdkMemberType
+	return JavaSystemserverLibsSdkMemberType
 }
 
 func (b systemServerClasspathFragmentContentDependencyTag) ExportMember() bool {
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index 78b62d9..98aa408 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -89,7 +89,7 @@
 	output := android.PathForModuleOut(ctx, "linker.config.pb").OutputPath
 
 	builder := android.NewRuleBuilder(pctx, ctx)
-	BuildLinkerConfig(ctx, builder, input, nil, output)
+	BuildLinkerConfig(ctx, builder, input, nil, nil, output)
 	builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String())
 
 	l.outputFilePath = output
@@ -101,7 +101,7 @@
 }
 
 func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder,
-	input android.Path, otherModules []android.Module, output android.OutputPath) {
+	input android.Path, provideModules []android.Module, requireModules []android.Module, output android.OutputPath) {
 
 	// First, convert the input json to protobuf format
 	interimOutput := android.PathForModuleOut(ctx, "temp.pb")
@@ -111,9 +111,9 @@
 		FlagWithInput("-s ", input).
 		FlagWithOutput("-o ", interimOutput)
 
-	// Secondly, if there's provideLibs gathered from otherModules, append them
+	// Secondly, if there's provideLibs gathered from provideModules, append them
 	var provideLibs []string
-	for _, m := range otherModules {
+	for _, m := range provideModules {
 		if c, ok := m.(*cc.Module); ok && cc.IsStubTarget(c) {
 			for _, ps := range c.PackagingSpecs() {
 				provideLibs = append(provideLibs, ps.FileName())
@@ -122,18 +122,45 @@
 	}
 	provideLibs = android.FirstUniqueStrings(provideLibs)
 	sort.Strings(provideLibs)
+
+	var requireLibs []string
+	for _, m := range requireModules {
+		if c, ok := m.(*cc.Module); ok && c.HasStubsVariants() && !c.Host() {
+			requireLibs = append(requireLibs, c.ImplementationModuleName(ctx)+".so")
+		}
+	}
+
+	requireLibs = android.FirstUniqueStrings(requireLibs)
+	sort.Strings(requireLibs)
+
 	if len(provideLibs) > 0 {
+		prevOutput := interimOutput
+		interimOutput = android.PathForModuleOut(ctx, "temp_provideLibs.pb")
 		builder.Command().
 			BuiltTool("conv_linker_config").
 			Flag("append").
-			FlagWithInput("-s ", interimOutput).
-			FlagWithOutput("-o ", output).
+			FlagWithInput("-s ", prevOutput).
+			FlagWithOutput("-o ", interimOutput).
 			FlagWithArg("--key ", "provideLibs").
 			FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(provideLibs, " ")))
-	} else {
-		// If nothing to add, just cp to the final output
-		builder.Command().Text("cp").Input(interimOutput).Output(output)
+		builder.Temporary(prevOutput)
 	}
+	if len(requireLibs) > 0 {
+		prevOutput := interimOutput
+		interimOutput = android.PathForModuleOut(ctx, "temp_requireLibs.pb")
+		builder.Command().
+			BuiltTool("conv_linker_config").
+			Flag("append").
+			FlagWithInput("-s ", prevOutput).
+			FlagWithOutput("-o ", interimOutput).
+			FlagWithArg("--key ", "requireLibs").
+			FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(requireLibs, " ")))
+		builder.Temporary(prevOutput)
+	}
+
+	// cp to the final output
+	builder.Command().Text("cp").Input(interimOutput).Output(output)
+
 	builder.Temporary(interimOutput)
 	builder.DeleteTemporaryFiles()
 }
diff --git a/phony/phony.go b/phony/phony.go
index b8dbd00..68fbf48 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -23,10 +23,16 @@
 )
 
 func init() {
-	android.RegisterModuleType("phony", PhonyFactory)
-	android.RegisterModuleType("phony_rule", PhonyRuleFactory)
+	registerPhonyModuleTypes(android.InitRegistrationContext)
 }
 
+func registerPhonyModuleTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("phony", PhonyFactory)
+	ctx.RegisterModuleType("phony_rule", PhonyRuleFactory)
+}
+
+var PrepareForTestWithPhony = android.FixtureRegisterWithContext(registerPhonyModuleTypes)
+
 type phony struct {
 	android.ModuleBase
 	requiredModuleNames       []string
diff --git a/python/python.go b/python/python.go
index d3cbd76..2b1974e 100644
--- a/python/python.go
+++ b/python/python.go
@@ -545,7 +545,6 @@
 			var stagedProtoSrcs android.Paths
 			for _, srcFile := range protoSrcs {
 				stagedProtoSrc := pkgPathStagingDir.Join(ctx, pkgPath, srcFile.Rel())
-				rule.Command().Text("mkdir -p").Flag(filepath.Base(stagedProtoSrc.String()))
 				rule.Command().Text("cp -f").Input(srcFile).Output(stagedProtoSrc)
 				stagedProtoSrcs = append(stagedProtoSrcs, stagedProtoSrc)
 			}
diff --git a/python/scripts/precompile_python.py b/python/scripts/precompile_python.py
index aa1a5df..07b8fe9 100644
--- a/python/scripts/precompile_python.py
+++ b/python/scripts/precompile_python.py
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import print_function
 import argparse
 import py_compile
 import os
@@ -63,11 +64,23 @@
     parser.add_argument('dst_zip')
     args = parser.parse_args()
 
+    errors = []
     with open(args.dst_zip, 'wb') as outf, open(args.src_zip, 'rb') as inf:
         with zipfile.ZipFile(outf, mode='w') as outzip, zipfile.ZipFile(inf, mode='r') as inzip:
             for name in inzip.namelist():
                 with inzip.open(name, mode='r') as inzipf:
-                    process_one_file(name, inzipf, outzip)
+                    try:
+                        process_one_file(name, inzipf, outzip)
+                    except py_compile.PyCompileError as e:
+                        errors.append(e)
+
+    if errors:
+        for i, error in enumerate(errors):
+            # Print an empty line in between each error
+            if i > 0:
+                print(file=sys.stderr)
+            print(str(error).strip(), file=sys.stderr)
+        sys.exit(1)
 
 
 if __name__ == "__main__":
diff --git a/rust/Android.bp b/rust/Android.bp
index 637042d..c5e94a0 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -62,7 +62,6 @@
         "sanitize_test.go",
         "source_provider_test.go",
         "test_test.go",
-        "vendor_snapshot_test.go",
     ],
     pluginFor: ["soong_build"],
 }
diff --git a/rust/builder.go b/rust/builder.go
index c855cfb..2f5e12a 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -32,7 +32,7 @@
 				"-C linker=${config.RustLinker} " +
 				"-C link-args=\"${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}\" " +
 				"--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
-				" && grep \"^$out:\" $out.d.raw > $out.d",
+				" && grep ^$out: $out.d.raw > $out.d",
 			CommandDeps: []string{"$rustcCmd"},
 			// Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
 			// Rustc emits unneeded dependency lines for the .d and input .rs files.
diff --git a/rust/compiler.go b/rust/compiler.go
index c1bdbeb..03fdf2b 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -75,6 +75,8 @@
 	strippedOutputFilePath() android.OptionalPath
 
 	checkedCrateRootPath() (android.Path, error)
+
+	Aliases() map[string]string
 }
 
 func (compiler *baseCompiler) edition() string {
@@ -140,6 +142,12 @@
 	// flags to pass to the linker
 	Ld_flags []string `android:"arch_variant"`
 
+	// Rust crate dependencies to rename. Each entry should be a string of the form "dependencyname:alias".
+	//
+	// "dependencyname" here should be the name of the crate, not the Android module. This is
+	// equivalent to writing `alias = { package = "dependencyname" }` in a `Cargo.toml`.
+	Aliases []string
+
 	// list of rust rlib crate dependencies
 	Rlibs []string `android:"arch_variant"`
 
@@ -281,6 +289,18 @@
 	return Bool(compiler.Properties.Prefer_rlib)
 }
 
+func (compiler *baseCompiler) Aliases() map[string]string {
+	aliases := map[string]string{}
+	for _, entry := range compiler.Properties.Aliases {
+		dep, alias, found := strings.Cut(entry, ":")
+		if !found {
+			panic(fmt.Errorf("invalid aliases entry %q missing ':'", entry))
+		}
+		aliases[dep] = alias
+	}
+	return aliases
+}
+
 func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage {
 	// For devices, we always link stdlibs in as dylibs by default.
 	if compiler.preferRlib() {
diff --git a/rust/library.go b/rust/library.go
index 7f004fc..3560d73 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -54,9 +54,13 @@
 	Shared VariantLibraryProperties `android:"arch_variant"`
 	Static VariantLibraryProperties `android:"arch_variant"`
 
-	// path to include directories to pass to cc_* modules, only relevant for static/shared variants.
+	// TODO: Remove this when all instances of Include_dirs have been removed from rust_ffi modules.
+	// path to include directories to pass to cc_* modules, only relevant for static/shared variants (deprecated, use export_include_dirs instead).
 	Include_dirs []string `android:"path,arch_variant"`
 
+	// path to include directories to export to cc_* modules, only relevant for static/shared variants.
+	Export_include_dirs []string `android:"path,arch_variant"`
+
 	// Whether this library is part of the Rust toolchain sysroot.
 	Sysroot *bool
 }
@@ -465,6 +469,7 @@
 	flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName())
 	if library.shared() || library.static() {
 		library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
+		library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Export_include_dirs)...)
 	}
 	if library.shared() {
 		if ctx.Darwin() {
diff --git a/rust/library_test.go b/rust/library_test.go
index e03074d..7275b66 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -403,3 +403,22 @@
 	}
 
 }
+
+func TestRustFFIExportedIncludes(t *testing.T) {
+	ctx := testRust(t, `
+		rust_ffi {
+			name: "libbar",
+			srcs: ["foo.rs"],
+			crate_name: "bar",
+			export_include_dirs: ["rust_includes"],
+			host_supported: true,
+		}
+		cc_library_static {
+			name: "libfoo",
+			srcs: ["foo.cpp"],
+			shared_libs: ["libbar"],
+			host_supported: true,
+		}`)
+	libfooStatic := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_static").Rule("cc")
+	android.AssertStringDoesContain(t, "cFlags for lib module", libfooStatic.Args["cFlags"], " -Irust_includes ")
+}
diff --git a/rust/rust.go b/rust/rust.go
index 668dd8f..7d81c72 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1142,6 +1142,7 @@
 		}
 	}
 }
+
 func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
 	var depPaths PathDeps
 
@@ -1433,16 +1434,29 @@
 	mod.transitiveAndroidMkSharedLibs = android.NewDepSet[string](android.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs)
 
 	var rlibDepFiles RustLibraries
+	aliases := mod.compiler.Aliases()
 	for _, dep := range directRlibDeps {
-		rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()})
+		crateName := dep.CrateName()
+		if alias, aliased := aliases[crateName]; aliased {
+			crateName = alias
+		}
+		rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
 	}
 	var dylibDepFiles RustLibraries
 	for _, dep := range directDylibDeps {
-		dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()})
+		crateName := dep.CrateName()
+		if alias, aliased := aliases[crateName]; aliased {
+			crateName = alias
+		}
+		dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
 	}
 	var procMacroDepFiles RustLibraries
 	for _, dep := range directProcMacroDeps {
-		procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()})
+		crateName := dep.CrateName()
+		if alias, aliased := aliases[crateName]; aliased {
+			crateName = alias
+		}
+		procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
 	}
 
 	var staticLibDepFiles android.Paths
diff --git a/rust/rust_test.go b/rust/rust_test.go
index d609c2f..295a734 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -470,6 +470,35 @@
 	m.Output("libwaldo.dylib.so.bloaty.csv")
 }
 
+// Test that aliases are respected.
+func TestRustAliases(t *testing.T) {
+	ctx := testRust(t, `
+		rust_library {
+			name: "libbar",
+			crate_name: "bar",
+			srcs: ["src/lib.rs"],
+		}
+		rust_library {
+			name: "libbaz",
+			crate_name: "baz",
+			srcs: ["src/lib.rs"],
+		}
+		rust_binary {
+			name: "foo",
+			srcs: ["src/main.rs"],
+			rustlibs: ["libbar", "libbaz"],
+			aliases: ["bar:bar_renamed"],
+		}`)
+
+	fooRustc := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+	if !strings.Contains(fooRustc.Args["libFlags"], "--extern bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so") {
+		t.Errorf("--extern bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"])
+	}
+	if !strings.Contains(fooRustc.Args["libFlags"], "--extern baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so") {
+		t.Errorf("--extern baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"])
+	}
+}
+
 func assertString(t *testing.T, got, expected string) {
 	t.Helper()
 	if got != expected {
diff --git a/rust/testing.go b/rust/testing.go
index d9cacdc..986e34e 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -47,7 +47,7 @@
 
 var PrepareForTestWithRustIncludeVndk = android.GroupFixturePreparers(
 	PrepareForIntegrationTestWithRust,
-	cc.PrepareForTestWithCcIncludeVndk,
+	cc.PrepareForIntegrationTestWithCc,
 )
 
 func GatherRequiredDepsForTest() string {
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
deleted file mode 100644
index 7ebe66b..0000000
--- a/rust/vendor_snapshot_test.go
+++ /dev/null
@@ -1,1573 +0,0 @@
-// Copyright 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package rust
-
-import (
-	"fmt"
-	"path/filepath"
-	"reflect"
-	"strings"
-	"testing"
-
-	"android/soong/android"
-	"android/soong/cc"
-)
-
-func TestVendorSnapshotCapture(t *testing.T) {
-	bp := `
-	rust_ffi {
-		name: "libffivendor_available",
-		crate_name: "ffivendor_available",
-		srcs: ["lib.rs"],
-		vendor_available: true,
-		include_dirs: ["rust_headers/"],
-	}
-
-	rust_ffi {
-		name: "libffivendor",
-		crate_name: "ffivendor",
-		srcs: ["lib.rs"],
-		vendor: true,
-		include_dirs: ["rust_headers/"],
-	}
-
-	rust_library {
-		name: "librustvendor_available",
-		crate_name: "rustvendor_available",
-		srcs: ["lib.rs"],
-		vendor_available: true,
-	}
-
-	rust_library {
-		name: "librustvendor",
-		crate_name: "rustvendor",
-		srcs: ["lib.rs"],
-		vendor: true,
-	}
-
-	rust_binary {
-		name: "vendor_available_bin",
-		vendor_available: true,
-		srcs: ["srcs/lib.rs"],
-	}
-
-	rust_binary {
-		name: "vendor_bin",
-		vendor: true,
-		srcs: ["srcs/lib.rs"],
-	}
-    `
-	skipTestIfOsNotSupported(t)
-	result := android.GroupFixturePreparers(
-		prepareForRustTest,
-		rustMockedFiles.AddToFixture(),
-		android.FixtureModifyProductVariables(
-			func(variables android.FixtureProductVariables) {
-				variables.DeviceVndkVersion = StringPtr("current")
-				variables.Platform_vndk_version = StringPtr("29")
-			},
-		),
-	).RunTestWithBp(t, bp)
-	ctx := result.TestContext
-
-	// Check Vendor snapshot output.
-
-	snapshotDir := "vendor-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-	var jsonFiles []string
-	for _, arch := range [][]string{
-		[]string{"arm64", "armv8-a"},
-		[]string{"arm", "armv7-a-neon"},
-	} {
-		archType := arch[0]
-		archVariant := arch[1]
-		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
-		// For shared libraries, only non-VNDK vendor_available modules are captured
-		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.so", sharedDir, sharedVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(sharedDir, "libffivendor_available.so.json"))
-
-		// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
-		staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant)
-		staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.a", staticDir, staticVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor", "libffivendor.a", staticDir, staticVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(staticDir, "libffivendor_available.a.json"))
-		jsonFiles = append(jsonFiles,
-			filepath.Join(staticDir, "libffivendor.a.json"))
-
-		// For rlib libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
-		rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
-		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib", rlibDir, rlibVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
-		jsonFiles = append(jsonFiles,
-			filepath.Join(rlibDir, "librustvendor.rlib.json"))
-
-		// For rlib libraries, all rlib-std variants vendor:true and vendor_available modules (including VNDK) are captured.
-		rlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibStdVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib-std.rlib", rlibDir, rlibStdVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
-		jsonFiles = append(jsonFiles,
-			filepath.Join(rlibDir, "librustvendor.rlib.json"))
-
-		// For dylib libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
-		dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
-		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.dylib.so", dylibDir, dylibVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(dylibDir, "librustvendor_available.dylib.so.json"))
-		jsonFiles = append(jsonFiles,
-			filepath.Join(dylibDir, "librustvendor.dylib.so.json"))
-
-		// For binary executables, all vendor:true and vendor_available modules are captured.
-		if archType == "arm64" {
-			binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
-			binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
-			cc.CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
-			cc.CheckSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
-			jsonFiles = append(jsonFiles,
-				filepath.Join(binaryDir, "vendor_available_bin.json"))
-			jsonFiles = append(jsonFiles,
-				filepath.Join(binaryDir, "vendor_bin.json"))
-		}
-	}
-
-	for _, jsonFile := range jsonFiles {
-		// verify all json files exist
-		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
-			t.Errorf("%q expected but not found; #%v", jsonFile, jsonFiles)
-		}
-	}
-
-	// fake snapshot should have all outputs in the normal snapshot.
-	fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
-
-	for _, output := range snapshotSingleton.AllOutputs() {
-		fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
-		if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
-			t.Errorf("%q expected but not found", fakeOutput)
-		}
-	}
-}
-
-func TestVendorSnapshotDirected(t *testing.T) {
-	bp := `
-	rust_ffi_shared {
-		name: "libffivendor_available",
-		crate_name: "ffivendor_available",
-		srcs: ["lib.rs"],
-		vendor_available: true,
-	}
-
-	rust_library {
-		name: "librustvendor_available",
-		crate_name: "rustvendor_available",
-		srcs: ["lib.rs"],
-		vendor_available: true,
-	}
-
-	rust_ffi_shared {
-		name: "libffivendor_exclude",
-		crate_name: "ffivendor_exclude",
-		srcs: ["lib.rs"],
-		vendor_available: true,
-	}
-
-	rust_library {
-		name: "librustvendor_exclude",
-		crate_name: "rustvendor_exclude",
-		srcs: ["lib.rs"],
-		vendor_available: true,
-	}
-`
-	ctx := testRustVndk(t, bp)
-	ctx.Config().TestProductVariables.VendorSnapshotModules = make(map[string]bool)
-	ctx.Config().TestProductVariables.VendorSnapshotModules["librustvendor_available"] = true
-	ctx.Config().TestProductVariables.VendorSnapshotModules["libffivendor_available"] = true
-	ctx.Config().TestProductVariables.DirectedVendorSnapshot = true
-
-	// Check Vendor snapshot output.
-
-	snapshotDir := "vendor-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
-	var includeJsonFiles []string
-
-	for _, arch := range [][]string{
-		[]string{"arm64", "armv8-a"},
-		[]string{"arm", "armv7-a-neon"},
-	} {
-		archType := arch[0]
-		archVariant := arch[1]
-		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
-		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
-		rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
-		rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
-		dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
-		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-
-		// Included modules
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib-std.rlib.json"))
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_available.dylib.so.json"))
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_available.so.json"))
-
-		// Excluded modules. Modules not included in the directed vendor snapshot
-		// are still include as fake modules.
-		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib", rlibDir, rlibVariant)
-		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.dylib.so", dylibDir, dylibVariant)
-		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "libffivendor_exclude", "libffivendor_exclude.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib.json"))
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib-std.rlib.json"))
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_exclude.dylib.so.json"))
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_exclude.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)
-		}
-	}
-}
-
-func TestVendorSnapshotExclude(t *testing.T) {
-
-	// This test verifies that the exclude_from_vendor_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 vendor snapshot based on their path (framework or
-	// vendor) and the exclude_from_vendor_snapshot property.
-
-	frameworkBp := `
-		rust_ffi_shared {
-			name: "libinclude",
-			crate_name: "include",
-			srcs: ["include.rs"],
-			vendor_available: true,
-		}
-
-		rust_ffi_shared {
-			name: "libexclude",
-			crate_name: "exclude",
-			srcs: ["exclude.rs"],
-			vendor: true,
-			exclude_from_vendor_snapshot: true,
-		}
-
-		rust_ffi_shared {
-			name: "libavailable_exclude",
-			crate_name: "available_exclude",
-			srcs: ["lib.rs"],
-			vendor_available: true,
-			exclude_from_vendor_snapshot: true,
-		}
-
-		rust_library {
-			name: "librust_include",
-			crate_name: "rust_include",
-			srcs: ["include.rs"],
-			vendor_available: true,
-		}
-
-		rust_library {
-			name: "librust_exclude",
-			crate_name: "rust_exclude",
-			srcs: ["exclude.rs"],
-			vendor: true,
-			exclude_from_vendor_snapshot: true,
-		}
-
-		rust_library {
-			name: "librust_available_exclude",
-			crate_name: "rust_available_exclude",
-			srcs: ["lib.rs"],
-			vendor_available: true,
-			exclude_from_vendor_snapshot: true,
-		}
-	`
-
-	mockFS := map[string][]byte{
-		"framework/Android.bp": []byte(frameworkBp),
-		"framework/include.rs": nil,
-		"framework/exclude.rs": nil,
-	}
-
-	ctx := testRustVndkFs(t, "", mockFS)
-
-	// Test an include and exclude framework module.
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, sharedVendorVariant)
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, sharedVendorVariant)
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, sharedVendorVariant)
-
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, rlibVendorVariant)
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibVendorVariant)
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibVendorVariant)
-
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, rlibDylibStdVendorVariant)
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibDylibStdVendorVariant)
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibDylibStdVendorVariant)
-
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, dylibVendorVariant)
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, dylibVendorVariant)
-	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, dylibVendorVariant)
-
-	// Verify the content of the vendor snapshot.
-
-	snapshotDir := "vendor-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
-	var includeJsonFiles []string
-	var excludeJsonFiles []string
-
-	for _, arch := range [][]string{
-		[]string{"arm64", "armv8-a"},
-		[]string{"arm", "armv7-a-neon"},
-	} {
-		archType := arch[0]
-		archVariant := arch[1]
-		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
-		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-
-		rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
-		rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
-		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
-		dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
-		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-
-		// Included modules
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib", rlibDir, rlibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib-std.rlib.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.dylib.so", dylibDir, dylibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librust_include.dylib.so.json"))
-
-		// Excluded modules
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_exclude", "librust_exclude.rlib", rlibDir, rlibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_exclude.rlib.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib", rlibDir, rlibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.rlib-std.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_exclude", "librust_exclude.dylib.so", dylibDir, dylibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_exclude.dylib.so.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.dylib.so", dylibDir, dylibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_available_exclude.dylib.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 TestVendorSnapshotUse(t *testing.T) {
-	frameworkBp := `
-	cc_library {
-		name: "libvndk",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		nocrt: true,
-	}
-
-	cc_library {
-		name: "libvendor",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		system_shared_libs: [],
-	}
-
-	cc_library {
-		name: "libvendor_available",
-		vendor_available: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		system_shared_libs: [],
-	}
-
-	cc_library {
-		name: "lib32",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		system_shared_libs: [],
-		compile_multilib: "32",
-	}
-
-	cc_library {
-		name: "lib64",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		stl: "none",
-		system_shared_libs: [],
-		compile_multilib: "64",
-	}
-
-	rust_binary {
-		name: "bin",
-		vendor: true,
-		srcs: ["bin.rs"],
-	}
-
-	rust_binary {
-		name: "bin32",
-		vendor: true,
-		compile_multilib: "32",
-		srcs: ["bin.rs"],
-	}
-
-	rust_library {
-		name: "librust_vendor_available",
-		crate_name: "rust_vendor",
-		vendor_available: true,
-		srcs: ["client.rs"],
-	}
-
-`
-
-	vndkBp := `
-	vndk_prebuilt_shared {
-		name: "libvndk",
-		version: "30",
-		target_arch: "arm64",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		arch: {
-			arm64: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-			arm: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-		},
-	}
-
-	// old snapshot module which has to be ignored
-	vndk_prebuilt_shared {
-		name: "libvndk",
-		version: "26",
-		target_arch: "arm64",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		arch: {
-			arm64: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-			arm: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-		},
-	}
-
-	// different arch snapshot which has to be ignored
-	vndk_prebuilt_shared {
-		name: "libvndk",
-		version: "30",
-		target_arch: "arm",
-		vendor_available: true,
-		product_available: true,
-		vndk: {
-			enabled: true,
-		},
-		arch: {
-			arm: {
-				srcs: ["libvndk.so"],
-				export_include_dirs: ["include/libvndk"],
-			},
-		},
-	}
-`
-
-	vendorProprietaryBp := `
-	cc_library {
-		name: "libvendor_without_snapshot",
-		vendor: true,
-		nocrt: true,
-		no_libcrt: true,
-		no_crt_pad_segment: true,
-		stl: "none",
-		system_shared_libs: [],
-	}
-
-	rust_ffi_shared {
-		name: "libclient",
-		crate_name: "client",
-		vendor: true,
-		shared_libs: ["libvndk", "libvendor_available"],
-		static_libs: ["libvendor", "libvendor_without_snapshot"],
-		rustlibs: ["librust_vendor_available"],
-		arch: {
-			arm64: {
-				shared_libs: ["lib64"],
-			},
-			arm: {
-				shared_libs: ["lib32"],
-			},
-		},
-		srcs: ["client.rs"],
-	}
-
-	rust_library {
-		name: "libclient_rust",
-		crate_name: "client_rust",
-		vendor: true,
-		shared_libs: ["libvndk", "libvendor_available"],
-		static_libs: ["libvendor", "libvendor_without_snapshot"],
-		rustlibs: ["librust_vendor_available"],
-		arch: {
-			arm64: {
-				shared_libs: ["lib64"],
-			},
-			arm: {
-				shared_libs: ["lib32"],
-			},
-		},
-		srcs: ["client.rs"],
-	}
-
-	rust_binary {
-		name: "bin_without_snapshot",
-		vendor: true,
-		static_libs: ["libvndk"],
-		srcs: ["bin.rs"],
-		rustlibs: ["librust_vendor_available"],
-	}
-
-	vendor_snapshot {
-		name: "vendor_snapshot",
-		version: "30",
-		arch: {
-			arm64: {
-				vndk_libs: [
-					"libvndk",
-				],
-				static_libs: [
-					"libvendor",
-					"libvndk",
-					"libclang_rt.builtins",
-					"note_memtag_heap_sync",
-				],
-				shared_libs: [
-					"libvendor_available",
-					"lib64",
-				],
-				rlibs: [
-					"libstd",
-					"librust_vendor_available",
-					"librust_vendor_available.rlib-std"
-				],
-				dylibs: [
-					"libstd",
-					"librust_vendor_available",
-				],
-				binaries: [
-					"bin",
-				],
-                objects: [
-				    "crtend_so",
-					"crtbegin_so",
-					"crtbegin_dynamic",
-					"crtend_android"
-				],
-			},
-			arm: {
-				vndk_libs: [
-					"libvndk",
-				],
-				static_libs: [
-					"libvendor",
-					"libvndk",
-					"libclang_rt.builtins",
-				],
-				shared_libs: [
-					"libvendor_available",
-					"lib32",
-				],
-				rlibs: [
-					"libstd",
-					"librust_vendor_available",
-				],
-				dylibs: [
-					"libstd",
-					"librust_vendor_available",
-				],
-				binaries: [
-					"bin32",
-				],
-                objects: [
-				    "crtend_so",
-					"crtbegin_so",
-					"crtbegin_dynamic",
-					"crtend_android"
-				],
-
-			},
-		}
-	}
-
-	vendor_snapshot_object {
-		name: "crtend_so",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		stl: "none",
-		crt: true,
-		arch: {
-			arm64: {
-				src: "crtend_so.o",
-			},
-			arm: {
-				src: "crtend_so.o",
-			},
-		},
-	}
-
-	vendor_snapshot_object {
-		name: "crtbegin_so",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		stl: "none",
-		crt: true,
-		arch: {
-			arm64: {
-				src: "crtbegin_so.o",
-			},
-			arm: {
-				src: "crtbegin_so.o",
-			},
-		},
-	}
-
-	vendor_snapshot_rlib {
-		name: "libstd",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		sysroot: true,
-		arch: {
-			arm64: {
-				src: "libstd.rlib",
-			},
-			arm: {
-				src: "libstd.rlib",
-			},
-		},
-	}
-
-	vendor_snapshot_rlib {
-		name: "librust_vendor_available",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "librust_vendor_available.rlib",
-			},
-			arm: {
-				src: "librust_vendor_available.rlib",
-			},
-		},
-	}
-
-	vendor_snapshot_rlib {
-		name: "librust_vendor_available.rlib-std",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "librust_vendor_available.rlib-std.rlib",
-			},
-			arm: {
-				src: "librust_vendor_available.rlib-std.rlib",
-			},
-		},
-	}
-
-	vendor_snapshot_dylib {
-		name: "libstd",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		sysroot: true,
-		arch: {
-			arm64: {
-				src: "libstd.dylib.so",
-			},
-			arm: {
-				src: "libstd.dylib.so",
-			},
-		},
-	}
-
-	vendor_snapshot_dylib {
-		name: "librust_vendor_available",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "librust_vendor_available.dylib.so",
-			},
-			arm: {
-				src: "librust_vendor_available.dylib.so",
-			},
-		},
-	}
-
-	vendor_snapshot_object {
-		name: "crtend_android",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		stl: "none",
-		crt: true,
-		arch: {
-			arm64: {
-				src: "crtend_so.o",
-			},
-			arm: {
-				src: "crtend_so.o",
-			},
-		},
-	}
-
-	vendor_snapshot_object {
-		name: "crtbegin_dynamic",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		stl: "none",
-		crt: true,
-		arch: {
-			arm64: {
-				src: "crtbegin_so.o",
-			},
-			arm: {
-				src: "crtbegin_so.o",
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "libvndk",
-		version: "30",
-		target_arch: "arm64",
-		compile_multilib: "both",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "libvndk.a",
-			},
-			arm: {
-				src: "libvndk.a",
-			},
-		},
-		shared_libs: ["libvndk"],
-		export_shared_lib_headers: ["libvndk"],
-	}
-
-	vendor_snapshot_static {
-		name: "libclang_rt.builtins",
-		version: "30",
-		target_arch: "arm64",
-		vendor: true,
-		arch: {
-			arm: {
-				src: "libclang_rt.builtins-arm-android.a",
-			},
-			arm64: {
-				src: "libclang_rt.builtins-aarch64-android.a",
-			},
-		},
-    }
-
-	vendor_snapshot_shared {
-		name: "lib32",
-		version: "30",
-		target_arch: "arm64",
-		compile_multilib: "32",
-		vendor: true,
-		no_crt_pad_segment: true,
-		arch: {
-			arm: {
-				src: "lib32.so",
-			},
-		},
-	}
-
-	vendor_snapshot_shared {
-		name: "lib64",
-		version: "30",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		no_crt_pad_segment: true,
-		arch: {
-			arm64: {
-				src: "lib64.so",
-			},
-		},
-	}
-	vendor_snapshot_shared {
-		name: "liblog",
-		version: "30",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		no_crt_pad_segment: true,
-		arch: {
-			arm64: {
-				src: "liblog.so",
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "libvendor",
-		version: "30",
-		target_arch: "arm64",
-		compile_multilib: "both",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "libvendor.a",
-				export_include_dirs: ["include/libvendor"],
-			},
-			arm: {
-				src: "libvendor.a",
-				export_include_dirs: ["include/libvendor"],
-			},
-		},
-	}
-
-	vendor_snapshot_shared {
-		name: "libvendor_available",
-		version: "30",
-		target_arch: "arm64",
-		compile_multilib: "both",
-		vendor: true,
-		no_crt_pad_segment: true,
-		arch: {
-			arm64: {
-				src: "libvendor_available.so",
-				export_include_dirs: ["include/libvendor"],
-			},
-			arm: {
-				src: "libvendor_available.so",
-				export_include_dirs: ["include/libvendor"],
-			},
-		},
-	}
-
-	vendor_snapshot_binary {
-		name: "bin",
-		version: "30",
-		target_arch: "arm64",
-		compile_multilib: "64",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "bin",
-			},
-		},
-	}
-
-	vendor_snapshot_binary {
-		name: "bin32",
-		version: "30",
-		target_arch: "arm64",
-		compile_multilib: "32",
-		vendor: true,
-		arch: {
-			arm: {
-				src: "bin32",
-			},
-		},
-	}
-
-	// Test sanitizers use the snapshot libraries
-	rust_binary {
-		name: "memtag_binary",
-		srcs: ["vendor/bin.rs"],
-		vendor: true,
-		compile_multilib: "64",
-		sanitize: {
-			memtag_heap: true,
-			diag: {
-				memtag_heap: true,
-			}
-		},
-	}
-
-	// old snapshot module which has to be ignored
-	vendor_snapshot_binary {
-		name: "bin",
-		version: "26",
-		target_arch: "arm64",
-		compile_multilib: "first",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "bin",
-			},
-		},
-	}
-
-	// different arch snapshot which has to be ignored
-	vendor_snapshot_binary {
-		name: "bin",
-		version: "30",
-		target_arch: "arm",
-		compile_multilib: "first",
-		vendor: true,
-		arch: {
-			arm64: {
-				src: "bin",
-			},
-		},
-	}
-
-	vendor_snapshot_static {
-		name: "note_memtag_heap_sync",
-		vendor: true,
-		target_arch: "arm64",
-		version: "30",
-		arch: {
-			arm64: {
-				src: "note_memtag_heap_sync.a",
-			},
-		},
-	}
-
-`
-
-	mockFS := android.MockFS{
-		"framework/Android.bp":                          []byte(frameworkBp),
-		"framework/bin.rs":                              nil,
-		"note_memtag_heap_sync.a":                       nil,
-		"vendor/Android.bp":                             []byte(vendorProprietaryBp),
-		"vendor/bin":                                    nil,
-		"vendor/bin32":                                  nil,
-		"vendor/bin.rs":                                 nil,
-		"vendor/client.rs":                              nil,
-		"vendor/include/libvndk/a.h":                    nil,
-		"vendor/include/libvendor/b.h":                  nil,
-		"vendor/libvndk.a":                              nil,
-		"vendor/libvendor.a":                            nil,
-		"vendor/libvendor.so":                           nil,
-		"vendor/lib32.so":                               nil,
-		"vendor/lib64.so":                               nil,
-		"vendor/liblog.so":                              nil,
-		"vendor/libstd.rlib":                            nil,
-		"vendor/librust_vendor_available.rlib":          nil,
-		"vendor/librust_vendor_available.rlib-std.rlib": nil,
-		"vendor/libstd.dylib.so":                        nil,
-		"vendor/librust_vendor_available.dylib.so":      nil,
-		"vendor/crtbegin_so.o":                          nil,
-		"vendor/crtend_so.o":                            nil,
-		"vendor/libclang_rt.builtins-aarch64-android.a": nil,
-		"vendor/libclang_rt.builtins-arm-android.a":     nil,
-		"vndk/Android.bp":                               []byte(vndkBp),
-		"vndk/include/libvndk/a.h":                      nil,
-		"vndk/libvndk.so":                               nil,
-	}
-
-	sharedVariant := "android_vendor.30_arm64_armv8-a_shared"
-	rlibVariant := "android_vendor.30_arm64_armv8-a_rlib_dylib-std"
-	rlibRlibStdVariant := "android_vendor.30_arm64_armv8-a_rlib_rlib-std"
-	dylibVariant := "android_vendor.30_arm64_armv8-a_dylib"
-	staticVariant := "android_vendor.30_arm64_armv8-a_static"
-	binaryVariant := "android_vendor.30_arm64_armv8-a"
-
-	shared32Variant := "android_vendor.30_arm_armv7-a-neon_shared"
-	binary32Variant := "android_vendor.30_arm_armv7-a-neon"
-
-	ctx := testRustVndkFsVersions(t, "", mockFS, "30", "current", "31")
-
-	// libclient uses libvndk.vndk.30.arm64, libvendor.vendor_static.30.arm64, libvendor_without_snapshot
-	libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustc").Args["linkFlags"]
-	for _, input := range [][]string{
-		[]string{sharedVariant, "libvndk.vndk.30.arm64"},
-		[]string{staticVariant, "libvendor.vendor_static.30.arm64"},
-		[]string{staticVariant, "libvendor_without_snapshot"},
-	} {
-		outputPaths := cc.GetOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
-		if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
-			t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
-		}
-	}
-
-	libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).transitiveAndroidMkSharedLibs.ToList()
-	if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib64", "liblog.vendor", "libc.vendor", "libm.vendor", "libdl.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
-	}
-
-	libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs
-	if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot", "libclang_rt.builtins.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
-	}
-
-	libclientAndroidMkDylibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkDylibs
-	if g, w := libclientAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted libclient libclientAndroidMkDylibs %q, got %q", w, libclientAndroidMkDylibs)
-	}
-
-	libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).transitiveAndroidMkSharedLibs.ToList()
-	if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib32", "liblog.vendor", "libc.vendor", "libm.vendor", "libdl.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g)
-	}
-
-	libclientRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibVariant).Module().(*Module).Properties.AndroidMkRlibs
-	if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g)
-	}
-
-	libclientRlibStdRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibRlibStdVariant).Module().(*Module).Properties.AndroidMkRlibs
-	if g, w := libclientRlibStdRustAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g)
-	}
-
-	libclientRustDylibAndroidMkDylibs := ctx.ModuleForTests("libclient_rust", dylibVariant).Module().(*Module).Properties.AndroidMkDylibs
-	if g, w := libclientRustDylibAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted dylib libclient libclientRustDylibAndroidMkDylibs %q, got %q", w, g)
-	}
-
-	// rust vendor snapshot must have ".vendor" suffix in AndroidMk
-	librustVendorAvailableSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_rlib.30.arm64", rlibVariant).Module()
-	librustVendorSnapshotMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0]
-	expectedRustVendorSnapshotName := "librust_vendor_available.vendor"
-	if librustVendorSnapshotMkName != expectedRustVendorSnapshotName {
-		t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotMkName, expectedRustVendorSnapshotName)
-	}
-
-	librustVendorAvailableDylibSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_dylib.30.arm64", dylibVariant).Module()
-	librustVendorSnapshotDylibMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableDylibSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0]
-	expectedRustVendorDylibSnapshotName := "librust_vendor_available.vendor"
-	if librustVendorSnapshotDylibMkName != expectedRustVendorDylibSnapshotName {
-		t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotDylibMkName, expectedRustVendorDylibSnapshotName)
-	}
-
-	rustVendorBinModule := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Module()
-	rustVendorBinMkDylibName := android.AndroidMkEntriesForTest(t, ctx, rustVendorBinModule)[0].EntryMap["LOCAL_DYLIB_LIBRARIES"][0]
-	if rustVendorBinMkDylibName != expectedRustVendorSnapshotName {
-		t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkDylibName, expectedRustVendorSnapshotName)
-	}
-
-	binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustc").Args["linkFlags"]
-	libVndkStaticOutputPaths := cc.GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.30.arm64"})
-	if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
-		t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
-			libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
-	}
-
-	// bin is installed by bin.vendor_binary.30.arm64
-	ctx.ModuleForTests("bin.vendor_binary.30.arm64", binaryVariant).Output("bin")
-
-	// bin32 is installed by bin32.vendor_binary.30.arm64
-	ctx.ModuleForTests("bin32.vendor_binary.30.arm64", binary32Variant).Output("bin32")
-
-	// bin_without_snapshot is installed by bin_without_snapshot
-	ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
-
-	// libvendor, libvendor_available and bin don't have vendor.30 variant
-	libvendorVariants := ctx.ModuleVariantsForTests("libvendor")
-	if android.InList(sharedVariant, libvendorVariants) {
-		t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant)
-	}
-
-	libvendorAvailableVariants := ctx.ModuleVariantsForTests("libvendor_available")
-	if android.InList(sharedVariant, libvendorAvailableVariants) {
-		t.Errorf("libvendor_available must not have variant %#v, but it does", sharedVariant)
-	}
-
-	binVariants := ctx.ModuleVariantsForTests("bin")
-	if android.InList(binaryVariant, binVariants) {
-		t.Errorf("bin must not have variant %#v, but it does", sharedVariant)
-	}
-
-	memtagStaticLibs := ctx.ModuleForTests("memtag_binary", "android_vendor.30_arm64_armv8-a").Module().(*Module).Properties.AndroidMkStaticLibs
-	if g, w := memtagStaticLibs, []string{"libclang_rt.builtins.vendor", "note_memtag_heap_sync.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted memtag_binary AndroidMkStaticLibs %q, got %q", w, g)
-	}
-}
-
-func TestRecoverySnapshotCapture(t *testing.T) {
-	bp := `
-	rust_ffi {
-		name: "librecovery",
-		recovery: true,
-		srcs: ["foo.rs"],
-		crate_name: "recovery",
-	}
-
-	rust_ffi {
-		name: "librecovery_available",
-		recovery_available: true,
-		srcs: ["foo.rs"],
-		crate_name: "recovery_available",
-	}
-
-	rust_library {
-		name: "librecovery_rustlib",
-		recovery: true,
-		srcs: ["foo.rs"],
-		crate_name: "recovery_rustlib",
-	}
-
-	rust_library {
-		name: "librecovery_available_rustlib",
-		recovery_available: true,
-		srcs: ["foo.rs"],
-		crate_name: "recovery_available_rustlib",
-	}
-
-	rust_binary {
-		name: "recovery_bin",
-		recovery: true,
-		srcs: ["foo.rs"],
-	}
-
-	rust_binary {
-		name: "recovery_available_bin",
-		recovery_available: true,
-		srcs: ["foo.rs"],
-	}
-
-`
-	// Check Recovery snapshot output.
-
-	ctx := testRustRecoveryFsVersions(t, bp, rustMockedFiles, "", "29", "current")
-	snapshotDir := "recovery-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
-	var jsonFiles []string
-
-	for _, arch := range [][]string{
-		[]string{"arm64", "armv8-a"},
-	} {
-		archType := arch[0]
-		archVariant := arch[1]
-		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
-		// For shared libraries, all recovery:true and recovery_available modules are captured.
-		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(sharedDir, "librecovery.so.json"),
-			filepath.Join(sharedDir, "librecovery_available.so.json"))
-
-		// For static libraries, all recovery:true and recovery_available modules are captured.
-		staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant)
-		staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(staticDir, "librecovery.a.json"),
-			filepath.Join(staticDir, "librecovery_available.a.json"))
-
-		// For rlib libraries, all recovery:true and recovery_available modules are captured.
-		rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
-		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"),
-			filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json"))
-
-		rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"),
-			filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json"))
-
-		// For dylib libraries, all recovery:true and recovery_available modules are captured.
-		dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
-		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant)
-		jsonFiles = append(jsonFiles,
-			filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json"),
-			filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.so.json"))
-
-		// For binary executables, all recovery:true and recovery_available modules are captured.
-		if archType == "arm64" {
-			binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
-			binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
-			cc.CheckSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
-			cc.CheckSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
-			jsonFiles = append(jsonFiles,
-				filepath.Join(binaryDir, "recovery_bin.json"),
-				filepath.Join(binaryDir, "recovery_available_bin.json"))
-		}
-	}
-
-	for _, jsonFile := range jsonFiles {
-		// verify all json files exist
-		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
-			t.Errorf("%q expected but not found", jsonFile)
-		}
-	}
-}
-
-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 := `
-		rust_ffi_shared {
-			name: "libinclude",
-			srcs: ["src/include.rs"],
-			recovery_available: true,
-			crate_name: "include",
-		}
-		rust_ffi_shared {
-			name: "libexclude",
-			srcs: ["src/exclude.rs"],
-			recovery: true,
-			exclude_from_recovery_snapshot: true,
-			crate_name: "exclude",
-		}
-		rust_ffi_shared {
-			name: "libavailable_exclude",
-			srcs: ["src/exclude.rs"],
-			recovery_available: true,
-			exclude_from_recovery_snapshot: true,
-			crate_name: "available_exclude",
-		}
-		rust_library {
-			name: "libinclude_rustlib",
-			srcs: ["src/include.rs"],
-			recovery_available: true,
-			crate_name: "include_rustlib",
-		}
-		rust_library {
-			name: "libexclude_rustlib",
-			srcs: ["src/exclude.rs"],
-			recovery: true,
-			exclude_from_recovery_snapshot: true,
-			crate_name: "exclude_rustlib",
-		}
-		rust_library {
-			name: "libavailable_exclude_rustlib",
-			srcs: ["src/exclude.rs"],
-			recovery_available: true,
-			exclude_from_recovery_snapshot: true,
-			crate_name: "available_exclude_rustlib",
-		}
-	`
-
-	vendorProprietaryBp := `
-		rust_ffi_shared {
-			name: "librecovery",
-			srcs: ["recovery.rs"],
-			recovery: true,
-			crate_name: "recovery",
-		}
-		rust_library {
-			name: "librecovery_rustlib",
-			srcs: ["recovery.rs"],
-			recovery: true,
-			crate_name: "recovery_rustlib",
-		}
-	`
-
-	mockFS := map[string][]byte{
-		"framework/Android.bp": []byte(frameworkBp),
-		"framework/include.rs": nil,
-		"framework/exclude.rs": nil,
-		"device/Android.bp":    []byte(vendorProprietaryBp),
-		"device/recovery.rs":   nil,
-	}
-
-	ctx := testRustRecoveryFsVersions(t, "", mockFS, "", "29", "current")
-
-	// Test an include and exclude framework module.
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false, sharedRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, sharedRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, sharedRecoveryVariant)
-
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant)
-
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRlibStdRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRlibStdRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant)
-
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, dylibRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, dylibRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, dylibRecoveryVariant)
-
-	// A recovery module is excluded, but by its path not the exclude_from_recovery_snapshot property
-	// ('device/' and 'vendor/' are default excluded). See snapshot/recovery_snapshot.go for more detail.
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, sharedRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRlibStdRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, dylibRecoveryVariant)
-
-	// Verify the content of the recovery snapshot.
-
-	snapshotDir := "recovery-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", 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)
-		rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
-		rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
-		dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
-		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-
-		// Included modules
-
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib", rlibDir, rlibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib-std.rlib.json"))
-
-		// Excluded modules
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
-
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib", rlibDir, rlibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib", rlibDir, rlibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib.json"))
-
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib-std.rlib.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib-std.rlib.json"))
-
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.dylib.so", dylibDir, dylibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.dylib.so.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.dylib.so.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.dylib.so", dylibDir, dylibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.dylib.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 TestRecoverySnapshotDirected(t *testing.T) {
-	bp := `
-	rust_ffi_shared {
-		name: "librecovery",
-		recovery: true,
-		crate_name: "recovery",
-		srcs: ["foo.rs"],
-	}
-
-	rust_ffi_shared {
-		name: "librecovery_available",
-		recovery_available: true,
-		crate_name: "recovery_available",
-		srcs: ["foo.rs"],
-	}
-
-	rust_library {
-		name: "librecovery_rustlib",
-		recovery: true,
-		crate_name: "recovery",
-		srcs: ["foo.rs"],
-	}
-
-	rust_library {
-		name: "librecovery_available_rustlib",
-		recovery_available: true,
-		crate_name: "recovery_available",
-		srcs: ["foo.rs"],
-	}
-
-	/* TODO: Uncomment when Rust supports the "prefer" property for prebuilts
-	rust_library_rlib {
-		name: "libfoo_rlib",
-		recovery: true,
-		crate_name: "foo",
-	}
-
-	rust_prebuilt_rlib {
-		name: "libfoo_rlib",
-		recovery: true,
-		prefer: true,
-		srcs: ["libfoo.rlib"],
-		crate_name: "foo",
-	}
-	*/
-`
-	ctx := testRustRecoveryFsVersions(t, bp, rustMockedFiles, "current", "29", "current")
-	ctx.Config().TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
-	ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery"] = true
-	ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery_rustlib"] = true
-	ctx.Config().TestProductVariables.DirectedRecoverySnapshot = true
-
-	// Check recovery snapshot output.
-	snapshotDir := "recovery-snapshot"
-	snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-	snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
-	var includeJsonFiles []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)
-		rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
-		rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
-		dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
-		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
-		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-
-		// Included modules
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json"))
-
-		// TODO: When Rust supports the "prefer" property for prebuilts, perform this check.
-		/*
-			// Check that snapshot captures "prefer: true" prebuilt
-			cc.CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo_rlib", "libfoo_rlib.rlib", rlibDir, rlibVariant)
-			includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo_rlib.rlib.json"))
-		*/
-
-		// Excluded modules. Modules not included in the directed recovery snapshot
-		// are still included as fake modules.
-		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json"))
-		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json"))
-		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json"))
-		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.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, %#v", jsonFile, includeJsonFiles)
-		}
-	}
-}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index f36329b..d039a81 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -305,3 +305,14 @@
         },
     },
 }
+
+python_binary_host {
+    name: "buildinfo",
+    main: "buildinfo.py",
+    srcs: ["buildinfo.py"],
+    version: {
+        py3: {
+            embedded_launcher: true,
+        },
+    },
+}
diff --git a/scripts/buildinfo.py b/scripts/buildinfo.py
new file mode 100755
index 0000000..e4fb0da
--- /dev/null
+++ b/scripts/buildinfo.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""A tool for generating buildinfo.prop"""
+
+import argparse
+import contextlib
+import subprocess
+
+def parse_args():
+  """Parse commandline arguments."""
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--use-vbmeta-digest-in-fingerprint', action='store_true')
+  parser.add_argument('--build-flavor', required=True)
+  parser.add_argument('--build-hostname-file', required=True, type=argparse.FileType('r')),
+  parser.add_argument('--build-id', required=True)
+  parser.add_argument('--build-keys', required=True)
+  parser.add_argument('--build-number-file', required=True, type=argparse.FileType('r'))
+  parser.add_argument('--build-thumbprint-file', type=argparse.FileType('r'))
+  parser.add_argument('--build-type', required=True)
+  parser.add_argument('--build-username', required=True)
+  parser.add_argument('--build-variant', required=True)
+  parser.add_argument('--cpu-abis', action='append', required=True)
+  parser.add_argument('--date-file', required=True, type=argparse.FileType('r'))
+  parser.add_argument('--default-locale')
+  parser.add_argument('--default-wifi-channels', action='append', default=[])
+  parser.add_argument('--device', required=True)
+  parser.add_argument("--display-build-number", action='store_true')
+  parser.add_argument('--platform-base-os', required=True)
+  parser.add_argument('--platform-display-version', required=True)
+  parser.add_argument('--platform-min-supported-target-sdk-version', required=True)
+  parser.add_argument('--platform-preview-sdk-fingerprint-file',
+                      required=True,
+                      type=argparse.FileType('r'))
+  parser.add_argument('--platform-preview-sdk-version', required=True)
+  parser.add_argument('--platform-sdk-version', required=True)
+  parser.add_argument('--platform-security-patch', required=True)
+  parser.add_argument('--platform-version', required=True)
+  parser.add_argument('--platform-version-codename',required=True)
+  parser.add_argument('--platform-version-all-codenames', action='append', required=True)
+  parser.add_argument('--platform-version-known-codenames', required=True)
+  parser.add_argument('--platform-version-last-stable', required=True)
+  parser.add_argument('--product', required=True)
+
+  parser.add_argument('--out', required=True, type=argparse.FileType('w'))
+
+  return parser.parse_args()
+
+def main():
+  option = parse_args()
+
+  build_hostname = option.build_hostname_file.read().strip()
+  build_number = option.build_number_file.read().strip()
+  build_version_tags = option.build_keys
+  if option.build_type == "debug":
+    build_version_tags = "debug," + build_version_tags
+
+  raw_date = option.date_file.read().strip()
+  date = subprocess.check_output(["date", "-d", f"@{raw_date}"], text=True).strip()
+  date_utc = subprocess.check_output(["date", "-d", f"@{raw_date}", "+%s"], text=True).strip()
+
+  # build_desc is human readable strings that describe this build. This has the same info as the
+  # build fingerprint.
+  # e.g. "aosp_cf_x86_64_phone-userdebug VanillaIceCream MAIN eng.20240319.143939 test-keys"
+  build_desc = f"{option.product}-{option.build_variant} {option.platform_version} " \
+               f"{option.build_id} {build_number} {build_version_tags}"
+
+  platform_preview_sdk_fingerprint = option.platform_preview_sdk_fingerprint_file.read().strip()
+
+  with contextlib.redirect_stdout(option.out):
+    print("# begin build properties")
+    print("# autogenerated by buildinfo.py")
+
+    # The ro.build.id will be set dynamically by init, by appending the unique vbmeta digest.
+    if option.use_vbmeta_digest_in_fingerprint:
+      print(f"ro.build.legacy.id={option.build_id}")
+    else:
+      print(f"ro.build.id?={option.build_id}")
+
+    # ro.build.display.id is shown under Settings -> About Phone
+    if option.build_variant == "user":
+      # User builds should show:
+      # release build number or branch.buld_number non-release builds
+
+      # Dev. branches should have DISPLAY_BUILD_NUMBER set
+      if option.display_build_number:
+        print(f"ro.build.display.id?={option.build_id} {build_number} {option.build_keys}")
+      else:
+        print(f"ro.build.display.id?={option.build_id} {option.build_keys}")
+    else:
+      # Non-user builds should show detailed build information (See build desc above)
+      print(f"ro.build.display.id?={build_desc}")
+    print(f"ro.build.version.incremental={build_number}")
+    print(f"ro.build.version.sdk={option.platform_sdk_version}")
+    print(f"ro.build.version.preview_sdk={option.platform_preview_sdk_version}")
+    print(f"ro.build.version.preview_sdk_fingerprint={platform_preview_sdk_fingerprint}")
+    print(f"ro.build.version.codename={option.platform_version_codename}")
+    print(f"ro.build.version.all_codenames={','.join(option.platform_version_all_codenames)}")
+    print(f"ro.build.version.known_codenames={option.platform_version_known_codenames}")
+    print(f"ro.build.version.release={option.platform_version_last_stable}")
+    print(f"ro.build.version.release_or_codename={option.platform_version}")
+    print(f"ro.build.version.release_or_preview_display={option.platform_display_version}")
+    print(f"ro.build.version.security_patch={option.platform_security_patch}")
+    print(f"ro.build.version.base_os={option.platform_base_os}")
+    print(f"ro.build.version.min_supported_target_sdk={option.platform_min_supported_target_sdk_version}")
+    print(f"ro.build.date={date}")
+    print(f"ro.build.date.utc={date_utc}")
+    print(f"ro.build.type={option.build_variant}")
+    print(f"ro.build.user={option.build_username}")
+    print(f"ro.build.host={build_hostname}")
+    # TODO: Remove any tag-related optional property declarations once the goals
+    # from go/arc-android-sigprop-changes have been achieved.
+    print(f"ro.build.tags?={build_version_tags}")
+    # ro.build.flavor are used only by the test harness to distinguish builds.
+    # Only add _asan for a sanitized build if it isn't already a part of the
+    # flavor (via a dedicated lunch config for example).
+    print(f"ro.build.flavor={option.build_flavor}")
+
+    # These values are deprecated, use "ro.product.cpu.abilist"
+    # instead (see below).
+    print(f"# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,")
+    print(f"# use ro.product.cpu.abilist instead.")
+    print(f"ro.product.cpu.abi={option.cpu_abis[0]}")
+    if len(option.cpu_abis) > 1:
+      print(f"ro.product.cpu.abi2={option.cpu_abis[1]}")
+
+    if option.default_locale:
+      print(f"ro.product.locale={option.default_locale}")
+    print(f"ro.wifi.channels={' '.join(option.default_wifi_channels)}")
+
+    print(f"# ro.build.product is obsolete; use ro.product.device")
+    print(f"ro.build.product={option.device}")
+
+    print(f"# Do not try to parse description or thumbprint")
+    print(f"ro.build.description?={build_desc}")
+    if option.build_thumbprint_file:
+      build_thumbprint = option.build_thumbprint_file.read().strip()
+      print(f"ro.build.thumbprint={build_thumbprint}")
+
+    print(f"# end build properties")
+
+if __name__ == "__main__":
+  main()
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 5d41958..8d3bbfa 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -152,6 +152,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: [],
+}
+
 prebuilt_bootclasspath_fragment {
     name: "art-bootclasspath-fragment",
     prefer: false,
@@ -187,6 +192,7 @@
     apex_available: ["com.android.art"],
     jars: ["java_boot_libs/snapshot/jars/are/invalid/core2.jar"],
 }
+
 `),
 		checkAllCopyRules(`
 .intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
@@ -353,6 +359,15 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: [
+        "prebuilt_myothersdklibrary",
+        "prebuilt_mysdklibrary",
+        "prebuilt_mycoreplatform",
+    ],
+}
+
 prebuilt_bootclasspath_fragment {
     name: "mybootclasspathfragment",
     prefer: false,
@@ -642,6 +657,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mysdklibrary"],
+}
+
 prebuilt_bootclasspath_fragment {
     name: "mybootclasspathfragment",
     prefer: false,
@@ -881,6 +901,14 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: [
+        "prebuilt_mynewlibrary",
+        "prebuilt_mysdklibrary",
+    ],
+}
+
 prebuilt_bootclasspath_fragment {
     name: "mybootclasspathfragment",
     prefer: false,
@@ -1008,6 +1036,9 @@
 		android.FixtureMergeEnv(map[string]string{
 			"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease,
 		}),
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+		}),
 
 		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
 			variables.BuildFlags = map[string]string{
@@ -1226,6 +1257,9 @@
 		android.FixtureMergeEnv(map[string]string{
 			"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S",
 		}),
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+		}),
 		android.FixtureWithRootAndroidBp(`
 			sdk {
 				name: "mysdk",
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 265579a..9490d12 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -123,6 +123,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_sdkmember"],
+}
+
 cc_prebuilt_library_shared {
     name: "sdkmember",
     prefer: false,
@@ -226,6 +231,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_crtobj"],
+}
+
 cc_prebuilt_object {
     name: "crtobj",
     prefer: false,
@@ -333,6 +343,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
@@ -406,6 +421,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
@@ -465,6 +485,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mymodule_exports.contributions",
+    contents: ["prebuilt_mynativebinary"],
+}
+
 cc_prebuilt_binary {
     name: "mynativebinary",
     prefer: false,
@@ -523,6 +548,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_mynativebinary"],
+}
+
 cc_prebuilt_binary {
     name: "mynativebinary",
     prefer: false,
@@ -621,6 +651,14 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: [
+        "prebuilt_mynativebinary",
+        "prebuilt_mynativelib",
+    ],
+}
+
 cc_prebuilt_binary {
     name: "mynativebinary",
     prefer: false,
@@ -696,6 +734,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mymodule_exports.contributions",
+    contents: ["prebuilt_linker"],
+}
+
 cc_prebuilt_binary {
     name: "linker",
     prefer: false,
@@ -755,6 +798,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
@@ -856,6 +904,15 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: [
+        "prebuilt_mynativelib",
+        "prebuilt_myothernativelib",
+        "prebuilt_mysystemnativelib",
+    ],
+}
+
 cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
@@ -953,6 +1010,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
@@ -1029,6 +1091,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
@@ -1095,6 +1162,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library_static {
     name: "mynativelib",
     prefer: false,
@@ -1158,6 +1230,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library_static {
     name: "mynativelib",
     prefer: false,
@@ -1222,6 +1299,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library {
     name: "mynativelib",
     prefer: false,
@@ -1298,6 +1380,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library {
     name: "mynativelib",
     prefer: false,
@@ -1394,6 +1481,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library {
     name: "mynativelib",
     prefer: false,
@@ -1520,6 +1612,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library_static {
     name: "mynativelib",
     prefer: false,
@@ -1572,6 +1669,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativeheaders"],
+}
+
 cc_prebuilt_library_headers {
     name: "mynativeheaders",
     prefer: false,
@@ -1594,6 +1696,9 @@
 		PrepareForTestWithSdkBuildComponents,
 		ccTestFs.AddToFixture(),
 		prepareForTestWithNativeBridgeTarget,
+		android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+			android.RegisterApexContributionsBuildComponents(ctx)
+		}),
 	).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -1616,6 +1721,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativeheaders"],
+}
+
 cc_prebuilt_library_headers {
     name: "mynativeheaders",
     prefer: false,
@@ -1679,6 +1789,9 @@
 			cc.PrepareForTestWithCcDefaultModules,
 			PrepareForTestWithSdkBuildComponents,
 			ccTestFs.AddToFixture(),
+			android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+				android.RegisterApexContributionsBuildComponents(ctx)
+			}),
 		).RunTestWithBp(t, fmt.Sprintf(`
 		sdk {
 			name: "mysdk",
@@ -1701,6 +1814,11 @@
 			checkAndroidBpContents(fmt.Sprintf(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativeheaders"],
+}
+
 cc_prebuilt_library_headers {
     name: "mynativeheaders",
     prefer: false,
@@ -1750,6 +1868,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativeheaders"],
+}
+
 cc_prebuilt_library_headers {
     name: "mynativeheaders",
     prefer: false,
@@ -1807,6 +1930,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativeheaders"],
+}
+
 cc_prebuilt_library_headers {
     name: "mynativeheaders",
     prefer: false,
@@ -1870,6 +1998,15 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: [
+        "prebuilt_sslnil",
+        "prebuilt_sslempty",
+        "prebuilt_sslnonempty",
+    ],
+}
+
 cc_prebuilt_library_shared {
     name: "sslnil",
     prefer: false,
@@ -1943,6 +2080,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_sslvariants"],
+}
+
 cc_prebuilt_library_shared {
     name: "sslvariants",
     prefer: false,
@@ -2002,6 +2144,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_stubslib"],
+}
+
 cc_prebuilt_library_shared {
     name: "stubslib",
     prefer: false,
@@ -2056,6 +2203,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_stubslib"],
+}
+
 cc_prebuilt_library_shared {
     name: "stubslib",
     prefer: false,
@@ -2114,6 +2266,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mylib"],
+}
+
 cc_prebuilt_library_shared {
     name: "mylib",
     prefer: false,
@@ -2178,6 +2335,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mynativelib"],
+}
+
 cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
diff --git a/sdk/compat_config_sdk_test.go b/sdk/compat_config_sdk_test.go
index 45e8e0e..75b5229 100644
--- a/sdk/compat_config_sdk_test.go
+++ b/sdk/compat_config_sdk_test.go
@@ -36,6 +36,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myconfig"],
+}
+
 prebuilt_platform_compat_config {
     name: "myconfig",
     prefer: false,
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
index 2605fd1..9d0a242 100644
--- a/sdk/exports_test.go
+++ b/sdk/exports_test.go
@@ -46,6 +46,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 1b2b0f1..275860f 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -108,6 +108,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -154,6 +159,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -193,6 +203,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -245,6 +260,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -291,6 +311,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: [],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -313,6 +338,9 @@
 			android.FixtureMergeEnv(map[string]string{
 				"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease,
 			}),
+			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+				variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+			}),
 		).RunTestWithBp(t, `
 		sdk {
 			name: "mysdk",
@@ -395,6 +423,11 @@
 			checkAndroidBpContents(fmt.Sprintf(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mylib"],
+}
+
 java_import {
     name: "mylib",
     prefer: false,
@@ -459,6 +492,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: [],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -504,6 +542,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -542,6 +585,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_myjavatests"],
+}
+
 java_test_import {
     name: "myjavatests",
     prefer: false,
@@ -582,6 +630,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: ["prebuilt_myjavatests"],
+}
+
 java_test_import {
     name: "myjavatests",
     prefer: false,
@@ -661,6 +714,15 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: [
+        "prebuilt_exported-system-module",
+        "prebuilt_myjavalib",
+        "prebuilt_my-system-modules",
+    ],
+}
+
 java_import {
     name: "exported-system-module",
     prefer: false,
@@ -790,6 +852,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_my-system-modules"],
+}
+
 java_import {
     name: "mysdk_system-module",
     prefer: false,
@@ -854,6 +921,15 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "myexports.contributions",
+    contents: [
+        "prebuilt_hostjavalib",
+        "prebuilt_androidjavalib",
+        "prebuilt_myjavalib",
+    ],
+}
+
 java_import {
     name: "hostjavalib",
     prefer: false,
@@ -920,6 +996,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -993,6 +1074,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib-foo"],
+}
+
 java_sdk_library_import {
     name: "myjavalib-foo",
     prefer: false,
@@ -1046,6 +1132,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1093,6 +1184,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1147,6 +1243,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1204,6 +1305,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1272,6 +1378,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1320,6 +1431,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1371,6 +1487,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1436,6 +1557,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1509,6 +1635,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1569,6 +1700,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
@@ -1626,6 +1762,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_sdk_library_import {
     name: "myjavalib",
     prefer: false,
diff --git a/sdk/license_sdk_test.go b/sdk/license_sdk_test.go
index 829edf1..754f019 100644
--- a/sdk/license_sdk_test.go
+++ b/sdk/license_sdk_test.go
@@ -69,6 +69,11 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
diff --git a/sdk/member_trait_test.go b/sdk/member_trait_test.go
index 99caf13..673d6fb 100644
--- a/sdk/member_trait_test.go
+++ b/sdk/member_trait_test.go
@@ -137,6 +137,11 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -202,6 +207,17 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: [
+        "prebuilt_myjavalib",
+        "prebuilt_myjavalib_extra",
+        "prebuilt_myjavalib_special",
+        "prebuilt_anotherjavalib",
+        "prebuilt_anotherjavalib_special",
+    ],
+}
+
 java_test_import {
     name: "myjavalib",
     prefer: false,
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index c4df146..f9d49d9 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -118,6 +118,16 @@
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: [
+        "prebuilt_myjavalib",
+        "prebuilt_mypublicjavalib",
+        "prebuilt_mydefaultedjavalib",
+        "prebuilt_myprivatejavalib",
+    ],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -398,6 +408,11 @@
 			checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_myjavalib"],
+}
+
 java_import {
     name: "myjavalib",
     prefer: false,
@@ -453,6 +468,11 @@
 			checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mysdklibrary"],
+}
+
 prebuilt_bootclasspath_fragment {
     name: "mybootclasspathfragment",
     prefer: false,
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index 3c0b8ae..c1c4ed6 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -34,6 +34,9 @@
 				env["SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE"] = targetBuildRelease
 			}
 		}),
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+		}),
 		prepareForSdkTestWithApex,
 
 		android.FixtureWithRootAndroidBp(sdk+`
@@ -242,6 +245,11 @@
 	expectedLatestSnapshot := `
 // This is auto-generated. DO NOT EDIT.
 
+apex_contributions_defaults {
+    name: "mysdk.contributions",
+    contents: ["prebuilt_mysdklibrary"],
+}
+
 java_sdk_library_import {
     name: "mysdklibrary",
     prefer: false,
diff --git a/sdk/update.go b/sdk/update.go
index a731414..b8ae38a 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -24,6 +24,7 @@
 
 	"android/soong/apex"
 	"android/soong/cc"
+	"android/soong/java"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -388,6 +389,7 @@
 
 	// Create the prebuilt modules for each of the member modules.
 	traits := s.gatherTraits()
+	memberNames := []string{} // soong module names of the members. contains the prebuilt_ prefix.
 	for _, member := range members {
 		memberType := member.memberType
 		if !memberType.ArePrebuiltsRequired() {
@@ -409,6 +411,38 @@
 
 		prebuiltModule := memberType.AddPrebuiltModule(memberCtx, member)
 		s.createMemberSnapshot(memberCtx, member, prebuiltModule.(*bpModule))
+
+		if member.memberType != android.LicenseModuleSdkMemberType && !builder.isInternalMember(member.name) {
+			// More exceptions
+			// 1. Skip BCP and SCCP fragments
+			// 2. Skip non-sdk contents of BCP and SCCP fragments
+			//
+			// The non-sdk contents of BCP/SSCP fragments should only be used for dexpreopt and hiddenapi,
+			// and are not available to the rest of the build.
+			if android.InList(member.memberType,
+				[]android.SdkMemberType{
+					// bcp
+					java.BootclasspathFragmentSdkMemberType,
+					java.JavaBootLibsSdkMemberType,
+					// sscp
+					java.SystemServerClasspathFragmentSdkMemberType,
+					java.JavaSystemserverLibsSdkMemberType,
+				},
+			) {
+				continue
+			}
+
+			memberNames = append(memberNames, android.PrebuiltNameFromSource(member.name))
+		}
+	}
+
+	// create an apex_contributions_defaults for this module's sdk.
+	// this module type is supported in V and above.
+	if targetApiLevel.GreaterThan(android.ApiLevelUpsideDownCake) {
+		ac := newModule("apex_contributions_defaults")
+		ac.AddProperty("name", s.Name()+".contributions")
+		ac.AddProperty("contents", memberNames)
+		bpFile.AddModule(ac)
 	}
 
 	// Create a transformer that will transform a module by replacing any references
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 2f25a8c..81c678d 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -94,7 +94,6 @@
 	"gcert":          Allowed,
 	"gcertstatus":    Allowed,
 	"gcloud":         Allowed,
-	"getopt":         Allowed,
 	"git":            Allowed,
 	"hexdump":        Allowed,
 	"jar":            Allowed,