Merge "rustc-1.75.0 Build 11471753" into main
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go
index b6c9023..3d9663c 100644
--- a/aconfig/all_aconfig_declarations.go
+++ b/aconfig/all_aconfig_declarations.go
@@ -31,7 +31,8 @@
 }
 
 type allAconfigDeclarationsSingleton struct {
-	intermediatePath android.OutputPath
+	intermediateBinaryProtoPath android.OutputPath
+	intermediateTextProtoPath   android.OutputPath
 }
 
 func (this *allAconfigDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
@@ -59,20 +60,35 @@
 		panic(fmt.Errorf("Only one aconfig_declarations allowed for each package."))
 	}
 
-	// Generate build action for aconfig
-	this.intermediatePath = android.PathForIntermediates(ctx, "all_aconfig_declarations.pb")
+	// Generate build action for aconfig (binary proto output)
+	this.intermediateBinaryProtoPath = android.PathForIntermediates(ctx, "all_aconfig_declarations.pb")
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        AllDeclarationsRule,
 		Inputs:      cacheFiles,
-		Output:      this.intermediatePath,
+		Output:      this.intermediateBinaryProtoPath,
 		Description: "all_aconfig_declarations",
 		Args: map[string]string{
 			"cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
 		},
 	})
-	ctx.Phony("all_aconfig_declarations", this.intermediatePath)
+	ctx.Phony("all_aconfig_declarations", this.intermediateBinaryProtoPath)
+
+	// Generate build action for aconfig (text proto output)
+	this.intermediateTextProtoPath = android.PathForIntermediates(ctx, "all_aconfig_declarations.textproto")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        AllDeclarationsRuleTextProto,
+		Inputs:      cacheFiles,
+		Output:      this.intermediateTextProtoPath,
+		Description: "all_aconfig_declarations_textproto",
+		Args: map[string]string{
+			"cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
+		},
+	})
+	ctx.Phony("all_aconfig_declarations_textproto", this.intermediateTextProtoPath)
 }
 
 func (this *allAconfigDeclarationsSingleton) MakeVars(ctx android.MakeVarsContext) {
-	ctx.DistForGoal("droid", this.intermediatePath)
+	ctx.DistForGoal("droid", this.intermediateBinaryProtoPath)
+	ctx.DistForGoalWithFilename("sdk", this.intermediateBinaryProtoPath, "flags.pb")
+	ctx.DistForGoalWithFilename("sdk", this.intermediateTextProtoPath, "flags.textproto")
 }
diff --git a/aconfig/codegen/Android.bp b/aconfig/codegen/Android.bp
index 494f7e6..0c78b94 100644
--- a/aconfig/codegen/Android.bp
+++ b/aconfig/codegen/Android.bp
@@ -17,6 +17,7 @@
         "soong-rust",
     ],
     srcs: [
+        "aconfig_declarations_group.go",
         "cc_aconfig_library.go",
         "init.go",
         "java_aconfig_library.go",
@@ -24,6 +25,7 @@
         "testing.go",
     ],
     testSrcs: [
+        "aconfig_declarations_group_test.go",
         "java_aconfig_library_test.go",
         "cc_aconfig_library_test.go",
         "rust_aconfig_library_test.go",
diff --git a/aconfig/codegen/aconfig_declarations_group.go b/aconfig/codegen/aconfig_declarations_group.go
new file mode 100644
index 0000000..203b6be
--- /dev/null
+++ b/aconfig/codegen/aconfig_declarations_group.go
@@ -0,0 +1,129 @@
+// Copyright 2024 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 codegen
+
+import (
+	"android/soong/aconfig"
+	"android/soong/android"
+	"fmt"
+
+	"github.com/google/blueprint"
+)
+
+type dependencyTag struct {
+	blueprint.BaseDependencyTag
+	name string
+}
+
+var (
+	aconfigDeclarationsGroupTag = dependencyTag{name: "aconfigDeclarationsGroup"}
+	javaAconfigLibraryTag       = dependencyTag{name: "javaAconfigLibrary"}
+	ccAconfigLibraryTag         = dependencyTag{name: "ccAconfigLibrary"}
+	rustAconfigLibraryTag       = dependencyTag{name: "rustAconfigLibrary"}
+)
+
+type AconfigDeclarationsGroup struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties AconfigDeclarationsGroupProperties
+
+	aconfigDeclarationNames      []string
+	intermediateCacheOutputPaths android.Paths
+	javaSrcjars                  android.Paths
+}
+
+type AconfigDeclarationsGroupProperties struct {
+
+	// Name of the aconfig_declarations_group modules
+	Aconfig_declarations_groups []string
+
+	// Name of the java_aconfig_library modules
+	Java_aconfig_libraries []string
+
+	// Name of the cc_aconfig_library modules
+	Cc_aconfig_libraries []string
+
+	// Name of the rust_aconfig_library modules
+	Rust_aconfig_libraries []string
+}
+
+func AconfigDeclarationsGroupFactory() android.Module {
+	module := &AconfigDeclarationsGroup{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	return module
+}
+
+func (adg *AconfigDeclarationsGroup) DepsMutator(ctx android.BottomUpMutatorContext) {
+	ctx.AddDependency(ctx.Module(), aconfigDeclarationsGroupTag, adg.properties.Aconfig_declarations_groups...)
+	ctx.AddDependency(ctx.Module(), javaAconfigLibraryTag, adg.properties.Java_aconfig_libraries...)
+	ctx.AddDependency(ctx.Module(), ccAconfigLibraryTag, adg.properties.Cc_aconfig_libraries...)
+	ctx.AddDependency(ctx.Module(), rustAconfigLibraryTag, adg.properties.Rust_aconfig_libraries...)
+}
+
+func (adg *AconfigDeclarationsGroup) VisitDeps(ctx android.ModuleContext) {
+	ctx.VisitDirectDeps(func(dep android.Module) {
+		tag := ctx.OtherModuleDependencyTag(dep)
+		if provider, ok := android.OtherModuleProvider(ctx, dep, aconfig.CodegenInfoProvider); ok {
+
+			// aconfig declaration names and cache files are collected for all aconfig library dependencies
+			adg.aconfigDeclarationNames = append(adg.aconfigDeclarationNames, provider.AconfigDeclarations...)
+			adg.intermediateCacheOutputPaths = append(adg.intermediateCacheOutputPaths, provider.IntermediateCacheOutputPaths...)
+
+			switch tag {
+			case aconfigDeclarationsGroupTag:
+				// Will retrieve outputs from another language codegen modules when support is added
+				adg.javaSrcjars = append(adg.javaSrcjars, provider.Srcjars...)
+			case javaAconfigLibraryTag:
+				adg.javaSrcjars = append(adg.javaSrcjars, provider.Srcjars...)
+			}
+		}
+	})
+}
+
+func (adg *AconfigDeclarationsGroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	adg.VisitDeps(ctx)
+	adg.aconfigDeclarationNames = android.FirstUniqueStrings(adg.aconfigDeclarationNames)
+	adg.intermediateCacheOutputPaths = android.FirstUniquePaths(adg.intermediateCacheOutputPaths)
+
+	android.SetProvider(ctx, aconfig.CodegenInfoProvider, aconfig.CodegenInfo{
+		AconfigDeclarations:          adg.aconfigDeclarationNames,
+		IntermediateCacheOutputPaths: adg.intermediateCacheOutputPaths,
+		Srcjars:                      adg.javaSrcjars,
+	})
+}
+
+var _ android.OutputFileProducer = (*AconfigDeclarationsGroup)(nil)
+
+func (adg *AconfigDeclarationsGroup) OutputFiles(tag string) (android.Paths, error) {
+	switch tag {
+	case "":
+		return adg.intermediateCacheOutputPaths, nil
+	case ".srcjars":
+		return adg.javaSrcjars, nil
+	default:
+		return nil, fmt.Errorf("unsupported module reference tag %s", tag)
+	}
+}
+
+func (adg *AconfigDeclarationsGroup) Srcjars() android.Paths {
+	return adg.javaSrcjars
+}
+
+func (adg *AconfigDeclarationsGroup) AconfigDeclarations() []string {
+	return adg.aconfigDeclarationNames
+}
diff --git a/aconfig/codegen/aconfig_declarations_group_test.go b/aconfig/codegen/aconfig_declarations_group_test.go
new file mode 100644
index 0000000..ec7cea3
--- /dev/null
+++ b/aconfig/codegen/aconfig_declarations_group_test.go
@@ -0,0 +1,79 @@
+// Copyright 2024 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 codegen
+
+import (
+	"android/soong/android"
+	"android/soong/java"
+	"testing"
+)
+
+func TestAconfigDeclarationsGroup(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		PrepareForTestWithAconfigBuildComponents,
+		java.PrepareForTestWithJavaDefaultModules,
+	).RunTestWithBp(t, `
+		aconfig_declarations {
+			name: "foo-aconfig",
+			package: "com.example.package",
+			srcs: ["foo.aconfig"],
+		}
+
+		java_aconfig_library {
+			name: "foo-java",
+			aconfig_declarations: "foo-aconfig",
+		}
+
+		aconfig_declarations {
+			name: "bar-aconfig",
+			package: "com.example.package",
+			srcs: ["foo.aconfig"],
+		}
+
+		java_aconfig_library {
+			name: "bar-java",
+			aconfig_declarations: "bar-aconfig",
+		}
+
+		aconfig_declarations_group {
+			name: "my_group",
+			java_aconfig_libraries: [
+				"foo-java",
+				"bar-java",
+			],
+		}
+
+		java_library {
+			name: "baz",
+			srcs: [
+				":my_group{.srcjars}",
+			],
+		}
+	`)
+
+	// Check if aconfig_declarations_group module depends on the aconfig_library modules
+	java.CheckModuleDependencies(t, result.TestContext, "my_group", "", []string{
+		`bar-java`,
+		`foo-java`,
+	})
+
+	// Check if srcjar files are correctly passed to the reverse dependency of
+	// aconfig_declarations_group module
+	bazModule := result.ModuleForTests("baz", "android_common")
+	bazJavacSrcjars := bazModule.Rule("javac").Args["srcJars"]
+	errorMessage := "baz javac argument expected to contain srcjar provided by aconfig_declrations_group"
+	android.AssertStringDoesContain(t, errorMessage, bazJavacSrcjars, "foo-java.srcjar")
+	android.AssertStringDoesContain(t, errorMessage, bazJavacSrcjars, "bar-java.srcjar")
+}
diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go
index 0bff9d2..73a8951 100644
--- a/aconfig/codegen/init.go
+++ b/aconfig/codegen/init.go
@@ -77,6 +77,7 @@
 }
 
 func RegisterBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("aconfig_declarations_group", AconfigDeclarationsGroupFactory)
 	ctx.RegisterModuleType("cc_aconfig_library", CcAconfigLibraryFactory)
 	ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory)
 	ctx.RegisterModuleType("rust_aconfig_library", RustAconfigLibraryFactory)
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
index d4c6da5..7d7296e 100644
--- a/aconfig/codegen/java_aconfig_library.go
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 
+	"android/soong/aconfig"
 	"android/soong/android"
 	"android/soong/java"
 
@@ -118,6 +119,12 @@
 		module.AddJarJarRenameRule(declarations.Package+".FakeFeatureFlagsImpl", "")
 	}
 
+	android.SetProvider(ctx, aconfig.CodegenInfoProvider, aconfig.CodegenInfo{
+		AconfigDeclarations:          []string{declarationsModules[0].Name()},
+		IntermediateCacheOutputPaths: android.Paths{declarations.IntermediateCacheOutputPath},
+		Srcjars:                      android.Paths{srcJarPath},
+	})
+
 	return srcJarPath
 }
 
diff --git a/aconfig/init.go b/aconfig/init.go
index 77f5ed3..e64429f 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -20,6 +20,20 @@
 	"github.com/google/blueprint"
 )
 
+type CodegenInfo struct {
+	// AconfigDeclarations is the name of the aconfig_declarations modules that
+	// the codegen module is associated with
+	AconfigDeclarations []string
+
+	// Paths to the cache files of the associated aconfig_declaration modules
+	IntermediateCacheOutputPaths android.Paths
+
+	// Paths to the srcjar files generated from the java_aconfig_library modules
+	Srcjars android.Paths
+}
+
+var CodegenInfoProvider = blueprint.NewProvider[CodegenInfo]()
+
 var (
 	pctx = android.NewPackageContext("android/soong/aconfig")
 
@@ -61,6 +75,21 @@
 				"${aconfig}",
 			},
 		}, "cache_files")
+	AllDeclarationsRuleTextProto = pctx.AndroidStaticRule("All_aconfig_declarations_dump_textproto",
+		blueprint.RuleParams{
+			Command: `${aconfig} dump-cache --dedup --format textproto --out ${out} ${cache_files}`,
+			CommandDeps: []string{
+				"${aconfig}",
+			},
+		}, "cache_files")
+
+	CreateStorageRule = pctx.AndroidStaticRule("aconfig_create_storage",
+		blueprint.RuleParams{
+			Command: `${aconfig} create-storage --container ${container} --file ${file_type} --out ${out} ${cache_files}`,
+			CommandDeps: []string{
+				"${aconfig}",
+			},
+		}, "container", "file_type", "cache_files")
 
 	// For exported_java_aconfig_library: Generate a JAR from all
 	// java_aconfig_libraries to be consumed by apps built outside the
diff --git a/android/all_teams.go b/android/all_teams.go
index dd7d2db..b177e20 100644
--- a/android/all_teams.go
+++ b/android/all_teams.go
@@ -68,10 +68,6 @@
 	this.teams_for_mods = make(map[string]moduleTeamInfo)
 
 	ctx.VisitAllModules(func(module Module) {
-		if !module.Enabled() {
-			return
-		}
-
 		bpFile := ctx.BlueprintFile(module)
 
 		// Package Modules and Team Modules are stored in a map so we can look them up by name for
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index 236abf6..89e27b9 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -98,6 +98,10 @@
 func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) {
 	addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
 		for _, content := range m.Contents() {
+			// Skip any apexes that have been added to the product specific ignore list
+			if InList(content, ctx.Config().BuildIgnoreApexContributionContents()) {
+				continue
+			}
 			if !ctx.OtherModuleExists(content) && !ctx.Config().AllowMissingDependencies() {
 				ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name())
 			}
diff --git a/android/config.go b/android/config.go
index e57bc2c..75471b9 100644
--- a/android/config.go
+++ b/android/config.go
@@ -654,6 +654,7 @@
 		"framework-nfc":                     {},
 		"framework-ondevicepersonalization": {},
 		"framework-pdf":                     {},
+		"framework-pdf-v":                   {},
 		"framework-permission":              {},
 		"framework-permission-s":            {},
 		"framework-scheduling":              {},
@@ -1342,6 +1343,22 @@
 	return String(c.productVariables.VendorApiLevel)
 }
 
+func (c *config) PrevVendorApiLevel() string {
+	vendorApiLevel, err := strconv.Atoi(c.VendorApiLevel())
+	if err != nil {
+		panic(fmt.Errorf("Cannot parse vendor API level %s to an integer: %s",
+			c.VendorApiLevel(), err))
+	}
+	if vendorApiLevel < 202404 || vendorApiLevel%100 != 4 {
+		panic("Unknown vendor API level " + c.VendorApiLevel())
+	}
+	// The version before trunk stable is 34.
+	if vendorApiLevel == 202404 {
+		return "34"
+	}
+	return strconv.Itoa(vendorApiLevel - 100)
+}
+
 func (c *config) VendorApiLevelFrozen() bool {
 	return c.productVariables.GetBuildFlagBool("RELEASE_BOARD_API_LEVEL_FROZEN")
 }
@@ -2044,3 +2061,7 @@
 	}
 	return ret
 }
+
+func (c *config) BuildIgnoreApexContributionContents() []string {
+	return c.productVariables.BuildIgnoreApexContributionContents
+}
diff --git a/android/variable.go b/android/variable.go
index 758967e..2520020 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -494,6 +494,8 @@
 	BuildFlags map[string]string `json:",omitempty"`
 
 	BuildFromSourceStub *bool `json:",omitempty"`
+
+	BuildIgnoreApexContributionContents []string `json:",omitempty"`
 }
 
 type PartitionQualifiedVariablesType struct {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 5cc50dd..02dc6e6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -11115,25 +11115,23 @@
 	mod := ctx.ModuleForTests("myapex", "android_common_myapex")
 	s := mod.Rule("apexRule").Args["copy_commands"]
 	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
-	if len(copyCmds) != 5 {
+	if len(copyCmds) != 8 {
 		t.Fatalf("Expected 5 commands, got %d in:\n%s", len(copyCmds), s)
 	}
 
 	ensureMatches(t, copyCmds[4], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
+	ensureMatches(t, copyCmds[5], "^cp -f .*/package.map .*/image.apex$")
+	ensureMatches(t, copyCmds[6], "^cp -f .*/flag.map .*/image.apex$")
+	ensureMatches(t, copyCmds[7], "^cp -f .*/flag.val .*/image.apex$")
 
-	combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
-	s = " " + combineAconfigRule.Args["cache_files"]
-	aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
-	if len(aconfigArgs) != 2 {
-		t.Fatalf("Expected 2 commands, got %d in:\n%s", len(aconfigArgs), s)
+	inputs := []string{
+		"my_aconfig_declarations_foo/intermediate.pb",
+		"my_aconfig_declarations_bar/intermediate.pb",
 	}
-	android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
-	android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_bar/intermediate.pb")
-
-	buildParams := combineAconfigRule.BuildParams
-	android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
-	android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_bar/intermediate.pb")
-	ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+	VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
+	VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
+	VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
+	VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
 }
 
 func TestAconfigFilesJavaAndCcDeps(t *testing.T) {
@@ -11241,30 +11239,24 @@
 	mod := ctx.ModuleForTests("myapex", "android_common_myapex")
 	s := mod.Rule("apexRule").Args["copy_commands"]
 	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
-	if len(copyCmds) != 9 {
-		t.Fatalf("Expected 9 commands, got %d in:\n%s", len(copyCmds), s)
+	if len(copyCmds) != 12 {
+		t.Fatalf("Expected 12 commands, got %d in:\n%s", len(copyCmds), s)
 	}
 
 	ensureMatches(t, copyCmds[8], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
+	ensureMatches(t, copyCmds[9], "^cp -f .*/package.map .*/image.apex$")
+	ensureMatches(t, copyCmds[10], "^cp -f .*/flag.map .*/image.apex$")
+	ensureMatches(t, copyCmds[11], "^cp -f .*/flag.val .*/image.apex$")
 
-	combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
-	s = " " + combineAconfigRule.Args["cache_files"]
-	aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
-	if len(aconfigArgs) != 3 {
-		t.Fatalf("Expected 3 commands, got %d in:\n%s", len(aconfigArgs), s)
+	inputs := []string{
+		"my_aconfig_declarations_foo/intermediate.pb",
+		"my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/myapex/aconfig_merged.pb",
+		"my_aconfig_declarations_baz/intermediate.pb",
 	}
-	android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
-	android.EnsureListContainsSuffix(t, aconfigArgs, "my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/myapex/aconfig_merged.pb")
-	android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_baz/intermediate.pb")
-
-	buildParams := combineAconfigRule.BuildParams
-	if len(buildParams.Inputs) != 3 {
-		t.Fatalf("Expected 3 input, got %d", len(buildParams.Inputs))
-	}
-	android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
-	android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/myapex/aconfig_merged.pb")
-	android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_baz/intermediate.pb")
-	ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+	VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
+	VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
+	VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
+	VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
 }
 
 func TestAconfigFilesRustDeps(t *testing.T) {
@@ -11388,28 +11380,43 @@
 	mod := ctx.ModuleForTests("myapex", "android_common_myapex")
 	s := mod.Rule("apexRule").Args["copy_commands"]
 	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
-	if len(copyCmds) != 23 {
-		t.Fatalf("Expected 23 commands, got %d in:\n%s", len(copyCmds), s)
+	if len(copyCmds) != 26 {
+		t.Fatalf("Expected 26 commands, got %d in:\n%s", len(copyCmds), s)
 	}
 
 	ensureMatches(t, copyCmds[22], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
+	ensureMatches(t, copyCmds[23], "^cp -f .*/package.map .*/image.apex$")
+	ensureMatches(t, copyCmds[24], "^cp -f .*/flag.map .*/image.apex$")
+	ensureMatches(t, copyCmds[25], "^cp -f .*/flag.val .*/image.apex$")
 
-	combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
-	s = " " + combineAconfigRule.Args["cache_files"]
+	inputs := []string{
+		"my_aconfig_declarations_foo/intermediate.pb",
+		"my_rust_binary/android_arm64_armv8-a_apex10000/myapex/aconfig_merged.pb",
+	}
+	VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
+	VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
+	VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
+	VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
+}
+
+func VerifyAconfigRule(t *testing.T, mod *android.TestingModule, desc string, inputs []string, output string, container string, file_type string) {
+	aconfigRule := mod.Description(desc)
+	s := " " + aconfigRule.Args["cache_files"]
 	aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
-	if len(aconfigArgs) != 2 {
-		t.Fatalf("Expected 2 commands, got %d in:\n%s", len(aconfigArgs), s)
+	if len(aconfigArgs) != len(inputs) {
+		t.Fatalf("Expected %d commands, got %d in:\n%s", len(inputs), len(aconfigArgs), s)
 	}
-	android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
-	android.EnsureListContainsSuffix(t, aconfigArgs, "my_rust_binary/android_arm64_armv8-a_apex10000/myapex/aconfig_merged.pb")
 
-	buildParams := combineAconfigRule.BuildParams
-	if len(buildParams.Inputs) != 2 {
-		t.Fatalf("Expected 3 input, got %d", len(buildParams.Inputs))
+	ensureEquals(t, container, aconfigRule.Args["container"])
+	ensureEquals(t, file_type, aconfigRule.Args["file_type"])
+
+	buildParams := aconfigRule.BuildParams
+	for _, input := range inputs {
+		android.EnsureListContainsSuffix(t, aconfigArgs, input)
+		android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), input)
 	}
-	android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
-	android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_rust_binary/android_arm64_armv8-a_apex10000/myapex/aconfig_merged.pb")
-	ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+
+	ensureContains(t, buildParams.Output.String(), output)
 }
 
 func TestAconfigFilesOnlyMatchCurrentApex(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index 3d61219..e49cf28 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -85,6 +85,18 @@
 	pctx.HostBinToolVariable("aconfig", "aconfig")
 }
 
+type createStorageStruct struct {
+	Output_file string
+	Desc        string
+	File_type   string
+}
+
+var createStorageInfo = []createStorageStruct{
+	{"package.map", "create_aconfig_package_map_file", "package_map"},
+	{"flag.map", "create_aconfig_flag_map_file", "flag_map"},
+	{"flag.val", "create_aconfig_flag_val_file", "flag_val"},
+}
+
 var (
 	apexManifestRule = pctx.StaticRule("apexManifestRule", blueprint.RuleParams{
 		Command: `rm -f $out && ${jsonmodify} $in ` +
@@ -648,6 +660,25 @@
 		copyCommands = append(copyCommands, "cp -f "+apexAconfigFile.String()+" "+imageDir.String())
 		implicitInputs = append(implicitInputs, apexAconfigFile)
 		defaultReadOnlyFiles = append(defaultReadOnlyFiles, apexAconfigFile.Base())
+
+		for _, info := range createStorageInfo {
+			outputFile := android.PathForModuleOut(ctx, info.Output_file)
+			ctx.Build(pctx, android.BuildParams{
+				Rule:        aconfig.CreateStorageRule,
+				Inputs:      a.aconfigFiles,
+				Output:      outputFile,
+				Description: info.Desc,
+				Args: map[string]string{
+					"container":   ctx.ModuleName(),
+					"file_type":   info.File_type,
+					"cache_files": android.JoinPathsWithPrefix(a.aconfigFiles, "--cache "),
+				},
+			})
+
+			copyCommands = append(copyCommands, "cp -f "+outputFile.String()+" "+imageDir.String())
+			implicitInputs = append(implicitInputs, outputFile)
+			defaultReadOnlyFiles = append(defaultReadOnlyFiles, outputFile.Base())
+		}
 	}
 
 	////////////////////////////////////////////////////////////////////////////////////
diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go
index 43fb71d..b72b6d3 100644
--- a/bloaty/bloaty.go
+++ b/bloaty/bloaty.go
@@ -85,6 +85,9 @@
 func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonContext) {
 	var deps android.Paths
 	ctx.VisitAllModules(func(m android.Module) {
+		if !m.ExportedToMake() {
+			return
+		}
 		filePaths, ok := android.SingletonModuleProvider(ctx, m, fileSizeMeasurerKey)
 		if !ok {
 			return
diff --git a/cc/check.go b/cc/check.go
index 58ff5b2..32d1f06 100644
--- a/cc/check.go
+++ b/cc/check.go
@@ -45,6 +45,8 @@
 				ctx.PropertyErrorf(prop, "-Weverything is not allowed in Android.bp files.  "+
 					"Build with `m ANDROID_TEMPORARILY_ALLOW_WEVERYTHING=true` to experiment locally with -Weverything.")
 			}
+		} else if strings.HasPrefix(flag, "-target") || strings.HasPrefix(flag, "--target") {
+			ctx.PropertyErrorf(prop, "Bad flag: `%s`, use the correct target soong rule.", flag)
 		} else if strings.Contains(flag, " ") {
 			args := strings.Split(flag, " ")
 			if args[0] == "-include" {
diff --git a/cc/config/global.go b/cc/config/global.go
index d3c2658..b21d56c 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -367,8 +367,6 @@
 		"-Wno-gnu-offsetof-extensions",
 		// TODO: Enable this warning http://b/315245071
 		"-Wno-fortify-source",
-		"-Wno-tautological-negation-compare",
-		"-Wno-tautological-undefined-compare",
 	}
 
 	llvmNextExtraCommonGlobalCflags = []string{
diff --git a/cc/library.go b/cc/library.go
index 4684d32..e2b4d4f 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1354,38 +1354,28 @@
 		fileName+".lsdump")
 }
 
-func getRefAbiDumpDir(isNdk, isLlndk bool) string {
-	var dirName string
-	if isNdk {
-		dirName = "ndk"
-	} else if isLlndk {
-		dirName = "vndk"
-	} else {
-		dirName = "platform"
-	}
-	return filepath.Join("prebuilts", "abi-dumps", dirName)
-}
-
-func prevRefAbiDumpVersion(ctx ModuleContext, dumpDir string) int {
+// Return the previous and current SDK versions for cross-version ABI diff.
+func crossVersionAbiDiffSdkVersions(ctx ModuleContext, dumpDir string) (string, string) {
 	sdkVersionInt := ctx.Config().PlatformSdkVersion().FinalInt()
 	sdkVersionStr := ctx.Config().PlatformSdkVersion().String()
 
 	if ctx.Config().PlatformSdkFinal() {
-		return sdkVersionInt - 1
+		return strconv.Itoa(sdkVersionInt - 1), sdkVersionStr
 	} else {
 		// The platform SDK version can be upgraded before finalization while the corresponding abi dumps hasn't
 		// been generated. Thus the Cross-Version Check chooses PLATFORM_SDK_VERION - 1 as previous version.
 		// This situation could be identified by checking the existence of the PLATFORM_SDK_VERION dump directory.
 		versionedDumpDir := android.ExistentPathForSource(ctx, dumpDir, sdkVersionStr)
 		if versionedDumpDir.Valid() {
-			return sdkVersionInt
+			return sdkVersionStr, strconv.Itoa(sdkVersionInt + 1)
 		} else {
-			return sdkVersionInt - 1
+			return strconv.Itoa(sdkVersionInt - 1), sdkVersionStr
 		}
 	}
 }
 
-func currRefAbiDumpVersion(ctx ModuleContext) string {
+// Return the SDK version for same-version ABI diff.
+func currRefAbiDumpSdkVersion(ctx ModuleContext) string {
 	if ctx.Config().PlatformSdkFinal() {
 		// After sdk finalization, the ABI of the latest API level must be consistent with the source code,
 		// so choose PLATFORM_SDK_VERSION as the current version.
@@ -1435,17 +1425,17 @@
 }
 
 func (library *libraryDecorator) sameVersionAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
-	baseName string, isLlndkOrNdk bool) {
+	baseName, nameExt string, isLlndkOrNdk bool) {
 
 	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
 	errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName
 
-	library.sourceAbiDiff(ctx, referenceDump, baseName, "",
+	library.sourceAbiDiff(ctx, referenceDump, baseName, nameExt,
 		isLlndkOrNdk, false /* allowExtensions */, "current", errorMessage)
 }
 
 func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
-	baseName, nameExt string, isLlndkOrNdk bool, refDumpDir string) {
+	baseName, nameExt string, refDumpDir string) {
 
 	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
 	errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName + " -ref-dump-dir $$ANDROID_BUILD_TOP/" + refDumpDir
@@ -1455,7 +1445,7 @@
 	}
 
 	library.sourceAbiDiff(ctx, referenceDump, baseName, nameExt,
-		isLlndkOrNdk, false /* allowExtensions */, "current", errorMessage)
+		false /* isLlndkOrNdk */, false /* allowExtensions */, "current", errorMessage)
 }
 
 func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
@@ -1470,38 +1460,56 @@
 		}
 		exportedHeaderFlags := strings.Join(SourceAbiFlags, " ")
 		headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
-		// The logic must be consistent with classifySourceAbiDump.
-		isNdk := ctx.isNdk(ctx.Config())
-		isLlndk := ctx.isImplementationForLLNDKPublic()
-		currVersion := currRefAbiDumpVersion(ctx)
+		currSdkVersion := currRefAbiDumpSdkVersion(ctx)
+		currVendorVersion := ctx.Config().VendorApiLevel()
 		library.sAbiOutputFile = transformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags,
 			android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)),
 			headerAbiChecker.Exclude_symbol_versions,
 			headerAbiChecker.Exclude_symbol_tags,
-			currVersion)
+			currSdkVersion)
 
 		for _, tag := range classifySourceAbiDump(ctx) {
-			addLsdumpPath(tag + ":" + library.sAbiOutputFile.String())
-		}
+			addLsdumpPath(string(tag) + ":" + library.sAbiOutputFile.String())
 
-		dumpDir := getRefAbiDumpDir(isNdk, isLlndk)
-		binderBitness := ctx.DeviceConfig().BinderBitness()
-		// Check against the previous version.
-		prevVersionInt := prevRefAbiDumpVersion(ctx, dumpDir)
-		prevVersion := strconv.Itoa(prevVersionInt)
-		prevDumpDir := filepath.Join(dumpDir, prevVersion, binderBitness)
-		prevDumpFile := getRefAbiDumpFile(ctx, prevDumpDir, fileName)
-		if prevDumpFile.Valid() {
-			library.crossVersionAbiDiff(ctx, prevDumpFile.Path(),
-				fileName, isLlndk || isNdk,
-				strconv.Itoa(prevVersionInt+1), prevVersion)
-		}
-		// Check against the current version.
-		currDumpDir := filepath.Join(dumpDir, currVersion, binderBitness)
-		currDumpFile := getRefAbiDumpFile(ctx, currDumpDir, fileName)
-		if currDumpFile.Valid() {
-			library.sameVersionAbiDiff(ctx, currDumpFile.Path(),
-				fileName, isLlndk || isNdk)
+			dumpDirName := tag.dirName()
+			if dumpDirName == "" {
+				continue
+			}
+			dumpDir := filepath.Join("prebuilts", "abi-dumps", dumpDirName)
+			isLlndk := (tag == llndkLsdumpTag)
+			isNdk := (tag == ndkLsdumpTag)
+			binderBitness := ctx.DeviceConfig().BinderBitness()
+			nameExt := ""
+			if isLlndk {
+				nameExt = "llndk"
+			}
+			// Check against the previous version.
+			var prevVersion, currVersion string
+			// If this release config does not define VendorApiLevel, fall back to the old policy.
+			if isLlndk && currVendorVersion != "" {
+				prevVersion = ctx.Config().PrevVendorApiLevel()
+				currVersion = currVendorVersion
+			} else {
+				prevVersion, currVersion = crossVersionAbiDiffSdkVersions(ctx, dumpDir)
+			}
+			prevDumpDir := filepath.Join(dumpDir, prevVersion, binderBitness)
+			prevDumpFile := getRefAbiDumpFile(ctx, prevDumpDir, fileName)
+			if prevDumpFile.Valid() {
+				library.crossVersionAbiDiff(ctx, prevDumpFile.Path(),
+					fileName, isLlndk || isNdk, currVersion, nameExt+prevVersion)
+			}
+			// Check against the current version.
+			if isLlndk && currVendorVersion != "" {
+				currVersion = currVendorVersion
+			} else {
+				currVersion = currSdkVersion
+			}
+			currDumpDir := filepath.Join(dumpDir, currVersion, binderBitness)
+			currDumpFile := getRefAbiDumpFile(ctx, currDumpDir, fileName)
+			if currDumpFile.Valid() {
+				library.sameVersionAbiDiff(ctx, currDumpFile.Path(),
+					fileName, nameExt, isLlndk || isNdk)
+			}
 		}
 		// Check against the opt-in reference dumps.
 		for i, optInDumpDir := range headerAbiChecker.Ref_dump_dirs {
@@ -1513,8 +1521,7 @@
 				continue
 			}
 			library.optInAbiDiff(ctx, optInDumpFile.Path(),
-				fileName, "opt"+strconv.Itoa(i), isLlndk || isNdk,
-				optInDumpDirPath.String())
+				fileName, "opt"+strconv.Itoa(i), optInDumpDirPath.String())
 		}
 	}
 }
diff --git a/cc/sabi.go b/cc/sabi.go
index 4ca9f5c..af26726 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -26,6 +26,30 @@
 	lsdumpPathsLock sync.Mutex
 )
 
+type lsdumpTag string
+
+const (
+	llndkLsdumpTag    lsdumpTag = "LLNDK"
+	ndkLsdumpTag      lsdumpTag = "NDK"
+	platformLsdumpTag lsdumpTag = "PLATFORM"
+	productLsdumpTag  lsdumpTag = "PRODUCT"
+	vendorLsdumpTag   lsdumpTag = "VENDOR"
+)
+
+// Return the prebuilt ABI dump directory for a tag; an empty string for an opt-in dump.
+func (tag *lsdumpTag) dirName() string {
+	switch *tag {
+	case ndkLsdumpTag:
+		return "ndk"
+	case llndkLsdumpTag:
+		return "vndk"
+	case platformLsdumpTag:
+		return "platform"
+	default:
+		return ""
+	}
+}
+
 // Properties for ABI compatibility checker in Android.bp.
 type headerAbiCheckerProperties struct {
 	// Enable ABI checks (even if this is not an LLNDK/VNDK lib)
@@ -98,8 +122,8 @@
 }
 
 // Returns a slice of strings that represent the ABI dumps generated for this module.
-func classifySourceAbiDump(ctx android.BaseModuleContext) []string {
-	result := []string{}
+func classifySourceAbiDump(ctx android.BaseModuleContext) []lsdumpTag {
+	result := []lsdumpTag{}
 	m := ctx.Module().(*Module)
 	headerAbiChecker := m.library.getHeaderAbiCheckerProperties(ctx)
 	if headerAbiChecker.explicitlyDisabled() {
@@ -107,21 +131,21 @@
 	}
 	if !m.InProduct() && !m.InVendor() {
 		if m.isImplementationForLLNDKPublic() {
-			result = append(result, "LLNDK")
+			result = append(result, llndkLsdumpTag)
 		}
 		// Return NDK if the library is both NDK and APEX.
 		// TODO(b/309880485): Split NDK and APEX ABI.
 		if m.IsNdk(ctx.Config()) {
-			result = append(result, "NDK")
+			result = append(result, ndkLsdumpTag)
 		} else if m.library.hasStubsVariants() || headerAbiChecker.enabled() {
-			result = append(result, "PLATFORM")
+			result = append(result, platformLsdumpTag)
 		}
 	} else if headerAbiChecker.enabled() {
 		if m.InProduct() {
-			result = append(result, "PRODUCT")
+			result = append(result, productLsdumpTag)
 		}
 		if m.InVendor() {
-			result = append(result, "VENDOR")
+			result = append(result, vendorLsdumpTag)
 		}
 	}
 	return result
diff --git a/java/aar.go b/java/aar.go
index f61fc83..0edee83 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -23,6 +23,7 @@
 
 	"android/soong/android"
 	"android/soong/dexpreopt"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
@@ -414,17 +415,11 @@
 		linkFlags = append(linkFlags, "--static-lib")
 	}
 
+	linkFlags = append(linkFlags, "--no-static-lib-packages")
 	if a.isLibrary && a.useResourceProcessorBusyBox(ctx) {
-		// When building an android_library using ResourceProcessorBusyBox the resources are merged into
-		// package-res.apk with --merge-only, but --no-static-lib-packages is not used so that R.txt only
-		// contains resources from this library.
+		// When building an android_library using ResourceProcessorBusyBox pass --merge-only to skip resource
+		// references validation until the final app link step when all static libraries are present.
 		linkFlags = append(linkFlags, "--merge-only")
-	} else {
-		// When building and app or when building an android_library without ResourceProcessorBusyBox
-		// --no-static-lib-packages is used to put all the resources into the app.  If ResourceProcessorBusyBox
-		// is used then the app's R.txt will be post-processed along with the R.txt files from dependencies to
-		// sort resources into the right packages in R.class.
-		linkFlags = append(linkFlags, "--no-static-lib-packages")
 	}
 
 	packageRes := android.PathForModuleOut(ctx, "package-res.apk")
@@ -808,6 +803,9 @@
 func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	a.aapt.isLibrary = true
 	a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+	if a.usesLibrary.shouldDisableDexpreopt {
+		a.dexpreopter.disableDexpreopt()
+	}
 	a.aapt.buildActions(ctx,
 		aaptBuildActionOptions{
 			sdkContext:                     android.SdkContext(a),
@@ -1177,6 +1175,7 @@
 		"--static-lib",
 		"--merge-only",
 		"--auto-add-overlay",
+		"--no-static-lib-packages",
 	}
 
 	linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
@@ -1250,6 +1249,7 @@
 		TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
 		ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
 		ImplementationJars:             android.PathsIfNonNil(a.classpathFile),
+		StubsLinkType:                  Implementation,
 		// TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
 	})
 
diff --git a/java/app.go b/java/app.go
index 05f042d..9736ffd 100755
--- a/java/app.go
+++ b/java/app.go
@@ -778,6 +778,9 @@
 	a.onDeviceDir = android.InstallPathToOnDevicePath(ctx, a.installDir)
 
 	a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+	if a.usesLibrary.shouldDisableDexpreopt {
+		a.dexpreopter.disableDexpreopt()
+	}
 
 	var noticeAssetPath android.WritablePath
 	if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
@@ -1113,6 +1116,8 @@
 		if a.rJar != nil {
 			return []android.Path{a.rJar}, nil
 		}
+	case ".apk":
+		return []android.Path{a.outputFile}, nil
 	case ".export-package.apk":
 		return []android.Path{a.exportPackage}, nil
 	case ".manifest.xml":
@@ -1207,10 +1212,10 @@
 			Cmd   *string
 		}{
 			Name:  proptools.StringPtr(rroManifestName),
-			Tools: []string{"characteristics_rro_generator"},
+			Tools: []string{"characteristics_rro_generator", "aapt2"},
 			Out:   []string{"AndroidManifest.xml"},
-			Srcs:  []string{":" + a.Name() + "{.manifest.xml}"},
-			Cmd:   proptools.StringPtr("$(location characteristics_rro_generator) $(in) $(out)"),
+			Srcs:  []string{":" + a.Name() + "{.apk}"},
+			Cmd:   proptools.StringPtr("$(location characteristics_rro_generator) $$($(location aapt2) dump packagename $(in)) $(out)"),
 		}
 		ctx.CreateModule(genrule.GenRuleFactory, &rroManifestProperties)
 
@@ -1564,6 +1569,9 @@
 
 	// Whether to enforce verify_uses_library check.
 	enforce bool
+
+	// Whether dexpreopt should be disabled
+	shouldDisableDexpreopt bool
 }
 
 func (u *usesLibrary) addLib(lib string, optional bool) {
@@ -1645,6 +1653,15 @@
 			}
 		}
 
+		// Skip java_sdk_library dependencies that provide stubs, but not an implementation.
+		// This will be restricted to optional_uses_libs
+		if sdklib, ok := m.(SdkLibraryDependency); ok {
+			if tag == usesLibOptTag && sdklib.DexJarBuildPath(ctx).PathOrNil() == nil {
+				u.shouldDisableDexpreopt = true
+				return
+			}
+		}
+
 		if lib, ok := m.(UsesLibraryDependency); ok {
 			libName := dep
 			if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil {
diff --git a/java/app_import.go b/java/app_import.go
index 12ead0a..74255b7 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -319,6 +319,9 @@
 
 	a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
 	a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+	if a.usesLibrary.shouldDisableDexpreopt {
+		a.dexpreopter.disableDexpreopt()
+	}
 
 	if a.usesLibrary.enforceUsesLibraries() {
 		a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
diff --git a/java/app_test.go b/java/app_test.go
index 362bef9..125c971 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -4378,3 +4378,26 @@
 		"--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
 	)
 }
+
+// Test that dexpreopt is disabled if an optional_uses_libs exists, but does not provide an implementation.
+func TestNoDexpreoptOptionalUsesLibDoesNotHaveImpl(t *testing.T) {
+	bp := `
+		java_sdk_library_import {
+			name: "sdklib_noimpl",
+			public: {
+				jars: ["stub.jar"],
+			},
+		}
+		android_app {
+			name: "app",
+			srcs: ["a.java"],
+			sdk_version: "current",
+			optional_uses_libs: [
+				"sdklib_noimpl",
+			],
+		}
+	`
+	result := prepareForJavaTest.RunTestWithBp(t, bp)
+	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)
+}
diff --git a/java/base.go b/java/base.go
index 4e2366f..7f4ea08 100644
--- a/java/base.go
+++ b/java/base.go
@@ -26,6 +26,7 @@
 	"github.com/google/blueprint/pathtools"
 	"github.com/google/blueprint/proptools"
 
+	"android/soong/aconfig"
 	"android/soong/android"
 	"android/soong/dexpreopt"
 	"android/soong/java/config"
@@ -205,6 +206,13 @@
 	// Note that currently not all actions implemented by android_apps are sandboxed, so you
 	// may only see this being necessary in lint builds.
 	Compile_data []string `android:"path"`
+
+	// Property signifying whether the module compiles stubs or not.
+	// Should be set to true when srcs of this module are stub files.
+	// This property does not need to be set to true when the module depends on
+	// the stubs via libs, but should be set to true when the module depends on
+	// the stubs via static libs.
+	Is_stubs_module *bool
 }
 
 // Properties that are specific to device modules. Host module factories should not add these when
@@ -532,6 +540,8 @@
 	// Values that will be set in the JarJarProvider data for jarjar repackaging,
 	// and merged with our dependencies' rules.
 	jarjarRenameRules map[string]string
+
+	stubsLinkType StubsLinkType
 }
 
 func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -1212,6 +1222,7 @@
 			ExportedPlugins:                j.exportedPluginJars,
 			ExportedPluginClasses:          j.exportedPluginClasses,
 			ExportedPluginDisableTurbine:   j.exportedDisableTurbine,
+			StubsLinkType:                  j.stubsLinkType,
 		})
 
 		j.outputFile = j.headerJarFile
@@ -1729,6 +1740,7 @@
 		ExportedPluginClasses:          j.exportedPluginClasses,
 		ExportedPluginDisableTurbine:   j.exportedDisableTurbine,
 		JacocoReportClassesFile:        j.jacocoReportClassesFile,
+		StubsLinkType:                  j.stubsLinkType,
 	})
 
 	// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
@@ -2372,11 +2384,26 @@
 // classes until a module with jarjar_prefix is reached, and all as yet unrenamed classes will then
 // be renamed from that module.
 // TODO: Add another property to suppress the forwarding of
+type DependencyUse int
+
+const (
+	RenameUseInvalid DependencyUse = iota
+	RenameUseInclude
+	RenameUseExclude
+)
+
+type RenameUseElement struct {
+	DepName   string
+	RenameUse DependencyUse
+	Why       string // token for determining where in the logic the decision was made.
+}
+
 type JarJarProviderData struct {
 	// Mapping of class names: original --> renamed.  If the value is "", the class will be
 	// renamed by the next rdep that has the jarjar_prefix attribute (or this module if it has
 	// attribute). Rdeps of that module will inherit the renaming.
-	Rename map[string]string
+	Rename    map[string]string
+	RenameUse []RenameUseElement
 }
 
 func (this JarJarProviderData) GetDebugString() string {
@@ -2440,17 +2467,114 @@
 func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProviderData) {
 	// Gather repackage information from deps
 	// If the dep jas a JarJarProvider, it is used.  Otherwise, any BaseJarJarProvider is used.
+
+	module := ctx.Module()
+	moduleName := module.Name()
+
 	ctx.VisitDirectDepsIgnoreBlueprint(func(m android.Module) {
-		if ctx.OtherModuleDependencyTag(m) == proguardRaiseTag {
-			return
-		}
-		merge := func(theirs *JarJarProviderData) {
-			for orig, renamed := range theirs.Rename {
-				if result == nil {
-					result = &JarJarProviderData{
-						Rename: make(map[string]string),
+		tag := ctx.OtherModuleDependencyTag(m)
+		// This logic mirrors that in (*Module).collectDeps above.  There are several places
+		// where we explicitly return RenameUseExclude, even though it is the default, to
+		// indicate that it has been verified to be the case.
+		//
+		// Note well: there are probably cases that are getting to the unconditional return
+		// and are therefore wrong.
+		shouldIncludeRenames := func() (DependencyUse, string) {
+			if moduleName == m.Name() {
+				return RenameUseInclude, "name" // If we have the same module name, include the renames.
+			}
+			if sc, ok := module.(android.SdkContext); ok {
+				if ctx.Device() {
+					sdkDep := decodeSdkDep(ctx, sc)
+					if !sdkDep.invalidVersion && sdkDep.useFiles {
+						return RenameUseExclude, "useFiles"
 					}
 				}
+			}
+			if IsJniDepTag(tag) || tag == certificateTag || tag == proguardRaiseTag {
+				return RenameUseExclude, "tags"
+			}
+			if _, ok := m.(SdkLibraryDependency); ok {
+				switch tag {
+				case sdkLibTag, libTag:
+					return RenameUseExclude, "sdklibdep" // matches collectDeps()
+				}
+				return RenameUseInvalid, "sdklibdep" // dep is not used in collectDeps()
+			} else if ji, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
+				switch ji.StubsLinkType {
+				case Stubs:
+					return RenameUseExclude, "info"
+				case Implementation:
+					return RenameUseInclude, "info"
+				default:
+					//fmt.Printf("LJ: %v -> %v StubsLinkType unknown\n", module, m)
+					// Fall through to the heuristic logic.
+				}
+				switch reflect.TypeOf(m).String() {
+				case "*java.GeneratedJavaLibraryModule":
+					// Probably a java_aconfig_library module.
+					// TODO: make this check better.
+					return RenameUseInclude, "reflect"
+				}
+				switch tag {
+				case bootClasspathTag:
+					return RenameUseExclude, "tagswitch"
+				case sdkLibTag, libTag, instrumentationForTag:
+					return RenameUseInclude, "tagswitch"
+				case java9LibTag:
+					return RenameUseExclude, "tagswitch"
+				case staticLibTag:
+					return RenameUseInclude, "tagswitch"
+				case pluginTag:
+					return RenameUseInclude, "tagswitch"
+				case errorpronePluginTag:
+					return RenameUseInclude, "tagswitch"
+				case exportedPluginTag:
+					return RenameUseInclude, "tagswitch"
+				case kotlinStdlibTag, kotlinAnnotationsTag:
+					return RenameUseExclude, "tagswitch"
+				case kotlinPluginTag:
+					return RenameUseInclude, "tagswitch"
+				default:
+					return RenameUseExclude, "tagswitch"
+				}
+			} else if _, ok := m.(android.SourceFileProducer); ok {
+				switch tag {
+				case sdkLibTag, libTag, staticLibTag:
+					return RenameUseInclude, "srcfile"
+				default:
+					return RenameUseExclude, "srcfile"
+				}
+			} else if _, ok := android.OtherModuleProvider(ctx, m, aconfig.CodegenInfoProvider); ok {
+				return RenameUseInclude, "aconfig_declarations_group"
+			} else {
+				switch tag {
+				case bootClasspathTag:
+					return RenameUseExclude, "else"
+				case systemModulesTag:
+					return RenameUseInclude, "else"
+				}
+			}
+			// If we got here, choose the safer option, which may lead to a build failure, rather
+			// than runtime failures on the device.
+			return RenameUseExclude, "end"
+		}
+
+		if result == nil {
+			result = &JarJarProviderData{
+				Rename:    make(map[string]string),
+				RenameUse: make([]RenameUseElement, 0),
+			}
+		}
+		how, why := shouldIncludeRenames()
+		result.RenameUse = append(result.RenameUse, RenameUseElement{DepName: m.Name(), RenameUse: how, Why: why})
+		if how != RenameUseInclude {
+			// Nothing to merge.
+			return
+		}
+
+		merge := func(theirs *JarJarProviderData) {
+			for orig, renamed := range theirs.Rename {
 				if preexisting, exists := (*result).Rename[orig]; !exists || preexisting == "" {
 					result.Rename[orig] = renamed
 				} else if preexisting != "" && renamed != "" && preexisting != renamed {
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index efd13b8..3f8735c 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -137,6 +137,7 @@
 		ResourceJars:                   d.resourceJars,
 		SrcJarArgs:                     d.srcJarArgs,
 		SrcJarDeps:                     d.srcJarDeps,
+		StubsLinkType:                  Implementation,
 		// TODO: Not sure if aconfig flags that have been moved between device and host variants
 		// make sense.
 	})
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 9db9b1b..1cfa642 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -102,6 +102,11 @@
 	dexpreoptProperties       DexpreoptProperties
 	importDexpreoptProperties ImportDexpreoptProperties
 
+	// If true, the dexpreopt rules will not be generated
+	// Unlike Dex_preopt.Enabled which is user-facing,
+	// shouldDisableDexpreopt is a mutated propery.
+	shouldDisableDexpreopt bool
+
 	installPath         android.InstallPath
 	uncompressedDex     bool
 	isSDKLibrary        bool
@@ -197,6 +202,10 @@
 		return true
 	}
 
+	if d.shouldDisableDexpreopt {
+		return true
+	}
+
 	// If the module is from a prebuilt APEX, it shouldn't be installable, but it can still be
 	// dexpreopted.
 	if !ctx.Module().(DexpreopterInterface).IsInstallable() && !forPrebuiltApex(ctx) {
@@ -528,3 +537,7 @@
 func (d *dexpreopter) OutputProfilePathOnHost() android.Path {
 	return d.outputProfilePathOnHost
 }
+
+func (d *dexpreopter) disableDexpreopt() {
+	d.shouldDisableDexpreopt = true
+}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index cfbf2b4..6a66f45 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -21,6 +21,7 @@
 
 	"github.com/google/blueprint/proptools"
 
+	"android/soong/aconfig"
 	"android/soong/android"
 	"android/soong/java/config"
 )
@@ -413,9 +414,12 @@
 		case aconfigDeclarationTag:
 			if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey); ok {
 				deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPath)
+			} else if dep, ok := android.OtherModuleProvider(ctx, module, aconfig.CodegenInfoProvider); ok {
+				deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
 			} else {
-				ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
-					"flags_packages property, but %s is not aconfig_declarations module type",
+				ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+
+					"module type is allowed for flags_packages property, but %s is neither "+
+					"of these supported module types",
 					module.Name(),
 				)
 			}
diff --git a/java/java.go b/java/java.go
index d7d271c..af4c3be 100644
--- a/java/java.go
+++ b/java/java.go
@@ -87,6 +87,14 @@
 	android.RegisterSdkMemberType(javaTestSdkMemberType)
 }
 
+type StubsLinkType int
+
+const (
+	Unknown StubsLinkType = iota
+	Stubs
+	Implementation
+)
+
 var (
 	// Supports adding java header libraries to module_exports and sdk.
 	javaHeaderLibsSdkMemberType = &librarySdkMemberType{
@@ -296,6 +304,11 @@
 	// JacocoReportClassesFile is the path to a jar containing uninstrumented classes that will be
 	// instrumented by jacoco.
 	JacocoReportClassesFile android.Path
+
+	// StubsLinkType provides information about whether the provided jars are stub jars or
+	// 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
 }
 
 var JavaInfoProvider = blueprint.NewProvider[JavaInfo]()
@@ -686,14 +699,195 @@
 	}
 }
 
-func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+// list of java_library modules that set platform_apis: true
+// this property is a no-op for java_library
+// TODO (b/215379393): Remove this allowlist
+var (
+	aospPlatformApiAllowlist = map[string]bool{
+		"adservices-test-scenarios":                         true,
+		"aidl-cpp-java-test-interface-java":                 true,
+		"aidl-test-extras-java":                             true,
+		"aidl-test-interface-java":                          true,
+		"aidl-test-interface-permission-java":               true,
+		"aidl_test_java_client_permission":                  true,
+		"aidl_test_java_client_sdk1":                        true,
+		"aidl_test_java_client_sdk29":                       true,
+		"aidl_test_java_client":                             true,
+		"aidl_test_java_service_permission":                 true,
+		"aidl_test_java_service_sdk1":                       true,
+		"aidl_test_java_service_sdk29":                      true,
+		"aidl_test_java_service":                            true,
+		"aidl_test_loggable_interface-java":                 true,
+		"aidl_test_nonvintf_parcelable-V1-java":             true,
+		"aidl_test_nonvintf_parcelable-V2-java":             true,
+		"aidl_test_unstable_parcelable-java":                true,
+		"aidl_test_vintf_parcelable-V1-java":                true,
+		"aidl_test_vintf_parcelable-V2-java":                true,
+		"android.aidl.test.trunk-V1-java":                   true,
+		"android.aidl.test.trunk-V2-java":                   true,
+		"android.frameworks.location.altitude-V1-java":      true,
+		"android.frameworks.location.altitude-V2-java":      true,
+		"android.frameworks.stats-V1-java":                  true,
+		"android.frameworks.stats-V2-java":                  true,
+		"android.frameworks.stats-V3-java":                  true,
+		"android.hardware.authsecret-V1-java":               true,
+		"android.hardware.authsecret-V2-java":               true,
+		"android.hardware.biometrics.common-V1-java":        true,
+		"android.hardware.biometrics.common-V2-java":        true,
+		"android.hardware.biometrics.common-V3-java":        true,
+		"android.hardware.biometrics.common-V4-java":        true,
+		"android.hardware.biometrics.face-V1-java":          true,
+		"android.hardware.biometrics.face-V2-java":          true,
+		"android.hardware.biometrics.face-V3-java":          true,
+		"android.hardware.biometrics.face-V4-java":          true,
+		"android.hardware.biometrics.fingerprint-V1-java":   true,
+		"android.hardware.biometrics.fingerprint-V2-java":   true,
+		"android.hardware.biometrics.fingerprint-V3-java":   true,
+		"android.hardware.biometrics.fingerprint-V4-java":   true,
+		"android.hardware.bluetooth.lmp_event-V1-java":      true,
+		"android.hardware.confirmationui-V1-java":           true,
+		"android.hardware.confirmationui-V2-java":           true,
+		"android.hardware.gatekeeper-V1-java":               true,
+		"android.hardware.gatekeeper-V2-java":               true,
+		"android.hardware.gnss-V1-java":                     true,
+		"android.hardware.gnss-V2-java":                     true,
+		"android.hardware.gnss-V3-java":                     true,
+		"android.hardware.gnss-V4-java":                     true,
+		"android.hardware.graphics.common-V1-java":          true,
+		"android.hardware.graphics.common-V2-java":          true,
+		"android.hardware.graphics.common-V3-java":          true,
+		"android.hardware.graphics.common-V4-java":          true,
+		"android.hardware.graphics.common-V5-java":          true,
+		"android.hardware.identity-V1-java":                 true,
+		"android.hardware.identity-V2-java":                 true,
+		"android.hardware.identity-V3-java":                 true,
+		"android.hardware.identity-V4-java":                 true,
+		"android.hardware.identity-V5-java":                 true,
+		"android.hardware.identity-V6-java":                 true,
+		"android.hardware.keymaster-V1-java":                true,
+		"android.hardware.keymaster-V2-java":                true,
+		"android.hardware.keymaster-V3-java":                true,
+		"android.hardware.keymaster-V4-java":                true,
+		"android.hardware.keymaster-V5-java":                true,
+		"android.hardware.oemlock-V1-java":                  true,
+		"android.hardware.oemlock-V2-java":                  true,
+		"android.hardware.power.stats-V1-java":              true,
+		"android.hardware.power.stats-V2-java":              true,
+		"android.hardware.power.stats-V3-java":              true,
+		"android.hardware.power-V1-java":                    true,
+		"android.hardware.power-V2-java":                    true,
+		"android.hardware.power-V3-java":                    true,
+		"android.hardware.power-V4-java":                    true,
+		"android.hardware.power-V5-java":                    true,
+		"android.hardware.rebootescrow-V1-java":             true,
+		"android.hardware.rebootescrow-V2-java":             true,
+		"android.hardware.security.authgraph-V1-java":       true,
+		"android.hardware.security.keymint-V1-java":         true,
+		"android.hardware.security.keymint-V2-java":         true,
+		"android.hardware.security.keymint-V3-java":         true,
+		"android.hardware.security.keymint-V4-java":         true,
+		"android.hardware.security.secureclock-V1-java":     true,
+		"android.hardware.security.secureclock-V2-java":     true,
+		"android.hardware.thermal-V1-java":                  true,
+		"android.hardware.thermal-V2-java":                  true,
+		"android.hardware.threadnetwork-V1-java":            true,
+		"android.hardware.weaver-V1-java":                   true,
+		"android.hardware.weaver-V2-java":                   true,
+		"android.hardware.weaver-V3-java":                   true,
+		"android.security.attestationmanager-java":          true,
+		"android.security.authorization-java":               true,
+		"android.security.compat-java":                      true,
+		"android.security.legacykeystore-java":              true,
+		"android.security.maintenance-java":                 true,
+		"android.security.metrics-java":                     true,
+		"android.system.keystore2-V1-java":                  true,
+		"android.system.keystore2-V2-java":                  true,
+		"android.system.keystore2-V3-java":                  true,
+		"android.system.keystore2-V4-java":                  true,
+		"binderReadParcelIface-java":                        true,
+		"binderRecordReplayTestIface-java":                  true,
+		"car-experimental-api-static-lib":                   true,
+		"collector-device-lib-platform":                     true,
+		"com.android.car.oem":                               true,
+		"com.google.hardware.pixel.display-V10-java":        true,
+		"com.google.hardware.pixel.display-V1-java":         true,
+		"com.google.hardware.pixel.display-V2-java":         true,
+		"com.google.hardware.pixel.display-V3-java":         true,
+		"com.google.hardware.pixel.display-V4-java":         true,
+		"com.google.hardware.pixel.display-V5-java":         true,
+		"com.google.hardware.pixel.display-V6-java":         true,
+		"com.google.hardware.pixel.display-V7-java":         true,
+		"com.google.hardware.pixel.display-V8-java":         true,
+		"com.google.hardware.pixel.display-V9-java":         true,
+		"conscrypt-support":                                 true,
+		"cts-keystore-test-util":                            true,
+		"cts-keystore-user-auth-helper-library":             true,
+		"ctsmediautil":                                      true,
+		"CtsNetTestsNonUpdatableLib":                        true,
+		"DpmWrapper":                                        true,
+		"flickerlib-apphelpers":                             true,
+		"flickerlib-helpers":                                true,
+		"flickerlib-parsers":                                true,
+		"flickerlib":                                        true,
+		"hardware.google.bluetooth.ccc-V1-java":             true,
+		"hardware.google.bluetooth.sar-V1-java":             true,
+		"monet":                                             true,
+		"pixel-power-ext-V1-java":                           true,
+		"pixel-power-ext-V2-java":                           true,
+		"pixel_stateresidency_provider_aidl_interface-java": true,
+		"pixel-thermal-ext-V1-java":                         true,
+		"protolog-lib":                                      true,
+		"RkpRegistrationCheck":                              true,
+		"rotary-service-javastream-protos":                  true,
+		"service_based_camera_extensions":                   true,
+		"statsd-helper-test":                                true,
+		"statsd-helper":                                     true,
+		"test-piece-2-V1-java":                              true,
+		"test-piece-2-V2-java":                              true,
+		"test-piece-3-V1-java":                              true,
+		"test-piece-3-V2-java":                              true,
+		"test-piece-3-V3-java":                              true,
+		"test-piece-4-V1-java":                              true,
+		"test-piece-4-V2-java":                              true,
+		"test-root-package-V1-java":                         true,
+		"test-root-package-V2-java":                         true,
+		"test-root-package-V3-java":                         true,
+		"test-root-package-V4-java":                         true,
+		"testServiceIface-java":                             true,
+		"wm-flicker-common-app-helpers":                     true,
+		"wm-flicker-common-assertions":                      true,
+		"wm-shell-flicker-utils":                            true,
+		"wycheproof-keystore":                               true,
+	}
 
+	// Union of aosp and internal allowlists
+	PlatformApiAllowlist = map[string]bool{}
+)
+
+func init() {
+	for k, v := range aospPlatformApiAllowlist {
+		PlatformApiAllowlist[k] = v
+	}
+}
+
+func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	j.provideHiddenAPIPropertyInfo(ctx)
 
 	j.sdkVersion = j.SdkVersion(ctx)
 	j.minSdkVersion = j.MinSdkVersion(ctx)
 	j.maxSdkVersion = j.MaxSdkVersion(ctx)
 
+	// SdkLibrary.GenerateAndroidBuildActions(ctx) sets the stubsLinkType to Unknown.
+	// If the stubsLinkType has already been set to Unknown, the stubsLinkType should
+	// not be overridden.
+	if j.stubsLinkType != Unknown {
+		if proptools.Bool(j.properties.Is_stubs_module) {
+			j.stubsLinkType = Stubs
+		} else {
+			j.stubsLinkType = Implementation
+		}
+	}
+
 	j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
 
 	proguardSpecInfo := j.collectProguardSpecInfo(ctx)
@@ -719,6 +913,9 @@
 		setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
 		j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
 		j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+		if j.usesLibrary.shouldDisableDexpreopt {
+			j.dexpreopter.disableDexpreopt()
+		}
 	}
 	j.compile(ctx, nil, nil, nil)
 
@@ -2018,6 +2215,7 @@
 		ImplementationAndResourcesJars: android.PathsIfNonNil(al.stubsJar),
 		ImplementationJars:             android.PathsIfNonNil(al.stubsJar),
 		AidlIncludeDirs:                android.Paths{},
+		StubsLinkType:                  Stubs,
 		// No aconfig libraries on api libraries
 	})
 }
@@ -2102,6 +2300,9 @@
 	// The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
 	// (without any prebuilt_ prefix)
 	Created_by_java_sdk_library_name *string `blueprint:"mutated"`
+
+	// Property signifying whether the module provides stubs jar or not.
+	Is_stubs_module *bool
 }
 
 type Import struct {
@@ -2132,6 +2333,8 @@
 
 	sdkVersion    android.SdkSpec
 	minSdkVersion android.ApiLevel
+
+	stubsLinkType StubsLinkType
 }
 
 var _ PermittedPackagesForUpdatableBootJars = (*Import)(nil)
@@ -2226,6 +2429,12 @@
 	if ctx.Windows() {
 		j.HideFromMake()
 	}
+
+	if proptools.Bool(j.properties.Is_stubs_module) {
+		j.stubsLinkType = Stubs
+	} else {
+		j.stubsLinkType = Implementation
+	}
 }
 
 func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -2359,6 +2568,7 @@
 		ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile),
 		ImplementationJars:             android.PathsIfNonNil(j.combinedClasspathFile),
 		AidlIncludeDirs:                j.exportAidlIncludeDirs,
+		StubsLinkType:                  j.stubsLinkType,
 		// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
 	})
 }
diff --git a/java/sdk_library.go b/java/sdk_library.go
index fbde042..d532aaa 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1572,6 +1572,8 @@
 
 	// Only build an implementation library if required.
 	if module.requiresRuntimeImplementationLibrary() {
+		// stubsLinkType must be set before calling Library.GenerateAndroidBuildActions
+		module.Library.stubsLinkType = Unknown
 		module.Library.GenerateAndroidBuildActions(ctx)
 	}
 
@@ -1797,6 +1799,7 @@
 		Dir     *string
 		Tag     *string
 	}
+	Is_stubs_module *bool
 }
 
 func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
@@ -1821,6 +1824,7 @@
 	// We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
 	// interop with older developer tools that don't support 1.9.
 	props.Java_version = proptools.StringPtr("1.8")
+	props.Is_stubs_module = proptools.BoolPtr(true)
 
 	return props
 }
@@ -1993,8 +1997,10 @@
 			tag     string
 			pattern string
 		}{
-			{tag: ".api.txt", pattern: "%s.txt"},
-			{tag: ".removed-api.txt", pattern: "%s-removed.txt"},
+			// "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"},
 		} {
 			props.Dists = append(props.Dists, android.Dist{
 				Targets: []string{"sdk", "win_sdk"},
@@ -2709,6 +2715,7 @@
 		Libs                             []string
 		Jars                             []string
 		Compile_dex                      *bool
+		Is_stubs_module                  *bool
 
 		android.UserSuppliedPrebuiltProperties
 	}{}
@@ -2730,6 +2737,7 @@
 		compileDex = proptools.BoolPtr(true)
 	}
 	props.Compile_dex = compileDex
+	props.Is_stubs_module = proptools.BoolPtr(true)
 
 	mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
 }
diff --git a/rust/testing.go b/rust/testing.go
index 0b34c97..d9cacdc 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -75,6 +75,7 @@
 			apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
 			min_sdk_version: "29",
 			vendor_available: true,
+			host_supported: true,
 			recovery_available: true,
 			llndk: {
 				symbol_file: "liblog.map.txt",
diff --git a/sysprop/Android.bp b/sysprop/Android.bp
index 1d5eb31..a00a5e4 100644
--- a/sysprop/Android.bp
+++ b/sysprop/Android.bp
@@ -11,6 +11,7 @@
         "soong-android",
         "soong-cc",
         "soong-java",
+        "soong-rust",
     ],
     srcs: [
         "sysprop_library.go",
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 766f3e7..2258232 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -21,6 +21,7 @@
 	"io"
 	"os"
 	"path"
+	"strings"
 	"sync"
 
 	"github.com/google/blueprint"
@@ -29,6 +30,7 @@
 	"android/soong/android"
 	"android/soong/cc"
 	"android/soong/java"
+	"android/soong/rust"
 )
 
 type dependencyTag struct {
@@ -51,7 +53,16 @@
 	genSrcjars android.Paths
 }
 
+type syspropRustGenRule struct {
+	android.ModuleBase
+
+	properties syspropGenProperties
+
+	genSrcs android.Paths
+}
+
 var _ android.OutputFileProducer = (*syspropJavaGenRule)(nil)
+var _ android.OutputFileProducer = (*syspropRustGenRule)(nil)
 
 var (
 	syspropJava = pctx.AndroidStaticRule("syspropJava",
@@ -64,11 +75,20 @@
 				"$soongZipCmd",
 			},
 		}, "scope")
+	syspropRust = pctx.AndroidStaticRule("syspropRust",
+		blueprint.RuleParams{
+			Command: `rm -rf $out_dir && mkdir -p $out_dir && ` +
+				`$syspropRustCmd --scope $scope --rust-output-dir $out_dir $in`,
+			CommandDeps: []string{
+				"$syspropRustCmd",
+			},
+		}, "scope", "out_dir")
 )
 
 func init() {
 	pctx.HostBinToolVariable("soongZipCmd", "soong_zip")
 	pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java")
+	pctx.HostBinToolVariable("syspropRustCmd", "sysprop_rust")
 }
 
 // syspropJavaGenRule module generates srcjar containing generated java APIs.
@@ -122,6 +142,56 @@
 	return g
 }
 
+// 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) {
+	var checkApiFileTimeStamp android.WritablePath
+
+	ctx.VisitDirectDeps(func(dep android.Module) {
+		if m, ok := dep.(*syspropLibrary); ok {
+			checkApiFileTimeStamp = m.checkApiFileTimeStamp
+		}
+	})
+
+	for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
+		syspropDir := strings.TrimSuffix(syspropFile.String(), syspropFile.Ext())
+		outputDir := android.PathForModuleGen(ctx, syspropDir, "src")
+		libPath := android.PathForModuleGen(ctx, syspropDir, "src", "lib.rs")
+		parsersPath := android.PathForModuleGen(ctx, syspropDir, "src", "gen_parsers_and_formatters.rs")
+
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        syspropRust,
+			Description: "sysprop_rust " + syspropFile.Rel(),
+			Outputs:     android.WritablePaths{libPath, parsersPath},
+			Input:       syspropFile,
+			Implicit:    checkApiFileTimeStamp,
+			Args: map[string]string{
+				"scope":   g.properties.Scope,
+				"out_dir": outputDir.String(),
+			},
+		})
+
+		g.genSrcs = append(g.genSrcs, libPath, parsersPath)
+	}
+}
+
+func (g *syspropRustGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// Add a dependency from the stubs to sysprop library so that the generator rule can depend on
+	// the check API rule of the sysprop library.
+	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
+}
+
 type syspropLibrary struct {
 	android.ModuleBase
 	android.ApexModuleBase
@@ -180,6 +250,12 @@
 		// Forwarded to java_library.min_sdk_version
 		Min_sdk_version *string
 	}
+
+	Rust struct {
+		// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+		// Forwarded to rust_library.min_sdk_version
+		Min_sdk_version *string
+	}
 }
 
 var (
@@ -233,6 +309,21 @@
 	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"
+}
+
+func (m *syspropLibrary) rustCrateName() string {
+	moduleName := strings.ToLower(m.BaseModuleName())
+	moduleName = strings.ReplaceAll(moduleName, "-", "_")
+	moduleName = strings.ReplaceAll(moduleName, ".", "_")
+	return moduleName
+}
+
 func (m *syspropLibrary) BaseModuleName() string {
 	return m.ModuleBase.Name()
 }
@@ -436,6 +527,18 @@
 	Min_sdk_version   *string
 }
 
+type rustLibraryProperties struct {
+	Name              *string
+	Srcs              []string
+	Installable       *bool
+	Crate_name        string
+	Rustlibs          []string
+	Vendor_available  *bool
+	Product_available *bool
+	Apex_available    []string
+	Min_sdk_version   *string
+}
+
 func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
 	if len(m.properties.Srcs) == 0 {
 		ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
@@ -564,6 +667,28 @@
 		})
 	}
 
+	// 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(),
+		Rustlibs: []string{
+			"librustutils",
+		},
+		Vendor_available:  m.properties.Vendor_available,
+		Product_available: m.properties.Product_available,
+		Apex_available:    m.ApexProperties.Apex_available,
+		Min_sdk_version:   proptools.StringPtr("29"),
+	}
+	ctx.CreateModule(rust.RustLibraryFactory, &rustProps)
+
 	// syspropLibraries will be used by property_contexts to check types.
 	// Record absolute paths of sysprop_library to prevent soong_namespace problem.
 	if m.ExportedToMake() {
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index e5b3dea..9dd696f 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -22,6 +22,7 @@
 	"android/soong/android"
 	"android/soong/cc"
 	"android/soong/java"
+	"android/soong/rust"
 
 	"github.com/google/blueprint/proptools"
 )
@@ -46,18 +47,6 @@
 			recovery_available: true,
 		}
 
-		cc_library {
-			name: "liblog",
-			no_libcrt: true,
-			nocrt: true,
-			system_shared_libs: [],
-			recovery_available: true,
-			host_supported: true,
-			llndk: {
-				symbol_file: "liblog.map.txt",
-			}
-		}
-
 		java_library {
 			name: "sysprop-library-stub-platform",
 			sdk_version: "core_current",
@@ -74,6 +63,15 @@
 			product_specific: true,
 			sdk_version: "core_current",
 		}
+
+		rust_library {
+			name: "librustutils",
+			crate_name: "rustutils",
+			srcs: ["librustutils/lib.rs"],
+			product_available: true,
+			vendor_available: true,
+			min_sdk_version: "29",
+		}
 	`
 
 	mockFS := android.MockFS{
@@ -115,11 +113,14 @@
 		"android/sysprop/PlatformProperties.sysprop": nil,
 		"com/android/VendorProperties.sysprop":       nil,
 		"com/android2/OdmProperties.sysprop":         nil,
+
+		"librustutils/lib.rs": nil,
 	}
 
 	result := android.GroupFixturePreparers(
 		cc.PrepareForTestWithCcDefaultModules,
 		java.PrepareForTestWithJavaDefaultModules,
+		rust.PrepareForTestWithRustDefaultModules,
 		PrepareForTestWithSyspropBuildComponents,
 		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
 			variables.DeviceSystemSdkVersions = []string{"28"}
@@ -356,6 +357,10 @@
 	javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
 	propFromJava := javaModule.ApexProperties.Apex_available
 	android.AssertDeepEquals(t, "apex_available forwarding to java module", expected, propFromJava)
+
+	rustModule := result.ModuleForTests("libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
+	propFromRust := rustModule.ApexProperties.Apex_available
+	android.AssertDeepEquals(t, "apex_available forwarding to rust module", expected, propFromRust)
 }
 
 func TestMinSdkVersionIsForwarded(t *testing.T) {
@@ -371,6 +376,9 @@
 			java: {
 				min_sdk_version: "30",
 			},
+			rust: {
+				min_sdk_version: "29",
+			}
 		}
 	`)
 
@@ -381,4 +389,8 @@
 	javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
 	propFromJava := javaModule.MinSdkVersionString()
 	android.AssertStringEquals(t, "min_sdk_version forwarding to java module", "30", propFromJava)
+
+	rustModule := result.ModuleForTests("libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
+	propFromRust := proptools.String(rustModule.Properties.Min_sdk_version)
+	android.AssertStringEquals(t, "min_sdk_version forwarding to rust module", "29", propFromRust)
 }