Merge "Add re_analysis environment varibles fields to soong_metrics"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 6405e9f..a5fcee4 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -477,6 +477,7 @@
 		"code_coverage.policy",
 		"code_coverage.policy.other",
 		"codec2_soft_exports",
+		"compatibility_matrix_schema",
 		"flatbuffer_headers",
 		"framework-connectivity-protos",
 		"gemmlowp_headers",
@@ -766,6 +767,27 @@
 		"libauto_value_plugin",
 		"auto_value_plugin_resources",
 		"auto_value_extension",
+
+		// Used by xsd_config
+		"xsdc",
+
+		// cc_test that can be run by b test
+		"binderRpcWireProtocolTest",
+		"binderUnitTest",
+		"cpu_features-bit_utils_test",
+		"liblp_test",
+		"android.hardware.audio.common.test.utility_tests",
+		"HalAudioStreamWorkerTest",
+		"libjavacore-unit-tests",
+		"NeuralNetworksTest_utils",
+		"NeuralNetworksTest_logtag",
+		"NeuralNetworksTest_operations",
+		"nanoapp_chqts_shared_tests",
+		"fakeservicemanager_test",
+		"tristate_test",
+		"binderUtilsHostTest",
+		"run_dex2oat_test",
+		"bluetooth-address-unit-tests",
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
@@ -778,6 +800,7 @@
 		"java_import_host",
 		"java_sdk_library",
 		"sysprop_library",
+		"xsd_config",
 	}
 
 	// Add the names of modules that bp2build should never convert, if it is
@@ -847,9 +870,6 @@
 		"host_bionic_linker_asm",    // depends on extract_linker, a go binary.
 		"host_bionic_linker_script", // depends on extract_linker, a go binary.
 
-		// in cmd attribute of genrule rule //system/timezone/output_data:robolectric_tzdata: label '//system/timezone/output_data:iana/tzdata' in $(location) expression is not a declared prerequisite of this rule
-		"robolectric_tzdata",
-
 		// rust support
 		"libtombstoned_client_rust_bridge_code", "libtombstoned_client_wrapper", // rust conversions are not supported
 
@@ -897,8 +917,6 @@
 		"static_crasher",                // depends on unconverted modules: libdebuggerd_handler
 		"test_fips",                     // depends on unconverted modules: adb
 		"timezone-host",                 // depends on unconverted modules: art.module.api.annotations
-		"truth-host-prebuilt",           // depends on unconverted modules: truth-prebuilt
-		"truth-prebuilt",                // depends on unconverted modules: asm-7.0, guava
 
 		// '//bionic/libc:libc_bp2build_cc_library_static' is duplicated in the 'deps' attribute of rule
 		"toybox-static",
@@ -945,12 +963,10 @@
 		"svcenc", "svcdec",
 
 		// Failing host cc_tests
-		"memunreachable_unit_test",
 		"libprocinfo_test",
 		"ziparchive-tests",
 		"gtest_isolated_tests",
 		"libunwindstack_unit_test",
-		"task_profiles_test",
 		"power_tests", // failing test on server, but not on host
 
 		// reflect: call of reflect.Value.NumField on interface Value
@@ -1030,7 +1046,6 @@
 		"libBionicLoaderTests",  // depends on unconverted modules: libmeminfo
 		"libapexutil_tests",     // depends on unconverted modules: apex-info-list-tinyxml, libapexutil
 		"libcutils_sockets_test",
-		"libexpectedutils_test",
 		"libhwbinder_latency",
 		"liblog-host-test", // failing tests
 		"libminijail_test",
@@ -1067,7 +1082,6 @@
 		"scudo_unit_tests",
 		"stats-log-api-gen-test", // depends on unconverted modules: libstats_proto_host
 		"syscall_filter_unittest_gtest",
-		"sysprop_test", // depends on unconverted modules: libcom.android.sysprop.tests
 		"thread_exit_cb_helper",
 		"tls_properties_helper",
 		"ulp",
@@ -1467,6 +1481,13 @@
 
 		// python_test_host with test data
 		"sbom_writers_test",
+
+		// TODO(B/283193845): tradefed and its java_test_host dependents
+		"tradefed",
+		"permissive_mte_test",
+		"ICU4CTestRunner",
+
+		"HelloWorldHostTest", // TODO(b/280452825): Convert HelloWorldHostTest to b test
 	}
 
 	MixedBuildsDisabledList = []string{
@@ -1585,12 +1606,13 @@
 	}
 
 	// These should be the libs that are included by the apexes in the StagingMixedBuildsEnabledList
-	StagingDclaMixedBuildsEnabledList = []string{}
+	StagingDclaMixedBuildsEnabledList = []string{
+		"libstagefright_flacdec",
+		"libutils",
+	}
 
 	// TODO(b/269342245): Enable the rest of the DCLA libs
 	// "libssl",
-	// "libstagefright_flacdec",
-	// "libutils",
 
 	// The list of module types which are expected to spend lots of build time.
 	// With `--ninja_weight_source=soong`, ninja builds these module types and deps first.
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 47dd161..d71eca2 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -674,6 +674,18 @@
 		// We don't need to set --host_platforms because it's set in bazelrc files
 		// that the bazel shell script wrapper passes
 
+		// Optimize Ninja rebuilds by ensuring Bazel write into product-agnostic
+		// output paths for the configured targets that shouldn't be affected by
+		// TARGET_PRODUCT. Otherwise product agnostic modules will be rebuilt by
+		// Ninja when the product changes, unconditionally.
+		//
+		// For example, Mainline APEXes should be identical regardless of the
+		// product (modulo arch/cpu).
+		//
+		// This flag forcibly disables the platform prefix in the intermediate
+		// outputs during a mixed build.
+		"--noexperimental_platform_in_output_dir",
+
 		// Suppress noise
 		"--ui_event_filters=-INFO",
 		"--noshow_progress",
@@ -719,9 +731,9 @@
 #####################################################
 def _config_node_transition_impl(settings, attr):
     if attr.os == "android" and attr.arch == "target":
-        target = "{PRODUCT}-{VARIANT}"
+        target = "current_product-{VARIANT}"
     else:
-        target = "{PRODUCT}-{VARIANT}_%s_%s" % (attr.os, attr.arch)
+        target = "current_product-{VARIANT}_%s_%s" % (attr.os, attr.arch)
     apex_name = ""
     if attr.within_apex:
         # //build/bazel/rules/apex:apex_name has to be set to a non_empty value,
@@ -732,7 +744,7 @@
         # value here.
         apex_name = "dcla_apex"
     outputs = {
-        "//command_line_option:platforms": "@soong_injection//product_config_platforms/products/{PRODUCT}-{VARIANT}:%s" % target,
+        "//command_line_option:platforms": "@soong_injection//product_config_platforms:%s" % target,
         "@//build/bazel/rules/apex:within_apex": attr.within_apex,
         "@//build/bazel/rules/apex:min_sdk_version": attr.apex_sdk_version,
         "@//build/bazel/rules/apex:apex_name": apex_name,
@@ -958,9 +970,9 @@
   platform_name = platforms[0].name
   if platform_name == "host":
     return "HOST"
-  if not platform_name.startswith("{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}"):
-    fail("expected platform name of the form '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_android_<arch>' or '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
-  platform_name = platform_name.removeprefix("{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}").removeprefix("_")
+  if not platform_name.startswith("current_product-{TARGET_BUILD_VARIANT}"):
+    fail("expected platform name of the form 'current_product-{TARGET_BUILD_VARIANT}_android_<arch>' or 'current_product-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
+  platform_name = platform_name.removeprefix("current_product-{TARGET_BUILD_VARIANT}").removeprefix("_")
   config_key = ""
   if not platform_name:
     config_key = "target|android"
@@ -969,7 +981,7 @@
   elif platform_name.startswith("linux_"):
     config_key = platform_name.removeprefix("linux_") + "|linux"
   else:
-    fail("expected platform name of the form '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_android_<arch>' or '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
+    fail("expected platform name of the form 'current_product-{TARGET_BUILD_VARIANT}_android_<arch>' or 'current_product-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
 
   within_apex = buildoptions.get("//build/bazel/rules/apex:within_apex")
   apex_sdk_version = buildoptions.get("//build/bazel/rules/apex:min_sdk_version")
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index ddbdbd4..872e908 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -242,6 +242,11 @@
 
 	// Don't transform OriginalModuleName
 	newPath.OriginalModuleName = path.OriginalModuleName
+	// if it wasn't a module, store the original path. We may need the original path to replace
+	// references if it is actually in another package
+	if path.OriginalModuleName == "" {
+		newPath.OriginalModuleName = path.Label
+	}
 
 	if strings.HasPrefix(path.Label, "//") {
 		// Assume absolute labels are already correct (e.g. //path/to/some/package:foo.h)
diff --git a/android/config.go b/android/config.go
index bed57e3..d4703ff 100644
--- a/android/config.go
+++ b/android/config.go
@@ -517,6 +517,8 @@
 		config: config,
 	}
 
+	config.productVariables.Build_from_text_stub = boolPtr(config.buildFromTextStub)
+
 	// Soundness check of the build and source directories. This won't catch strange
 	// configurations with symlinks, but at least checks the obvious case.
 	absBuildDir, err := filepath.Abs(cmdArgs.SoongOutDir)
@@ -1710,10 +1712,6 @@
 	return c.productVariables.ProductPrivateSepolicyDirs
 }
 
-func (c *config) MissingUsesLibraries() []string {
-	return c.productVariables.MissingUsesLibraries
-}
-
 func (c *config) TargetMultitreeUpdateMeta() bool {
 	return c.productVariables.MultitreeUpdateMeta
 }
@@ -1929,6 +1927,10 @@
 	return InList(name, c.config.productVariables.BuildBrokenInputDirModules)
 }
 
+func (c *config) BuildWarningBadOptionalUsesLibsAllowlist() []string {
+	return c.productVariables.BuildWarningBadOptionalUsesLibsAllowlist
+}
+
 func (c *deviceConfig) GenruleSandboxing() bool {
 	return Bool(c.config.productVariables.GenruleSandboxing)
 }
@@ -1941,10 +1943,6 @@
 	return c.productVariables.SelinuxIgnoreNeverallows
 }
 
-func (c *deviceConfig) SepolicySplit() bool {
-	return c.config.productVariables.SepolicySplit
-}
-
 func (c *deviceConfig) SepolicyFreezeTestExtraDirs() []string {
 	return c.config.productVariables.SepolicyFreezeTestExtraDirs
 }
@@ -2021,6 +2019,7 @@
 
 func (c *config) SetBuildFromTextStub(b bool) {
 	c.buildFromTextStub = b
+	c.productVariables.Build_from_text_stub = boolPtr(b)
 }
 
 func (c *config) AddForceEnabledModules(forceEnabled []string) {
diff --git a/android/module.go b/android/module.go
index 98084f3..ba32710 100644
--- a/android/module.go
+++ b/android/module.go
@@ -4014,3 +4014,53 @@
 	WriteFileRule(ctx, outFile, string(j))
 	ctx.Phony("soong_config_trace", outFile)
 }
+
+// Interface implemented by xsd_config which has 1:many mappings in bp2build workspace
+// This interface exists because we want to
+// 1. Determine the name of the additional targets generated by the primary soong module
+// 2. Enable distinguishing an xsd_config module from other Soong modules using type assertion
+type XsdConfigBp2buildTargets interface {
+	CppBp2buildTargetName() string
+	JavaBp2buildTargetName() string
+}
+
+// PartitionXsdSrcs partitions srcs into xsd_config modules and others
+// Since xsd_config are soong modules, we cannot use file extension for partitioning
+func PartitionXsdSrcs(ctx BazelConversionPathContext, srcs []string) ([]string, []string) {
+	//isXsd returns true if src is a soong module of type xsd_config
+	isXsd := func(src string) bool {
+		mod, exists := ctx.ModuleFromName(src)
+		if !exists {
+			return false
+		}
+		_, _isXsd := mod.(XsdConfigBp2buildTargets)
+		return _isXsd
+	}
+	nonXsd := []string{}
+	xsd := []string{}
+
+	for _, src := range srcs {
+		if isXsd(src) {
+			xsd = append(xsd, src)
+		} else {
+			nonXsd = append(nonXsd, src)
+		}
+	}
+
+	return nonXsd, xsd
+}
+
+// Replaces //a/b/my_xsd_config with //a/b/my_xsd_config-{cpp|java}
+// The new target name is provided by the `targetName` callback function
+func XsdConfigBp2buildTarget(ctx BazelConversionPathContext, mod blueprint.Module, targetName func(xsd XsdConfigBp2buildTargets) string) string {
+	xsd, isXsd := mod.(XsdConfigBp2buildTargets)
+	if !isXsd {
+		ctx.ModuleErrorf("xsdConfigJavaTarget called on %v, which is not an xsd_config", mod)
+	}
+	ret := BazelModuleLabel(ctx, mod)
+	// Remove the base module name
+	ret = strings.TrimSuffix(ret, mod.Name())
+	// Append the language specific target name
+	ret += targetName(xsd)
+	return ret
+}
diff --git a/android/neverallow.go b/android/neverallow.go
index 5b5e613..f2e8c85 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -59,6 +59,7 @@
 	AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
 	AddNeverAllowRules(createBp2BuildRule())
 	AddNeverAllowRules(createCcStubsRule())
+	AddNeverAllowRules(createJavaExcludeStaticLibsRule())
 }
 
 // Add a NeverAllow rule to the set of rules to apply.
@@ -253,6 +254,14 @@
 	}
 }
 
+func createJavaExcludeStaticLibsRule() Rule {
+	return NeverAllow().
+		NotIn("build/soong").
+		ModuleType("java_library").
+		WithMatcher("exclude_static_libs", isSetMatcherInstance).
+		Because("exclude_static_libs property is only allowed for java modules defined in build/soong")
+}
+
 func neverallowMutator(ctx BottomUpMutatorContext) {
 	m, ok := ctx.Module().(Module)
 	if !ok {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index ddd982d..1639bbf 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -344,6 +344,23 @@
 			`module "outside_allowed_list": violates neverallow`,
 		},
 	},
+	// Test for the rule restricting use of exclude_static_libs
+	{
+		name: `"exclude_static_libs" outside allowed directory`,
+		fs: map[string][]byte{
+			"a/b/Android.bp": []byte(`
+				java_library {
+					name: "baz",
+					exclude_static_libs: [
+						"bar",
+					],
+				}
+			`),
+		},
+		expectedErrors: []string{
+			`exclude_static_libs property is only allowed for java modules defined in build/soong`,
+		},
+	},
 }
 
 var prepareForNeverAllowTest = GroupFixturePreparers(
@@ -430,9 +447,10 @@
 }
 
 type mockJavaLibraryProperties struct {
-	Libs           []string
-	Sdk_version    *string
-	Uncompress_dex *bool
+	Libs                []string
+	Sdk_version         *string
+	Uncompress_dex      *bool
+	Exclude_static_libs []string
 }
 
 type mockJavaLibraryModule struct {
diff --git a/android/sdk_version.go b/android/sdk_version.go
index 08762ef..80aeb2e 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -84,12 +84,6 @@
 	}
 }
 
-// JavaLibraryName returns the soong module containing the Java APIs of that API surface.
-func (k SdkKind) JavaLibraryName(c Config) string {
-	name := k.DefaultJavaLibraryName()
-	return JavaApiLibraryName(c, name)
-}
-
 // JavaApiLibraryName returns the name of .txt equivalent of a java_library, but does
 // not check if either module exists.
 // TODO: Return .txt (single-tree or multi-tree equivalents) based on config
@@ -335,11 +329,10 @@
 
 // Export the name of the soong modules representing the various Java API surfaces.
 func javaSdkMakeVars(ctx MakeVarsContext) {
-	ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.JavaLibraryName(ctx.Config()))
-	ctx.Strict("ANDROID_SYSTEM_STUBS", SdkSystem.JavaLibraryName(ctx.Config()))
-	ctx.Strict("ANDROID_TEST_STUBS", SdkTest.JavaLibraryName(ctx.Config()))
-	ctx.Strict("ANDROID_MODULE_LIB_STUBS", SdkModule.JavaLibraryName(ctx.Config()))
-	ctx.Strict("ANDROID_SYSTEM_SERVER_STUBS", SdkSystemServer.JavaLibraryName(ctx.Config()))
-	// TODO (jihoonkang): Create a .txt equivalent for core.current.stubs
-	ctx.Strict("ANDROID_CORE_STUBS", SdkCore.JavaLibraryName(ctx.Config()))
+	ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.DefaultJavaLibraryName())
+	ctx.Strict("ANDROID_SYSTEM_STUBS", SdkSystem.DefaultJavaLibraryName())
+	ctx.Strict("ANDROID_TEST_STUBS", SdkTest.DefaultJavaLibraryName())
+	ctx.Strict("ANDROID_MODULE_LIB_STUBS", SdkModule.DefaultJavaLibraryName())
+	ctx.Strict("ANDROID_SYSTEM_SERVER_STUBS", SdkSystemServer.DefaultJavaLibraryName())
+	ctx.Strict("ANDROID_CORE_STUBS", SdkCore.DefaultJavaLibraryName())
 }
diff --git a/android/variable.go b/android/variable.go
index 77888e5..6362953 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -109,6 +109,11 @@
 			Cflags []string
 		}
 
+		Build_from_text_stub struct {
+			Static_libs         []string
+			Exclude_static_libs []string
+		}
+
 		// debuggable is true for eng and userdebug builds, and can be used to turn on additional
 		// debugging features that don't significantly impact runtime behavior.  userdebug builds
 		// are used for dogfooding and performance testing, and should be as similar to user builds
@@ -286,6 +291,7 @@
 	Uml                          *bool    `json:",omitempty"`
 	Arc                          *bool    `json:",omitempty"`
 	MinimizeJavaDebugInfo        *bool    `json:",omitempty"`
+	Build_from_text_stub         *bool    `json:",omitempty"`
 
 	Check_elf_files *bool `json:",omitempty"`
 
@@ -420,8 +426,6 @@
 
 	TargetFSConfigGen []string `json:",omitempty"`
 
-	MissingUsesLibraries []string `json:",omitempty"`
-
 	EnforceProductPartitionInterface *bool `json:",omitempty"`
 
 	EnforceInterPartitionJavaSdkLibrary *bool    `json:",omitempty"`
@@ -451,14 +455,14 @@
 	BuildBrokenVendorPropertyNamespace bool     `json:",omitempty"`
 	BuildBrokenInputDirModules         []string `json:",omitempty"`
 
+	BuildWarningBadOptionalUsesLibsAllowlist []string `json:",omitempty"`
+
 	BuildDebugfsRestrictionsEnabled bool `json:",omitempty"`
 
 	RequiresInsecureExecmemForSwiftshader bool `json:",omitempty"`
 
 	SelinuxIgnoreNeverallows bool `json:",omitempty"`
 
-	SepolicySplit bool `json:",omitempty"`
-
 	SepolicyFreezeTestExtraDirs         []string `json:",omitempty"`
 	SepolicyFreezeTestExtraPrebuiltDirs []string `json:",omitempty"`
 
@@ -528,6 +532,7 @@
 		Malloc_pattern_fill_contents: boolPtr(false),
 		Safestack:                    boolPtr(false),
 		TrimmedApex:                  boolPtr(false),
+		Build_from_text_stub:         boolPtr(false),
 
 		BootJars:     ConfiguredJarList{apexes: []string{}, jars: []string{}},
 		ApexBootJars: ConfiguredJarList{apexes: []string{}, jars: []string{}},
diff --git a/apex/apex.go b/apex/apex.go
index f49492e..32d7250 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -220,6 +220,13 @@
 	// imageApex or flattenedApex depending on Config.FlattenApex(). When payload_type is zip,
 	// this becomes zipApex.
 	ApexType apexPackaging `blueprint:"mutated"`
+
+	// Name that dependencies can specify in their apex_available properties to refer to this module.
+	// If not specified, this defaults to Soong module name. This must be the name of a Soong module.
+	Apex_available_name *string
+
+	// Variant version of the mainline module. Must be an integer between 0-9
+	Variant_version *string
 }
 
 type ApexNativeDependencies struct {
@@ -3134,6 +3141,13 @@
 		}
 
 		apexName := ctx.ModuleName()
+		for _, props := range ctx.Module().GetProperties() {
+			if apexProps, ok := props.(*apexBundleProperties); ok {
+				if apexProps.Apex_available_name != nil {
+					apexName = *apexProps.Apex_available_name
+				}
+			}
+		}
 		fromName := ctx.OtherModuleName(from)
 		toName := ctx.OtherModuleName(to)
 
@@ -3516,6 +3530,8 @@
 	Logging_parent        *string
 	Tests                 bazel.LabelListAttribute
 	Base_apex_name        *string
+	Apex_available_name   *string
+	Variant_version       *string
 }
 
 type convertedNativeSharedLibs struct {
@@ -3666,6 +3682,8 @@
 		Package_name:          packageName,
 		Logging_parent:        loggingParent,
 		Tests:                 testsAttrs,
+		Apex_available_name:   a.properties.Apex_available_name,
+		Variant_version:       a.properties.Variant_version,
 	}
 
 	props := bazel.BazelTargetModuleProperties{
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 38e24e8..c781be4 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6717,6 +6717,266 @@
 	}`)
 }
 
+func TestApexAvailable_ApexAvailableNameWithVersionCodeError(t *testing.T) {
+	t.Run("negative variant_version produces error", func(t *testing.T) {
+		testApexError(t, "expected an integer between 0-9; got -1", `
+			apex {
+				name: "myapex",
+				key: "myapex.key",
+				apex_available_name: "com.android.foo",
+				variant_version: "-1",
+				updatable: false,
+			}
+			apex_key {
+				name: "myapex.key",
+				public_key: "testkey.avbpubkey",
+				private_key: "testkey.pem",
+			}
+		`)
+	})
+
+	t.Run("variant_version greater than 9 produces error", func(t *testing.T) {
+		testApexError(t, "expected an integer between 0-9; got 10", `
+			apex {
+				name: "myapex",
+				key: "myapex.key",
+				apex_available_name: "com.android.foo",
+				variant_version: "10",
+				updatable: false,
+			}
+			apex_key {
+				name: "myapex.key",
+				public_key: "testkey.avbpubkey",
+				private_key: "testkey.pem",
+			}
+		`)
+	})
+}
+
+func TestApexAvailable_ApexAvailableNameWithVersionCode(t *testing.T) {
+	context := android.GroupFixturePreparers(
+		android.PrepareForIntegrationTestWithAndroid,
+		PrepareForTestWithApexBuildComponents,
+		android.FixtureMergeMockFs(android.MockFS{
+			"system/sepolicy/apex/foo-file_contexts": nil,
+			"system/sepolicy/apex/bar-file_contexts": nil,
+		}),
+	)
+	result := context.RunTestWithBp(t, `
+		apex {
+			name: "foo",
+			key: "myapex.key",
+			apex_available_name: "com.android.foo",
+			variant_version: "0",
+			updatable: false,
+		}
+		apex {
+			name: "bar",
+			key: "myapex.key",
+			apex_available_name: "com.android.foo",
+			variant_version: "3",
+			updatable: false,
+		}
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+	`)
+
+	fooManifestRule := result.ModuleForTests("foo", "android_common_foo_image").Rule("apexManifestRule")
+	fooExpectedDefaultVersion := android.DefaultUpdatableModuleVersion
+	fooActualDefaultVersion := fooManifestRule.Args["default_version"]
+	if fooActualDefaultVersion != fooExpectedDefaultVersion {
+		t.Errorf("expected to find defaultVersion %q; got %q", fooExpectedDefaultVersion, fooActualDefaultVersion)
+	}
+
+	barManifestRule := result.ModuleForTests("bar", "android_common_bar_image").Rule("apexManifestRule")
+	defaultVersionInt, _ := strconv.Atoi(android.DefaultUpdatableModuleVersion)
+	barExpectedDefaultVersion := fmt.Sprint(defaultVersionInt + 3)
+	barActualDefaultVersion := barManifestRule.Args["default_version"]
+	if barActualDefaultVersion != barExpectedDefaultVersion {
+		t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
+	}
+}
+
+func TestApexAvailable_ApexAvailableName(t *testing.T) {
+	t.Run("using name of apex that sets apex_available_name is not allowed", func(t *testing.T) {
+		testApexError(t, "Consider adding \"myapex\" to 'apex_available' property of \"AppFoo\"", `
+			apex {
+				name: "myapex_sminus",
+				key: "myapex.key",
+				apps: ["AppFoo"],
+				apex_available_name: "myapex",
+				updatable: false,
+			}
+			apex {
+				name: "myapex",
+				key: "myapex.key",
+				apps: ["AppFoo"],
+				updatable: false,
+			}
+			apex_key {
+				name: "myapex.key",
+				public_key: "testkey.avbpubkey",
+				private_key: "testkey.pem",
+			}
+			android_app {
+				name: "AppFoo",
+				srcs: ["foo/bar/MyClass.java"],
+				sdk_version: "none",
+				system_modules: "none",
+				apex_available: [ "myapex_sminus" ],
+			}`,
+			android.FixtureMergeMockFs(android.MockFS{
+				"system/sepolicy/apex/myapex_sminus-file_contexts": nil,
+			}),
+		)
+	})
+
+	t.Run("apex_available_name allows module to be used in two different apexes", func(t *testing.T) {
+		testApex(t, `
+			apex {
+				name: "myapex_sminus",
+				key: "myapex.key",
+				apps: ["AppFoo"],
+				apex_available_name: "myapex",
+				updatable: false,
+			}
+			apex {
+				name: "myapex",
+				key: "myapex.key",
+				apps: ["AppFoo"],
+				updatable: false,
+			}
+			apex_key {
+				name: "myapex.key",
+				public_key: "testkey.avbpubkey",
+				private_key: "testkey.pem",
+			}
+			android_app {
+				name: "AppFoo",
+				srcs: ["foo/bar/MyClass.java"],
+				sdk_version: "none",
+				system_modules: "none",
+				apex_available: [ "myapex" ],
+			}`,
+			android.FixtureMergeMockFs(android.MockFS{
+				"system/sepolicy/apex/myapex_sminus-file_contexts": nil,
+			}),
+		)
+	})
+
+	t.Run("override_apexes work with apex_available_name", func(t *testing.T) {
+		testApex(t, `
+			override_apex {
+				name: "myoverrideapex_sminus",
+				base: "myapex_sminus",
+				key: "myapex.key",
+				apps: ["AppFooOverride"],
+			}
+			override_apex {
+				name: "myoverrideapex",
+				base: "myapex",
+				key: "myapex.key",
+				apps: ["AppFooOverride"],
+			}
+			apex {
+				name: "myapex_sminus",
+				key: "myapex.key",
+				apps: ["AppFoo"],
+				apex_available_name: "myapex",
+				updatable: false,
+			}
+			apex {
+				name: "myapex",
+				key: "myapex.key",
+				apps: ["AppFoo"],
+				updatable: false,
+			}
+			apex_key {
+				name: "myapex.key",
+				public_key: "testkey.avbpubkey",
+				private_key: "testkey.pem",
+			}
+			android_app {
+				name: "AppFooOverride",
+				srcs: ["foo/bar/MyClass.java"],
+				sdk_version: "none",
+				system_modules: "none",
+				apex_available: [ "myapex" ],
+			}
+			android_app {
+				name: "AppFoo",
+				srcs: ["foo/bar/MyClass.java"],
+				sdk_version: "none",
+				system_modules: "none",
+				apex_available: [ "myapex" ],
+			}`,
+			android.FixtureMergeMockFs(android.MockFS{
+				"system/sepolicy/apex/myapex_sminus-file_contexts": nil,
+			}),
+		)
+	})
+}
+
+func TestApexAvailable_ApexAvailableNameWithOverrides(t *testing.T) {
+	context := android.GroupFixturePreparers(
+		android.PrepareForIntegrationTestWithAndroid,
+		PrepareForTestWithApexBuildComponents,
+		java.PrepareForTestWithDexpreopt,
+		android.FixtureMergeMockFs(android.MockFS{
+			"system/sepolicy/apex/myapex-file_contexts":        nil,
+			"system/sepolicy/apex/myapex_sminus-file_contexts": nil,
+		}),
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.BuildId = proptools.StringPtr("buildid")
+		}),
+	)
+	context.RunTestWithBp(t, `
+	override_apex {
+		name: "myoverrideapex_sminus",
+		base: "myapex_sminus",
+	}
+	override_apex {
+		name: "myoverrideapex",
+		base: "myapex",
+	}
+	apex {
+		name: "myapex",
+		key: "myapex.key",
+		apps: ["AppFoo"],
+		updatable: false,
+	}
+	apex {
+		name: "myapex_sminus",
+		apex_available_name: "myapex",
+		key: "myapex.key",
+		apps: ["AppFoo_sminus"],
+		updatable: false,
+	}
+	apex_key {
+		name: "myapex.key",
+		public_key: "testkey.avbpubkey",
+		private_key: "testkey.pem",
+	}
+	android_app {
+		name: "AppFoo",
+		srcs: ["foo/bar/MyClass.java"],
+		sdk_version: "none",
+		system_modules: "none",
+		apex_available: [ "myapex" ],
+	}
+	android_app {
+		name: "AppFoo_sminus",
+		srcs: ["foo/bar/MyClass.java"],
+		sdk_version: "none",
+		min_sdk_version: "29",
+		system_modules: "none",
+		apex_available: [ "myapex" ],
+	}`)
+}
+
 func TestApexAvailable_CheckForPlatform(t *testing.T) {
 	ctx := testApex(t, `
 	apex {
diff --git a/apex/builder.go b/apex/builder.go
index 7c6522d..c691a33 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -275,6 +275,22 @@
 
 	manifestJsonFullOut := android.PathForModuleOut(ctx, "apex_manifest_full.json")
 	defaultVersion := android.DefaultUpdatableModuleVersion
+	if a.properties.Variant_version != nil {
+		defaultVersionInt, err := strconv.Atoi(defaultVersion)
+		if err != nil {
+			ctx.ModuleErrorf("expected DefaultUpdatableModuleVersion to be an int, but got %s", defaultVersion)
+		}
+		if defaultVersionInt%10 != 0 {
+			ctx.ModuleErrorf("expected DefaultUpdatableModuleVersion to end in a zero, but got %s", defaultVersion)
+		}
+		variantVersion := []rune(*a.properties.Variant_version)
+		if len(variantVersion) != 1 || variantVersion[0] < '0' || variantVersion[0] > '9' {
+			ctx.PropertyErrorf("variant_version", "expected an integer between 0-9; got %s", *a.properties.Variant_version)
+		}
+		defaultVersionRunes := []rune(defaultVersion)
+		defaultVersionRunes[len(defaultVersion)-1] = []rune(variantVersion)[0]
+		defaultVersion = string(defaultVersionRunes)
+	}
 	if override := ctx.Config().Getenv("OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION"); override != "" {
 		defaultVersion = override
 	}
diff --git a/bazel/bazel_proxy.go b/bazel/bazel_proxy.go
index 2940b99..229818d 100644
--- a/bazel/bazel_proxy.go
+++ b/bazel/bazel_proxy.go
@@ -26,10 +26,11 @@
 	"time"
 )
 
-// Logs fatal events of ProxyServer.
+// Logs events of ProxyServer.
 type ServerLogger interface {
 	Fatal(v ...interface{})
 	Fatalf(format string, v ...interface{})
+	Println(v ...interface{})
 }
 
 // CmdRequest is a request to the Bazel Proxy server.
@@ -71,9 +72,10 @@
 // The ProxyServer will only live as long as soong_ui does; the
 // underlying Bazel server will live past the duration of the build.
 type ProxyServer struct {
-	logger       ServerLogger
-	outDir       string
-	workspaceDir string
+	logger          ServerLogger
+	outDir          string
+	workspaceDir    string
+	bazeliskVersion string
 	// The server goroutine will listen on this channel and stop handling requests
 	// once it is written to.
 	done chan struct{}
@@ -119,12 +121,17 @@
 }
 
 // NewProxyServer is a constructor for a ProxyServer.
-func NewProxyServer(logger ServerLogger, outDir string, workspaceDir string) *ProxyServer {
+func NewProxyServer(logger ServerLogger, outDir string, workspaceDir string, bazeliskVersion string) *ProxyServer {
+	if len(bazeliskVersion) > 0 {
+		logger.Println("** Using Bazelisk for this build, due to env var USE_BAZEL_VERSION=" + bazeliskVersion + " **")
+	}
+
 	return &ProxyServer{
-		logger:       logger,
-		outDir:       outDir,
-		workspaceDir: workspaceDir,
-		done:         make(chan struct{}),
+		logger:          logger,
+		outDir:          outDir,
+		workspaceDir:    workspaceDir,
+		done:            make(chan struct{}),
+		bazeliskVersion: bazeliskVersion,
 	}
 }
 
@@ -155,6 +162,9 @@
 		return fmt.Errorf("Error decoding request: %s", err)
 	}
 
+	if len(b.bazeliskVersion) > 0 {
+		req.Env = append(req.Env, "USE_BAZEL_VERSION="+b.bazeliskVersion)
+	}
 	stdout, stderr, cmdErr := ExecBazel("./build/bazel/bin/bazel", b.workspaceDir, req)
 	errorString := ""
 	if cmdErr != nil {
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 9ec3a40..4ecd05d 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -72,7 +72,6 @@
         "license_conversion_test.go",
         "license_kind_conversion_test.go",
         "linker_config_conversion_test.go",
-        "ndk_headers_conversion_test.go",
         "package_conversion_test.go",
         "performance_test.go",
         "prebuilt_etc_conversion_test.go",
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index 3abef9d..66d0cc5 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -68,6 +68,14 @@
 	"@//build/bazel/product_config:__subpackages__",
 	"@soong_injection//product_config_platforms:__subpackages__",
 ])
+
+load("//{PRODUCT_FOLDER}:soong.variables.bzl", _soong_variables = "variables")
+load("@//build/bazel/product_config:android_product.bzl", "android_product")
+
+android_product(
+    name = "current_product-{VARIANT}",
+    soong_variables = _soong_variables,
+)
 `)),
 		newFile(
 			"product_config_platforms",
@@ -78,6 +86,7 @@
 # TODO: When we start generating the platforms for more than just the
 # currently lunched product, they should all be listed here
 product_labels = [
+  "@soong_injection//product_config_platforms:current_product-{VARIANT}",
   "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}"
 ]
 `)),
@@ -85,25 +94,30 @@
 			"product_config_platforms",
 			"common.bazelrc",
 			productReplacer.Replace(`
-build --platforms @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
+# current_product refers to the current TARGET_PRODUCT set, usually through
+# 'lunch' or 'banchan'.  Every build will have a primary TARGET_PRODUCT, but
+# bazel supports using other products in tests or configuration transitions. The
+# other products can be found in
+# @soong_injection//product_config_platforms/products/...
+build --platforms @soong_injection//product_config_platforms:current_product-{VARIANT}_linux_x86_64
 
-build:android --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
-build:linux_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
-build:linux_bionic_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_bionic_x86_64
-build:linux_musl_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86
-build:linux_musl_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86_64
+build:android --platforms=@soong_injection//product_config_platforms:current_product-{VARIANT}
+build:linux_x86_64 --platforms=@soong_injection//product_config_platforms:current_product-{VARIANT}_linux_x86_64
+build:linux_bionic_x86_64 --platforms=@soong_injection//product_config_platforms:current_product-{VARIANT}_linux_bionic_x86_64
+build:linux_musl_x86 --platforms=@soong_injection//product_config_platforms:current_product-{VARIANT}_linux_musl_x86
+build:linux_musl_x86_64 --platforms=@soong_injection//product_config_platforms:current_product-{VARIANT}_linux_musl_x86_64
 `)),
 		newFile(
 			"product_config_platforms",
 			"linux.bazelrc",
 			productReplacer.Replace(`
-build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
+build --host_platform @soong_injection//product_config_platforms:current_product-{VARIANT}_linux_x86_64
 `)),
 		newFile(
 			"product_config_platforms",
 			"darwin.bazelrc",
 			productReplacer.Replace(`
-build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64
+build --host_platform product_config_platforms:current_product-{VARIANT}_darwin_x86_64
 `)),
 		newFile(
 			"product_config_platforms",
@@ -111,7 +125,7 @@
 			productReplacer.Replace(`
 flags:
   --cpu=k8
-    @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
+	@soong_injection//product_config_platforms:current_product-{VARIANT}
 `)),
 	}
 
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 8a83cc0..610a9ca 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -1036,3 +1036,73 @@
 		},
 	})
 }
+
+func TestCcBinaryWithCfi(t *testing.T) {
+	runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+		description: "cc_binary has correct features when cfi is enabled",
+		blueprint: `
+{rule_name} {
+	name: "foo",
+	sanitize: {
+		cfi: true,
+	},
+}`,
+		targets: []testBazelTarget{
+			{"cc_binary", "foo", AttrNameToString{
+				"features":       `["android_cfi"]`,
+				"local_includes": `["."]`,
+			}},
+		},
+	})
+}
+
+func TestCcBinaryWithCfiOsSpecific(t *testing.T) {
+	runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+		description: "cc_binary has correct features when cfi is enabled for specific variants",
+		blueprint: `
+{rule_name} {
+	name: "foo",
+	target: {
+		android: {
+			sanitize: {
+				cfi: true,
+			},
+		},
+	},
+}`,
+		targets: []testBazelTarget{
+			{"cc_binary", "foo", AttrNameToString{
+				"features": `select({
+        "//build/bazel/platforms/os:android": ["android_cfi"],
+        "//conditions:default": [],
+    })`,
+				"local_includes": `["."]`,
+			}},
+		},
+	})
+}
+
+func TestCcBinaryWithCfiAndCfiAssemblySupport(t *testing.T) {
+	runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+		description: "cc_binary has correct features when cfi is enabled with cfi assembly support",
+		blueprint: `
+{rule_name} {
+	name: "foo",
+	sanitize: {
+		cfi: true,
+		config: {
+			cfi_assembly_support: true,
+		},
+	},
+}`,
+		targets: []testBazelTarget{
+			{"cc_binary", "foo", AttrNameToString{
+				"features": `[
+        "android_cfi",
+        "android_cfi_assembly_support",
+    ]`,
+				"local_includes": `["."]`,
+			}},
+		},
+	})
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 3dd9373..c2dba67 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -4718,3 +4718,97 @@
 		},
 	})
 }
+
+func TestCcLibraryWithCfi(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library has correct features when cfi is enabled",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+cc_library {
+	name: "foo",
+	sanitize: {
+		cfi: true,
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+				"features":       `["android_cfi"]`,
+				"local_includes": `["."]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"features":       `["android_cfi"]`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibraryWithCfiOsSpecific(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library has correct features when cfi is enabled for specific variants",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+cc_library {
+	name: "foo",
+	target: {
+		android: {
+			sanitize: {
+				cfi: true,
+			},
+		},
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+				"features": `select({
+        "//build/bazel/platforms/os:android": ["android_cfi"],
+        "//conditions:default": [],
+    })`,
+				"local_includes": `["."]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"features": `select({
+        "//build/bazel/platforms/os:android": ["android_cfi"],
+        "//conditions:default": [],
+    })`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibraryWithCfiAndCfiAssemblySupport(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library has correct features when cfi is enabled with cfi_assembly_support",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+cc_library {
+	name: "foo",
+	sanitize: {
+		cfi: true,
+		config: {
+			cfi_assembly_support: true,
+		},
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+				"features": `[
+        "android_cfi",
+        "android_cfi_assembly_support",
+    ]`,
+				"local_includes": `["."]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"features": `[
+        "android_cfi",
+        "android_cfi_assembly_support",
+    ]`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 6c9f9a1..7f0ba44 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -1445,3 +1445,73 @@
 		},
 	})
 }
+
+func TestCcLibrarySharedWithCfi(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Description: "cc_library_shared has correct features when cfi is enabled for specific variants",
+		Blueprint: `
+cc_library_shared {
+	name: "foo",
+	sanitize: {
+		cfi: true,
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"features":       `["android_cfi"]`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibrarySharedWithCfiOsSpecific(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Description: "cc_library_shared has correct features when cfi is enabled",
+		Blueprint: `
+cc_library_shared {
+	name: "foo",
+	target: {
+		android: {
+			sanitize: {
+				cfi: true,
+			},
+		},
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"features": `select({
+        "//build/bazel/platforms/os:android": ["android_cfi"],
+        "//conditions:default": [],
+    })`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibrarySharedWithCfiAndCfiAssemblySupport(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Description: "cc_library_shared has correct features when cfi is enabled with cfi assembly support",
+		Blueprint: `
+cc_library_static {
+	name: "foo",
+	sanitize: {
+		cfi: true,
+		config: {
+			cfi_assembly_support: true,
+		},
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+				"features": `[
+        "android_cfi",
+        "android_cfi_assembly_support",
+    ]`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 2705aaf..f537871 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -2075,3 +2075,73 @@
 		},
 	})
 }
+
+func TestCcLibraryStaticWithCfi(t *testing.T) {
+	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		Description: "cc_library_static has correct features when cfi is enabled",
+		Blueprint: `
+cc_library_static {
+	name: "foo",
+	sanitize: {
+		cfi: true,
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+				"features":       `["android_cfi"]`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibraryStaticWithCfiOsSpecific(t *testing.T) {
+	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		Description: "cc_library_static has correct features when cfi is enabled for specific variants",
+		Blueprint: `
+cc_library_static {
+	name: "foo",
+	target: {
+		android: {
+			sanitize: {
+				cfi: true,
+			},
+		},
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+				"features": `select({
+        "//build/bazel/platforms/os:android": ["android_cfi"],
+        "//conditions:default": [],
+    })`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibraryStaticWithCfiAndCfiAssemblySupport(t *testing.T) {
+	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		Description: "cc_library_static has correct features when cfi is enabled with cfi_assembly_support",
+		Blueprint: `
+cc_library_static {
+	name: "foo",
+	sanitize: {
+		cfi: true,
+		config: {
+			cfi_assembly_support: true,
+		},
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+				"features": `[
+        "android_cfi",
+        "android_cfi_assembly_support",
+    ]`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index 3490881..5cf4fb2 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -49,6 +49,7 @@
     srcs: ["other_tool.in"],
     cmd: "cp $(in) $(out)",
 }`, genruleTarget, genruleTarget),
+		"other/file.txt": "",
 	}
 }
 
@@ -293,17 +294,20 @@
 	bp := `%s {
     name: "foo",
     out: ["foo.out"],
-    srcs: [":other.tool"],
+    srcs: [":other.tool", "other/file.txt",],
     tool_files: [":foo.tool"],
-    cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
+    cmd: "$(locations :foo.tool) $(location other/file.txt) -s $(out) $(location :other.tool)",
     bazel_module: { bp2build_available: true },
 }`
 
 	for _, tc := range testCases {
 		moduleAttrs := AttrNameToString{
-			"cmd":   `"$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)"`,
-			"outs":  `["foo.out"]`,
-			"srcs":  `["//other:other.tool"]`,
+			"cmd":  `"$(locations //other:foo.tool) $(location //other:file.txt) -s $(OUTS) $(location //other:other.tool)"`,
+			"outs": `["foo.out"]`,
+			"srcs": `[
+        "//other:other.tool",
+        "//other:file.txt",
+    ]`,
 			"tools": `["//other:foo.tool"]`,
 		}
 
diff --git a/bp2build/java_test_host_conversion_test.go b/bp2build/java_test_host_conversion_test.go
new file mode 100644
index 0000000..f411ffb
--- /dev/null
+++ b/bp2build/java_test_host_conversion_test.go
@@ -0,0 +1,149 @@
+// 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 bp2build
+
+import (
+	"testing"
+
+	"android/soong/android"
+	"android/soong/java"
+)
+
+func runJavaTestHostTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	(&tc).ModuleTypeUnderTest = "java_test_host"
+	(&tc).ModuleTypeUnderTestFactory = java.TestHostFactory
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("java_library", java.LibraryFactory)
+	}, tc)
+}
+
+func TestJavaTestHostGeneral(t *testing.T) {
+	runJavaTestHostTestCase(t, Bp2buildTestCase{
+		Description: "java_test_host general",
+		Filesystem:  map[string]string{},
+		Blueprint: `
+java_test_host {
+    name: "java_test_host-1",
+    srcs: ["a.java", "b.java"],
+    libs: ["lib_a"],
+    static_libs: ["static_libs_a"],
+    exclude_srcs: ["b.java"],
+    javacflags: ["-Xdoclint:all/protected"],
+    java_version: "8",
+}
+
+java_library {
+    name: "lib_a",
+    bazel_module: { bp2build_available: false },
+}
+
+java_library {
+    name: "static_libs_a",
+    bazel_module: { bp2build_available: false },
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_library", "java_test_host-1_lib", AttrNameToString{
+				"deps": `[
+        ":lib_a-neverlink",
+        ":static_libs_a",
+    ]`,
+				"java_version": `"8"`,
+				"javacopts":    `["-Xdoclint:all/protected"]`,
+				"srcs":         `["a.java"]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+			MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
+				"runtime_deps": `[":java_test_host-1_lib"]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	})
+}
+
+func TestJavaTestHostNoSrcs(t *testing.T) {
+	runJavaTestHostTestCase(t, Bp2buildTestCase{
+		Description: "java_test_host without srcs",
+		Filesystem:  map[string]string{},
+		Blueprint: `
+java_test_host {
+    name: "java_test_host-1",
+    libs: ["lib_a"],
+    static_libs: ["static_libs_a"],
+}
+
+java_library {
+    name: "lib_a",
+    bazel_module: { bp2build_available: false },
+}
+
+java_library {
+    name: "static_libs_a",
+    bazel_module: { bp2build_available: false },
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
+				"runtime_deps": `[
+        ":lib_a-neverlink",
+        ":static_libs_a",
+    ]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	})
+}
+
+func TestJavaTestHostKotlinSrcs(t *testing.T) {
+	runJavaTestHostTestCase(t, Bp2buildTestCase{
+		Description: "java_test_host with .kt in srcs",
+		Filesystem:  map[string]string{},
+		Blueprint: `
+java_test_host {
+    name: "java_test_host-1",
+    srcs: ["a.java", "b.kt"],
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
+				"runtime_deps": `[":java_test_host-1_lib"]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+			MakeBazelTarget("kt_jvm_library", "java_test_host-1_lib", AttrNameToString{
+				"srcs": `[
+        "a.java",
+        "b.kt",
+    ]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/ndk_headers_conversion_test.go b/bp2build/ndk_headers_conversion_test.go
deleted file mode 100644
index 9d0f1f2..0000000
--- a/bp2build/ndk_headers_conversion_test.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2022 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 bp2build
-
-import (
-	"fmt"
-	"testing"
-
-	"android/soong/cc"
-)
-
-func TestNdkHeaderFilepaths(t *testing.T) {
-	bpTemplate := `
-	ndk_headers {
-		name: "foo",
-		srcs: %v,
-		exclude_srcs: %v,
-	}
-	`
-	testCases := []struct {
-		desc         string
-		srcs         string
-		excludeSrcs  string
-		expectedHdrs string
-	}{
-		{
-			desc:         "Single header file",
-			srcs:         `["foo.h"]`,
-			excludeSrcs:  `[]`,
-			expectedHdrs: `["foo.h"]`,
-		},
-		{
-			desc:        "Multiple header files",
-			srcs:        `["foo.h", "foo_other.h"]`,
-			excludeSrcs: `[]`,
-			expectedHdrs: `[
-        "foo.h",
-        "foo_other.h",
-    ]`,
-		},
-		{
-			desc:         "Multiple header files with excludes",
-			srcs:         `["foo.h", "foo_other.h"]`,
-			excludeSrcs:  `["foo_other.h"]`,
-			expectedHdrs: `["foo.h"]`,
-		},
-		{
-			desc:        "Multiple header files via Soong-supported globs",
-			srcs:        `["*.h"]`,
-			excludeSrcs: `[]`,
-			expectedHdrs: `[
-        "foo.h",
-        "foo_other.h",
-    ]`,
-		},
-	}
-	for _, testCase := range testCases {
-		fs := map[string]string{
-			"foo.h":       "",
-			"foo_other.h": "",
-		}
-		expectedApiContributionTargetName := "foo.contribution"
-		expectedBazelTarget := MakeBazelTargetNoRestrictions(
-			"cc_api_headers",
-			expectedApiContributionTargetName,
-			AttrNameToString{
-				"hdrs": testCase.expectedHdrs,
-			},
-		)
-		RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
-			Description:          testCase.desc,
-			Blueprint:            fmt.Sprintf(bpTemplate, testCase.srcs, testCase.excludeSrcs),
-			ExpectedBazelTargets: []string{expectedBazelTarget},
-			Filesystem:           fs,
-		})
-	}
-}
-
-func TestNdkHeaderIncludeDir(t *testing.T) {
-	bpTemplate := `
-	ndk_headers {
-		name: "foo",
-		from: %v,
-		to: "this/value/is/ignored",
-	}
-	`
-	testCases := []struct {
-		desc               string
-		from               string
-		expectedIncludeDir string
-	}{
-		{
-			desc:               "Empty `from` value",
-			from:               `""`,
-			expectedIncludeDir: `""`,
-		},
-		{
-			desc:               "Non-Empty `from` value",
-			from:               `"include"`,
-			expectedIncludeDir: `"include"`,
-		},
-	}
-	for _, testCase := range testCases {
-		expectedApiContributionTargetName := "foo.contribution"
-		expectedBazelTarget := MakeBazelTargetNoRestrictions(
-			"cc_api_headers",
-			expectedApiContributionTargetName,
-			AttrNameToString{
-				"include_dir": testCase.expectedIncludeDir,
-			},
-		)
-		RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
-			Description:          testCase.desc,
-			Blueprint:            fmt.Sprintf(bpTemplate, testCase.from),
-			ExpectedBazelTargets: []string{expectedBazelTarget},
-		})
-	}
-}
-
-func TestVersionedNdkHeaderFilepaths(t *testing.T) {
-	bp := `
-	versioned_ndk_headers {
-		name: "common_libc",
-		from: "include"
-	}
-	`
-	fs := map[string]string{
-		"include/math.h":    "",
-		"include/stdio.h":   "",
-		"include/arm/arm.h": "",
-		"include/x86/x86.h": "",
-	}
-	expectedApiContributionTargetName := "common_libc.contribution"
-	expectedBazelTarget := MakeBazelTargetNoRestrictions(
-		"cc_api_headers",
-		expectedApiContributionTargetName,
-		AttrNameToString{
-			"include_dir": `"include"`,
-			"hdrs": `[
-        "include/math.h",
-        "include/stdio.h",
-        "include/arm/arm.h",
-        "include/x86/x86.h",
-    ]`,
-		},
-	)
-	RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
-		Blueprint:            bp,
-		Filesystem:           fs,
-		ExpectedBazelTargets: []string{expectedBazelTarget},
-	})
-}
diff --git a/bp2build/ndk_library_conversion_test.go b/bp2build/ndk_library_conversion_test.go
deleted file mode 100644
index 819ab25..0000000
--- a/bp2build/ndk_library_conversion_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2022 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 bp2build
-
-import (
-	"testing"
-
-	"android/soong/cc"
-)
-
-func TestNdkLibraryContributionSymbolFile(t *testing.T) {
-	bp := `
-	ndk_library {
-		name: "libfoo",
-		symbol_file: "libfoo.map.txt",
-	}
-	`
-	expectedBazelTarget := MakeBazelTargetNoRestrictions(
-		"cc_api_contribution",
-		"libfoo.ndk.contribution",
-		AttrNameToString{
-			"api":                    `"libfoo.map.txt"`,
-			"api_surfaces":           `["publicapi"]`,
-			"library_name":           `"libfoo"`,
-			"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
-		},
-	)
-	RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
-		Blueprint:            bp,
-		ExpectedBazelTargets: []string{expectedBazelTarget},
-	})
-}
-
-func TestNdkLibraryContributionHeaders(t *testing.T) {
-	bp := `
-	ndk_library {
-		name: "libfoo",
-		symbol_file: "libfoo.map.txt",
-		export_header_libs: ["libfoo_headers"],
-	}
-	`
-	fs := map[string]string{
-		"header_directory/Android.bp": `
-		ndk_headers {
-			name: "libfoo_headers",
-		}
-		`,
-	}
-	expectedBazelTarget := MakeBazelTargetNoRestrictions(
-		"cc_api_contribution",
-		"libfoo.ndk.contribution",
-		AttrNameToString{
-			"api":                    `"libfoo.map.txt"`,
-			"api_surfaces":           `["publicapi"]`,
-			"library_name":           `"libfoo"`,
-			"hdrs":                   `["//header_directory:libfoo_headers.contribution"]`,
-			"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
-		},
-	)
-	RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
-		Blueprint:            bp,
-		Filesystem:           fs,
-		ExpectedBazelTargets: []string{expectedBazelTarget},
-	})
-}
diff --git a/cc/afdo.go b/cc/afdo.go
index 49f6987..137ea97 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -34,7 +34,7 @@
 
 var afdoProfileProjectsConfigKey = android.NewOnceKey("AfdoProfileProjects")
 
-const afdoCFlagsFormat = "-fprofile-sample-accurate -fprofile-sample-use=%s"
+const afdoCFlagsFormat = "-fprofile-sample-use=%s"
 
 func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
 	getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 259ba39..34cc574 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -591,7 +591,8 @@
 	anySrcs := false
 	// Add srcs-like dependencies such as generated files.
 	// First create a LabelList containing these dependencies, then merge the values with srcs.
-	generatedSrcsLabelList := android.BazelLabelForModuleDepsExcludes(ctx, props.Generated_sources, props.Exclude_generated_sources)
+	genSrcs, _ := android.PartitionXsdSrcs(ctx, props.Generated_sources)
+	generatedSrcsLabelList := android.BazelLabelForModuleDepsExcludes(ctx, genSrcs, props.Exclude_generated_sources)
 	if len(props.Generated_sources) > 0 || len(props.Exclude_generated_sources) > 0 {
 		anySrcs = true
 	}
@@ -716,6 +717,14 @@
 	return ret
 }
 
+// Replaces //a/b/my_xsd_config with //a/b/my_xsd_config-cpp
+func xsdConfigCppTarget(ctx android.BazelConversionPathContext, mod blueprint.Module) string {
+	callback := func(xsd android.XsdConfigBp2buildTargets) string {
+		return xsd.CppBp2buildTargetName()
+	}
+	return android.XsdConfigBp2buildTarget(ctx, mod, callback)
+}
+
 // bp2BuildParseBaseProps returns all compiler, linker, library attributes of a cc module..
 func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes {
 	archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
@@ -754,7 +763,14 @@
 		for cfg := range configs {
 			var allHdrs []string
 			if baseCompilerProps, ok := archVariantCompilerProps[axis][cfg].(*BaseCompilerProperties); ok {
-				allHdrs = baseCompilerProps.Generated_headers
+				ah, allHdrsXsd := android.PartitionXsdSrcs(ctx, baseCompilerProps.Generated_headers)
+				allHdrs = ah
+				// in the synthetic bp2build workspace, xsd sources are compiled to a static library
+				xsdCppConfigLibraryLabels := android.BazelLabelForModuleDepsWithFn(ctx, allHdrsXsd, xsdConfigCppTarget)
+				iwad := linkerAttrs.implementationWholeArchiveDeps.SelectValue(axis, cfg)
+				(&iwad).Append(xsdCppConfigLibraryLabels)
+				linkerAttrs.implementationWholeArchiveDeps.SetSelectValue(axis, cfg, bazel.FirstUniqueBazelLabelList(iwad))
+
 				if baseCompilerProps.Lex != nil {
 					compilerAttrs.lexopts.SetSelectValue(axis, cfg, baseCompilerProps.Lex.Flags)
 				}
@@ -1757,6 +1773,12 @@
 			for _, sanitizer := range sanitizerProps.Sanitize.Misc_undefined {
 				features = append(features, "ubsan_"+sanitizer)
 			}
+			if proptools.Bool(sanitizerProps.Sanitize.Cfi) {
+				features = append(features, "android_cfi")
+				if proptools.Bool(sanitizerProps.Sanitize.Config.Cfi_assembly_support) {
+					features = append(features, "android_cfi_assembly_support")
+				}
+			}
 			sanitizerFeatures.SetSelectValue(axis, config, features)
 		}
 	})
diff --git a/cc/cc.go b/cc/cc.go
index 0e7f6c8..426bac8 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -524,6 +524,7 @@
 	isAfdoCompile() bool
 	isPgoCompile() bool
 	isCfi() bool
+	isFuzzer() bool
 	isNDKStubLibrary() bool
 	useClangLld(actx ModuleContext) bool
 	isForPlatform() bool
@@ -1365,6 +1366,13 @@
 	return false
 }
 
+func (c *Module) isFuzzer() bool {
+	if sanitize := c.sanitize; sanitize != nil {
+		return Bool(sanitize.Properties.SanitizeMutated.Fuzzer)
+	}
+	return false
+}
+
 func (c *Module) isNDKStubLibrary() bool {
 	if _, ok := c.compiler.(*stubDecorator); ok {
 		return true
@@ -1660,6 +1668,10 @@
 	return ctx.mod.isCfi()
 }
 
+func (ctx *moduleContextImpl) isFuzzer() bool {
+	return ctx.mod.isFuzzer()
+}
+
 func (ctx *moduleContextImpl) isNDKStubLibrary() bool {
 	return ctx.mod.isNDKStubLibrary()
 }
@@ -1916,7 +1928,6 @@
 
 	unsupportedSanitizers := []*bool{
 		sanitizeProps.Safestack,
-		sanitizeProps.Cfi,
 		sanitizeProps.Scudo,
 		BoolPtr(len(c.sanitize.Properties.Sanitize.Recover) > 0),
 		BoolPtr(c.sanitize.Properties.Sanitize.Blocklist != nil),
@@ -1935,6 +1946,8 @@
 			if ubsanEnabled && !c.MinimalRuntimeNeeded() {
 				return false
 			}
+		} else if san == cfi {
+			continue
 		} else if c.sanitize.isSanitizerEnabled(san) {
 			return false
 		}
@@ -4100,8 +4113,6 @@
 		// Aggressively generate api targets for all header modules
 		// This is necessary since the header module does not know if it is a dep of API surface stub library
 		apiLibraryHeadersBp2Build(ctx, c)
-	case ndkLibrary:
-		ndkLibraryBp2build(ctx, c)
 	}
 }
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 173911b..701c3bb 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -5538,7 +5538,7 @@
 			name:    "foo_cfi",
 			variant: "android_arm64_armv8-a_static_cfi_apex28",
 			expectedOutputPaths: []string{
-				"out/soong/.intermediates/foo_cfi/android_arm64_armv8-a_static_cfi_apex28/foo_cfi.a",
+				"outputbase/execroot/__main__/foo_cfi.a",
 			},
 		},
 		{
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index d55a13d..efa4549 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -42,6 +42,8 @@
 		"-bugprone-unchecked-optional-access",
 		// http://b/265438407
 		"-misc-use-anonymous-namespace",
+		// http://b/285005947
+		"-performance-avoid-endl",
 	}
 
 	// Some clang-tidy checks are included in some tidy_checks_as_errors lists,
@@ -56,6 +58,14 @@
 		"-bugprone-signed-char-misuse",
 		// http://b/241819232
 		"-misc-const-correctness",
+		// http://b/285356805
+		"-bugprone-unsafe-functions",
+		"-cert-msc24-c",
+		"-cert-msc33-c",
+		// http://b/285356799
+		"-modernize-type-traits",
+		// http://b/285361108
+		"-readability-avoid-unconditional-preprocessor-if",
 	}
 
 	extraArgFlags = []string{
diff --git a/cc/lto.go b/cc/lto.go
index 581856b..8d6e3e7 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -43,22 +43,16 @@
 	// referred to in blueprint files as "lto"
 	Lto struct {
 		Never *bool `android:"arch_variant"`
-		Full  *bool `android:"arch_variant"`
 		Thin  *bool `android:"arch_variant"`
 	} `android:"arch_variant"`
 
 	// Dep properties indicate that this module needs to be built with LTO
 	// since it is an object dependency of an LTO module.
-	FullEnabled  bool `blueprint:"mutated"`
 	ThinEnabled  bool `blueprint:"mutated"`
 	NoLtoEnabled bool `blueprint:"mutated"`
-	FullDep      bool `blueprint:"mutated"`
 	ThinDep      bool `blueprint:"mutated"`
 	NoLtoDep     bool `blueprint:"mutated"`
 
-	// Use clang lld instead of gnu ld.
-	Use_clang_lld *bool
-
 	// Use -fwhole-program-vtables cflag.
 	Whole_program_vtables *bool
 }
@@ -77,17 +71,10 @@
 	}
 }
 
-func (lto *lto) useClangLld(ctx BaseModuleContext) bool {
-	if lto.Properties.Use_clang_lld != nil {
-		return Bool(lto.Properties.Use_clang_lld)
-	}
-	return true
-}
-
 func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
 	// TODO(b/131771163): Disable LTO when using explicit fuzzing configurations.
 	// LTO breaks fuzzer builds.
-	if inList("-fsanitize=fuzzer-no-link", flags.Local.CFlags) {
+	if ctx.isFuzzer() {
 		return flags
 	}
 
@@ -96,8 +83,6 @@
 		var ltoLdFlag string
 		if lto.ThinLTO() {
 			ltoCFlag = "-flto=thin -fsplit-lto-unit"
-		} else if lto.FullLTO() {
-			ltoCFlag = "-flto"
 		} else {
 			ltoCFlag = "-flto=thin -fsplit-lto-unit"
 			ltoLdFlag = "-Wl,--lto-O0"
@@ -112,7 +97,7 @@
 			flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables")
 		}
 
-		if (lto.DefaultThinLTO(ctx) || lto.ThinLTO()) && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) {
+		if (lto.DefaultThinLTO(ctx) || lto.ThinLTO()) && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") {
 			// Set appropriate ThinLTO cache policy
 			cacheDirFormat := "-Wl,--thinlto-cache-dir="
 			cacheDir := android.PathForOutput(ctx, "thinlto-cache").String()
@@ -136,13 +121,13 @@
 }
 
 func (lto *lto) LTO(ctx BaseModuleContext) bool {
-	return lto.ThinLTO() || lto.FullLTO() || lto.DefaultThinLTO(ctx)
+	return lto.ThinLTO() || lto.DefaultThinLTO(ctx)
 }
 
 func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool {
 	// LP32 has many subtle issues and less test coverage.
 	lib32 := ctx.Arch().ArchType.Multilib == "lib32"
-	// CFI enables full LTO.
+	// CFI adds LTO flags by itself.
 	cfi := ctx.isCfi()
 	// Performance and binary size are less important for host binaries and tests.
 	host := ctx.Host()
@@ -153,10 +138,6 @@
 	return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !cfi && !host && !test && !vndk
 }
 
-func (lto *lto) FullLTO() bool {
-	return lto != nil && (proptools.Bool(lto.Properties.Lto.Full) || lto.Properties.FullEnabled)
-}
-
 func (lto *lto) ThinLTO() bool {
 	return lto != nil && (proptools.Bool(lto.Properties.Lto.Thin) || lto.Properties.ThinEnabled)
 }
@@ -174,12 +155,8 @@
 	globalThinLTO := GlobalThinLTO(mctx)
 
 	if m, ok := mctx.Module().(*Module); ok {
-		full := m.lto.FullLTO()
 		thin := m.lto.ThinLTO()
 		never := m.lto.Never()
-		if full && thin {
-			mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive")
-		}
 
 		mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
 			tag := mctx.OtherModuleDependencyTag(dep)
@@ -197,9 +174,6 @@
 			}
 
 			if dep, ok := dep.(*Module); ok {
-				if full && !dep.lto.FullLTO() {
-					dep.lto.Properties.FullDep = true
-				}
 				if !globalThinLTO && thin && !dep.lto.ThinLTO() {
 					dep.lto.Properties.ThinDep = true
 				}
@@ -222,9 +196,6 @@
 		// Create variations for LTO types required as static
 		// dependencies
 		variationNames := []string{""}
-		if m.lto.Properties.FullDep && !m.lto.FullLTO() {
-			variationNames = append(variationNames, "lto-full")
-		}
 		if !globalThinLTO && m.lto.Properties.ThinDep && !m.lto.ThinLTO() {
 			variationNames = append(variationNames, "lto-thin")
 		}
@@ -234,13 +205,10 @@
 
 		// Use correct dependencies if LTO property is explicitly set
 		// (mutually exclusive)
-		if m.lto.FullLTO() {
-			mctx.SetDependencyVariation("lto-full")
-		}
 		if !globalThinLTO && m.lto.ThinLTO() {
 			mctx.SetDependencyVariation("lto-thin")
 		}
-		// Never must be the last, it overrides Thin or Full.
+		// Never must be the last, it overrides Thin.
 		if globalThinLTO && m.lto.Never() {
 			mctx.SetDependencyVariation("lto-none")
 		}
@@ -257,9 +225,6 @@
 				}
 
 				// LTO properties for dependencies
-				if name == "lto-full" {
-					variation.lto.Properties.FullEnabled = true
-				}
 				if name == "lto-thin" {
 					variation.lto.Properties.ThinEnabled = true
 				}
@@ -268,7 +233,6 @@
 				}
 				variation.Properties.PreventInstall = true
 				variation.Properties.HideFromMake = true
-				variation.lto.Properties.FullDep = false
 				variation.lto.Properties.ThinDep = false
 				variation.lto.Properties.NoLtoDep = false
 			}
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 7354be9..d0ae4a5 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -19,10 +19,8 @@
 	"path/filepath"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
-	"android/soong/bazel"
 )
 
 var (
@@ -81,7 +79,6 @@
 
 type headerModule struct {
 	android.ModuleBase
-	android.BazelModuleBase
 
 	properties headerProperties
 
@@ -147,39 +144,6 @@
 	}
 }
 
-// TODO(b/243196151): Populate `system` and `arch` metadata
-type bazelCcApiHeadersAttributes struct {
-	Hdrs        bazel.LabelListAttribute
-	Include_dir *string
-}
-
-func createCcApiHeadersTarget(ctx android.TopDownMutatorContext, includes []string, excludes []string, include_dir *string) {
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class:        "cc_api_headers",
-		Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
-	}
-	attrs := &bazelCcApiHeadersAttributes{
-		Hdrs: bazel.MakeLabelListAttribute(
-			android.BazelLabelForModuleSrcExcludes(
-				ctx,
-				includes,
-				excludes,
-			),
-		),
-		Include_dir: include_dir,
-	}
-	ctx.CreateBazelTargetModule(props, android.CommonAttributes{
-		Name: android.ApiContributionTargetName(ctx.ModuleName()),
-	}, attrs)
-}
-
-var _ android.ApiProvider = (*headerModule)(nil)
-
-func (h *headerModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
-	// Generate `cc_api_headers` target for Multi-tree API export
-	createCcApiHeadersTarget(ctx, h.properties.Srcs, h.properties.Exclude_srcs, h.properties.From)
-}
-
 // ndk_headers installs the sets of ndk headers defined in the srcs property
 // to the sysroot base + "usr/include" + to directory + directory component.
 // ndk_headers requires the license file to be specified. Example:
@@ -226,7 +190,6 @@
 // Note that this is really only built to handle bionic/libc/include.
 type versionedHeaderModule struct {
 	android.ModuleBase
-	android.BazelModuleBase
 
 	properties versionedHeaderProperties
 
@@ -264,15 +227,6 @@
 	processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, srcFiles, installPaths)
 }
 
-var _ android.ApiProvider = (*versionedHeaderModule)(nil)
-
-func (h *versionedHeaderModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
-	// Glob all .h files under `From`
-	includePattern := headerGlobPattern(proptools.String(h.properties.From))
-	// Generate `cc_api_headers` target for Multi-tree API export
-	createCcApiHeadersTarget(ctx, []string{includePattern}, []string{}, h.properties.From)
-}
-
 func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir android.Path,
 	srcFiles android.Paths, installPaths []android.WritablePath) android.Path {
 	// The versioner depends on a dependencies directory to simplify determining include paths
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index f8a3559..f0b7cc5 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -599,24 +599,3 @@
 	}
 	return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix)
 }
-
-func ndkLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class:        "cc_api_contribution",
-		Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
-	}
-	stubLibrary := m.compiler.(*stubDecorator)
-	attrs := &bazelCcApiContributionAttributes{
-		Library_name: stubLibrary.implementationModuleName(m.Name()),
-		Api_surfaces: bazel.MakeStringListAttribute(
-			[]string{android.PublicApi.String()}),
-	}
-	if symbolFile := stubLibrary.properties.Symbol_file; symbolFile != nil {
-		apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(symbolFile)).Label
-		attrs.Api = *bazel.MakeLabelAttribute(apiLabel)
-	}
-	apiHeaders := apiHeaderLabels(ctx, stubLibrary.properties.Export_header_libs)
-	attrs.Hdrs = bazel.MakeLabelListAttribute(apiHeaders)
-	apiContributionTargetName := android.ApiContributionTargetName(ctx.ModuleName())
-	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: apiContributionTargetName}, attrs)
-}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 6e732b6..a5691ee 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -64,13 +64,14 @@
 
 	cfiBlocklistPath     = "external/compiler-rt/lib/cfi"
 	cfiBlocklistFilename = "cfi_blocklist.txt"
+	cfiEnableFlag        = "-fsanitize=cfi"
 	cfiCrossDsoFlag      = "-fsanitize-cfi-cross-dso"
 	cfiCflags            = []string{"-flto", cfiCrossDsoFlag,
 		"-fsanitize-ignorelist=" + cfiBlocklistPath + "/" + cfiBlocklistFilename}
 	// -flto and -fvisibility are required by clang when -fsanitize=cfi is
 	// used, but have no effect on assembly files
 	cfiAsflags = []string{"-flto", "-fvisibility=default"}
-	cfiLdflags = []string{"-flto", cfiCrossDsoFlag, "-fsanitize=cfi",
+	cfiLdflags = []string{"-flto", cfiCrossDsoFlag, cfiEnableFlag,
 		"-Wl,-plugin-opt,O1"}
 	cfiExportsMapPath      = "build/soong/cc/config"
 	cfiExportsMapFilename  = "cfi_exports.map"
@@ -395,8 +396,8 @@
 
 	// Leave out "-flto" from the slices exported to bazel, as we will use the
 	// dedicated LTO feature for this. For C Flags and Linker Flags, also leave
-	// out the cross DSO flag which will be added separately by transitions.
-	exportedVars.ExportStringList("CfiCFlags", cfiCflags[2:])
+	// out the cross DSO flag which will be added separately under the correct conditions.
+	exportedVars.ExportStringList("CfiCFlags", append(cfiCflags[2:], cfiEnableFlag))
 	exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[2:])
 	exportedVars.ExportStringList("CfiAsFlags", cfiAsflags[1:])
 
diff --git a/cc/test.go b/cc/test.go
index 27de06b..3f5f710 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -70,6 +70,10 @@
 	// Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an
 	// integer value and the value is less than the min_vndk_version, skip this module.
 	Min_vndk_version *int64
+
+	// Extra <option> tags to add to the auto generated test xml file under the test runner, e.g., GTest.
+	// The "key" is optional in each of these.
+	Test_runner_options []tradefed.Option
 }
 
 type TestBinaryProperties struct {
@@ -398,6 +402,7 @@
 		TestConfigTemplateProp: test.Properties.Test_config_template,
 		TestSuites:             test.testDecorator.InstallerProperties.Test_suites,
 		Config:                 configs,
+		TestRunnerOptions:      test.Properties.Test_options.Test_runner_options,
 		AutoGenConfig:          test.Properties.Auto_gen_config,
 		TestInstallBase:        testInstallBase,
 		DeviceTemplate:         "${NativeTestConfigTemplate}",
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index e006c9d..2e6b6d4 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -16,6 +16,7 @@
 
 import (
 	"bytes"
+	"errors"
 	"flag"
 	"fmt"
 	"os"
@@ -135,12 +136,24 @@
 
 	writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
 
-	if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") {
+	if needToWriteNinjaHint(ctx) {
 		writeNinjaHint(ctx)
 	}
 	return cmdlineArgs.OutFile
 }
 
+func needToWriteNinjaHint(ctx *android.Context) bool {
+	switch ctx.Config().GetenvWithDefault("SOONG_GENERATES_NINJA_HINT", "") {
+	case "always":
+		return true
+	case "depend":
+		if _, err := os.Stat(filepath.Join(ctx.Config().OutDir(), ".ninja_log")); errors.Is(err, os.ErrNotExist) {
+			return true
+		}
+	}
+	return false
+}
+
 // Run the code-generation phase to convert BazelTargetModules to BUILD files.
 func runQueryView(queryviewDir, queryviewMarker string, ctx *android.Context) {
 	ctx.EventHandler.Begin("queryview")
@@ -460,7 +473,7 @@
 		// The actual output (build.ninja) was written in the RunBlueprint() call
 		// above
 		writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
-		if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") {
+		if needToWriteNinjaHint(ctx) {
 			writeNinjaHint(ctx)
 		}
 		return cmdlineArgs.OutFile
@@ -552,6 +565,12 @@
 		}
 		writeMetrics(configuration, ctx.EventHandler, metricsDir)
 	}
+
+	// Register this environment variablesas being an implicit dependencies of
+	// soong_build. Changes to this environment variable will result in
+	// retriggering soong_build.
+	configuration.Getenv("USE_BAZEL_VERSION")
+
 	writeUsedEnvironmentFile(configuration)
 
 	// Touch the output file so that it's the newest file created by soong_build.
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 2a1b404..b470304 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -170,6 +170,27 @@
 	return false
 }
 
+type UsePlatformLibs string
+
+const (
+	unknown_use_platform_libs UsePlatformLibs = "unknown_use_platform_libs"
+	// Use the native libraries on the device, typically in /system directory
+	use_platform_libs = "use_platform_libs"
+	// Do not use any native libraries (ART will not be initialized)
+	use_none = "use_none"
+)
+
+func (use_platform_libs UsePlatformLibs) isValidUsePlatformLibs() bool {
+	switch use_platform_libs {
+	case "",
+		unknown_use_platform_libs,
+		use_platform_libs,
+		use_none:
+		return true
+	}
+	return false
+}
+
 type UserData string
 
 const (
@@ -284,6 +305,10 @@
 		if !config.Automatically_route_to.isValidAutomaticallyRouteTo() {
 			panic(fmt.Errorf("Invalid automatically_route_to in fuzz config in %s", moduleName))
 		}
+
+		if !config.Use_platform_libs.isValidUsePlatformLibs() {
+			panic(fmt.Errorf("Invalid use_platform_libs in fuzz config in %s", moduleName))
+		}
 	}
 	return true
 }
@@ -341,6 +366,8 @@
 	Target_modules []string `json:"target_modules,omitempty"`
 	// Specifies a bug assignee to replace default ISE assignment
 	Triage_assignee string `json:"triage_assignee,omitempty"`
+	// Specifies libs used to initialize ART (java only, 'use_none' for no initialization)
+	Use_platform_libs UsePlatformLibs `json:"use_platform_libs,omitempty"`
 }
 
 type FuzzFrameworks struct {
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index 875dbab..2954f8b 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -14,10 +14,6 @@
 
 package genrule
 
-import (
-	"android/soong/android"
-)
-
 var (
 	DepfileAllowList = []string{
 		"depfile_allowed_for_test",
@@ -136,12 +132,3 @@
 		"external/perfetto",
 	}
 )
-var DepfileAllowSet = map[string]bool{}
-var SandboxingDenyModuleSet = map[string]bool{}
-var SandboxingDenyPathSet = map[string]bool{}
-
-func init() {
-	android.AddToStringSet(DepfileAllowSet, DepfileAllowList)
-	android.AddToStringSet(SandboxingDenyModuleSet, append(DepfileAllowList, SandboxingDenyModuleList...))
-	android.AddToStringSet(SandboxingDenyPathSet, SandboxingDenyPathList)
-}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index c830fcc..4992625 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -24,6 +24,7 @@
 	"path/filepath"
 	"strconv"
 	"strings"
+	"sync"
 
 	"android/soong/bazel/cquery"
 
@@ -60,6 +61,12 @@
 	PrepareForTestWithGenRuleBuildComponents,
 )
 
+var DepfileAllowSet map[string]bool
+var SandboxingDenyModuleSet map[string]bool
+var SandboxingDenyPathSet map[string]bool
+var SandboxingDenyModuleSetLock sync.Mutex
+var DepfileAllowSetLock sync.Mutex
+
 func RegisterGenruleBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
 
@@ -595,6 +602,12 @@
 	// Allowlist genrule to use depfile until we have a solution to remove it.
 	// TODO(b/235582219): Remove allowlist for genrule
 	if Bool(g.properties.Depfile) {
+		if DepfileAllowSet == nil {
+			DepfileAllowSetLock.Lock()
+			defer DepfileAllowSetLock.Unlock()
+			DepfileAllowSet = map[string]bool{}
+			android.AddToStringSet(DepfileAllowSet, DepfileAllowList)
+		}
 		// TODO(b/283852474): Checking the GenruleSandboxing flag is temporary in
 		// order to pass the presubmit before internal master is updated.
 		if ctx.DeviceConfig().GenruleSandboxing() && !DepfileAllowSet[g.Name()] {
@@ -1024,8 +1037,19 @@
 }
 
 func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder {
-	if !ctx.DeviceConfig().GenruleSandboxing() || SandboxingDenyPathSet[ctx.ModuleDir()] ||
-		SandboxingDenyModuleSet[ctx.ModuleName()] {
+	if !ctx.DeviceConfig().GenruleSandboxing() {
+		return r.SandboxTools()
+	}
+	if SandboxingDenyModuleSet == nil {
+		SandboxingDenyModuleSetLock.Lock()
+		defer SandboxingDenyModuleSetLock.Unlock()
+		SandboxingDenyModuleSet = map[string]bool{}
+		SandboxingDenyPathSet = map[string]bool{}
+		android.AddToStringSet(SandboxingDenyModuleSet, append(DepfileAllowList, SandboxingDenyModuleList...))
+		android.AddToStringSet(SandboxingDenyPathSet, SandboxingDenyPathList)
+	}
+
+	if SandboxingDenyPathSet[ctx.ModuleDir()] || SandboxingDenyModuleSet[ctx.ModuleName()] {
 		return r.SandboxTools()
 	}
 	return r.SandboxInputs()
diff --git a/java/app.go b/java/app.go
index 561ce1d..d9272e4 100755
--- a/java/app.go
+++ b/java/app.go
@@ -18,6 +18,7 @@
 // related module types, including their override variants.
 
 import (
+	"fmt"
 	"path/filepath"
 	"strings"
 
@@ -288,7 +289,13 @@
 	}
 
 	if a.appProperties.Privapp_allowlist != nil && !Bool(a.appProperties.Privileged) {
-		ctx.PropertyErrorf("privapp_allowlist", "privileged must be set in order to use privapp_allowlist")
+		// There are a few uids that are explicitly considered privileged regardless of their
+		// app's location. Bluetooth is one such app. It should arguably be moved to priv-app,
+		// but for now, allow it not to be in priv-app.
+		privilegedBecauseOfUid := ctx.ModuleName() == "Bluetooth"
+		if !privilegedBecauseOfUid {
+			ctx.PropertyErrorf("privapp_allowlist", "privileged must be set in order to use privapp_allowlist (with a few exceptions)")
+		}
 	}
 
 	for _, cert := range a.appProperties.Additional_certificates {
@@ -795,8 +802,9 @@
 	shouldInstallAppPackage := (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() && !a.appProperties.PreventInstall
 	if shouldInstallAppPackage {
 		if a.privAppAllowlist.Valid() {
-			installPath := android.PathForModuleInstall(ctx, "etc", "permissions")
-			ctx.InstallFile(installPath, a.privAppAllowlist.Path().Base(), a.privAppAllowlist.Path())
+			allowlistInstallPath := android.PathForModuleInstall(ctx, "etc", "permissions")
+			allowlistInstallFilename := a.installApkName + ".xml"
+			ctx.InstallFile(allowlistInstallPath, allowlistInstallFilename, a.privAppAllowlist.Path())
 		}
 
 		var extraInstalledPaths android.Paths
@@ -1390,10 +1398,15 @@
 	}
 }
 
-// presentOptionalUsesLibs returns optional_uses_libs after filtering out MissingUsesLibraries, which don't exist in the
-// build.
+// presentOptionalUsesLibs returns optional_uses_libs after filtering out libraries that don't exist in the source tree.
 func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
-	optionalUsesLibs, _ := android.FilterList(u.usesLibraryProperties.Optional_uses_libs, ctx.Config().MissingUsesLibraries())
+	optionalUsesLibs := android.FilterListPred(u.usesLibraryProperties.Optional_uses_libs, func(s string) bool {
+		exists := ctx.OtherModuleExists(s)
+		if !exists && !android.InList(ctx.ModuleName(), ctx.Config().BuildWarningBadOptionalUsesLibsAllowlist()) {
+			fmt.Printf("Warning: Module '%s' depends on non-existing optional_uses_libs '%s'\n", ctx.ModuleName(), s)
+		}
+		return exists
+	})
 	return optionalUsesLibs
 }
 
diff --git a/java/app_test.go b/java/app_test.go
index 7f9f0ed..cf7d174 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2645,7 +2645,7 @@
 		PrepareForTestWithJavaSdkLibraryFiles,
 		FixtureWithLastReleaseApis("runtime-library", "foo", "quuz", "qux", "bar", "fred"),
 		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
-			variables.MissingUsesLibraries = []string{"baz"}
+			variables.BuildWarningBadOptionalUsesLibsAllowlist = []string{"app", "prebuilt"}
 		}),
 	).RunTestWithBp(t, bp)
 
@@ -3545,8 +3545,8 @@
 	}
 
 	// verify that permissions are copied to device
-	app.Output("out/soong/target/product/test_device/system/etc/permissions/privapp_allowlist_com.android.foo.xml")
-	overrideApp.Output("out/soong/target/product/test_device/system/etc/permissions/privapp_allowlist_com.google.android.foo.xml")
+	app.Output("out/soong/target/product/test_device/system/etc/permissions/foo.xml")
+	overrideApp.Output("out/soong/target/product/test_device/system/etc/permissions/bar.xml")
 }
 
 func TestPrivappAllowlistAndroidMk(t *testing.T) {
@@ -3597,7 +3597,7 @@
 		t,
 		"androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
 		baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
-		"privapp_allowlist_com.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/privapp_allowlist_com.android.foo.xml",
+		"privapp_allowlist_com.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/foo.xml",
 	)
 
 	overrideAndroidApp := overrideApp.Module().(*AndroidApp)
@@ -3624,6 +3624,6 @@
 		t,
 		"androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
 		overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
-		"\\S+soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/privapp_allowlist_com.google.android.foo.xml",
+		"\\S+soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/bar.xml",
 	)
 }
diff --git a/java/base.go b/java/base.go
index 374138c..ed61e12 100644
--- a/java/base.go
+++ b/java/base.go
@@ -79,6 +79,9 @@
 	// list of java libraries that will be compiled into the resulting jar
 	Static_libs []string `android:"arch_variant"`
 
+	// list of java libraries that should not be used to build this module
+	Exclude_static_libs []string `android:"arch_variant"`
+
 	// manifest file to be included in resulting jar
 	Manifest *string `android:"path"`
 
@@ -724,6 +727,8 @@
 	}
 
 	libDeps := ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+
+	j.properties.Static_libs = android.RemoveListFromList(j.properties.Static_libs, j.properties.Exclude_static_libs)
 	ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
 
 	// Add dependency on libraries that provide additional hidden api annotations.
@@ -1923,22 +1928,22 @@
 
 func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool) {
 	switch name {
-	case android.SdkCore.JavaLibraryName(ctx.Config()),
-		android.JavaApiLibraryName(ctx.Config(), "legacy.core.platform.api.stubs"),
-		android.JavaApiLibraryName(ctx.Config(), "stable.core.platform.api.stubs"),
+	case android.SdkCore.DefaultJavaLibraryName(),
+		"legacy.core.platform.api.stubs",
+		"stable.core.platform.api.stubs",
 		"stub-annotations", "private-stub-annotations-jar",
-		android.JavaApiLibraryName(ctx.Config(), "core-lambda-stubs"),
+		"core-lambda-stubs",
 		"core-generated-annotation-stubs":
 		return javaCore, true
-	case android.SdkPublic.JavaLibraryName(ctx.Config()):
+	case android.SdkPublic.DefaultJavaLibraryName():
 		return javaSdk, true
-	case android.SdkSystem.JavaLibraryName(ctx.Config()):
+	case android.SdkSystem.DefaultJavaLibraryName():
 		return javaSystem, true
-	case android.SdkModule.JavaLibraryName(ctx.Config()):
+	case android.SdkModule.DefaultJavaLibraryName():
 		return javaModule, true
-	case android.SdkSystemServer.JavaLibraryName(ctx.Config()):
+	case android.SdkSystemServer.DefaultJavaLibraryName():
 		return javaSystemServer, true
-	case android.SdkTest.JavaLibraryName(ctx.Config()):
+	case android.SdkTest.DefaultJavaLibraryName():
 		return javaSystem, true
 	}
 
@@ -2188,5 +2193,9 @@
 		if binary, ok := ctx.Module().(*Binary); ok {
 			javaBinaryHostBp2Build(ctx, binary)
 		}
+	case "java_test_host":
+		if testHost, ok := ctx.Module().(*TestHost); ok {
+			javaTestHostBp2Build(ctx, testHost)
+		}
 	}
 }
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index 958f4ce..eadd9c6 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -33,19 +33,45 @@
     "win_sdk",
 ]
 
-java_library {
-    name: "core.current.stubs",
+java_defaults {
+    name: "core.current.stubs.defaults",
     visibility: ["//visibility:public"],
+    sdk_version: "none",
+    system_modules: "none",
+    dist: {
+        targets: dist_targets,
+    },
+}
+
+java_library {
+    name: "core.current.stubs.from-source",
+    defaults: [
+        "core.current.stubs.defaults",
+    ],
     static_libs: [
         "art.module.public.api.stubs",
         "conscrypt.module.public.api.stubs",
         "i18n.module.public.api.stubs",
     ],
-    sdk_version: "none",
-    system_modules: "none",
+}
 
-    dist: {
-        targets: dist_targets,
+java_library {
+    name: "core.current.stubs",
+    defaults: [
+        "core.current.stubs.defaults",
+    ],
+    static_libs: [
+        "core.current.stubs.from-source",
+    ],
+    product_variables: {
+        build_from_text_stub: {
+            static_libs: [
+                "core.current.stubs.from-text",
+            ],
+            exclude_static_libs: [
+                "core.current.stubs.from-source",
+            ],
+        },
     },
 }
 
@@ -199,18 +225,46 @@
 // API annotations are available to the dex tools that enable enforcement of runtime
 // accessibility. b/119068555
 java_library {
-    name: "legacy.core.platform.api.stubs",
+    name: "legacy.core.platform.api.stubs.from-source",
     visibility: core_platform_visibility,
-    hostdex: true,
-    compile_dex: true,
-
-    sdk_version: "none",
-    system_modules: "none",
+    defaults: [
+        "core.platform.api.stubs.defaults",
+    ],
     static_libs: [
         "art.module.public.api.stubs.module_lib",
         "conscrypt.module.platform.api.stubs",
         "legacy.i18n.module.platform.api.stubs",
     ],
+}
+
+java_library {
+    name: "legacy.core.platform.api.stubs",
+    visibility: core_platform_visibility,
+    defaults: [
+        "core.platform.api.stubs.defaults",
+    ],
+    static_libs: [
+        "legacy.core.platform.api.stubs.from-source",
+    ],
+    product_variables: {
+        build_from_text_stub: {
+            static_libs: [
+                "stable.core.platform.api.stubs.from-text",
+            ],
+            exclude_static_libs: [
+                "stable.core.platform.api.stubs.from-source",
+            ],
+        },
+    },
+}
+
+java_defaults {
+    name: "core.platform.api.stubs.defaults",
+    hostdex: true,
+    compile_dex: true,
+
+    sdk_version: "none",
+    system_modules: "none",
     patch_module: "java.base",
 }
 
@@ -233,20 +287,38 @@
 }
 
 java_library {
-    name: "stable.core.platform.api.stubs",
+    name: "stable.core.platform.api.stubs.from-source",
     visibility: core_platform_visibility,
-    hostdex: true,
-    compile_dex: true,
-
-    sdk_version: "none",
-    system_modules: "none",
+    defaults: [
+        "core.platform.api.stubs.defaults",
+    ],
     static_libs: [
         "art.module.public.api.stubs.module_lib",
         // conscrypt only has a stable version, so it is okay to depend on it here:
         "conscrypt.module.platform.api.stubs",
         "stable.i18n.module.platform.api.stubs",
     ],
-    patch_module: "java.base",
+}
+
+java_library {
+    name: "stable.core.platform.api.stubs",
+    visibility: core_platform_visibility,
+    defaults: [
+        "core.platform.api.stubs.defaults",
+    ],
+    static_libs: [
+        "stable.core.platform.api.stubs.from-source",
+    ],
+    product_variables: {
+        build_from_text_stub: {
+            static_libs: [
+                "stable.core.platform.api.stubs.from-text",
+            ],
+            exclude_static_libs: [
+                "stable.core.platform.api.stubs.from-source",
+            ],
+        },
+    },
 }
 
 // Same as stable.core.platform.api.stubs, but android annotations are
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 116c833..35f6097 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -816,7 +816,7 @@
 		cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
 	}
 
-	if global.EnableUffdGc {
+	if global.EnableUffdGc && image.target.Os == android.Android {
 		cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
 	}
 
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 8a521aa..151c94a 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -535,6 +535,14 @@
 		// b/223382732
 		FlagWithArg("--hide ", "ChangedDefault")
 
+	// Force metalava to ignore classes on the classpath when an API file contains missing classes.
+	// See b/285140653 for more information.
+	cmd.FlagWithArg("--api-class-resolution ", "api")
+
+	// Force metalava to sort overloaded methods by their order in the source code.
+	// See b/285312164 for more information.
+	cmd.FlagWithArg("--api-overloaded-method-order ", "source")
+
 	return cmd
 }
 
diff --git a/java/fuzz.go b/java/fuzz.go
index 5dfaacf..b3c2fd4 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -30,8 +30,12 @@
 const (
 	hostString   = "host"
 	targetString = "target"
+	deviceString = "device"
 )
 
+// Any shared libs for these deps will also be packaged
+var artDeps = []string{"libdl_android"}
+
 func init() {
 	RegisterJavaFuzzBuildComponents(android.InitRegistrationContext)
 }
@@ -78,7 +82,18 @@
 }
 
 func (j *JavaFuzzTest) DepsMutator(ctx android.BottomUpMutatorContext) {
+	if j.Os().Class.String() == deviceString {
+		j.testProperties.Jni_libs = append(j.testProperties.Jni_libs, artDeps...)
+	}
+
 	if len(j.testProperties.Jni_libs) > 0 {
+		if j.fuzzPackagedModule.FuzzProperties.Fuzz_config == nil {
+			config := &fuzz.FuzzConfig{}
+			j.fuzzPackagedModule.FuzzProperties.Fuzz_config = config
+		}
+		// this will be used by the ingestion pipeline to determine the version
+		// of jazzer to add to the fuzzer package
+		j.fuzzPackagedModule.FuzzProperties.Fuzz_config.IsJni = proptools.BoolPtr(true)
 		for _, target := range ctx.MultiTargets() {
 			sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
 			ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, j.testProperties.Jni_libs...)
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index e54275b..da9c997 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -236,12 +236,12 @@
 		testStubModules = append(testStubModules, "sdk_test_current_android")
 	} else {
 		// Use stub modules built from source
-		publicStubModules = append(publicStubModules, android.SdkPublic.JavaLibraryName(config))
-		systemStubModules = append(systemStubModules, android.SdkSystem.JavaLibraryName(config))
-		testStubModules = append(testStubModules, android.SdkTest.JavaLibraryName(config))
+		publicStubModules = append(publicStubModules, android.SdkPublic.DefaultJavaLibraryName())
+		systemStubModules = append(systemStubModules, android.SdkSystem.DefaultJavaLibraryName())
+		testStubModules = append(testStubModules, android.SdkTest.DefaultJavaLibraryName())
 	}
 	// We do not have prebuilts of the core platform api yet
-	corePlatformStubModules = append(corePlatformStubModules, android.JavaApiLibraryName(config, "legacy.core.platform.api.stubs"))
+	corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
 
 	// Allow products to define their own stubs for custom product jars that apps can use.
 	publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
diff --git a/java/java.go b/java/java.go
index aa9f936..a8793fe 100644
--- a/java/java.go
+++ b/java/java.go
@@ -936,6 +936,10 @@
 	// Extra <option> tags to add to the auto generated test xml file. The "key"
 	// is optional in each of these.
 	Tradefed_options []tradefed.Option
+
+	// Extra <option> tags to add to the auto generated test xml file under the test runner, e.g., AndroidJunitTest.
+	// The "key" is optional in each of these.
+	Test_runner_options []tradefed.Option
 }
 
 type testProperties struct {
@@ -1218,6 +1222,7 @@
 		TestSuites:              j.testProperties.Test_suites,
 		Config:                  configs,
 		OptionsForAutogenerated: j.testProperties.Test_options.Tradefed_options,
+		TestRunnerOptions:       j.testProperties.Test_options.Test_runner_options,
 		AutoGenConfig:           j.testProperties.Auto_gen_config,
 		UnitTest:                j.testProperties.Test_options.Unit_test,
 		DeviceTemplate:          "${JavaTestConfigTemplate}",
@@ -1416,6 +1421,8 @@
 		nil,
 		nil)
 
+	android.InitBazelModule(module)
+
 	InitJavaModuleMultiTargets(module, android.HostSupported)
 
 	return module
@@ -1728,6 +1735,14 @@
 		FlagWithArg("--hide ", "InvalidNullabilityOverride").
 		FlagWithArg("--hide ", "ChangedDefault")
 
+	// Force metalava to ignore classes on the classpath when an API file contains missing classes.
+	// See b/285140653 for more information.
+	cmd.FlagWithArg("--api-class-resolution ", "api")
+
+	// Force metalava to sort overloaded methods by their order in the source code.
+	// See b/285312164 for more information.
+	cmd.FlagWithArg("--api-overloaded-method-order ", "source")
+
 	return cmd
 }
 
@@ -2798,6 +2813,14 @@
 	hasKotlin bool
 }
 
+// Replaces //a/b/my_xsd_config with //a/b/my_xsd_config-java
+func xsdConfigJavaTarget(ctx android.BazelConversionPathContext, mod blueprint.Module) string {
+	callback := func(xsd android.XsdConfigBp2buildTargets) string {
+		return xsd.JavaBp2buildTargetName()
+	}
+	return android.XsdConfigBp2buildTarget(ctx, mod, callback)
+}
+
 // convertLibraryAttrsBp2Build returns a javaCommonAttributes struct with
 // converted attributes shared across java_* modules and a bp2BuildJavaInfo struct
 // which has other non-attribute information needed for bp2build conversion
@@ -2812,8 +2835,15 @@
 	for axis, configToProps := range archVariantProps {
 		for config, _props := range configToProps {
 			if archProps, ok := _props.(*CommonProperties); ok {
-				archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Srcs, archProps.Exclude_srcs)
+				srcsNonXsd, srcsXsd := android.PartitionXsdSrcs(ctx, archProps.Srcs)
+				excludeSrcsNonXsd, _ := android.PartitionXsdSrcs(ctx, archProps.Exclude_srcs)
+				archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, srcsNonXsd, excludeSrcsNonXsd)
 				srcs.SetSelectValue(axis, config, archSrcs)
+
+				// Add to static deps
+				xsdJavaConfigLibraryLabels := android.BazelLabelForModuleDepsWithFn(ctx, srcsXsd, xsdConfigJavaTarget)
+				staticDeps.Append(xsdJavaConfigLibraryLabels)
+
 			}
 		}
 	}
@@ -3114,23 +3144,89 @@
 		return
 	}
 
-	libName := m.Name() + "_lib"
+	libInfo := libraryCreationInfo{
+		deps: deps,
+		attrs: commonAttrs,
+		baseName: m.Name(),
+		hasKotlin: bp2BuildInfo.hasKotlin,
+	}
+	libName := createLibraryTarget(ctx, libInfo)
+	binAttrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
+
+	// Create the BazelTargetModule.
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs)
+}
+
+type javaTestHostAttributes struct {
+	*javaCommonAttributes
+	Deps         bazel.LabelListAttribute
+	Runtime_deps bazel.LabelListAttribute
+}
+
+// javaTestHostBp2Build is for java_test_host bp2build.
+func javaTestHostBp2Build(ctx android.TopDownMutatorContext, m *TestHost) {
+	commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx)
+	depLabels := bp2BuildInfo.DepLabels
+
+	deps := depLabels.Deps
+	deps.Append(depLabels.StaticDeps)
+
+	var runtimeDeps bazel.LabelListAttribute
+	attrs := &javaTestHostAttributes{
+		Runtime_deps: runtimeDeps,
+	}
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "java_test",
+		Bzl_load_location: "//build/bazel/rules/java:test.bzl",
+	}
+
+	if commonAttrs.Srcs.IsEmpty() {
+		// if there are no sources, then the dependencies can only be used at runtime
+		attrs.Runtime_deps = deps
+		attrs.javaCommonAttributes = commonAttrs
+		ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
+		return
+	}
+
+	libInfo := libraryCreationInfo{
+		deps: deps,
+		attrs: commonAttrs,
+		baseName: m.Name(),
+		hasKotlin: bp2BuildInfo.hasKotlin,
+	}
+	libName := createLibraryTarget(ctx, libInfo)
+	attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
+
+	// Create the BazelTargetModule.
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
+}
+
+// libraryCreationInfo encapsulates the info needed to create java_library target from
+// java_binary_host or java_test_host.
+type libraryCreationInfo struct {
+	deps bazel.LabelListAttribute
+	attrs *javaCommonAttributes
+	baseName string
+	hasKotlin bool
+}
+
+// helper function that creates java_library target from java_binary_host or java_test_host,
+// and returns the library target name,
+func createLibraryTarget(ctx android.TopDownMutatorContext, libInfo libraryCreationInfo) string {
+	libName := libInfo.baseName + "_lib"
 	var libProps bazel.BazelTargetModuleProperties
-	if bp2BuildInfo.hasKotlin {
+	if libInfo.hasKotlin {
 		libProps = ktJvmLibraryBazelTargetModuleProperties()
 	} else {
 		libProps = javaLibraryBazelTargetModuleProperties()
 	}
 	libAttrs := &javaLibraryAttributes{
-		Deps:                 deps,
-		javaCommonAttributes: commonAttrs,
+		Deps:                 libInfo.deps,
+		javaCommonAttributes: libInfo.attrs,
 	}
 
 	ctx.CreateBazelTargetModule(libProps, android.CommonAttributes{Name: libName}, libAttrs)
-	binAttrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
-
-	// Create the BazelTargetModule.
-	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs)
+	return libName
 }
 
 type bazelJavaImportAttributes struct {
diff --git a/java/java_test.go b/java/java_test.go
index ea89e6e..561b187 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2298,3 +2298,58 @@
 		t.Errorf("Expected args[\"extraConfigs\"] to equal %q, was %q", expected, args["extraConfigs"])
 	}
 }
+
+func TestTestRunnerOptions(t *testing.T) {
+	result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
+java_test_host {
+	name: "foo",
+	test_options: {
+		test_runner_options: [
+			{
+				name: "test-timeout",
+				value: "10m"
+			}
+		]
+	}
+}
+`)
+
+	buildOS := result.Config.BuildOS.String()
+	args := result.ModuleForTests("foo", buildOS+"_common").
+		Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args
+	expected := proptools.NinjaAndShellEscape("<option name=\"test-timeout\" value=\"10m\" />\\n        ")
+	if args["extraTestRunnerConfigs"] != expected {
+		t.Errorf("Expected args[\"extraTestRunnerConfigs\"] to equal %q, was %q", expected, args["extraTestRunnerConfigs"])
+	}
+}
+
+func TestJavaExcludeStaticLib(t *testing.T) {
+	ctx, _ := testJava(t, `
+	java_library {
+		name: "bar",
+	}
+	java_library {
+		name: "foo",
+	}
+	java_library {
+		name: "baz",
+		static_libs: [
+			"foo",
+			"bar",
+		],
+		exclude_static_libs: [
+			"bar",
+		],
+	}
+	`)
+
+	// "bar" not included as dependency of "baz"
+	CheckModuleDependencies(t, ctx, "baz", "android_common", []string{
+		`core-lambda-stubs`,
+		`ext`,
+		`foo`,
+		`framework`,
+		`stable-core-platform-api-stubs-system-modules`,
+		`stable.core.platform.api.stubs`,
+	})
+}
diff --git a/java/sdk.go b/java/sdk.go
index 7fa604f..7699aab 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -151,7 +151,7 @@
 		systemModules := android.JavaApiLibraryName(ctx.Config(), fmt.Sprintf("core-%s-stubs-system-modules", systemModulesKind))
 		return sdkDep{
 			useModule:          true,
-			bootclasspath:      []string{module, android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)},
+			bootclasspath:      []string{module, config.DefaultLambdaStubsLibrary},
 			systemModules:      systemModules,
 			java9Classpath:     []string{module},
 			frameworkResModule: "framework-res",
@@ -193,20 +193,20 @@
 			noFrameworksLibs: true,
 		}
 	case android.SdkPublic, android.SdkSystem, android.SdkTest:
-		return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), sdkFrameworkAidlPath(ctx))
+		return toModule(sdkVersion.Kind.DefaultJavaLibraryName(), sdkFrameworkAidlPath(ctx))
 	case android.SdkCore:
 		return sdkDep{
 			useModule:        true,
-			bootclasspath:    []string{android.SdkCore.JavaLibraryName(ctx.Config()), android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)},
+			bootclasspath:    []string{android.SdkCore.DefaultJavaLibraryName(), config.DefaultLambdaStubsLibrary},
 			systemModules:    android.JavaApiLibraryName(ctx.Config(), "core-public-stubs-system-modules"),
 			noFrameworksLibs: true,
 		}
 	case android.SdkModule:
 		// TODO(146757305): provide .apk and .aidl that have more APIs for modules
-		return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), nonUpdatableFrameworkAidlPath(ctx))
+		return toModule(sdkVersion.Kind.DefaultJavaLibraryName(), nonUpdatableFrameworkAidlPath(ctx))
 	case android.SdkSystemServer:
 		// TODO(146757305): provide .apk and .aidl that have more APIs for modules
-		return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), sdkFrameworkAidlPath(ctx))
+		return toModule(sdkVersion.Kind.DefaultJavaLibraryName(), sdkFrameworkAidlPath(ctx))
 	default:
 		panic(fmt.Errorf("invalid sdk %q", sdkVersion.Raw))
 	}
@@ -269,9 +269,9 @@
 // Create framework.aidl by extracting anything that implements android.os.Parcelable from the SDK stubs modules.
 func createSdkFrameworkAidl(ctx android.SingletonContext) {
 	stubsModules := []string{
-		android.SdkPublic.JavaLibraryName(ctx.Config()),
-		android.SdkTest.JavaLibraryName(ctx.Config()),
-		android.SdkSystem.JavaLibraryName(ctx.Config()),
+		android.SdkPublic.DefaultJavaLibraryName(),
+		android.SdkTest.DefaultJavaLibraryName(),
+		android.SdkSystem.DefaultJavaLibraryName(),
 	}
 
 	combinedAidl := sdkFrameworkAidlPath(ctx)
@@ -286,7 +286,7 @@
 
 // Creates a version of framework.aidl for the non-updatable part of the platform.
 func createNonUpdatableFrameworkAidl(ctx android.SingletonContext) {
-	stubsModules := []string{android.SdkModule.JavaLibraryName(ctx.Config())}
+	stubsModules := []string{android.SdkModule.DefaultJavaLibraryName()}
 
 	combinedAidl := nonUpdatableFrameworkAidlPath(ctx)
 	tempPath := tempPathForRestat(ctx, combinedAidl)
diff --git a/rust/builder.go b/rust/builder.go
index 0aa2225..0dfaef4 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -261,7 +261,7 @@
 	// Disallow experimental features
 	modulePath := android.PathForModuleSrc(ctx).String()
 	if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) {
-		rustcFlags = append(rustcFlags, "-Zallow-features=\"custom_inner_attributes,mixed_integer_ops\"")
+		rustcFlags = append(rustcFlags, "-Zallow-features=\"\"")
 	}
 
 	// Collect linker flags
diff --git a/rust/config/global.go b/rust/config/global.go
index 748bb3d..60acc6e 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -51,9 +51,6 @@
 		// Use v0 mangling to distinguish from C++ symbols
 		"-C symbol-mangling-version=v0",
 		"--color always",
-		// TODO (b/267698452): Temporary workaround until the "no unstable
-		// features" policy is enforced.
-		"-A stable-features",
 		"-Zdylib-lto",
 	}
 
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index e350323..8893060 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -29,7 +29,7 @@
 # Test Setup
 ############
 
-OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)"
+OUTPUT_DIR="$(mktemp -d $(pwd)/tmp.XXXXXX)"
 SOONG_OUTPUT_DIR="$OUTPUT_DIR/soong"
 BAZEL_OUTPUT_DIR="$OUTPUT_DIR/bazel"
 
@@ -45,6 +45,12 @@
   call_bazel clean
   rm -rf "${OUTPUT_DIR}"
 }
+
+function deapexer() {
+  DEBUGFS_PATH="$(realpath $(call_bazel cquery --config=bp2build --config=linux_x86_64 --config=ci --output=files //external/e2fsprogs/debugfs))"
+  call_bazel run --config=bp2build //system/apex/tools:deapexer -- --debugfs_path=$DEBUGFS_PATH $@
+}
+
 trap cleanup EXIT
 
 ###########
@@ -72,10 +78,7 @@
 BAZEL_MINIMAL="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))"
 
 # # Build debugfs separately, as it's not a dep of apexer, but needs to be an explicit arg.
-call_bazel build --config=bp2build --config=linux_x86_64 //external/e2fsprogs/debugfs //system/apex/tools:deapexer
-DEBUGFS_PATH="$(realpath $(call_bazel cquery --config=bp2build --config=linux_x86_64 --config=ci --output=files //external/e2fsprogs/debugfs))"
-DEAPEXER="bazel-bin/system/apex/tools/deapexer"
-DEAPEXER="$DEAPEXER --debugfs_path=$DEBUGFS_PATH"
+call_bazel build --config=bp2build --config=linux_x86_64 //external/e2fsprogs/debugfs
 
 #######
 # Tests
@@ -91,8 +94,8 @@
   local SOONG_LIST="$OUTPUT_DIR/soong.list"
   local BAZEL_LIST="$OUTPUT_DIR/bazel.list"
 
-  $DEAPEXER list "$SOONG_APEX" > "$SOONG_LIST"
-  $DEAPEXER list "$BAZEL_APEX" > "$BAZEL_LIST"
+  deapexer list "$SOONG_APEX" > "$SOONG_LIST"
+  deapexer list "$BAZEL_APEX" > "$BAZEL_LIST"
 
   if cmp -s "$SOONG_LIST" "$BAZEL_LIST"
   then
diff --git a/tests/dcla_apex_comparison_test.sh b/tests/dcla_apex_comparison_test.sh
index 667dde0..e3c189f 100755
--- a/tests/dcla_apex_comparison_test.sh
+++ b/tests/dcla_apex_comparison_test.sh
@@ -55,6 +55,8 @@
   libc++.so
   libcrypto.so
   libcutils.so
+  libstagefright_flacdec.so
+  libutils.so
 )
 
 if [[ -z ${OUT_DIR+x} ]]; then
diff --git a/tests/genrule_sandbox_test.sh b/tests/genrule_sandbox_test.sh
new file mode 100755
index 0000000..21b476b
--- /dev/null
+++ b/tests/genrule_sandbox_test.sh
@@ -0,0 +1,111 @@
+#!/bin/bash
+
+# Copyright (C) 2023 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.
+
+set -e
+
+# Build the given genrule modules with GENRULE_SANDBOXING enabled and disabled,
+# then compare the output of the modules and report result.
+
+function die() { format=$1; shift; printf >&2 "$format\n" $@; exit 1; }
+
+function usage() {
+  die "usage: ${0##*/} <-t lunch_target> [module]..."
+}
+
+if [ ! -e "build/make/core/Makefile" ]; then
+  die "$0 must be run from the top of the Android source tree."
+fi
+
+declare TARGET=
+while getopts "t:" opt; do
+  case $opt in
+    t)
+      TARGET=$OPTARG ;;
+    *) usage ;;
+  esac
+done
+
+shift $((OPTIND-1))
+MODULES="$@"
+
+source build/envsetup.sh
+
+if [[ -n $TARGET ]]; then
+  lunch $TARGET
+fi
+
+if [[ -z ${OUT_DIR+x} ]]; then
+  OUT_DIR="out"
+fi
+
+OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)"
+PASS=true
+
+function cleanup {
+  if [ $PASS = true ]; then
+    rm -rf "${OUTPUT_DIR}"
+  fi
+}
+trap cleanup EXIT
+
+declare -A GEN_PATH_MAP
+
+function find_gen_paths() {
+  for module in $MODULES; do
+    module_path=$(pathmod "$module")
+    package_path=${module_path#$ANDROID_BUILD_TOP}
+    gen_path=$OUT_DIR/soong/.intermediates$package_path/$module
+    GEN_PATH_MAP[$module]=$gen_path
+  done
+}
+
+function store_outputs() {
+  local dir=$1; shift
+
+  for module in $MODULES; do
+    dest_dir=$dir/${module}
+    mkdir -p $dest_dir
+    gen_path=${GEN_PATH_MAP[$module]}
+    cp -r $gen_path $dest_dir
+  done
+}
+
+function cmp_outputs() {
+  local dir1=$1; shift
+  local dir2=$1; shift
+
+  for module in $MODULES; do
+    if ! diff -rq --exclude=genrule.sbox.textproto $dir1/$module $dir2/$module; then
+      PASS=false
+      echo "$module differ"
+    fi
+  done
+  if [ $PASS = true ]; then
+    echo "Test passed"
+  fi
+}
+
+if [ ! -f "$ANDROID_PRODUCT_OUT/module-info.json" ]; then
+  refreshmod
+fi
+
+find_gen_paths
+m --skip-soong-tests GENRULE_SANDBOXING=true "${MODULES[@]}"
+store_outputs "$OUTPUT_DIR/sandbox"
+m --skip-soong-tests GENRULE_SANDBOXING=false "${MODULES[@]}"
+store_outputs "$OUTPUT_DIR/non_sandbox"
+
+cmp_outputs "$OUTPUT_DIR/non_sandbox" "$OUTPUT_DIR/sandbox"
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 49b09af..3c55c51 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -40,9 +40,9 @@
 }
 
 var autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{
-	Command:     "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g;s&{OUTPUT_FILENAME}&'${outputFileName}'&g;s&{TEST_INSTALL_BASE}&'${testInstallBase}'&g' $template > $out",
+	Command:     "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g;s&{EXTRA_TEST_RUNNER_CONFIGS}&'${extraTestRunnerConfigs}'&g;s&{OUTPUT_FILENAME}&'${outputFileName}'&g;s&{TEST_INSTALL_BASE}&'${testInstallBase}'&g' $template > $out",
 	CommandDeps: []string{"$template"},
-}, "name", "template", "extraConfigs", "outputFileName", "testInstallBase")
+}, "name", "template", "extraConfigs", "outputFileName", "testInstallBase", "extraTestRunnerConfigs")
 
 func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string, autoGenConfig *bool, testConfigTemplateProp *string) (path android.Path, autogenPath android.WritablePath) {
 	p := getTestConfig(ctx, prop)
@@ -107,7 +107,7 @@
 
 }
 
-func autogenTemplate(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, outputFileName string, testInstallBase string) {
+func autogenTemplate(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, testRunnerConfigs []Option, outputFileName string, testInstallBase string) {
 	if template == "" {
 		ctx.ModuleErrorf("Empty template")
 	}
@@ -118,16 +118,27 @@
 	extraConfigs := strings.Join(configStrings, fmt.Sprintf("\\n%s", test_xml_indent))
 	extraConfigs = proptools.NinjaAndShellEscape(extraConfigs)
 
+	var testRunnerConfigStrings []string
+	for _, config := range testRunnerConfigs {
+		testRunnerConfigStrings = append(testRunnerConfigStrings, config.Config())
+	}
+	extraTestRunnerConfigs := strings.Join(testRunnerConfigStrings, fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent))
+	if len(extraTestRunnerConfigs) > 0 {
+		extraTestRunnerConfigs += fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent)
+	}
+	extraTestRunnerConfigs = proptools.NinjaAndShellEscape(extraTestRunnerConfigs)
+
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        autogenTestConfig,
 		Description: "test config",
 		Output:      output,
 		Args: map[string]string{
-			"name":            name,
-			"template":        template,
-			"extraConfigs":    extraConfigs,
-			"outputFileName":  outputFileName,
-			"testInstallBase": testInstallBase,
+			"name":                   name,
+			"template":               template,
+			"extraConfigs":           extraConfigs,
+			"outputFileName":         outputFileName,
+			"testInstallBase":        testInstallBase,
+			"extraTestRunnerConfigs": extraTestRunnerConfigs,
 		},
 	})
 }
@@ -142,6 +153,7 @@
 	TestSuites              []string
 	Config                  []Config
 	OptionsForAutogenerated []Option
+	TestRunnerOptions       []Option
 	AutoGenConfig           *bool
 	UnitTest                *bool
 	TestInstallBase         string
@@ -155,6 +167,7 @@
 	for _, c := range options.OptionsForAutogenerated {
 		configs = append(configs, c)
 	}
+	testRunnerConfigs := append([]Option{}, options.TestRunnerOptions...)
 	name := options.Name
 	if name == "" {
 		name = ctx.ModuleName()
@@ -163,15 +176,15 @@
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, options.TestConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, name, autogenPath, templatePath.String(), configs, options.OutputFileName, options.TestInstallBase)
+			autogenTemplate(ctx, name, autogenPath, templatePath.String(), configs, testRunnerConfigs, options.OutputFileName, options.TestInstallBase)
 		} else {
 			if ctx.Device() {
-				autogenTemplate(ctx, name, autogenPath, options.DeviceTemplate, configs, options.OutputFileName, options.TestInstallBase)
+				autogenTemplate(ctx, name, autogenPath, options.DeviceTemplate, configs, testRunnerConfigs, options.OutputFileName, options.TestInstallBase)
 			} else {
 				if Bool(options.UnitTest) {
-					autogenTemplate(ctx, name, autogenPath, options.HostUnitTestTemplate, configs, options.OutputFileName, options.TestInstallBase)
+					autogenTemplate(ctx, name, autogenPath, options.HostUnitTestTemplate, configs, testRunnerConfigs, options.OutputFileName, options.TestInstallBase)
 				} else {
-					autogenTemplate(ctx, name, autogenPath, options.HostTemplate, configs, options.OutputFileName, options.TestInstallBase)
+					autogenTemplate(ctx, name, autogenPath, options.HostTemplate, configs, testRunnerConfigs, options.OutputFileName, options.TestInstallBase)
 				}
 			}
 		}
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index ee53327..41cb5ab 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -135,6 +135,7 @@
 		productOut("obj/NOTICE_FILES"),
 		productOut("obj/PACKAGING"),
 		productOut("ramdisk"),
+		productOut("ramdisk_16k"),
 		productOut("debug_ramdisk"),
 		productOut("vendor_ramdisk"),
 		productOut("vendor_debug_ramdisk"),
diff --git a/ui/build/config.go b/ui/build/config.go
index 1698e63..bc0ab33 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -17,6 +17,7 @@
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"io/ioutil"
 	"math/rand"
@@ -140,6 +141,9 @@
 	EXTERNAL_FILE
 	// ninja uses a prioritized module list from Soong
 	HINT_FROM_SOONG
+	// If ninja log exists, use NINJA_LOG, if not, use HINT_FROM_SOONG instead.
+	// We can assume it is an incremental build if ninja log exists.
+	DEFAULT
 )
 const srcDirFileCheck = "build/soong/root.bp"
 
@@ -316,8 +320,9 @@
 
 func NewConfig(ctx Context, args ...string) Config {
 	ret := &configImpl{
-		environ:       OsEnvironment(),
-		sandboxConfig: &SandboxConfig{},
+		environ:               OsEnvironment(),
+		sandboxConfig:         &SandboxConfig{},
+		ninjaWeightListSource: DEFAULT,
 	}
 
 	// Default matching ninja
@@ -328,8 +333,21 @@
 	ret.parseArgs(ctx, args)
 
 	if ret.ninjaWeightListSource == HINT_FROM_SOONG {
-		ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "true")
+		ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "always")
+	} else if ret.ninjaWeightListSource == DEFAULT {
+		defaultNinjaWeightListSource := NINJA_LOG
+		if _, err := os.Stat(filepath.Join(ret.OutDir(), ninjaLogFileName)); errors.Is(err, os.ErrNotExist) {
+			ctx.Verboseln("$OUT/.ninja_log doesn't exist, use HINT_FROM_SOONG instead")
+			defaultNinjaWeightListSource = HINT_FROM_SOONG
+		} else {
+			ctx.Verboseln("$OUT/.ninja_log exist, use NINJA_LOG")
+		}
+		ret.ninjaWeightListSource = defaultNinjaWeightListSource
+		// soong_build generates ninja hint depending on ninja log existence.
+		// Set it "depend" to avoid soong re-run due to env variable change.
+		ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "depend")
 	}
+
 	// Make sure OUT_DIR is set appropriately
 	if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
 		ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
@@ -1729,6 +1747,16 @@
 	return c.Environment().IsEnvTrue("USE_PERSISTENT_BAZEL")
 }
 
+// GetBazeliskBazelVersion returns the Bazel version to use for this build,
+// or the empty string if the current canonical prod Bazel should be used.
+// This environment variable should only be set to debug the build system.
+// The Bazel version, if set, will be passed to Bazelisk, and Bazelisk will
+// handle downloading and invoking the correct Bazel binary.
+func (c *configImpl) GetBazeliskBazelVersion() string {
+	value, _ := c.Environment().Get("USE_BAZEL_VERSION")
+	return value
+}
+
 func (c *configImpl) BazelModulesForceEnabledByFlag() string {
 	return c.bazelForceEnabledModules
 }
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 5d56531..61aaad8 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -35,48 +35,6 @@
 	ninjaWeightListFileName = ".ninja_weight_list"
 )
 
-func useNinjaBuildLog(ctx Context, config Config, cmd *Cmd) {
-	ninjaLogFile := filepath.Join(config.OutDir(), ninjaLogFileName)
-	data, err := os.ReadFile(ninjaLogFile)
-	var outputBuilder strings.Builder
-	if err == nil {
-		lines := strings.Split(strings.TrimSpace(string(data)), "\n")
-		// ninja log: <start>	<end>	<restat>	<name>	<cmdhash>
-		// ninja weight list: <name>,<end-start+1>
-		for _, line := range lines {
-			if strings.HasPrefix(line, "#") {
-				continue
-			}
-			fields := strings.Split(line, "\t")
-			path := fields[3]
-			start, err := strconv.Atoi(fields[0])
-			if err != nil {
-				continue
-			}
-			end, err := strconv.Atoi(fields[1])
-			if err != nil {
-				continue
-			}
-			outputBuilder.WriteString(path)
-			outputBuilder.WriteString(",")
-			outputBuilder.WriteString(strconv.Itoa(end-start+1) + "\n")
-		}
-	} else {
-		// If there is no ninja log file, just pass empty ninja weight list.
-		// Because it is still efficient with critical path calculation logic even without weight.
-		ctx.Verbosef("There is an error during reading ninja log, so ninja will use empty weight list: %s", err)
-	}
-
-	weightListFile := filepath.Join(config.OutDir(), ninjaWeightListFileName)
-
-	err = os.WriteFile(weightListFile, []byte(outputBuilder.String()), 0644)
-	if err == nil {
-		cmd.Args = append(cmd.Args, "-o", "usesweightlist="+weightListFile)
-	} else {
-		ctx.Panicf("Could not write ninja weight list file %s", err)
-	}
-}
-
 // Constructs and runs the Ninja command line with a restricted set of
 // environment variables. It's important to restrict the environment Ninja runs
 // for hermeticity reasons, and to avoid spurious rebuilds.
@@ -131,7 +89,7 @@
 
 	switch config.NinjaWeightListSource() {
 	case NINJA_LOG:
-		useNinjaBuildLog(ctx, config, cmd)
+		cmd.Args = append(cmd.Args, "-o", "usesninjalogasweightlist=yes")
 	case EVENLY_DISTRIBUTED:
 		// pass empty weight list means ninja considers every tasks's weight as 1(default value).
 		cmd.Args = append(cmd.Args, "-o", "usesweightlist=/dev/null")
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index b3092ea..b3e871f 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -86,27 +86,29 @@
 // This list specifies whether a particular binary from $PATH is allowed to be
 // run during the build. For more documentation, see path_interposer.go .
 var Configuration = map[string]PathConfig{
-	"bash":    Allowed,
-	"dd":      Allowed,
-	"diff":    Allowed,
-	"dlv":     Allowed,
-	"expr":    Allowed,
-	"fuser":   Allowed,
-	"getopt":  Allowed,
-	"git":     Allowed,
-	"hexdump": Allowed,
-	"jar":     Allowed,
-	"java":    Allowed,
-	"javap":   Allowed,
-	"lsof":    Allowed,
-	"openssl": Allowed,
-	"pstree":  Allowed,
-	"rsync":   Allowed,
-	"sh":      Allowed,
-	"stubby":  Allowed,
-	"tr":      Allowed,
-	"unzip":   Allowed,
-	"zip":     Allowed,
+	"bash":           Allowed,
+	"dd":             Allowed,
+	"diff":           Allowed,
+	"dlv":            Allowed,
+	"expr":           Allowed,
+	"fuser":          Allowed,
+	"gcert":          Allowed,
+	"getopt":         Allowed,
+	"git":            Allowed,
+	"hexdump":        Allowed,
+	"jar":            Allowed,
+	"java":           Allowed,
+	"javap":          Allowed,
+	"lsof":           Allowed,
+	"openssl":        Allowed,
+	"prodcertstatus": Allowed,
+	"pstree":         Allowed,
+	"rsync":          Allowed,
+	"sh":             Allowed,
+	"stubby":         Allowed,
+	"tr":             Allowed,
+	"unzip":          Allowed,
+	"zip":            Allowed,
 
 	// Host toolchain is removed. In-tree toolchain should be used instead.
 	// GCC also can't find cc1 with this implementation.
diff --git a/ui/build/soong.go b/ui/build/soong.go
index e24abdd..b14208e 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -537,7 +537,7 @@
 		defer ctx.EndTrace()
 
 		if config.IsPersistentBazelEnabled() {
-			bazelProxy := bazel.NewProxyServer(ctx.Logger, config.OutDir(), filepath.Join(config.SoongOutDir(), "workspace"))
+			bazelProxy := bazel.NewProxyServer(ctx.Logger, config.OutDir(), filepath.Join(config.SoongOutDir(), "workspace"), config.GetBazeliskBazelVersion())
 			bazelProxy.Start()
 			defer bazelProxy.Close()
 		}
diff --git a/ui/metrics/BUILD.bazel b/ui/metrics/BUILD.bazel
index 2dc1ab6..ca39c59 100644
--- a/ui/metrics/BUILD.bazel
+++ b/ui/metrics/BUILD.bazel
@@ -23,6 +23,7 @@
 proto_library(
     name = "metrics-proto",
     srcs = [
+        "bazel_metrics_proto/bazel_metrics.proto",
         "bp2build_metrics_proto/bp2build_metrics.proto",
         "metrics_proto/metrics.proto",
     ],