Merge "Revert "Convert BuildIgnoreApexContritbutions variable to a boolean"" 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/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/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/config.go b/android/config.go
index 567ebd8..10c30d4 100644
--- a/android/config.go
+++ b/android/config.go
@@ -168,7 +168,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 +212,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 {
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/singleton.go b/android/singleton.go
index ccddeaf..5f93996 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -251,7 +251,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))
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/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/apex/aconfig_test.go b/apex/aconfig_test.go
index be98d45..a179dbf 100644
--- a/apex/aconfig_test.go
+++ b/apex/aconfig_test.go
@@ -193,6 +193,70 @@
 					mode: "exported",
 				}`,
 		},
+		{
+			name: "Rust lib passes for exported containers cross",
+			bp: apex_default_bp + `
+			apex {
+				name: "myapex",
+				manifest: ":myapex.manifest",
+				androidManifest: ":myapex.androidmanifest",
+				key: "myapex.key",
+				native_shared_libs: ["libmy_rust_library"],
+				binaries: ["my_rust_binary"],
+				updatable: false,
+			}
+			rust_library {
+				name: "libflags_rust", // test mock
+				crate_name: "flags_rust",
+				srcs: ["lib.rs"],
+				apex_available: ["myapex"],
+			}
+			rust_library {
+				name: "liblazy_static", // test mock
+				crate_name: "lazy_static",
+				srcs: ["src/lib.rs"],
+				apex_available: ["myapex"],
+			}
+			rust_ffi_shared {
+				name: "libmy_rust_library",
+				srcs: ["src/lib.rs"],
+				rustlibs: ["libmy_rust_aconfig_library_foo"],
+				crate_name: "my_rust_library",
+				apex_available: ["myapex"],
+			}
+			rust_binary {
+				name: "my_rust_binary",
+				srcs: ["foo/bar/MyClass.rs"],
+				rustlibs: ["libmy_rust_aconfig_library_bar"],
+				apex_available: ["myapex"],
+			}
+			aconfig_declarations {
+				name: "my_aconfig_declarations_foo",
+				package: "com.example.package",
+				container: "otherapex",
+				srcs: ["foo.aconfig"],
+			}
+			aconfig_declarations {
+				name: "my_aconfig_declarations_bar",
+				package: "com.example.package",
+				container: "otherapex",
+				srcs: ["bar.aconfig"],
+			}
+			rust_aconfig_library {
+				name: "libmy_rust_aconfig_library_foo",
+				aconfig_declarations: "my_aconfig_declarations_foo",
+				crate_name: "my_rust_aconfig_library_foo",
+				apex_available: ["myapex"],
+				mode: "exported",
+			}
+			rust_aconfig_library {
+				name: "libmy_rust_aconfig_library_bar",
+				aconfig_declarations: "my_aconfig_declarations_bar",
+				crate_name: "my_rust_aconfig_library_bar",
+				apex_available: ["myapex"],
+				mode: "exported",
+			}`,
+		},
 	}
 	for _, test := range testCases {
 		t.Run(test.name, func(t *testing.T) {
@@ -394,6 +458,93 @@
 			expectedError: `.*my_cc_binary_foo/myapex depends on my_cc_aconfig_library_foo/otherapex/production across containers`,
 		},
 		{
+			name: "Rust lib fails for non-exported containers cross",
+			bp: apex_default_bp + `
+			apex {
+				name: "myapex",
+				manifest: ":myapex.manifest",
+				androidManifest: ":myapex.androidmanifest",
+				key: "myapex.key",
+				native_shared_libs: ["libmy_rust_library"],
+				updatable: false,
+			}
+			rust_library {
+				name: "libflags_rust", // test mock
+				crate_name: "flags_rust",
+				srcs: ["lib.rs"],
+				apex_available: ["myapex"],
+			}
+			rust_library {
+				name: "liblazy_static", // test mock
+				crate_name: "lazy_static",
+				srcs: ["src/lib.rs"],
+				apex_available: ["myapex"],
+			}
+			rust_ffi_shared {
+				name: "libmy_rust_library",
+				srcs: ["src/lib.rs"],
+				rustlibs: ["libmy_rust_aconfig_library_foo"],
+				crate_name: "my_rust_library",
+				apex_available: ["myapex"],
+			}
+			aconfig_declarations {
+				name: "my_aconfig_declarations_foo",
+				package: "com.example.package",
+				container: "otherapex",
+				srcs: ["foo.aconfig"],
+			}
+			rust_aconfig_library {
+				name: "libmy_rust_aconfig_library_foo",
+				aconfig_declarations: "my_aconfig_declarations_foo",
+				crate_name: "my_rust_aconfig_library_foo",
+				apex_available: ["myapex"],
+			}`,
+			expectedError: `.*libmy_rust_aconfig_library_foo/myapex depends on libmy_rust_aconfig_library_foo/otherapex/production across containers`,
+		},
+		{
+			name: "Rust binary fails for non-exported containers cross",
+			bp: apex_default_bp + `
+			apex {
+				name: "myapex",
+				manifest: ":myapex.manifest",
+				androidManifest: ":myapex.androidmanifest",
+				key: "myapex.key",
+				binaries: ["my_rust_binary"],
+				updatable: false,
+			}
+			rust_library {
+				name: "libflags_rust", // test mock
+				crate_name: "flags_rust",
+				srcs: ["lib.rs"],
+				apex_available: ["myapex"],
+			}
+			rust_library {
+				name: "liblazy_static", // test mock
+				crate_name: "lazy_static",
+				srcs: ["src/lib.rs"],
+				apex_available: ["myapex"],
+			}
+			rust_binary {
+				name: "my_rust_binary",
+				srcs: ["foo/bar/MyClass.rs"],
+				rustlibs: ["libmy_rust_aconfig_library_bar"],
+				apex_available: ["myapex"],
+			}
+			aconfig_declarations {
+				name: "my_aconfig_declarations_bar",
+				package: "com.example.package",
+				container: "otherapex",
+				srcs: ["bar.aconfig"],
+			}
+			rust_aconfig_library {
+				name: "libmy_rust_aconfig_library_bar",
+				aconfig_declarations: "my_aconfig_declarations_bar",
+				crate_name: "my_rust_aconfig_library_bar",
+				apex_available: ["myapex"],
+			}`,
+			expectedError: `.*libmy_rust_aconfig_library_bar/myapex depends on libmy_rust_aconfig_library_bar/otherapex/production across containers`,
+		},
+		{
 			name: "Aconfig validation propagate along sourceOrOutputDependencyTag",
 			bp: apex_default_bp + `
 				apex {
diff --git a/apex/apex.go b/apex/apex.go
index 32a3638..ed2ca98 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 {
@@ -2120,7 +2119,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 +2265,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() {
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..0896206 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -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/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..e2d99eb 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -54,6 +54,9 @@
 
 	// Use -fwhole-program-vtables cflag.
 	Whole_program_vtables *bool
+
+	// Use --lto-O0 flag.
+	Lto_O0 *bool
 }
 
 type lto struct {
@@ -110,12 +113,8 @@
 		ltoCFlags := []string{"-flto=thin", "-fsplit-lto-unit"}
 		var ltoLdFlags []string
 
-		// The module did not explicitly turn on LTO. Only leverage LTO's
-		// better dead code elimination and CFG simplification, but do
-		// not perform costly optimizations for a balance between compile
-		// time, binary size and performance.
-		// Apply the same for Eng builds as well.
-		if !lto.ThinLTO() || ctx.Config().Eng() {
+		// Do not perform costly LTO optimizations for Eng builds.
+		if Bool(lto.Properties.Lto_O0) || ctx.Config().Eng() {
 			ltoLdFlags = append(ltoLdFlags, "-Wl,--lto-O0")
 		}
 
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..a42c576 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -71,10 +71,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 +132,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 +147,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 +251,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 +268,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 +279,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 +312,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 +325,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 +480,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...)
 				}
@@ -700,7 +759,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..1d9aa8e 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) {
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/system_image.go b/filesystem/system_image.go
index 34f4ffb..78ce377 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}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index a2a3f75..cf2a966 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -808,7 +808,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..5061879 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 {
@@ -348,6 +351,7 @@
 	classLoaderContexts            dexpreopt.ClassLoaderContextMap
 	excludedLibs                   []string
 	enforceDefaultTargetSdkVersion bool
+	forceNonFinalResourceIDs       bool
 	extraLinkFlags                 []string
 	aconfigTextFiles               android.Paths
 }
@@ -541,7 +545,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 +610,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 +621,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
@@ -804,6 +813,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 +830,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)
@@ -1213,7 +1227,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)
 
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/app.go b/java/app.go
index 4f6f1f3..2abc451 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
@@ -1507,7 +1516,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..b75cb16 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -4401,3 +4401,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..be286fe 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,
@@ -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
@@ -2295,6 +2297,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 +2356,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 b721f58..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" && ` +
@@ -223,16 +233,6 @@
 	if err != nil {
 		ctx.PropertyErrorf("min_sdk_version", "%s", err)
 	}
-	if effectiveVersion.FinalOrFutureInt() >= 35 {
-		// V is 35, but we have not bumped the SDK version yet, so check for both.
-		if ctx.Config().PlatformSdkVersion().FinalInt() >= 35 ||
-			ctx.Config().PlatformSdkCodename() == "VanillaIceCream" {
-			// TODO(b/329465418): Skip this module since it causes issue with app DRM
-			if ctx.ModuleName() != "framework-minus-apex" {
-				flags = append([]string{"-JDcom.android.tools.r8.dexContainerExperiment"}, flags...)
-			}
-		}
-	}
 
 	// If the specified SDK level is 10000, then configure the compiler to use the
 	// current platform SDK level and to compile the build as a platform build.
@@ -361,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 e606993..97feb9b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -82,8 +82,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 +154,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 +193,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 +309,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 +901,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)
@@ -1694,7 +1698,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
@@ -3005,7 +3009,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..194f9d9 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2757,3 +2757,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_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..fb584c5 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`,
@@ -1393,6 +1393,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/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/rust.go b/rust/rust.go
index 245ed2e..7d81c72 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1063,6 +1063,12 @@
 	return nil
 }
 
+func (d dependencyTag) PropagateAconfigValidation() bool {
+	return d == rlibDepTag || d == sourceDepTag
+}
+
+var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{}
+
 var _ android.LicenseAnnotationsDependencyTag = dependencyTag{}
 
 var (
@@ -1136,6 +1142,7 @@
 		}
 	}
 }
+
 func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
 	var depPaths PathDeps
 
@@ -1427,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/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/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 698aaf2..b9b68be 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -54,15 +54,13 @@
 }
 
 type syspropRustGenRule struct {
-	android.ModuleBase
+	*rust.BaseSourceProvider
 
-	properties syspropGenProperties
-
-	genSrcs android.Paths
+	properties rustLibraryProperties
 }
 
 var _ android.OutputFileProducer = (*syspropJavaGenRule)(nil)
-var _ android.OutputFileProducer = (*syspropRustGenRule)(nil)
+var _ rust.SourceProvider = (*syspropRustGenRule)(nil)
 
 var (
 	syspropJava = pctx.AndroidStaticRule("syspropJava",
@@ -144,7 +142,7 @@
 
 // syspropRustGenRule module generates rust source files containing generated rust APIs.
 // It also depends on check api rule, so api check has to pass to use sysprop_library.
-func (g *syspropRustGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (g *syspropRustGenRule) GenerateSource(ctx rust.ModuleContext, deps rust.PathDeps) android.Path {
 	var checkApiFileTimeStamp android.WritablePath
 
 	ctx.VisitDirectDeps(func(dep android.Module) {
@@ -153,25 +151,47 @@
 		}
 	})
 
-	for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
-		syspropDir := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcrust")
-		outputDir := syspropDir.Join(ctx, "src")
-		libPath := syspropDir.Join(ctx, "src", "lib.rs")
+	outputDir := android.PathForModuleOut(ctx, "src")
+	libFile := outputDir.Join(ctx, "lib.rs")
+	g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, libFile)
+	libFileLines := []string{"//! Autogenerated system property accessors."}
+
+	for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Sysprop_srcs) {
+		moduleName := syspropPathToRustModule(syspropFile)
+		moduleDir := outputDir.Join(ctx, moduleName)
+		modulePath := moduleDir.Join(ctx, "mod.rs")
 
 		ctx.Build(pctx, android.BuildParams{
 			Rule:        syspropRust,
 			Description: "sysprop_rust " + syspropFile.Rel(),
-			Outputs:     android.WritablePaths{libPath},
+			Output:      modulePath,
 			Input:       syspropFile,
 			Implicit:    checkApiFileTimeStamp,
 			Args: map[string]string{
 				"scope":   g.properties.Scope,
-				"out_dir": outputDir.String(),
+				"out_dir": moduleDir.String(),
 			},
 		})
 
-		g.genSrcs = append(g.genSrcs, libPath)
+		g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, modulePath)
+		libFileLines = append(libFileLines, fmt.Sprintf("pub mod %s;", moduleName))
 	}
+
+	libFileSource := strings.Join(libFileLines, "\n")
+	android.WriteFileRule(ctx, libFile, libFileSource)
+
+	return libFile
+}
+
+func (g *syspropRustGenRule) SourceProviderProps() []interface{} {
+	return append(g.BaseSourceProvider.SourceProviderProps(), &g.Properties)
+}
+
+// syspropPathToRustModule takes a path to a .sysprop file and returns the name to use for the
+// corresponding Rust module.
+func syspropPathToRustModule(syspropFilename android.Path) string {
+	filenameBase := strings.TrimSuffix(syspropFilename.Base(), ".sysprop")
+	return strings.ToLower(filenameBase)
 }
 
 func (g *syspropRustGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -180,15 +200,13 @@
 	ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api))
 }
 
-func (g *syspropRustGenRule) OutputFiles(_ string) (android.Paths, error) {
-	return g.genSrcs, nil
-}
-
 func syspropRustGenFactory() android.Module {
-	g := &syspropRustGenRule{}
-	g.AddProperties(&g.properties)
-	android.InitAndroidModule(g)
-	return g
+	g := &syspropRustGenRule{
+		BaseSourceProvider: rust.NewSourceProvider(),
+	}
+	sourceProvider := rust.NewSourceProviderModule(android.DeviceSupported, g, false, false)
+	sourceProvider.AddProperties(&g.properties)
+	return sourceProvider.Init()
 }
 
 type syspropLibrary struct {
@@ -308,10 +326,6 @@
 	return m.BaseModuleName() + "_java_gen_public"
 }
 
-func (m *syspropLibrary) rustGenModuleName() string {
-	return m.rustCrateName() + "_rust_gen"
-}
-
 func (m *syspropLibrary) rustGenStubName() string {
 	return "lib" + m.rustCrateName() + "_rust"
 }
@@ -528,6 +542,9 @@
 
 type rustLibraryProperties struct {
 	Name              *string
+	Sysprop_srcs      []string `android:"path"`
+	Scope             string
+	Check_api         *string
 	Srcs              []string
 	Installable       *bool
 	Crate_name        string
@@ -667,18 +684,15 @@
 	}
 
 	// Generate a Rust implementation library.
-	ctx.CreateModule(syspropRustGenFactory, &syspropGenProperties{
-		Srcs:      m.properties.Srcs,
-		Scope:     scope,
-		Name:      proptools.StringPtr(m.rustGenModuleName()),
-		Check_api: proptools.StringPtr(ctx.ModuleName()),
-	})
 	rustProps := rustLibraryProperties{
-		Name:        proptools.StringPtr(m.rustGenStubName()),
-		Srcs:        []string{":" + m.rustGenModuleName()},
-		Installable: proptools.BoolPtr(false),
-		Crate_name:  m.rustCrateName(),
+		Name:         proptools.StringPtr(m.rustGenStubName()),
+		Sysprop_srcs: m.properties.Srcs,
+		Scope:        scope,
+		Check_api:    proptools.StringPtr(ctx.ModuleName()),
+		Installable:  proptools.BoolPtr(false),
+		Crate_name:   m.rustCrateName(),
 		Rustlibs: []string{
+			"liblog_rust",
 			"librustutils",
 		},
 		Vendor_available:  m.properties.Vendor_available,
@@ -686,7 +700,7 @@
 		Apex_available:    m.ApexProperties.Apex_available,
 		Min_sdk_version:   proptools.StringPtr("29"),
 	}
-	ctx.CreateModule(rust.RustLibraryFactory, &rustProps)
+	ctx.CreateModule(syspropRustGenFactory, &rustProps)
 
 	// syspropLibraries will be used by property_contexts to check types.
 	// Record absolute paths of sysprop_library to prevent soong_namespace problem.
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 9dd696f..dfbbe7d 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -72,6 +72,15 @@
 			vendor_available: true,
 			min_sdk_version: "29",
 		}
+
+		rust_library {
+			name: "liblog_rust",
+			crate_name: "log",
+			srcs: ["log/src/lib.rs"],
+			product_available: true,
+			vendor_available: true,
+			min_sdk_version: "29",
+		}
 	`
 
 	mockFS := android.MockFS{
@@ -115,6 +124,7 @@
 		"com/android2/OdmProperties.sysprop":         nil,
 
 		"librustutils/lib.rs": nil,
+		"log/src/lib.rs":      nil,
 	}
 
 	result := android.GroupFixturePreparers(