Merge "Revert "Add workaround for a file with an mtime in the future"" into main
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index ae8276f..6927765 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -20,6 +20,7 @@
         "aconfig_values.go",
         "aconfig_value_set.go",
         "all_aconfig_declarations.go",
+        "cc_aconfig_library.go",
         "init.go",
         "java_aconfig_library.go",
         "testing.go",
@@ -28,6 +29,7 @@
         "aconfig_declarations_test.go",
         "aconfig_values_test.go",
         "aconfig_value_set_test.go",
+        "java_aconfig_library_test.go",
     ],
     pluginFor: ["soong_build"],
 }
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 007d529..565d185 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -125,12 +125,12 @@
 	intermediatePath := android.PathForModuleOut(ctx, "intermediate.pb")
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        aconfigRule,
-		Inputs:      inputFiles,
 		Output:      intermediatePath,
 		Description: "aconfig_declarations",
 		Args: map[string]string{
 			"release_version": ctx.Config().ReleaseVersion(),
 			"package":         module.properties.Package,
+			"declarations":    android.JoinPathsWithPrefix(inputFiles, "--declarations "),
 			"values":          joinAndPrefix(" --values ", module.properties.Values),
 		},
 	})
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index e14ca38..e0d8f7d 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -26,7 +26,10 @@
 		aconfig_declarations {
 			name: "module_name",
 			package: "com.example.package",
-			srcs: ["foo.aconfig"],
+			srcs: [
+				"foo.aconfig",
+				"bar.aconfig",
+			],
 		}
 	`
 	result := runTest(t, android.FixtureExpectsNoErrors, bp)
diff --git a/aconfig/cc_aconfig_library.go b/aconfig/cc_aconfig_library.go
new file mode 100644
index 0000000..14090bc
--- /dev/null
+++ b/aconfig/cc_aconfig_library.go
@@ -0,0 +1,128 @@
+// Copyright 2023 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 aconfig
+
+import (
+	"android/soong/android"
+	"android/soong/cc"
+	"github.com/google/blueprint"
+
+	"fmt"
+	"strings"
+)
+
+type ccDeclarationsTagType struct {
+	blueprint.BaseDependencyTag
+}
+
+var ccDeclarationsTag = ccDeclarationsTagType{}
+
+type CcAconfigLibraryProperties struct {
+	// name of the aconfig_declarations module to generate a library for
+	Aconfig_declarations string
+}
+
+type CcAconfigLibraryCallbacks struct {
+	properties *CcAconfigLibraryProperties
+
+	generatedDir android.WritablePath
+	headerDir    android.WritablePath
+	generatedCpp android.WritablePath
+	generatedH   android.WritablePath
+}
+
+func CcAconfigLibraryFactory() android.Module {
+	callbacks := &CcAconfigLibraryCallbacks{
+		properties: &CcAconfigLibraryProperties{},
+	}
+	return cc.GeneratedCcLibraryModuleFactory("cc_aconfig_library", callbacks)
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorInit(ctx cc.BaseModuleContext) {
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorProps() []interface{} {
+	return []interface{}{this.properties}
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorDeps(ctx cc.DepsContext, deps cc.Deps) cc.Deps {
+	// Add a dependency for the declarations module
+	declarations := this.properties.Aconfig_declarations
+	if len(declarations) == 0 {
+		ctx.PropertyErrorf("aconfig_declarations", "aconfig_declarations property required")
+	} else {
+		ctx.AddDependency(ctx.Module(), ccDeclarationsTag, declarations)
+	}
+
+	// Add a dependency for the aconfig flags base library
+	deps.SharedLibs = append(deps.SharedLibs, "server_configurable_flags")
+	// TODO: It'd be really nice if we could reexport this library and not make everyone do it.
+
+	return deps
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorSources(ctx cc.ModuleContext) cc.GeneratedSource {
+	result := cc.GeneratedSource{}
+
+	// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
+	declarationsModules := ctx.GetDirectDepsWithTag(ccDeclarationsTag)
+	if len(declarationsModules) != 1 {
+		panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+	}
+	declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+
+	// Figure out the generated file paths.  This has to match aconfig's codegen_cpp.rs.
+	this.generatedDir = android.PathForModuleGen(ctx)
+
+	this.headerDir = android.PathForModuleGen(ctx, "include")
+	result.IncludeDirs = []android.Path{this.headerDir}
+	result.ReexportedDirs = []android.Path{this.headerDir}
+
+	basename := strings.ReplaceAll(declarations.Package, ".", "_")
+
+	this.generatedCpp = android.PathForModuleGen(ctx, basename+".cc")
+	result.Sources = []android.Path{this.generatedCpp}
+
+	this.generatedH = android.PathForModuleGen(ctx, "include", basename+".h")
+	result.Headers = []android.Path{this.generatedH}
+
+	return result
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorFlags(ctx cc.ModuleContext, flags cc.Flags, deps cc.PathDeps) cc.Flags {
+	return flags
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContext, flags cc.Flags, deps cc.PathDeps) {
+	// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
+	declarationsModules := ctx.GetDirectDepsWithTag(ccDeclarationsTag)
+	if len(declarationsModules) != 1 {
+		panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+	}
+	declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:  cppRule,
+		Input: declarations.IntermediatePath,
+		Outputs: []android.WritablePath{
+			this.generatedCpp,
+			this.generatedH,
+		},
+		Description: "cc_aconfig_library",
+		Args: map[string]string{
+			"gendir": this.generatedDir.String(),
+		},
+	})
+}
diff --git a/aconfig/init.go b/aconfig/init.go
index 161fd42..3ed5faf 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -27,7 +27,7 @@
 		blueprint.RuleParams{
 			Command: `${aconfig} create-cache` +
 				` --package ${package}` +
-				` --declarations ${in}` +
+				` ${declarations}` +
 				` ${values}` +
 				` --cache ${out}.tmp` +
 				` && ( if cmp -s ${out}.tmp ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
@@ -36,10 +36,10 @@
 				"${aconfig}",
 			},
 			Restat: true,
-		}, "release_version", "package", "values")
+		}, "release_version", "package", "declarations", "values")
 
 	// For java_aconfig_library: Generate java file
-	srcJarRule = pctx.AndroidStaticRule("aconfig_srcjar",
+	javaRule = pctx.AndroidStaticRule("java_aconfig_library",
 		blueprint.RuleParams{
 			Command: `rm -rf ${out}.tmp` +
 				` && mkdir -p ${out}.tmp` +
@@ -55,6 +55,20 @@
 			Restat: true,
 		})
 
+	// For java_aconfig_library: Generate java file
+	cppRule = pctx.AndroidStaticRule("cc_aconfig_library",
+		blueprint.RuleParams{
+			Command: `rm -rf ${gendir}` +
+				` && mkdir -p ${gendir}` +
+				` && ${aconfig} create-cpp-lib` +
+				`    --cache ${in}` +
+				`    --out ${gendir}`,
+			CommandDeps: []string{
+				"$aconfig",
+				"$soong_zip",
+			},
+		}, "gendir")
+
 	// For all_aconfig_declarations
 	allDeclarationsRule = pctx.AndroidStaticRule("all_aconfig_declarations_dump",
 		blueprint.RuleParams{
@@ -75,6 +89,7 @@
 	ctx.RegisterModuleType("aconfig_declarations", DeclarationsFactory)
 	ctx.RegisterModuleType("aconfig_values", ValuesFactory)
 	ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
+	ctx.RegisterModuleType("cc_aconfig_library", CcAconfigLibraryFactory)
 	ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory)
 	ctx.RegisterParallelSingletonType("all_aconfig_declarations", AllAconfigDeclarationsFactory)
 }
diff --git a/aconfig/java_aconfig_library.go b/aconfig/java_aconfig_library.go
index 0eeb14f..53b2b10 100644
--- a/aconfig/java_aconfig_library.go
+++ b/aconfig/java_aconfig_library.go
@@ -51,7 +51,7 @@
 	}
 }
 
-func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(ctx android.ModuleContext) android.Path {
+func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(module *java.GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path {
 	// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
 	declarationsModules := ctx.GetDirectDepsWithTag(declarationsTag)
 	if len(declarationsModules) != 1 {
@@ -59,13 +59,18 @@
 	}
 	declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
 
+	// Generate the action to build the srcjar
 	srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
 	ctx.Build(pctx, android.BuildParams{
-		Rule:        srcJarRule,
+		Rule:        javaRule,
 		Input:       declarations.IntermediatePath,
 		Output:      srcJarPath,
 		Description: "aconfig.srcjar",
 	})
 
+	// Tell the java module about the .aconfig files, so they can be propagated up the dependency chain.
+	// TODO: It would be nice to have that propagation code here instead of on java.Module and java.JavaInfo.
+	module.AddAconfigIntermediate(declarations.IntermediatePath)
+
 	return srcJarPath
 }
diff --git a/aconfig/java_aconfig_library_test.go b/aconfig/java_aconfig_library_test.go
new file mode 100644
index 0000000..1808290
--- /dev/null
+++ b/aconfig/java_aconfig_library_test.go
@@ -0,0 +1,154 @@
+// Copyright 2023 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 aconfig
+
+import (
+	"strings"
+	"testing"
+
+	"android/soong/android"
+	"android/soong/java"
+)
+
+// Note: These tests cover the code in the java package. It'd be ideal of that code could
+// be in the aconfig package.
+
+// With the bp parameter that defines a my_module, make sure it has the LOCAL_ACONFIG_FILES entries
+func runJavaAndroidMkTest(t *testing.T, bp string) {
+	result := android.GroupFixturePreparers(
+		PrepareForTestWithAconfigBuildComponents,
+		java.PrepareForTestWithJavaDefaultModules).
+		ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+		RunTestWithBp(t, bp+`
+			aconfig_declarations {
+				name: "my_aconfig_declarations",
+				package: "com.example.package",
+				srcs: ["foo.aconfig"],
+			}
+
+			java_aconfig_library {
+				name: "my_java_aconfig_library",
+				aconfig_declarations: "my_aconfig_declarations",
+			}
+		`)
+
+	module := result.ModuleForTests("my_module", "android_common").Module()
+
+	entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
+
+	makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
+	android.AssertIntEquals(t, "len(LOCAL_ACONFIG_FILES)", 1, len(makeVar))
+	if !strings.HasSuffix(makeVar[0], "intermediate.pb") {
+		t.Errorf("LOCAL_ACONFIG_FILES should end with /intermediates.pb, instead it is: %s", makeVar[0])
+	}
+}
+
+func TestAndroidMkJavaLibrary(t *testing.T) {
+	bp := `
+		java_library {
+			name: "my_module",
+			srcs: [
+				"src/foo.java",
+			],
+			static_libs: [
+				"my_java_aconfig_library",
+			],
+			platform_apis: true,
+		}
+	`
+
+	runJavaAndroidMkTest(t, bp)
+}
+
+func TestAndroidMkAndroidApp(t *testing.T) {
+	bp := `
+		android_app {
+			name: "my_module",
+			srcs: [
+				"src/foo.java",
+			],
+			static_libs: [
+				"my_java_aconfig_library",
+			],
+			platform_apis: true,
+		}
+	`
+
+	runJavaAndroidMkTest(t, bp)
+}
+
+func TestAndroidMkBinary(t *testing.T) {
+	bp := `
+		java_binary {
+			name: "my_module",
+			srcs: [
+				"src/foo.java",
+			],
+			static_libs: [
+				"my_java_aconfig_library",
+			],
+			platform_apis: true,
+			main_class: "foo",
+		}
+	`
+
+	runJavaAndroidMkTest(t, bp)
+}
+
+func TestAndroidMkAndroidLibrary(t *testing.T) {
+	bp := `
+		android_library {
+			name: "my_module",
+			srcs: [
+				"src/foo.java",
+			],
+			static_libs: [
+				"my_java_aconfig_library",
+			],
+			platform_apis: true,
+		}
+	`
+
+	runJavaAndroidMkTest(t, bp)
+}
+
+func TestAndroidMkBinaryThatLinksAgainstAar(t *testing.T) {
+	// Tests AndroidLibrary's propagation of flags through JavaInfo
+	bp := `
+		android_library {
+			name: "some_library",
+			srcs: [
+				"src/foo.java",
+			],
+			static_libs: [
+				"my_java_aconfig_library",
+			],
+			platform_apis: true,
+		}
+		java_binary {
+			name: "my_module",
+			srcs: [
+				"src/bar.java",
+			],
+			static_libs: [
+				"some_library",
+			],
+			platform_apis: true,
+			main_class: "foo",
+		}
+	`
+
+	runJavaAndroidMkTest(t, bp)
+}
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index d320599..1f29d30 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -141,11 +141,12 @@
 		"external/expat":                         Bp2BuildDefaultTrueRecursively,
 		"external/f2fs-tools":                    Bp2BuildDefaultTrue,
 		"external/flac":                          Bp2BuildDefaultTrueRecursively,
+		"external/flatbuffers":                   Bp2BuildDefaultTrueRecursively,
 		"external/fmtlib":                        Bp2BuildDefaultTrueRecursively,
 		"external/fsverity-utils":                Bp2BuildDefaultTrueRecursively,
-		"external/guava":                         Bp2BuildDefaultTrueRecursively,
 		"external/google-benchmark":              Bp2BuildDefaultTrueRecursively,
 		"external/googletest":                    Bp2BuildDefaultTrueRecursively,
+		"external/guava":                         Bp2BuildDefaultTrueRecursively,
 		"external/gwp_asan":                      Bp2BuildDefaultTrueRecursively,
 		"external/hamcrest":                      Bp2BuildDefaultTrueRecursively,
 		"external/icu":                           Bp2BuildDefaultTrueRecursively,
@@ -227,6 +228,7 @@
 		"frameworks/hardware/interfaces/stats/aidl":          Bp2BuildDefaultTrue,
 		"frameworks/libs/modules-utils/build":                Bp2BuildDefaultTrueRecursively,
 		"frameworks/libs/net/common/native":                  Bp2BuildDefaultTrueRecursively,
+		"frameworks/native":                                  Bp2BuildDefaultTrue,
 		"frameworks/native/libs/adbd_auth":                   Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/arect":                       Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/gui":                         Bp2BuildDefaultTrue,
@@ -429,6 +431,7 @@
 		// external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
 		// e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed
 		"external/bazelbuild-rules_android":/* recursive = */ true,
+		"external/bazelbuild-rules_java":/* recursive = */ true,
 		"external/bazelbuild-rules_license":/* recursive = */ true,
 		"external/bazelbuild-rules_go":/* recursive = */ true,
 		"external/bazelbuild-kotlin-rules":/* recursive = */ true,
@@ -473,6 +476,8 @@
 	Bp2buildModuleAlwaysConvertList = []string{
 		"libidmap2_policies",
 		"libSurfaceFlingerProp",
+		"toolbox_input_labels",
+
 		// cc mainline modules
 
 		// com.android.media.swcodec
@@ -490,7 +495,6 @@
 		"code_coverage.policy.other",
 		"codec2_soft_exports",
 		"compatibility_matrix_schema",
-		"flatbuffer_headers",
 		"framework-connectivity-protos",
 		"gemmlowp_headers",
 		"gl_headers",
@@ -613,10 +617,6 @@
 		"libhidlbase", // needed by cc_hidl_library
 		"libhidl_gtest_helper",
 
-		//frameworks/native
-		"framework_native_aidl_binder",
-		"framework_native_aidl_gui",
-
 		//frameworks/native/libs/input
 		"inputconstants_aidl",
 
@@ -931,9 +931,6 @@
 		"test_fips",                     // depends on unconverted modules: adb
 		"timezone-host",                 // depends on unconverted modules: art.module.api.annotations
 
-		// '//bionic/libc:libc_bp2build_cc_library_static' is duplicated in the 'deps' attribute of rule
-		"toybox-static",
-
 		// aidl files not created
 		"overlayable_policy_aidl_interface",
 
@@ -1016,6 +1013,7 @@
 		"bionic-unit-tests-static",
 		"boringssl_crypto_test",
 		"boringssl_ssl_test",
+		"boringssl_test_support", //b/244431896
 		"cfi_test_helper",
 		"cfi_test_helper2",
 		"cintltst32",
@@ -1493,8 +1491,6 @@
 		"ICU4CTestRunner",
 		"DeviceLongPollingStubTest",
 
-		"HelloWorldHostTest", // TODO(b/280452825): Convert HelloWorldHostTest to b test
-
 		"libprotobuf-full-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
 		"libprotobuf-lite-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
 
diff --git a/android/api_levels.go b/android/api_levels.go
index 2391e6c..44c8640 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -275,10 +275,6 @@
 // relocations itself.
 var FirstPackedRelocationsVersion = uncheckedFinalApiLevel(23)
 
-// The first API level that does not require NDK code to link
-// libandroid_support.
-var FirstNonLibAndroidSupportVersion = uncheckedFinalApiLevel(21)
-
 // LastWithoutModuleLibCoreSystemModules is the last API level where prebuilts/sdk does not contain
 // a core-for-system-modules.jar for the module-lib API scope.
 var LastWithoutModuleLibCoreSystemModules = uncheckedFinalApiLevel(31)
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 5d93f06..94bc88b 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -16,6 +16,8 @@
 
 import (
 	"bytes"
+	"crypto/sha1"
+	"encoding/hex"
 	"fmt"
 	"os"
 	"path"
@@ -1222,7 +1224,11 @@
 		ctx.AddNinjaFileDeps(file)
 	}
 
+	depsetHashToDepset := map[string]bazel.AqueryDepset{}
+
 	for _, depset := range ctx.Config().BazelContext.AqueryDepsets() {
+		depsetHashToDepset[depset.ContentHash] = depset
+
 		var outputs []Path
 		var orderOnlies []Path
 		for _, depsetDepHash := range depset.TransitiveDepSetHashes {
@@ -1257,7 +1263,30 @@
 		}
 		if len(buildStatement.Command) > 0 {
 			rule := NewRuleBuilder(pctx, ctx)
-			createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx)
+			intermediateDir, intermediateDirHash := intermediatePathForSboxMixedBuildAction(ctx, buildStatement)
+			if buildStatement.ShouldRunInSbox {
+				// Create a rule to build the output inside a sandbox
+				// This will create two changes of working directory
+				// 1. From ANDROID_BUILD_TOP to sbox top
+				// 2. From sbox top to a a synthetic mixed build execution root relative to it
+				// Finally, the outputs will be copied to intermediateDir
+				rule.Sbox(intermediateDir,
+					PathForOutput(ctx, "mixed_build_sbox_intermediates", intermediateDirHash+".textproto")).
+					SandboxInputs().
+					// Since we will cd to mixed build execution root, set sbox's out subdir to empty
+					// Without this, we will try to copy from $SBOX_SANDBOX_DIR/out/out/bazel/output/execroot/__main__/...
+					SetSboxOutDirDirAsEmpty()
+
+				// Create another set of rules to copy files from the intermediate dir to mixed build execution root
+				for _, outputPath := range buildStatement.OutputPaths {
+					ctx.Build(pctx, BuildParams{
+						Rule:   CpIfChanged,
+						Input:  intermediateDir.Join(ctx, executionRoot, outputPath),
+						Output: PathForBazelOut(ctx, outputPath),
+					})
+				}
+			}
+			createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx, depsetHashToDepset)
 			desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths)
 			rule.Build(fmt.Sprintf("bazel %d", index), desc)
 			continue
@@ -1304,10 +1333,25 @@
 	}
 }
 
+// Returns a out dir path for a sandboxed mixed build action
+func intermediatePathForSboxMixedBuildAction(ctx PathContext, statement *bazel.BuildStatement) (OutputPath, string) {
+	// An artifact can be generated by a single buildstatement.
+	// Use the hash of the first artifact to create a unique path
+	uniqueDir := sha1.New()
+	uniqueDir.Write([]byte(statement.OutputPaths[0]))
+	uniqueDirHashString := hex.EncodeToString(uniqueDir.Sum(nil))
+	return PathForOutput(ctx, "mixed_build_sbox_intermediates", uniqueDirHashString), uniqueDirHashString
+}
+
 // Register bazel-owned build statements (obtained from the aquery invocation).
-func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx BuilderContext) {
+func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx BuilderContext, depsetHashToDepset map[string]bazel.AqueryDepset) {
 	// executionRoot is the action cwd.
-	cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot))
+	if buildStatement.ShouldRunInSbox {
+		// mkdir -p ensures that the directory exists when run via sbox
+		cmd.Text(fmt.Sprintf("mkdir -p '%s' && cd '%s' &&", executionRoot, executionRoot))
+	} else {
+		cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot))
+	}
 
 	// Remove old outputs, as some actions might not rerun if the outputs are detected.
 	if len(buildStatement.OutputPaths) > 0 {
@@ -1334,14 +1378,30 @@
 	}
 
 	for _, outputPath := range buildStatement.OutputPaths {
-		cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath))
+		if buildStatement.ShouldRunInSbox {
+			// The full path has three components that get joined together
+			// 1. intermediate output dir that `sbox` will place the artifacts at
+			// 2. mixed build execution root
+			// 3. artifact path returned by aquery
+			intermediateDir, _ := intermediatePathForSboxMixedBuildAction(ctx, buildStatement)
+			cmd.ImplicitOutput(intermediateDir.Join(ctx, executionRoot, outputPath))
+		} else {
+			cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath))
+		}
 	}
 	for _, inputPath := range buildStatement.InputPaths {
 		cmd.Implicit(PathForBazelOut(ctx, inputPath))
 	}
 	for _, inputDepsetHash := range buildStatement.InputDepsetHashes {
-		otherDepsetName := bazelDepsetName(inputDepsetHash)
-		cmd.Implicit(PathForPhony(ctx, otherDepsetName))
+		if buildStatement.ShouldRunInSbox {
+			// Bazel depsets are phony targets that are used to group files.
+			// We need to copy the grouped files into the sandbox
+			ds, _ := depsetHashToDepset[inputDepsetHash]
+			cmd.Implicits(PathsForBazelOut(ctx, ds.DirectArtifacts))
+		} else {
+			otherDepsetName := bazelDepsetName(inputDepsetHash)
+			cmd.Implicit(PathForPhony(ctx, otherDepsetName))
+		}
 	}
 
 	if depfile := buildStatement.Depfile; depfile != nil {
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index 65cd5a8..e08a471 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -181,13 +181,62 @@
 
 		cmd := RuleBuilderCommand{}
 		ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
-		createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx)
+		createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{})
 		if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
 			t.Errorf("expected: [%s], actual: [%s]", expected, actual)
 		}
 	}
 }
 
+func TestMixedBuildSandboxedAction(t *testing.T) {
+	input := `{
+ "artifacts": [
+   { "id": 1, "path_fragment_id": 1 },
+   { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+   "target_Id": 1,
+   "action_Key": "x",
+   "mnemonic": "x",
+   "arguments": ["touch", "foo"],
+   "input_dep_set_ids": [1],
+   "output_Ids": [1],
+   "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+   { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+   { "id": 1, "label": "one" },
+   { "id": 2, "label": "two" }]
+}`
+	data, err := JsonToActionGraphContainer(input)
+	if err != nil {
+		t.Error(err)
+	}
+	bazelContext, _ := testBazelContext(t, map[bazelCommand]string{aqueryCmd: string(data)})
+
+	err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
+	if err != nil {
+		t.Fatalf("TestMixedBuildSandboxedAction did not expect error invoking Bazel, but got %s", err)
+	}
+
+	statement := bazelContext.BuildStatementsToRegister()[0]
+	statement.ShouldRunInSbox = true
+
+	cmd := RuleBuilderCommand{}
+	ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
+	createCommand(&cmd, statement, "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{})
+	// Assert that the output is generated in an intermediate directory
+	// fe05bcdcdc4928012781a5f1a2a77cbb5398e106 is the sha1 checksum of "one"
+	if actual, expected := cmd.outputs[0].String(), "out/soong/mixed_build_sbox_intermediates/fe05bcdcdc4928012781a5f1a2a77cbb5398e106/test/exec_root/one"; expected != actual {
+		t.Errorf("expected: [%s], actual: [%s]", expected, actual)
+	}
+
+	// Assert the actual command remains unchanged inside the sandbox
+	if actual, expected := cmd.buf.String(), "mkdir -p 'test/exec_root' && cd 'test/exec_root' && rm -rf 'one' && touch foo"; expected != actual {
+		t.Errorf("expected: [%s], actual: [%s]", expected, actual)
+	}
+}
+
 func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
 	testConfig.productVariables.ClangCoverage = boolPtr(true)
 
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 2f5ff64..8956a18 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -179,7 +179,7 @@
 // paths, relative to the local module, or Bazel-labels (absolute if in a different package or
 // relative if within the same package).
 // Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
-// will have already been handled by the path_deps mutator.
+// will have already been handled by the pathdeps mutator.
 func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList {
 	return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
 }
@@ -189,7 +189,7 @@
 // references in paths, minus those in excludes, relative to the local module, or Bazel-labels
 // (absolute if in a different package or relative if within the same package).
 // Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
-// will have already been handled by the path_deps mutator.
+// will have already been handled by the pathdeps mutator.
 func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList {
 	excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil))
 	excluded := make([]string, 0, len(excludeLabels.Includes))
@@ -355,7 +355,7 @@
 //
 // Properties passed as the paths or excludes argument must have been annotated with struct tag
 // `android:"path"` so that dependencies on other modules will have already been handled by the
-// path_deps mutator.
+// pathdeps mutator.
 func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes []string) bazel.LabelList {
 	if paths == nil {
 		return bazel.LabelList{}
diff --git a/android/config.go b/android/config.go
index f95010e..2a243ee 100644
--- a/android/config.go
+++ b/android/config.go
@@ -18,7 +18,6 @@
 // product variables necessary for soong_build's operation.
 
 import (
-	"bytes"
 	"encoding/json"
 	"fmt"
 	"os"
@@ -431,32 +430,6 @@
 		return fmt.Errorf("cannot marshal arch variant product variable data: %s", err.Error())
 	}
 
-	configJson, err := json.MarshalIndent(&config, "", "    ")
-	if err != nil {
-		return fmt.Errorf("cannot marshal config data: %s", err.Error())
-	}
-	// The backslashes need to be escaped because this text is going to be put
-	// inside a Starlark string literal.
-	configJson = bytes.ReplaceAll(configJson, []byte("\\"), []byte("\\\\"))
-
-	bzl := []string{
-		bazel.GeneratedBazelFileWarning,
-		fmt.Sprintf(`_product_vars = json.decode("""%s""")`, configJson),
-		fmt.Sprintf(`_product_var_constraints = %s`, nonArchVariantProductVariablesJson),
-		fmt.Sprintf(`_arch_variant_product_var_constraints = %s`, archVariantProductVariablesJson),
-		"\n", `
-product_vars = _product_vars
-
-# TODO(b/269577299) Remove these when everything switches over to loading them from product_variable_constants.bzl
-product_var_constraints = _product_var_constraints
-arch_variant_product_var_constraints = _arch_variant_product_var_constraints
-`,
-	}
-	err = pathtools.WriteFileIfChanged(filepath.Join(dir, "product_variables.bzl"),
-		[]byte(strings.Join(bzl, "\n")), 0644)
-	if err != nil {
-		return fmt.Errorf("Could not write .bzl config file %s", err)
-	}
 	err = pathtools.WriteFileIfChanged(filepath.Join(dir, "product_variable_constants.bzl"), []byte(fmt.Sprintf(`
 product_var_constraints = %s
 arch_variant_product_var_constraints = %s
@@ -1355,6 +1328,10 @@
 	return c.bazelForceEnabledModules
 }
 
+func (c *config) IsVndkDeprecated() bool {
+	return !Bool(c.productVariables.KeepVndk)
+}
+
 func (c *deviceConfig) Arches() []Arch {
 	var arches []Arch
 	for _, target := range c.config.Targets[Android] {
diff --git a/android/paths.go b/android/paths.go
index fda4d2f..e16cb37 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -396,7 +396,7 @@
 //
 // Properties passed as the paths argument must have been annotated with struct tag
 // `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
-// path_deps mutator.
+// pathdeps mutator.
 // If a requested module is not found as a dependency:
 //   - if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having
 //     missing dependencies
@@ -425,7 +425,7 @@
 // excluding the items (similarly resolved
 // Properties passed as the paths argument must have been annotated with struct tag
 // `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
-// path_deps mutator.
+// pathdeps mutator.
 // If a requested module is not found as a dependency:
 //   - if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having
 //     missing dependencies
@@ -560,7 +560,7 @@
 // and a list of the module names of missing module dependencies are returned as the second return.
 // Properties passed as the paths argument must have been annotated with struct tag
 // `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
-// path_deps mutator.
+// pathdeps mutator.
 func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleMissingDepsPathContext, paths, excludes []string) (Paths, []string) {
 	return PathsAndMissingDepsRelativeToModuleSourceDir(SourceInput{
 		Context:      ctx,
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 0438eb8..777c1cf 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -53,6 +53,7 @@
 	remoteable       RemoteRuleSupports
 	rbeParams        *remoteexec.REParams
 	outDir           WritablePath
+	sboxOutSubDir    string
 	sboxTools        bool
 	sboxInputs       bool
 	sboxManifestPath WritablePath
@@ -65,9 +66,18 @@
 		pctx:           pctx,
 		ctx:            ctx,
 		temporariesSet: make(map[WritablePath]bool),
+		sboxOutSubDir:  sboxOutSubDir,
 	}
 }
 
+// SetSboxOutDirDirAsEmpty sets the out subdirectory to an empty string
+// This is useful for sandboxing actions that change the execution root to a path in out/ (e.g mixed builds)
+// For such actions, SetSboxOutDirDirAsEmpty ensures that the path does not become $SBOX_SANDBOX_DIR/out/out/bazel/output/execroot/__main__/...
+func (rb *RuleBuilder) SetSboxOutDirDirAsEmpty() *RuleBuilder {
+	rb.sboxOutSubDir = ""
+	return rb
+}
+
 // RuleBuilderInstall is a tuple of install from and to locations.
 type RuleBuilderInstall struct {
 	From Path
@@ -585,7 +595,7 @@
 		for _, output := range outputs {
 			rel := Rel(r.ctx, r.outDir.String(), output.String())
 			command.CopyAfter = append(command.CopyAfter, &sbox_proto.Copy{
-				From: proto.String(filepath.Join(sboxOutSubDir, rel)),
+				From: proto.String(filepath.Join(r.sboxOutSubDir, rel)),
 				To:   proto.String(output.String()),
 			})
 		}
diff --git a/android/util.go b/android/util.go
index e17d7b2..5375373 100644
--- a/android/util.go
+++ b/android/util.go
@@ -137,19 +137,17 @@
 }
 
 // IndexList returns the index of the first occurrence of the given string in the list or -1
-func IndexList(s string, list []string) int {
+func IndexList[T comparable](t T, list []T) int {
 	for i, l := range list {
-		if l == s {
+		if l == t {
 			return i
 		}
 	}
-
 	return -1
 }
 
-// InList checks if the string belongs to the list
-func InList(s string, list []string) bool {
-	return IndexList(s, list) != -1
+func InList[T comparable](t T, list []T) bool {
+	return IndexList(t, list) != -1
 }
 
 func setFromList[T comparable](l []T) map[T]bool {
diff --git a/android/variable.go b/android/variable.go
index f5dddaf..1c81f3c 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -475,6 +475,8 @@
 
 	ReleaseVersion          string   `json:",omitempty"`
 	ReleaseAconfigValueSets []string `json:",omitempty"`
+
+	KeepVndk *bool `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 480158c..3428328 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -116,6 +116,9 @@
 	InputDepsetHashes []string
 	InputPaths        []string
 	FileContents      string
+	// If ShouldRunInSbox is true, Soong will use sbox to created an isolated environment
+	// and run the mixed build action there
+	ShouldRunInSbox bool
 }
 
 // A helper type for aquery processing which facilitates retrieval of path IDs from their
@@ -496,6 +499,12 @@
 		Env:               actionEntry.EnvironmentVariables,
 		Mnemonic:          actionEntry.Mnemonic,
 	}
+	if buildStatement.Mnemonic == "GoToolchainBinaryBuild" {
+		// Unlike b's execution root, mixed build execution root contains a symlink to prebuilts/go
+		// This causes issues for `GOCACHE=$(mktemp -d) go build ...`
+		// To prevent this, sandbox this action in mixed builds as well
+		buildStatement.ShouldRunInSbox = true
+	}
 	return buildStatement, nil
 }
 
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index 8d5c99c..c8067af 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -163,12 +163,30 @@
 	return result, nil
 }
 
+var bazelPlatformSuffixes = []string{
+	"",
+	"_darwin_arm64",
+	"_darwin_x86_64",
+	"_linux_bionic_arm64",
+	"_linux_bionic_x86_64",
+	"_linux_musl_x86",
+	"_linux_musl_x86_64",
+	"_linux_x86",
+	"_linux_x86_64",
+	"_windows_x86",
+	"_windows_x86_64",
+}
+
 func platformMappingSingleProduct(label string, productVariables *android.ProductVariables) string {
 	buildSettings := ""
 	buildSettings += fmt.Sprintf("    --//build/bazel/product_config:apex_global_min_sdk_version_override=%s\n", proptools.String(productVariables.ApexGlobalMinSdkVersionOverride))
+	buildSettings += fmt.Sprintf("    --//build/bazel/product_config:cfi_include_paths=%s\n", strings.Join(productVariables.CFIIncludePaths, ","))
+	buildSettings += fmt.Sprintf("    --//build/bazel/product_config:cfi_exclude_paths=%s\n", strings.Join(productVariables.CFIExcludePaths, ","))
+	buildSettings += fmt.Sprintf("    --//build/bazel/product_config:enable_cfi=%t\n", proptools.BoolDefault(productVariables.EnableCFI, true))
+	buildSettings += fmt.Sprintf("    --//build/bazel/product_config:device_abi=%s\n", strings.Join(productVariables.DeviceAbi, ","))
 	result := ""
-	for _, extension := range []string{"", "_linux_x86_64", "_linux_bionic_x86_64", "_linux_musl_x86", "_linux_musl_x86_64"} {
-		result += "  " + label + extension + "\n" + buildSettings
+	for _, suffix := range bazelPlatformSuffixes {
+		result += "  " + label + suffix + "\n" + buildSettings
 	}
 	return result
 }
@@ -176,7 +194,23 @@
 func starlarkMapToProductVariables(in map[string]starlark.Value) (android.ProductVariables, error) {
 	var err error
 	result := android.ProductVariables{}
-	result.ApexGlobalMinSdkVersionOverride, err = starlark_import.NoneableString(in["ApexGlobalMinSdkVersionOverride"])
+	result.ApexGlobalMinSdkVersionOverride, err = starlark_import.UnmarshalNoneable[string](in["ApexGlobalMinSdkVersionOverride"])
+	if err != nil {
+		return result, err
+	}
+	result.CFIIncludePaths, err = starlark_import.Unmarshal[[]string](in["CFIIncludePaths"])
+	if err != nil {
+		return result, err
+	}
+	result.CFIExcludePaths, err = starlark_import.Unmarshal[[]string](in["CFIExcludePaths"])
+	if err != nil {
+		return result, err
+	}
+	result.EnableCFI, err = starlark_import.UnmarshalNoneable[bool](in["EnableCFI"])
+	if err != nil {
+		return result, err
+	}
+	result.DeviceAbi, err = starlark_import.Unmarshal[[]string](in["DeviceAbi"])
 	if err != nil {
 		return result, err
 	}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index a817386..0e6596b 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -471,17 +471,6 @@
 	return []BazelTarget{binTarget}, nil
 }
 
-var (
-	// TODO - b/284483729: Remove this denyilst
-	// Temporary denylist of go binaries that are currently used in mixed builds
-	// This denylist allows us to rollout bp2build converters for go targets without affecting mixed builds
-	goBinaryDenylist = []string{
-		"soong_zip",
-		"zip2zip",
-		"bazel_notice_gen",
-	}
-)
-
 func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (conversionResults, []error) {
 	buildFileToTargets := make(map[string]BazelTargets)
 
@@ -574,7 +563,7 @@
 				targets, targetErrs = generateBazelTargetsGoPackage(bpCtx, glib, nameToGoLibMap)
 				errs = append(errs, targetErrs...)
 				metrics.IncrementRuleClassCount("go_library")
-			} else if gbin, ok := m.(*bootstrap.GoBinary); ok && !android.InList(m.Name(), goBinaryDenylist) {
+			} else if gbin, ok := m.(*bootstrap.GoBinary); ok {
 				targets, targetErrs = generateBazelTargetsGoBinary(bpCtx, gbin, nameToGoLibMap)
 				errs = append(errs, targetErrs...)
 				metrics.IncrementRuleClassCount("go_binary")
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 4b36cc7..d9a7860 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -1214,3 +1214,82 @@
 		},
 	})
 }
+
+func TestCcBinaryStatic_SystemSharedLibUsedAsDep(t *testing.T) {
+	runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+		description: "cc_library_static system_shared_lib empty for linux_bionic variant",
+		blueprint: soongCcLibraryStaticPreamble +
+			simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
+
+cc_library {
+    name: "libm",
+    bazel_module: { bp2build_available: false },
+}
+
+cc_binary {
+    name: "used_in_bionic_oses",
+    target: {
+        android: {
+            static_libs: ["libc"],
+        },
+        linux_bionic: {
+            static_libs: ["libc"],
+        },
+    },
+    include_build_directory: false,
+    static_executable: true,
+}
+
+cc_binary {
+    name: "all",
+    static_libs: ["libc"],
+    include_build_directory: false,
+    static_executable: true,
+}
+
+cc_binary {
+    name: "keep_for_empty_system_shared_libs",
+    static_libs: ["libc"],
+    system_shared_libs: [],
+    include_build_directory: false,
+    static_executable: true,
+}
+
+cc_binary {
+    name: "used_with_stubs",
+    static_libs: ["libm"],
+    include_build_directory: false,
+    static_executable: true,
+}
+
+cc_binary {
+    name: "keep_with_stubs",
+    static_libs: ["libm"],
+    system_shared_libs: [],
+    include_build_directory: false,
+    static_executable: true,
+}
+`,
+		targets: []testBazelTarget{
+			{"cc_binary", "all", AttrNameToString{
+				"linkshared": "False",
+			}},
+			{"cc_binary", "keep_for_empty_system_shared_libs", AttrNameToString{
+				"deps":        `[":libc_bp2build_cc_library_static"]`,
+				"system_deps": `[]`,
+				"linkshared":  "False",
+			}},
+			{"cc_binary", "keep_with_stubs", AttrNameToString{
+				"linkshared":  "False",
+				"deps":        `[":libm_bp2build_cc_library_static"]`,
+				"system_deps": `[]`,
+			}},
+			{"cc_binary", "used_in_bionic_oses", AttrNameToString{
+				"linkshared": "False",
+			}},
+			{"cc_binary", "used_with_stubs", AttrNameToString{
+				"linkshared": "False",
+			}},
+		},
+	})
+}
diff --git a/bp2build/java_test_host_conversion_test.go b/bp2build/java_test_host_conversion_test.go
index f411ffb..f41345e 100644
--- a/bp2build/java_test_host_conversion_test.go
+++ b/bp2build/java_test_host_conversion_test.go
@@ -71,6 +71,11 @@
 			}),
 			MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
 				"runtime_deps": `[":java_test_host-1_lib"]`,
+				"deps": `[
+        ":lib_a-neverlink",
+        ":static_libs_a",
+    ]`,
+				"srcs": `["a.java"]`,
 				"target_compatible_with": `select({
         "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
         "//conditions:default": [],
@@ -128,6 +133,10 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
+				"srcs": `[
+        "a.java",
+        "b.kt",
+    ]`,
 				"runtime_deps": `[":java_test_host-1_lib"]`,
 				"target_compatible_with": `select({
         "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
diff --git a/cc/Android.bp b/cc/Android.bp
index f49dc1a..e88ea03 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -32,6 +32,7 @@
         "check.go",
         "coverage.go",
         "gen.go",
+        "generated_cc_library.go",
         "image.go",
         "linkable.go",
         "lto.go",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 85a2284..6e00aa8 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -1139,6 +1139,7 @@
 	wholeArchiveDeps                 bazel.LabelListAttribute
 	implementationWholeArchiveDeps   bazel.LabelListAttribute
 	systemDynamicDeps                bazel.LabelListAttribute
+	usedSystemDynamicDepAsStaticDep  map[string]bool
 	usedSystemDynamicDepAsDynamicDep map[string]bool
 
 	useVersionLib                 bazel.BoolAttribute
@@ -1201,6 +1202,18 @@
 	// https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
 	la.wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, props.Exclude_static_libs))
 
+	if isBinary && module.StaticExecutable() {
+		usedSystemStatic := android.FilterListPred(staticLibs, func(s string) bool {
+			return android.InList(s, soongSystemSharedLibs) && !android.InList(s, props.Exclude_static_libs)
+		})
+
+		for _, el := range usedSystemStatic {
+			if la.usedSystemDynamicDepAsStaticDep == nil {
+				la.usedSystemDynamicDepAsStaticDep = map[string]bool{}
+			}
+			la.usedSystemDynamicDepAsStaticDep[el] = true
+		}
+	}
 	staticDeps := maybePartitionExportedAndImplementationsDepsExcludes(
 		ctx,
 		!isBinary,
@@ -1233,6 +1246,7 @@
 	usedSystem := android.FilterListPred(sharedLibs, func(s string) bool {
 		return android.InList(s, soongSystemSharedLibs) && !android.InList(s, excludeSharedLibs)
 	})
+
 	for _, el := range usedSystem {
 		if la.usedSystemDynamicDepAsDynamicDep == nil {
 			la.usedSystemDynamicDepAsDynamicDep = map[string]bool{}
@@ -1625,6 +1639,15 @@
 		}
 		la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidPlatform, bazel.MakeLabelList(stubsToRemove))
 	}
+	if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsStaticDep) > 0 {
+		toRemove := bazelLabelForStaticDeps(ctx, android.SortedKeys(la.usedSystemDynamicDepAsStaticDep))
+		la.deps.Exclude(bazel.NoConfigAxis, "", toRemove)
+		la.deps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
+		la.deps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+		la.implementationDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
+		la.implementationDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
+		la.implementationDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+	}
 
 	la.deps.ResolveExcludes()
 	la.implementationDeps.ResolveExcludes()
diff --git a/cc/cc.go b/cc/cc.go
index f11cfec..be67286 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -569,6 +569,24 @@
 	props() []interface{}
 }
 
+// Information returned from Generator about the source code it's generating
+type GeneratedSource struct {
+	IncludeDirs    android.Paths
+	Sources        android.Paths
+	Headers        android.Paths
+	ReexportedDirs android.Paths
+}
+
+// generator allows injection of generated code
+type Generator interface {
+	GeneratorProps() []interface{}
+	GeneratorInit(ctx BaseModuleContext)
+	GeneratorDeps(ctx DepsContext, deps Deps) Deps
+	GeneratorFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags
+	GeneratorSources(ctx ModuleContext) GeneratedSource
+	GeneratorBuildActions(ctx ModuleContext, flags Flags, deps PathDeps)
+}
+
 // compiler is the interface for a compiler helper object. Different module decorators may implement
 // this helper differently.
 type compiler interface {
@@ -851,6 +869,7 @@
 	// type-specific logic. These members may reference different objects or the same object.
 	// Functions of these decorators will be invoked to initialize and register type-specific
 	// build statements.
+	generators   []Generator
 	compiler     compiler
 	linker       linker
 	installer    installer
@@ -1201,6 +1220,9 @@
 
 func (c *Module) Init() android.Module {
 	c.AddProperties(&c.Properties, &c.VendorProperties)
+	for _, generator := range c.generators {
+		c.AddProperties(generator.GeneratorProps()...)
+	}
 	if c.compiler != nil {
 		c.AddProperties(c.compiler.compilerProps()...)
 	}
@@ -1372,7 +1394,7 @@
 
 func (c *Module) isCfi() bool {
 	if sanitize := c.sanitize; sanitize != nil {
-		return Bool(sanitize.Properties.Sanitize.Cfi)
+		return Bool(sanitize.Properties.SanitizeMutated.Cfi)
 	}
 	return false
 }
@@ -2149,6 +2171,25 @@
 		return
 	}
 
+	for _, generator := range c.generators {
+		gen := generator.GeneratorSources(ctx)
+		deps.IncludeDirs = append(deps.IncludeDirs, gen.IncludeDirs...)
+		deps.ReexportedDirs = append(deps.ReexportedDirs, gen.ReexportedDirs...)
+		deps.GeneratedDeps = append(deps.GeneratedDeps, gen.Headers...)
+		deps.ReexportedGeneratedHeaders = append(deps.ReexportedGeneratedHeaders, gen.Headers...)
+		deps.ReexportedDeps = append(deps.ReexportedDeps, gen.Headers...)
+		if len(deps.Objs.objFiles) == 0 {
+			// If we are reusuing object files (which happens when we're a shared library and we're
+			// reusing our static variant's object files), then skip adding the actual source files,
+			// because we already have the object for it.
+			deps.GeneratedSources = append(deps.GeneratedSources, gen.Sources...)
+		}
+	}
+
+	if ctx.Failed() {
+		return
+	}
+
 	if c.stubLibraryMultipleApexViolation(actx) {
 		actx.PropertyErrorf("apex_available",
 			"Stub libraries should have a single apex_available (test apexes excluded). Got %v", c.ApexAvailable())
@@ -2163,6 +2204,9 @@
 		Toolchain: c.toolchain(ctx),
 		EmitXrefs: ctx.Config().EmitXrefRules(),
 	}
+	for _, generator := range c.generators {
+		flags = generator.GeneratorFlags(ctx, flags, deps)
+	}
 	if c.compiler != nil {
 		flags = c.compiler.compilerFlags(ctx, flags, deps)
 	}
@@ -2220,6 +2264,10 @@
 
 	flags.AssemblerWithCpp = inList("-xassembler-with-cpp", flags.Local.AsFlags)
 
+	for _, generator := range c.generators {
+		generator.GeneratorBuildActions(ctx, flags, deps)
+	}
+
 	var objs Objects
 	if c.compiler != nil {
 		objs = c.compiler.compile(ctx, flags, deps)
@@ -2307,6 +2355,9 @@
 }
 
 func (c *Module) begin(ctx BaseModuleContext) {
+	for _, generator := range c.generators {
+		generator.GeneratorInit(ctx)
+	}
 	if c.compiler != nil {
 		c.compiler.compilerInit(ctx)
 	}
@@ -2342,6 +2393,9 @@
 func (c *Module) deps(ctx DepsContext) Deps {
 	deps := Deps{}
 
+	for _, generator := range c.generators {
+		deps = generator.GeneratorDeps(ctx, deps)
+	}
 	if c.compiler != nil {
 		deps = c.compiler.compilerDeps(ctx, deps)
 	}
@@ -2950,20 +3004,20 @@
 			ctx.ModuleErrorf("links %q built against newer API version %q",
 				ctx.OtherModuleName(to.Module()), "current")
 		} else {
-			fromApi, err := strconv.Atoi(from.SdkVersion())
+			fromApi, err := android.ApiLevelFromUserWithConfig(ctx.Config(), from.SdkVersion())
 			if err != nil {
 				ctx.PropertyErrorf("sdk_version",
-					"Invalid sdk_version value (must be int or current): %q",
+					"Invalid sdk_version value (must be int, preview or current): %q",
 					from.SdkVersion())
 			}
-			toApi, err := strconv.Atoi(to.SdkVersion())
+			toApi, err := android.ApiLevelFromUserWithConfig(ctx.Config(), to.SdkVersion())
 			if err != nil {
 				ctx.PropertyErrorf("sdk_version",
-					"Invalid sdk_version value (must be int or current): %q",
+					"Invalid sdk_version value (must be int, preview or current): %q",
 					to.SdkVersion())
 			}
 
-			if toApi > fromApi {
+			if toApi.GreaterThan(fromApi) {
 				ctx.ModuleErrorf("links %q built against newer API version %q",
 					ctx.OtherModuleName(to.Module()), to.SdkVersion())
 			}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index a0ef575..62f75d1 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -261,5 +261,3 @@
 func LibFuzzerRuntimeInterceptors(t Toolchain) string {
 	return LibclangRuntimeLibrary(t, "fuzzer_interceptors")
 }
-
-var inList = android.InList
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 7f0a502..227fe8b 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -29,6 +29,7 @@
 func init() {
 	android.RegisterModuleType("cc_fuzz", LibFuzzFactory)
 	android.RegisterParallelSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
+	android.RegisterParallelSingletonType("cc_fuzz_presubmit_packaging", fuzzPackagingFactoryPresubmit)
 }
 
 type FuzzProperties struct {
@@ -356,9 +357,10 @@
 // their architecture & target/host specific zip file.
 type ccRustFuzzPackager struct {
 	fuzz.FuzzPackager
-	fuzzPackagingArchModules         string
-	fuzzTargetSharedDepsInstallPairs string
-	allFuzzTargetsName               string
+	fuzzPackagingArchModules         			string
+	fuzzTargetSharedDepsInstallPairs 			string
+	allFuzzTargetsName               			string
+	onlyIncludePresubmits						bool
 }
 
 func fuzzPackagingFactory() android.Singleton {
@@ -367,6 +369,18 @@
 		fuzzPackagingArchModules:         "SOONG_FUZZ_PACKAGING_ARCH_MODULES",
 		fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
 		allFuzzTargetsName:               "ALL_FUZZ_TARGETS",
+		onlyIncludePresubmits:			  false,
+	}
+	return fuzzPackager
+}
+
+func fuzzPackagingFactoryPresubmit() android.Singleton {
+
+	fuzzPackager := &ccRustFuzzPackager{
+		fuzzPackagingArchModules:         "SOONG_PRESUBMIT_FUZZ_PACKAGING_ARCH_MODULES",
+		fuzzTargetSharedDepsInstallPairs: "PRESUBMIT_FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
+		allFuzzTargetsName:               "ALL_PRESUBMIT_FUZZ_TARGETS",
+		onlyIncludePresubmits:			  true,
 	}
 	return fuzzPackager
 }
@@ -390,7 +404,6 @@
 		if !ok || ccModule.PreventInstall() {
 			return
 		}
-
 		// Discard non-fuzz targets.
 		if ok := fuzz.IsValid(ccModule.FuzzModuleStruct()); !ok {
 			return
@@ -407,6 +420,9 @@
 		} else if ccModule.Host() {
 			hostOrTargetString = "host"
 		}
+		if s.onlyIncludePresubmits == true {
+			hostOrTargetString = "presubmit-" + hostOrTargetString
+		}
 
 		fpm := fuzz.FuzzPackagedModule{}
 		if ok {
@@ -431,6 +447,14 @@
 		// The executable.
 		files = append(files, fuzz.FileToZip{SourceFilePath: android.OutputFileForModule(ctx, ccModule, "unstripped")})
 
+		if s.onlyIncludePresubmits == true {
+			if fpm.FuzzProperties.Fuzz_config == nil {
+				return
+			}
+			if !BoolDefault(fpm.FuzzProperties.Fuzz_config.Use_for_presubmit, false){
+				return
+			}
+		}
 		archDirs[archOs], ok = s.BuildZipFile(ctx, module, fpm, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
 		if !ok {
 			return
diff --git a/cc/generated_cc_library.go b/cc/generated_cc_library.go
new file mode 100644
index 0000000..55e19f9
--- /dev/null
+++ b/cc/generated_cc_library.go
@@ -0,0 +1,38 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+	"android/soong/android"
+)
+
+func GeneratedCcLibraryModuleFactory(moduleName string, callbacks Generator) android.Module {
+	module, _ := NewLibrary(android.HostAndDeviceSupported)
+
+	// Can be used as both a static and a shared library.
+	module.sdkMemberTypes = []android.SdkMemberType{
+		sharedLibrarySdkMemberType,
+		staticLibrarySdkMemberType,
+		staticAndSharedLibrarySdkMemberType,
+	}
+
+	//	TODO: Need to be bazelable
+	//	module.bazelable = true
+	//	module.bazelHandler = &ccLibraryBazelHandler{module: module}
+
+	module.generators = append(module.generators, callbacks)
+
+	return module.Init()
+}
diff --git a/cc/library.go b/cc/library.go
index 3dcb5d9..266fa75 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -2275,7 +2275,7 @@
 
 			// do not install vndk libs
 			// vndk libs are packaged into VNDK APEX
-			if ctx.isVndk() && !ctx.IsVndkExt() {
+			if ctx.isVndk() && !ctx.IsVndkExt() && !ctx.Config().IsVndkDeprecated() {
 				return
 			}
 		} else if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() {
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 62e31d1..626005b 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -646,10 +646,6 @@
 	if (ctx.Arch().ArchType != android.Arm64 && ctx.Arch().ArchType != android.Riscv64) || !ctx.toolchain().Bionic() {
 		s.Scs = nil
 	}
-	// ...but temporarily globally disabled on riscv64 (http://b/277909695).
-	if ctx.Arch().ArchType == android.Riscv64 {
-		s.Scs = nil
-	}
 
 	// Memtag_heap is only implemented on AArch64.
 	// Memtag ABI is Android specific for now, so disable for host.
diff --git a/cc/stl.go b/cc/stl.go
index f1433ef..ffc7c76 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -120,11 +120,6 @@
 	}()
 }
 
-func needsLibAndroidSupport(ctx BaseModuleContext) bool {
-	version := nativeApiLevelOrPanic(ctx, ctx.sdkVersion())
-	return version.LessThan(android.FirstNonLibAndroidSupportVersion)
-}
-
 func staticUnwinder(ctx android.BaseModuleContext) string {
 	vndkVersion := ctx.Module().(*Module).VndkVersion()
 
@@ -184,11 +179,6 @@
 		} else {
 			deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl, "ndk_libc++abi")
 		}
-		if needsLibAndroidSupport(ctx) {
-			// Use LateStaticLibs for ndk_libandroid_support so that its include directories
-			// come after ndk_libc++_static or ndk_libc++_shared.
-			deps.LateStaticLibs = append(deps.LateStaticLibs, "ndk_libandroid_support")
-		}
 		deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind")
 	default:
 		panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
diff --git a/cc/testing.go b/cc/testing.go
index d346739..d1632aa 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -423,11 +423,6 @@
 			export_include_dirs: ["ndk_libc++_shared"],
 		}
 
-		ndk_prebuilt_static_stl {
-			name: "ndk_libandroid_support",
-			export_include_dirs: ["ndk_libandroid_support"],
-		}
-
 		cc_library_static {
 			name: "libgoogle-benchmark",
 			sdk_version: "current",
@@ -573,16 +568,15 @@
 
 	// Additional files needed in tests that disallow non-existent source.
 	android.MockFS{
-		"defaults/cc/common/libc.map.txt":           nil,
-		"defaults/cc/common/libdl.map.txt":          nil,
-		"defaults/cc/common/libm.map.txt":           nil,
-		"defaults/cc/common/ndk_libandroid_support": nil,
-		"defaults/cc/common/ndk_libc++_shared":      nil,
-		"defaults/cc/common/crtbegin_so.c":          nil,
-		"defaults/cc/common/crtbegin.c":             nil,
-		"defaults/cc/common/crtend_so.c":            nil,
-		"defaults/cc/common/crtend.c":               nil,
-		"defaults/cc/common/crtbrand.c":             nil,
+		"defaults/cc/common/libc.map.txt":      nil,
+		"defaults/cc/common/libdl.map.txt":     nil,
+		"defaults/cc/common/libm.map.txt":      nil,
+		"defaults/cc/common/ndk_libc++_shared": nil,
+		"defaults/cc/common/crtbegin_so.c":     nil,
+		"defaults/cc/common/crtbegin.c":        nil,
+		"defaults/cc/common/crtend_so.c":       nil,
+		"defaults/cc/common/crtend.c":          nil,
+		"defaults/cc/common/crtbrand.c":        nil,
 
 		"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil,
 		"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a":   nil,
diff --git a/cc/util.go b/cc/util.go
index 6d8ac43..c93646b 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -28,8 +28,8 @@
 	return android.JoinWithPrefix(dirs.Strings(), "-I")
 }
 
-var indexList = android.IndexList
-var inList = android.InList
+var indexList = android.IndexList[string]
+var inList = android.InList[string]
 var filterList = android.FilterList
 var removeListFromList = android.RemoveListFromList
 var removeFromList = android.RemoveFromList
diff --git a/cmd/zip2zip/BUILD.bazel b/cmd/zip2zip/BUILD.bazel
deleted file mode 100644
index 1915a2d..0000000
--- a/cmd/zip2zip/BUILD.bazel
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-alias(
-    name = "zip2zip",
-    actual = "//prebuilts/build-tools:linux-x86/bin/zip2zip",
-)
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index ada4712..94b795f 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -371,6 +371,8 @@
 	// Specifies whether fuzz target should check presubmitted code changes for crashes.
 	// Defaults to false.
 	Use_for_presubmit *bool `json:"use_for_presubmit,omitempty"`
+	// Specify which paths to exclude from fuzzing coverage reports
+	Exclude_paths_from_reports []string `json:"exclude_paths_from_reports,omitempty"`
 }
 
 type FuzzFrameworks struct {
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index c6fa030..afa52cc 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -116,6 +116,25 @@
 		"aidl_camera_build_version",
 		"cronet_aml_base_android_runtime_unchecked_jni_headers",
 		"cronet_aml_base_android_runtime_jni_headers",
+		"aidl-golden-test-build-hook-gen",
+		"PacketStreamerStub_h",
+		"FrontendStub_cc",
+		"FrontendStub_h",
+		"PacketStreamerStub_cc",
+		"pixelstatsatoms.h",
+		"pixelatoms_defs.h",
+		"pixelstatsatoms.cpp",
+		"hidl_java_impl_test_gen",
+		"cronet_aml_base_android_runtime_jni_headers__testing",
+		"cronet_aml_base_android_runtime_unchecked_jni_headers__testing",
+		"hidl_cpp_impl_test_gen-sources",
+		"fdt_test_tree_multiple_memory_ranges_dtb",
+		"fdt_test_tree_one_memory_range_dtb",
+		"fdt_test_tree_empty_memory_range_dtb",
+		"ltp_config_arm_64_lowmem",
+		"ltp_config_arm_64_lowmem_hwasan",
+		"ltp_config_x86",
+		"libbssl_sys_src_nostd",
 	}
 
 	SandboxingDenyPathList = []string{
diff --git a/genrule/genrule.go b/genrule/genrule.go
index a470c5e..6306c27 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -296,6 +296,9 @@
 		for _, dir := range g.properties.Export_include_dirs {
 			g.exportedIncludeDirs = append(g.exportedIncludeDirs,
 				android.PathForModuleGen(ctx, g.subDir, ctx.ModuleDir(), dir))
+			// Also export without ModuleDir for consistency with Export_include_dirs not being set
+			g.exportedIncludeDirs = append(g.exportedIncludeDirs,
+				android.PathForModuleGen(ctx, g.subDir, dir))
 		}
 	} else {
 		g.exportedIncludeDirs = append(g.exportedIncludeDirs, android.PathForModuleGen(ctx, g.subDir))
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 6301bbf..7c14531 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -845,6 +845,49 @@
 		result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
 }
 
+func TestGenruleInterface(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForGenRuleTest,
+		android.FixtureMergeMockFs(android.MockFS{
+			"package-dir/Android.bp": []byte(`
+				genrule {
+					name: "module-name",
+					cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
+					srcs: [
+						"src/foo.proto",
+					],
+					out: ["proto.h", "bar/proto.h"],
+					export_include_dirs: [".", "bar"],
+				}
+			`),
+		}),
+	).RunTest(t)
+
+	exportedIncludeDirs := []string{
+		"out/soong/.intermediates/package-dir/module-name/gen/package-dir",
+		"out/soong/.intermediates/package-dir/module-name/gen",
+		"out/soong/.intermediates/package-dir/module-name/gen/package-dir/bar",
+		"out/soong/.intermediates/package-dir/module-name/gen/bar",
+	}
+	gen := result.Module("module-name", "").(*Module)
+
+	android.AssertPathsRelativeToTopEquals(
+		t,
+		"include path",
+		exportedIncludeDirs,
+		gen.GeneratedHeaderDirs(),
+	)
+	android.AssertPathsRelativeToTopEquals(
+		t,
+		"files",
+		[]string{
+			"out/soong/.intermediates/package-dir/module-name/gen/proto.h",
+			"out/soong/.intermediates/package-dir/module-name/gen/bar/proto.h",
+		},
+		gen.GeneratedSourceFiles(),
+	)
+}
+
 func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		prepareForGenRuleTest,
diff --git a/java/aar.go b/java/aar.go
index 01bd103..a682e3a 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -611,6 +611,8 @@
 
 	a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
 
+	a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName())
+
 	ctx.CheckbuildFile(a.proguardOptionsFile)
 	ctx.CheckbuildFile(a.exportPackage)
 	ctx.CheckbuildFile(a.aaptSrcJar)
@@ -986,6 +988,7 @@
 		TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
 		ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
 		ImplementationJars:             android.PathsIfNonNil(a.classpathFile),
+		// TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
 	})
 
 	if proptools.Bool(a.properties.Extract_jni) {
diff --git a/java/androidmk.go b/java/androidmk.go
index 13cc96a..4fca08d 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -123,6 +123,8 @@
 					if library.dexpreopter.configPath != nil {
 						entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath)
 					}
+
+					entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", library.getTransitiveAconfigFiles().ToList())
 				},
 			},
 		})
@@ -220,6 +222,7 @@
 				entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
 				entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion.String())
 				entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
+				// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
 			},
 		},
 	}}
@@ -244,6 +247,7 @@
 					entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", prebuilt.dexpreopter.builtInstalled)
 				}
 				entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
+				// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
 			},
 		},
 	}}
@@ -269,6 +273,7 @@
 				entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", prebuilt.extraAaptPackagesFile)
 				entries.SetPath("LOCAL_FULL_MANIFEST_FILE", prebuilt.manifest)
 				entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion.String())
+				// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
 			},
 		},
 	}}
@@ -295,6 +300,7 @@
 					if len(binary.dexpreopter.builtInstalled) > 0 {
 						entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
 					}
+					entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", binary.getTransitiveAconfigFiles().ToList())
 				},
 			},
 			ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -437,6 +443,10 @@
 				}
 
 				entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
+
+				if app.Name() != "framework-res" {
+					entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", app.getTransitiveAconfigFiles().ToList())
+				}
 			},
 		},
 		ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -455,11 +465,6 @@
 	if len(a.overridableAppProperties.Overrides) > 0 {
 		overridden = append(overridden, a.overridableAppProperties.Overrides...)
 	}
-	// When APK name is overridden via PRODUCT_PACKAGE_NAME_OVERRIDES
-	// ensure that the original name is overridden.
-	if a.Stem() != a.installApkName {
-		overridden = append(overridden, a.Stem())
-	}
 	return overridden
 }
 
@@ -517,6 +522,7 @@
 		entries.SetPath("LOCAL_FULL_MANIFEST_FILE", a.mergedManifestFile)
 		entries.AddStrings("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.exportedProguardFlagFiles.Strings()...)
 		entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
+		entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", a.getTransitiveAconfigFiles().ToList())
 	})
 
 	return entriesList
@@ -689,6 +695,7 @@
 				if Bool(a.properties.Export_package_resources) {
 					entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.outputFile)
 				}
+				// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
 			},
 		},
 	}}
@@ -722,6 +729,7 @@
 				entries.SetString("LOCAL_CERTIFICATE", r.certificate.AndroidMkString())
 				entries.SetPath("LOCAL_MODULE_PATH", r.installDir)
 				entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", r.properties.Overrides...)
+				// TODO: LOCAL_ACONFIG_FILES -- Might eventually need aconfig flags?
 			},
 		},
 	}}
@@ -739,6 +747,7 @@
 					entries.SetPath("LOCAL_APK_SET_INSTALL_FILE", apkSet.PackedAdditionalOutputs())
 					entries.SetPath("LOCAL_APKCERTS_FILE", apkSet.apkcertsFile)
 					entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...)
+					// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts -- Both declarations and values
 				},
 			},
 		},
diff --git a/java/app.go b/java/app.go
index 25909ec..8e4efd2 100755
--- a/java/app.go
+++ b/java/app.go
@@ -666,8 +666,17 @@
 	a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
 	a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
 
+	// 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())
+
 	// Check if the install APK name needs to be overridden.
-	a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Stem())
+	// Both android_app and override_android_app module are expected to possess
+	// its module bound apk path. However, override_android_app inherits ctx.ModuleName()
+	// 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()))
 
 	if ctx.ModuleName() == "framework-res" {
 		// framework-res.apk is installed as system/framework/framework-res.apk
diff --git a/java/app_import.go b/java/app_import.go
index e25bcd1..ad1765e 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -51,9 +51,9 @@
 		Description: "Uncompress dex files",
 	})
 
-	checkJniAndDexLibsAreUncompressedRule = pctx.AndroidStaticRule("check-jni-and-dex-libs-are-uncompressed", blueprint.RuleParams{
+	checkDexLibsAreUncompressedRule = pctx.AndroidStaticRule("check-dex-libs-are-uncompressed", blueprint.RuleParams{
 		// grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed
-		Command: "if (zipinfo $in 'lib/*.so' '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
+		Command: "if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
 			"echo $in: Contains compressed JNI libraries and/or dex files >&2;" +
 			"exit 1; " +
 			"else " +
@@ -61,6 +61,17 @@
 			"fi",
 		Description: "Check for compressed JNI libs or dex files",
 	})
+
+	checkJniLibsAreUncompressedRule = pctx.AndroidStaticRule("check-jni-libs-are-uncompressed", blueprint.RuleParams{
+		// grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed
+		Command: "if (zipinfo $in 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
+			"echo $in: Contains compressed JNI libraries >&2;" +
+			"exit 1; " +
+			"else " +
+			"touch $out; " +
+			"fi",
+		Description: "Check for compressed JNI libs or dex files",
+	})
 )
 
 func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
@@ -384,26 +395,40 @@
 }
 
 func (a *AndroidAppImport) validatePreprocessedApk(ctx android.ModuleContext, srcApk android.Path, dstApk android.WritablePath) {
+	var validations android.Paths
+
 	alignmentStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "alignment.stamp")
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   checkZipAlignment,
 		Input:  srcApk,
 		Output: alignmentStamp,
 	})
-	compressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "compression.stamp")
+
+	validations = append(validations, alignmentStamp)
+	jniCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "jni_compression.stamp")
 	ctx.Build(pctx, android.BuildParams{
-		Rule:   checkJniAndDexLibsAreUncompressedRule,
+		Rule:   checkJniLibsAreUncompressedRule,
 		Input:  srcApk,
-		Output: compressionStamp,
+		Output: jniCompressionStamp,
 	})
+	validations = append(validations, jniCompressionStamp)
+
+	if a.Privileged() {
+		// It's ok for non-privileged apps to have compressed dex files, see go/gms-uncompressed-jni-slides
+		dexCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "dex_compression.stamp")
+		ctx.Build(pctx, android.BuildParams{
+			Rule:   checkDexLibsAreUncompressedRule,
+			Input:  srcApk,
+			Output: dexCompressionStamp,
+		})
+		validations = append(validations, dexCompressionStamp)
+	}
+
 	ctx.Build(pctx, android.BuildParams{
-		Rule:   android.Cp,
-		Input:  srcApk,
-		Output: dstApk,
-		Validations: []android.Path{
-			alignmentStamp,
-			compressionStamp,
-		},
+		Rule:        android.Cp,
+		Input:       srcApk,
+		Output:      dstApk,
+		Validations: validations,
 	})
 }
 
diff --git a/java/base.go b/java/base.go
index cb08ef3..6a532da 100644
--- a/java/base.go
+++ b/java/base.go
@@ -21,6 +21,7 @@
 	"strings"
 
 	"android/soong/ui/metrics/bp2build_metrics_proto"
+
 	"github.com/google/blueprint/pathtools"
 	"github.com/google/blueprint/proptools"
 
@@ -502,6 +503,19 @@
 	sourceExtensions []string
 
 	annoSrcJars android.Paths
+
+	// output file name based on Stem property.
+	// This should be set in every ModuleWithStem's GenerateAndroidBuildActions
+	// or the module should override Stem().
+	stem string
+
+	// Aconfig "cache files" that went directly into this module.  Transitive ones are
+	// tracked via JavaInfo.TransitiveAconfigFiles
+	// TODO: Extract to something standalone to propagate tags via GeneratedJavaLibraryModule
+	aconfigIntermediates android.Paths
+
+	// Aconfig files for all transitive deps.  Also exposed via JavaInfo
+	transitiveAconfigFiles *android.DepSet[android.Path]
 }
 
 func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -1099,7 +1113,7 @@
 		j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
 	}
 
-	jarName := ctx.ModuleName() + ".jar"
+	jarName := j.Stem() + ".jar"
 
 	var uniqueJavaFiles android.Paths
 	set := make(map[string]bool)
@@ -1617,6 +1631,8 @@
 
 	ctx.CheckbuildFile(outputFile)
 
+	j.collectTransitiveAconfigFiles(ctx)
+
 	ctx.SetProvider(JavaInfoProvider, JavaInfo{
 		HeaderJars:                     android.PathsIfNonNil(j.headerJarFile),
 		TransitiveLibsHeaderJars:       j.transitiveLibsHeaderJars,
@@ -1631,6 +1647,7 @@
 		ExportedPluginClasses:          j.exportedPluginClasses,
 		ExportedPluginDisableTurbine:   j.exportedDisableTurbine,
 		JacocoReportClassesFile:        j.jacocoReportClassesFile,
+		TransitiveAconfigFiles:         j.transitiveAconfigFiles,
 	})
 
 	// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
@@ -1897,7 +1914,10 @@
 }
 
 func (j *Module) Stem() string {
-	return proptools.StringDefault(j.overridableDeviceProperties.Stem, j.Name())
+	if j.stem == "" {
+		panic("Stem() called before stem property was set")
+	}
+	return j.stem
 }
 
 func (j *Module) JacocoReportClassesFile() android.Path {
@@ -1908,6 +1928,34 @@
 	return Bool(j.properties.Installable)
 }
 
+func (j *Module) collectTransitiveAconfigFiles(ctx android.ModuleContext) {
+	// Aconfig files from this module
+	mine := j.aconfigIntermediates
+
+	// Aconfig files from transitive dependencies
+	fromDeps := []*android.DepSet[android.Path]{}
+	ctx.VisitDirectDeps(func(module android.Module) {
+		dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+		if dep.TransitiveAconfigFiles != nil {
+			fromDeps = append(fromDeps, dep.TransitiveAconfigFiles)
+		}
+	})
+
+	// DepSet containing aconfig files myself and from dependencies
+	j.transitiveAconfigFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps)
+}
+
+func (j *Module) AddAconfigIntermediate(path android.Path) {
+	j.aconfigIntermediates = append(j.aconfigIntermediates, path)
+}
+
+func (j *Module) getTransitiveAconfigFiles() *android.DepSet[android.Path] {
+	if j.transitiveAconfigFiles == nil {
+		panic(fmt.Errorf("java.Moduile: getTransitiveAconfigFiles called before collectTransitiveAconfigFiles module=%s", j.Name()))
+	}
+	return j.transitiveAconfigFiles
+}
+
 type sdkLinkType int
 
 const (
diff --git a/java/builder.go b/java/builder.go
index be4af55..94a6b84 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -42,7 +42,7 @@
 	// TODO(b/143658984): goma can't handle the --system argument to javac.
 	javac, javacRE = pctx.MultiCommandRemoteStaticRules("javac",
 		blueprint.RuleParams{
-			Command: `rm -rf "$outDir" "$annoDir" "$annoSrcJar" "$srcJarDir" "$out" && ` +
+			Command: `rm -rf "$outDir" "$annoDir" "$annoSrcJar.tmp" "$srcJarDir" "$out.tmp" && ` +
 				`mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
 				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
 				`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
@@ -51,8 +51,10 @@
 				`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
 				`-source $javaVersion -target $javaVersion ` +
 				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` +
-				`$annoSrcJarTemplate${config.SoongZipCmd} -jar -o $annoSrcJar -C $annoDir -D $annoDir && ` +
-				`$zipTemplate${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` +
+				`$annoSrcJarTemplate${config.SoongZipCmd} -jar -o $annoSrcJar.tmp -C $annoDir -D $annoDir && ` +
+				`$zipTemplate${config.SoongZipCmd} -jar -o $out.tmp -C $outDir -D $outDir && ` +
+				`if ! cmp -s "$out.tmp" "$out"; then mv "$out.tmp" "$out"; fi && ` +
+				`if ! cmp -s "$annoSrcJar.tmp" "$annoSrcJar"; then mv "$annoSrcJar.tmp" "$annoSrcJar"; fi && ` +
 				`rm -rf "$srcJarDir"`,
 			CommandDeps: []string{
 				"${config.JavacCmd}",
@@ -60,6 +62,7 @@
 				"${config.ZipSyncCmd}",
 			},
 			CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
+			Restat:           true,
 			Rspfile:          "$out.rsp",
 			RspfileContent:   "$in",
 		}, map[string]*remoteexec.REParams{
@@ -71,14 +74,14 @@
 			"$zipTemplate": &remoteexec.REParams{
 				Labels:       map[string]string{"type": "tool", "name": "soong_zip"},
 				Inputs:       []string{"${config.SoongZipCmd}", "$outDir"},
-				OutputFiles:  []string{"$out"},
+				OutputFiles:  []string{"$out.tmp"},
 				ExecStrategy: "${config.REJavacExecStrategy}",
 				Platform:     map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
 			},
 			"$annoSrcJarTemplate": &remoteexec.REParams{
 				Labels:       map[string]string{"type": "tool", "name": "soong_zip"},
 				Inputs:       []string{"${config.SoongZipCmd}", "$annoDir"},
-				OutputFiles:  []string{"$annoSrcJar"},
+				OutputFiles:  []string{"$annoSrcJar.tmp"},
 				ExecStrategy: "${config.REJavacExecStrategy}",
 				Platform:     map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
 			},
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 3581040..5460dc9 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -143,6 +143,8 @@
 		ResourceJars:                   d.resourceJars,
 		SrcJarArgs:                     d.srcJarArgs,
 		SrcJarDeps:                     d.srcJarDeps,
+		// TODO: Not sure if aconfig flags that have been moved between device and host variants
+		// make sense.
 	})
 
 }
diff --git a/java/generated_java_library.go b/java/generated_java_library.go
index 1b3de9f..f9baa85 100644
--- a/java/generated_java_library.go
+++ b/java/generated_java_library.go
@@ -30,7 +30,7 @@
 
 	// Called from inside GenerateAndroidBuildActions. Add the build rules to
 	// make the srcjar, and return the path to it.
-	GenerateSourceJarBuildActions(ctx android.ModuleContext) android.Path
+	GenerateSourceJarBuildActions(module *GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path
 }
 
 // GeneratedJavaLibraryModuleFactory provides a utility for modules that are generated
@@ -88,7 +88,7 @@
 	checkPropertyEmpty(ctx, module, "plugins", module.Library.properties.Plugins)
 	checkPropertyEmpty(ctx, module, "exported_plugins", module.Library.properties.Exported_plugins)
 
-	srcJarPath := module.callbacks.GenerateSourceJarBuildActions(ctx)
+	srcJarPath := module.callbacks.GenerateSourceJarBuildActions(module, ctx)
 	module.Library.properties.Generated_srcjars = append(module.Library.properties.Generated_srcjars, srcJarPath)
 	module.Library.GenerateAndroidBuildActions(ctx)
 }
diff --git a/java/generated_java_library_test.go b/java/generated_java_library_test.go
index 68f1f7e..7f52fd1 100644
--- a/java/generated_java_library_test.go
+++ b/java/generated_java_library_test.go
@@ -36,7 +36,8 @@
 func (callbacks *JavaGenLibTestCallbacks) DepsMutator(module *GeneratedJavaLibraryModule, ctx android.BottomUpMutatorContext) {
 }
 
-func (callbacks *JavaGenLibTestCallbacks) GenerateSourceJarBuildActions(ctx android.ModuleContext) android.Path {
+func (callbacks *JavaGenLibTestCallbacks) GenerateSourceJarBuildActions(module *GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path {
+	module.AddAconfigIntermediate(android.PathForOutput(ctx, "aconfig_cache_file"))
 	return android.PathForOutput(ctx, "blah.srcjar")
 }
 
diff --git a/java/java.go b/java/java.go
index 011dc1c..20d9afc 100644
--- a/java/java.go
+++ b/java/java.go
@@ -274,7 +274,14 @@
 	// instrumented by jacoco.
 	JacocoReportClassesFile android.Path
 
-	// TODO: Add device config declarations here?
+	// set of aconfig flags for all transitive libs deps
+	// TODO(joeo): It would be nice if this were over in the aconfig package instead of here.
+	// In order to do that, generated_java_library would need a way doing
+	// collectTransitiveAconfigFiles with one of the callbacks, and having that automatically
+	// propagated. If we were to clean up more of the stuff on JavaInfo that's not part of
+	// core java rules (e.g. AidlIncludeDirs), then maybe adding more framework to do that would be
+	// worth it.
+	TransitiveAconfigFiles *android.DepSet[android.Path]
 }
 
 var JavaInfoProvider = blueprint.NewProvider(JavaInfo{})
@@ -676,6 +683,8 @@
 	j.minSdkVersion = j.MinSdkVersion(ctx)
 	j.maxSdkVersion = j.MaxSdkVersion(ctx)
 
+	j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
+
 	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
 	if !apexInfo.IsForPlatform() {
 		j.hideApexVariantFromMake = true
@@ -728,6 +737,7 @@
 		}
 	})
 	j.exportedProguardFlagFiles = android.FirstUniquePaths(j.exportedProguardFlagFiles)
+
 }
 
 func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1468,6 +1478,8 @@
 }
 
 func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
+
 	if ctx.Arch().ArchType == android.Common {
 		// Compile the jar
 		if j.binaryProperties.Main_class != nil {
@@ -1912,6 +1924,7 @@
 		ImplementationAndResourcesJars: android.PathsIfNonNil(al.stubsJar),
 		ImplementationJars:             android.PathsIfNonNil(al.stubsJar),
 		AidlIncludeDirs:                android.Paths{},
+		// No aconfig libraries on api libraries
 	})
 }
 
@@ -2233,6 +2246,7 @@
 		ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile),
 		ImplementationJars:             android.PathsIfNonNil(j.combinedClasspathFile),
 		AidlIncludeDirs:                j.exportAidlIncludeDirs,
+		// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
 	})
 }
 
@@ -2653,7 +2667,7 @@
 var Bool = proptools.Bool
 var BoolDefault = proptools.BoolDefault
 var String = proptools.String
-var inList = android.InList
+var inList = android.InList[string]
 
 // Add class loader context (CLC) of a given dependency to the current CLC.
 func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
@@ -3151,6 +3165,7 @@
 
 type javaTestHostAttributes struct {
 	*javaCommonAttributes
+	Srcs         bazel.LabelListAttribute
 	Deps         bazel.LabelListAttribute
 	Runtime_deps bazel.LabelListAttribute
 }
@@ -3187,8 +3202,10 @@
 		hasKotlin: bp2BuildInfo.hasKotlin,
 	}
 	libName := createLibraryTarget(ctx, libInfo)
-	attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
 
+	attrs.Srcs = commonAttrs.Srcs
+	attrs.Deps = deps
+	attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
 	// Create the BazelTargetModule.
 	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
 }
@@ -3301,7 +3318,8 @@
 		HeaderJars:                     android.PathsIfNonNil(i.combinedClasspathFile),
 		ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile),
 		ImplementationJars:             android.PathsIfNonNil(i.combinedClasspathFile),
-		//TODO(b/240308299) include AIDL information from Bazel
+		// TODO(b/240308299) include AIDL information from Bazel
+		// TODO: aconfig files?
 	})
 
 	i.maybeInstall(ctx, jarName, outputFile)
diff --git a/java/java_test.go b/java/java_test.go
index 4738304..dd98677 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2351,3 +2351,22 @@
 		`stable.core.platform.api.stubs`,
 	})
 }
+
+func TestJavaLibraryWithResourcesStem(t *testing.T) {
+	ctx, _ := testJavaWithFS(t, `
+    java_library {
+        name: "foo",
+        java_resource_dirs: ["test-jar"],
+        stem: "test",
+    }
+    `,
+		map[string][]byte{
+			"test-jar/test/resource.txt": nil,
+		})
+
+	m := ctx.ModuleForTests("foo", "android_common")
+	outputs := fmt.Sprint(m.AllOutputs())
+	if !strings.Contains(outputs, "test.jar") {
+		t.Errorf("Module output does not contain expected jar %s", "test.jar")
+	}
+}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 7dc1b4b..59585aa 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
 	defaultBindgenFlags = []string{""}
 
 	// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
-	bindgenClangVersion = "clang-r487747c"
+	bindgenClangVersion = "clang-r498229"
 
 	_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
 		if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
diff --git a/starlark_import/unmarshal.go b/starlark_import/unmarshal.go
index 0e6f130..33c0cd9 100644
--- a/starlark_import/unmarshal.go
+++ b/starlark_import/unmarshal.go
@@ -289,16 +289,13 @@
 	}
 }
 
-// NoneableString converts a starlark.Value to a string pointer. If the starlark.Value is NoneType,
-// a nil pointer will be returned instead. All other types of starlark values are errors.
-func NoneableString(value starlark.Value) (*string, error) {
-	switch v := value.(type) {
-	case starlark.String:
-		result := v.GoString()
-		return &result, nil
-	case starlark.NoneType:
+// UnmarshalNoneable is like Unmarshal, but it will accept None as the top level (but not nested)
+// starlark value. If the value is None, a nil pointer will be returned, otherwise a pointer
+// to the result of Unmarshal will be returned.
+func UnmarshalNoneable[T any](value starlark.Value) (*T, error) {
+	if _, ok := value.(starlark.NoneType); ok {
 		return nil, nil
-	default:
-		return nil, fmt.Errorf("expected string or none, got %q", value.Type())
 	}
+	ret, err := Unmarshal[T](value)
+	return &ret, err
 }
diff --git a/tests/lib.sh b/tests/lib.sh
index 4aaf272..40b317b 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -147,6 +147,7 @@
   symlink_directory external/bazelbuild-rules_go
   symlink_directory external/bazelbuild-rules_license
   symlink_directory external/bazelbuild-kotlin-rules
+  symlink_directory external/bazelbuild-rules_java
 
   symlink_file WORKSPACE
   symlink_file BUILD
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 1241e89..afec6b1 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -85,7 +85,13 @@
   lz4=$out_dir/host/linux-x86/bin/lz4
 
   declare -A diff_excludes
-  diff_excludes[vendor]="-I /vendor/lib64/libkeystore2_crypto.so"
+  diff_excludes[product]="\
+    -I /product/etc/aconfig_flags.textproto \
+    -I /product/etc/build_flags.json"
+  diff_excludes[vendor]="\
+    -I /vendor/lib64/libkeystore2_crypto.so \
+    -I /vendor/etc/aconfig_flags.textproto \
+    -I /vendor/etc/build_flags.json"
   diff_excludes[system]="\
     -I /bin \
     -I /bugreports \
@@ -105,6 +111,8 @@
     -I /odm/priv-app \
     -I /odm/usr \
     -I /sdcard \
+    -I /system/etc/aconfig_flags.textproto \
+    -I /system/etc/build_flags.json \
     -I /system/lib64/android.hardware.confirmationui@1.0.so \
     -I /system/lib64/android.hardware.confirmationui-V1-ndk.so \
     -I /system/lib64/android.hardware.keymaster@4.1.so \
@@ -134,6 +142,9 @@
     -I /system/lib/vndk-sp-29 \
     -I /system/usr/icu \
     -I /vendor_dlkm/etc"
+  diff_excludes[system_ext]="\
+    -I /system_ext/etc/aconfig_flags.textproto \
+    -I /system_ext/etc/build_flags.json"
 
   # Example output of dump.erofs is as below, and the data used in the test start
   # at line 11. Column 1 is inode id, column 2 is inode type and column 3 is name.
diff --git a/zip/cmd/BUILD.bazel b/zip/cmd/BUILD.bazel
deleted file mode 100644
index e04a1e1..0000000
--- a/zip/cmd/BUILD.bazel
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (C) 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# TODO(b/194644518): Switch to the source version when Bazel can build go
-# binaries.
-alias(
-    name = "soong_zip",
-    actual = "//prebuilts/build-tools:linux-x86/bin/soong_zip",
-)