Merge changes from topic "revert-2605644-rulebuilder-ninja-vars-OAAWYCDDLT" into main

* changes:
  Revert "add rust_toolchain_rustc_prebuilt module type"
  Revert "add crate_root property to rust modules"
  Revert "allow Ninja variables in RuleBuilder API"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 9916451..849c823 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -178,6 +178,7 @@
 		"external/libjpeg-turbo":                 Bp2BuildDefaultTrueRecursively,
 		"external/libmpeg2":                      Bp2BuildDefaultTrueRecursively,
 		"external/libpng":                        Bp2BuildDefaultTrueRecursively,
+		"external/libphonenumber":                Bp2BuildDefaultTrueRecursively,
 		"external/libvpx":                        Bp2BuildDefaultTrueRecursively,
 		"external/libyuv":                        Bp2BuildDefaultTrueRecursively,
 		"external/lz4/lib":                       Bp2BuildDefaultTrue,
@@ -228,6 +229,7 @@
 		"frameworks/base/services/tests/servicestests/aidl":  Bp2BuildDefaultTrue,
 		"frameworks/base/startop/apps/test":                  Bp2BuildDefaultTrue,
 		"frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
+		"frameworks/base/tools/aapt":                         Bp2BuildDefaultTrue,
 		"frameworks/base/tools/aapt2":                        Bp2BuildDefaultTrue,
 		"frameworks/base/tools/codegen":                      Bp2BuildDefaultTrueRecursively,
 		"frameworks/base/tools/streaming_proto":              Bp2BuildDefaultTrueRecursively,
@@ -284,13 +286,9 @@
 		"hardware/interfaces/health/2.1":                          Bp2BuildDefaultTrue,
 		"hardware/interfaces/health/aidl":                         Bp2BuildDefaultTrue,
 		"hardware/interfaces/health/utils":                        Bp2BuildDefaultTrueRecursively,
-		"hardware/interfaces/media/1.0":                           Bp2BuildDefaultTrue,
-		"hardware/interfaces/media/bufferpool":                    Bp2BuildDefaultTrueRecursively,
+		"hardware/interfaces/media":                               Bp2BuildDefaultTrueRecursively,
 		"hardware/interfaces/media/bufferpool/aidl/default/tests": Bp2BuildDefaultFalseRecursively,
-		"hardware/interfaces/media/c2/1.0":                        Bp2BuildDefaultTrue,
-		"hardware/interfaces/media/c2/1.1":                        Bp2BuildDefaultTrue,
-		"hardware/interfaces/media/c2/1.2":                        Bp2BuildDefaultTrue,
-		"hardware/interfaces/media/omx/1.0":                       Bp2BuildDefaultTrue,
+		"hardware/interfaces/media/omx/1.0/vts":                   Bp2BuildDefaultFalseRecursively,
 		"hardware/interfaces/neuralnetworks":                      Bp2BuildDefaultTrueRecursively,
 		"hardware/interfaces/neuralnetworks/aidl/vts":             Bp2BuildDefaultFalseRecursively,
 		"hardware/interfaces/neuralnetworks/1.0/vts":              Bp2BuildDefaultFalseRecursively,
@@ -413,6 +411,7 @@
 		"system/tools/aidl/build/tests_bp2build":                 Bp2BuildDefaultTrue,
 		"system/tools/aidl/metadata":                             Bp2BuildDefaultTrue,
 		"system/tools/hidl/metadata":                             Bp2BuildDefaultTrue,
+		"system/tools/hidl/utils":                                Bp2BuildDefaultTrue,
 		"system/tools/mkbootimg":                                 Bp2BuildDefaultTrueRecursively,
 		"system/tools/sysprop":                                   Bp2BuildDefaultTrue,
 		"system/tools/xsdc/utils":                                Bp2BuildDefaultTrueRecursively,
@@ -421,7 +420,7 @@
 		"tools/apifinder":                            Bp2BuildDefaultTrue,
 		"tools/apksig":                               Bp2BuildDefaultTrue,
 		"tools/external_updater":                     Bp2BuildDefaultTrueRecursively,
-		"tools/metalava":                             Bp2BuildDefaultTrue,
+		"tools/metalava":                             Bp2BuildDefaultTrueRecursively,
 		"tools/platform-compat/java/android/compat":  Bp2BuildDefaultTrueRecursively,
 		"tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
 	}
@@ -909,6 +908,9 @@
 
 		"merge_annotation_zips_test",
 
+		// bouncycastle dep
+		"platform-test-annotations",
+
 		// java_resources with multiple resource_dirs
 		"emma",
 	}
@@ -1047,6 +1049,7 @@
 		"libgmock_ndk",                                            // depends on unconverted modules: libgtest_ndk_c++
 		"libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libnativetesthelper_jni, libgmock_ndk
 		"libnativetesthelper_jni",   // depends on unconverted modules: libgtest_ndk_c++
+		"libphonenumber_test",       // depends on android.test.mock
 		"libstatslog",               // depends on unconverted modules: libstatspull, statsd-aidl-ndk
 		"libstatslog_art",           // depends on unconverted modules: statslog_art.cpp, statslog_art.h
 		"linker_reloc_bench_main",   // depends on unconverted modules: liblinker_reloc_bench_*
@@ -1632,10 +1635,6 @@
 		// depends on libart-unstripped and new module type llvm_prebuilt_build_tool
 		"check_cfi",
 
-		// TODO(b/297070571): cannot convert prebuilts_etc module which possess identical name and src properties
-		"boringssl_self_test.zygote64.rc",
-		"boringssl_self_test.zygote64_32.rc",
-
 		// depends on unconverted module tradefed
 		"HelloWorldPerformanceTest",
 
@@ -1717,9 +1716,10 @@
 			Label: "//build/bazel/examples/partitions:system_image",
 			Host:  false,
 		},
-		{
-			Label: "//build/bazel/examples/partitions:run_test",
-			Host:  false,
-		},
+		// TODO(b/297269187) re-enable this
+		//{
+		//	Label: "//build/bazel/examples/partitions:run_test",
+		//	Host:  false,
+		//},
 	}
 )
diff --git a/android/apex.go b/android/apex.go
index 6119b08..d84499b 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -934,6 +934,19 @@
 	})
 }
 
+// Construct ApiLevel object from min_sdk_version string value
+func MinSdkVersionFromValue(ctx EarlyModuleContext, value string) ApiLevel {
+	if value == "" {
+		return NoneApiLevel
+	}
+	apiLevel, err := ApiLevelFromUser(ctx, value)
+	if err != nil {
+		ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
+		return NoneApiLevel
+	}
+	return apiLevel
+}
+
 // Implemented by apexBundle.
 type ApexTestInterface interface {
 	// Return true if the apex bundle is an apex_test
diff --git a/android/bazel.go b/android/bazel.go
index 94b36e3..e764b18 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -510,12 +510,6 @@
 	}
 
 	module := p.module
-	// In api_bp2build mode, all soong modules that can provide API contributions should be converted
-	// This is irrespective of its presence/absence in bp2build allowlists
-	if ctx.Config().BuildMode == ApiBp2build {
-		_, providesApis := module.(ApiProvider)
-		return providesApis
-	}
 
 	propValue := b.bazelProperties.Bazel_module.Bp2build_available
 	packagePath := moduleDirWithPossibleOverride(ctx, module, p.moduleDir)
@@ -533,13 +527,13 @@
 	moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[p.moduleType]
 	allowlistConvert := moduleNameAllowed || moduleTypeAllowed
 	if moduleNameAllowed && moduleTypeAllowed {
-		ctx.ModuleErrorf("A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert")
+		ctx.ModuleErrorf("A module %q of type %q cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert", moduleName, p.moduleType)
 		return false
 	}
 
 	if allowlist.moduleDoNotConvert[moduleName] {
 		if moduleNameAllowed {
-			ctx.ModuleErrorf("a module cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert")
+			ctx.ModuleErrorf("a module %q cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert", moduleName)
 		}
 		return false
 	}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 42ba9b4..4b98345 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -1382,10 +1382,7 @@
 			WriteFileRuleVerbatim(ctx, out, "")
 		case "FileWrite", "SourceSymlinkManifest":
 			out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
-			// TODO(b/297366783) This is a hack to make files from skylib's diff_test executable.
-			// We need to update bazel to have aquery tell us whether a file is supposed to be
-			// executable or not.
-			if strings.HasSuffix(buildStatement.OutputPaths[0], "-test.sh") {
+			if buildStatement.IsExecutable {
 				WriteExecutableFileRuleVerbatim(ctx, out, buildStatement.FileContents)
 			} else {
 				WriteFileRuleVerbatim(ctx, out, buildStatement.FileContents)
diff --git a/android/bazel_test.go b/android/bazel_test.go
index 194a6b3..15d3a6b 100644
--- a/android/bazel_test.go
+++ b/android/bazel_test.go
@@ -252,7 +252,7 @@
 		{
 			description:    "module in name allowlist and type allowlist fails",
 			shouldConvert:  false,
-			expectedErrors: []string{"A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert"},
+			expectedErrors: []string{"A module \"foo\" of type \"rule1\" cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert"},
 			module: TestBazelModule{
 				TestModuleInfo: bazel.TestModuleInfo{
 					ModuleName: "foo",
@@ -273,7 +273,7 @@
 		{
 			description:    "module in allowlist and denylist fails",
 			shouldConvert:  false,
-			expectedErrors: []string{"a module cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert"},
+			expectedErrors: []string{"a module \"foo\" cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert"},
 			module: TestBazelModule{
 				TestModuleInfo: bazel.TestModuleInfo{
 					ModuleName: "foo",
diff --git a/android/config.go b/android/config.go
index 0b15c79..645a263 100644
--- a/android/config.go
+++ b/android/config.go
@@ -87,7 +87,6 @@
 	SymlinkForestMarker string
 	Bp2buildMarker      string
 	BazelQueryViewDir   string
-	BazelApiBp2buildDir string
 	ModuleGraphFile     string
 	ModuleActionsFile   string
 	DocFile             string
@@ -121,9 +120,6 @@
 	// express build semantics.
 	GenerateQueryView
 
-	// Generate BUILD files for API contributions to API surfaces
-	ApiBp2build
-
 	// Create a JSON representation of the module graph and exit.
 	GenerateModuleGraph
 
@@ -641,7 +637,6 @@
 	setBuildMode(cmdArgs.SymlinkForestMarker, SymlinkForest)
 	setBuildMode(cmdArgs.Bp2buildMarker, Bp2build)
 	setBuildMode(cmdArgs.BazelQueryViewDir, GenerateQueryView)
-	setBuildMode(cmdArgs.BazelApiBp2buildDir, ApiBp2build)
 	setBuildMode(cmdArgs.ModuleGraphFile, GenerateModuleGraph)
 	setBuildMode(cmdArgs.DocFile, GenerateDocFile)
 	setBazelMode(cmdArgs.BazelMode, "--bazel-mode", BazelProdMode)
@@ -1662,11 +1657,18 @@
 	return HasAnyPrefix(path, c.productVariables.MemtagHeapSyncIncludePaths) && !c.MemtagHeapDisabledForPath(path)
 }
 
+func (c *config) HWASanDisabledForPath(path string) bool {
+	if len(c.productVariables.HWASanExcludePaths) == 0 {
+		return false
+	}
+	return HasAnyPrefix(path, c.productVariables.HWASanExcludePaths)
+}
+
 func (c *config) HWASanEnabledForPath(path string) bool {
 	if len(c.productVariables.HWASanIncludePaths) == 0 {
 		return false
 	}
-	return HasAnyPrefix(path, c.productVariables.HWASanIncludePaths)
+	return HasAnyPrefix(path, c.productVariables.HWASanIncludePaths) && !c.HWASanDisabledForPath(path)
 }
 
 func (c *config) VendorConfig(name string) VendorConfig {
@@ -1792,30 +1794,6 @@
 	return c.PlatformSepolicyVersion()
 }
 
-func (c *deviceConfig) BoardPlatVendorPolicy() []string {
-	return c.config.productVariables.BoardPlatVendorPolicy
-}
-
-func (c *deviceConfig) BoardReqdMaskPolicy() []string {
-	return c.config.productVariables.BoardReqdMaskPolicy
-}
-
-func (c *deviceConfig) BoardSystemExtPublicPrebuiltDirs() []string {
-	return c.config.productVariables.BoardSystemExtPublicPrebuiltDirs
-}
-
-func (c *deviceConfig) BoardSystemExtPrivatePrebuiltDirs() []string {
-	return c.config.productVariables.BoardSystemExtPrivatePrebuiltDirs
-}
-
-func (c *deviceConfig) BoardProductPublicPrebuiltDirs() []string {
-	return c.config.productVariables.BoardProductPublicPrebuiltDirs
-}
-
-func (c *deviceConfig) BoardProductPrivatePrebuiltDirs() []string {
-	return c.config.productVariables.BoardProductPrivatePrebuiltDirs
-}
-
 func (c *deviceConfig) SystemExtSepolicyPrebuiltApiDir() string {
 	return String(c.config.productVariables.SystemExtSepolicyPrebuiltApiDir)
 }
diff --git a/android/defs.go b/android/defs.go
index 682111e..b28d2fa 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -107,8 +107,8 @@
 
 	Cat = pctx.AndroidStaticRule("Cat",
 		blueprint.RuleParams{
-			Command:     "cat $in > $out",
-			Description: "concatenate licenses $out",
+			Command:     "rm -f $out && cat $in > $out",
+			Description: "concatenate files to $out",
 		})
 
 	// ubuntu 14.04 offcially use dash for /bin/sh, and its builtin echo command
@@ -116,7 +116,7 @@
 	// content to file.
 	writeFile = pctx.AndroidStaticRule("writeFile",
 		blueprint.RuleParams{
-			Command:     `/bin/bash -c 'echo -e -n "$$0" > $out' $content`,
+			Command:     `rm -f $out && /bin/bash -c 'echo -e -n "$$0" > $out' $content`,
 			Description: "writing file $out",
 		},
 		"content")
diff --git a/android/module.go b/android/module.go
index 19502ba..516810f 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1371,7 +1371,7 @@
 		for _, axis := range enabledPropertyOverrides.SortedConfigurationAxes() {
 			configToBools := enabledPropertyOverrides.ConfigurableValues[axis]
 			for cfg, val := range configToBools {
-				if axis != bazel.OsConfigurationAxis || osSupport[cfg] {
+				if axis != bazel.OsConfigurationAxis || osSupport[cfg] || val /*If enabled is explicitly requested via overrides */ {
 					enabledProperty.SetSelectValue(axis, cfg, &val)
 				}
 			}
@@ -1418,10 +1418,42 @@
 	moduleEnableConstraints := bazel.LabelListAttribute{}
 	moduleEnableConstraints.Append(platformEnabledAttribute)
 	moduleEnableConstraints.Append(productConfigEnabledAttribute)
+	addCompatibilityConstraintForCompileMultilib(ctx, &moduleEnableConstraints)
 
 	return constraintAttributes{Target_compatible_with: moduleEnableConstraints}
 }
 
+var (
+	incompatible = bazel.LabelList{[]bazel.Label{{Label: "@platforms//:incompatible"}}, nil}
+)
+
+// If compile_mulitilib is set to
+// 1. 32: Add an incompatibility constraint for non-32 arches
+// 1. 64: Add an incompatibility constraint for non-64 arches
+func addCompatibilityConstraintForCompileMultilib(ctx *topDownMutatorContext, enabled *bazel.LabelListAttribute) {
+	mod := ctx.Module().base()
+	multilib, _ := decodeMultilib(mod, mod.commonProperties.CompileOS, ctx.Config().IgnorePrefer32OnDevice())
+
+	switch multilib {
+	case "32":
+		// Add an incompatibility constraint for all known 64-bit arches
+		enabled.SetSelectValue(bazel.ArchConfigurationAxis, "arm64", incompatible)
+		enabled.SetSelectValue(bazel.ArchConfigurationAxis, "x86_64", incompatible)
+		enabled.SetSelectValue(bazel.ArchConfigurationAxis, "riscv64", incompatible)
+	case "64":
+		// Add an incompatibility constraint for all known 32-bit arches
+		enabled.SetSelectValue(bazel.ArchConfigurationAxis, "arm", incompatible)
+		enabled.SetSelectValue(bazel.ArchConfigurationAxis, "x86", incompatible)
+	case "both":
+		// Do nothing: "both" is trivially compatible with 32-bit and 64-bit
+		// The top level rule (e.g. apex/partition) will be responsible for building this module in both variants via an
+		// outgoing_transition.
+	default: // e.g. first, common
+		// TODO - b/299135307: Add bp2build support for these properties.
+	}
+
+}
+
 // Check product variables for `enabled: true` flag override.
 // Returns a list of the constraint_value targets who enable this override.
 func productVariableConfigEnableAttribute(ctx *topDownMutatorContext) bazel.LabelListAttribute {
diff --git a/android/proto.go b/android/proto.go
index 3c4b4c7..fc21d01 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -350,13 +350,12 @@
 var (
 	protoIncludeDirGeneratedSuffix = ".include_dir_bp2build_generated_proto"
 	protoIncludeDirsBp2buildKey    = NewOnceKey("protoIncludeDirsBp2build")
-	protoIncludeDirsBp2buildLock   sync.Mutex
 )
 
-func getProtoIncludeDirsBp2build(config Config) *map[protoIncludeDirKey]bool {
+func getProtoIncludeDirsBp2build(config Config) *sync.Map {
 	return config.Once(protoIncludeDirsBp2buildKey, func() interface{} {
-		return &map[protoIncludeDirKey]bool{}
-	}).(*map[protoIncludeDirKey]bool)
+		return &sync.Map{}
+	}).(*sync.Map)
 }
 
 // key for dynamically creating proto_library per proto.include_dirs
@@ -370,9 +369,6 @@
 // might create the targets in a subdirectory of `includeDir`
 // Returns the labels of the proto_library targets
 func createProtoLibraryTargetsForIncludeDirs(ctx Bp2buildMutatorContext, includeDirs []string) bazel.LabelList {
-	protoIncludeDirsBp2buildLock.Lock()
-	defer protoIncludeDirsBp2buildLock.Unlock()
-
 	var ret bazel.LabelList
 	for _, dir := range includeDirs {
 		if exists, _, _ := ctx.Config().fs.Exists(filepath.Join(dir, "Android.bp")); !exists {
@@ -389,11 +385,10 @@
 				Label: "//" + pkg + ":" + label,
 			})
 			key := protoIncludeDirKey{dir: dir, subpackgeInDir: pkg}
-			if _, exists := (*dirMap)[key]; exists {
+			if _, exists := dirMap.LoadOrStore(key, true); exists {
 				// A proto_library has already been created for this package relative to this include dir
 				continue
 			}
-			(*dirMap)[key] = true
 			srcs := protoLabelelsPartitionedByPkg[pkg]
 			rel, err := filepath.Rel(dir, pkg)
 			if err != nil {
@@ -413,6 +408,11 @@
 			// As a workarounds, delete `target_compatible_with`
 			alwaysEnabled := bazel.BoolAttribute{}
 			alwaysEnabled.Value = proptools.BoolPtr(true)
+			// Add android and linux explicitly so that fillcommonbp2buildmoduleattrs can override these configs
+			// When we extend b support for other os'es (darwin/windows), we should add those configs here as well
+			alwaysEnabled.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid, proptools.BoolPtr(true))
+			alwaysEnabled.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsLinux, proptools.BoolPtr(true))
+
 			ctx.CreateBazelTargetModuleWithRestrictions(
 				bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
 				CommonAttributes{
diff --git a/android/register.go b/android/register.go
index 64b0207..df97c75 100644
--- a/android/register.go
+++ b/android/register.go
@@ -197,13 +197,6 @@
 	RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators)
 }
 
-// RegisterForApiBazelConversion is similar to RegisterForBazelConversion except that
-// it only generates API targets in the generated  workspace
-func (ctx *Context) RegisterForApiBazelConversion() {
-	registerModuleTypes(ctx)
-	RegisterMutatorsForApiBazelConversion(ctx, bp2buildPreArchMutators)
-}
-
 // Register the pipeline of singletons, module types, and mutators for
 // generating build.ninja and other files for Kati, from Android.bp files.
 func (ctx *Context) Register() {
diff --git a/android/testing.go b/android/testing.go
index 5ad7ad0..32357db 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -467,12 +467,6 @@
 	RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch)
 }
 
-// RegisterForApiBazelConversion prepares a test context for API bp2build conversion.
-func (ctx *TestContext) RegisterForApiBazelConversion() {
-	ctx.config.BuildMode = ApiBp2build
-	RegisterMutatorsForApiBazelConversion(ctx.Context, ctx.bp2buildPreArch)
-}
-
 func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
 	// This function adapts the old style ParseFileList calls that are spread throughout the tests
 	// to the new style that takes a config.
diff --git a/android/variable.go b/android/variable.go
index 8805fe5..02eff25 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -315,6 +315,7 @@
 	MemtagHeapSyncIncludePaths  []string `json:",omitempty"`
 
 	HWASanIncludePaths []string `json:",omitempty"`
+	HWASanExcludePaths []string `json:",omitempty"`
 
 	VendorPath    *string `json:",omitempty"`
 	OdmPath       *string `json:",omitempty"`
@@ -372,17 +373,11 @@
 
 	MultitreeUpdateMeta bool `json:",omitempty"`
 
-	BoardVendorSepolicyDirs           []string `json:",omitempty"`
-	BoardOdmSepolicyDirs              []string `json:",omitempty"`
-	BoardReqdMaskPolicy               []string `json:",omitempty"`
-	BoardPlatVendorPolicy             []string `json:",omitempty"`
-	BoardSystemExtPublicPrebuiltDirs  []string `json:",omitempty"`
-	BoardSystemExtPrivatePrebuiltDirs []string `json:",omitempty"`
-	BoardProductPublicPrebuiltDirs    []string `json:",omitempty"`
-	BoardProductPrivatePrebuiltDirs   []string `json:",omitempty"`
-	SystemExtPublicSepolicyDirs       []string `json:",omitempty"`
-	SystemExtPrivateSepolicyDirs      []string `json:",omitempty"`
-	BoardSepolicyM4Defs               []string `json:",omitempty"`
+	BoardVendorSepolicyDirs      []string `json:",omitempty"`
+	BoardOdmSepolicyDirs         []string `json:",omitempty"`
+	SystemExtPublicSepolicyDirs  []string `json:",omitempty"`
+	SystemExtPrivateSepolicyDirs []string `json:",omitempty"`
+	BoardSepolicyM4Defs          []string `json:",omitempty"`
 
 	BoardSepolicyVers       *string `json:",omitempty"`
 	PlatformSepolicyVersion *string `json:",omitempty"`
diff --git a/apex/apex.go b/apex/apex.go
index 52a5e20..a116b85 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -18,6 +18,7 @@
 
 import (
 	"fmt"
+	"log"
 	"path/filepath"
 	"regexp"
 	"sort"
@@ -991,6 +992,13 @@
 				return false
 			}
 		}
+
+		//TODO: b/296491928 Vendor APEX should use libbinder.ndk instead of libbinder once VNDK is fully deprecated.
+		if useVndk && mctx.Config().IsVndkDeprecated() && child.Name() == "libbinder" {
+			log.Print("Libbinder is linked from Vendor APEX ", a.Name(), " with module ", parent.Name())
+			return false
+		}
+
 		// By default, all the transitive dependencies are collected, unless filtered out
 		// above.
 		return true
@@ -2008,6 +2016,9 @@
 			// If a module is directly included and also transitively depended on
 			// consider it as directly included.
 			e.transitiveDep = e.transitiveDep && f.transitiveDep
+			// If a module is added as both a JNI library and a regular shared library, consider it as a
+			// JNI library.
+			e.isJniLib = e.isJniLib || f.isJniLib
 			encountered[dest] = e
 		}
 	}
@@ -2222,6 +2233,11 @@
 				vctx.requireNativeLibs = append(vctx.requireNativeLibs, ":vndk")
 				return false
 			}
+
+			//TODO: b/296491928 Vendor APEX should use libbinder.ndk instead of libbinder once VNDK is fully deprecated.
+			if ch.UseVndk() && ctx.Config().IsVndkDeprecated() && child.Name() == "libbinder" {
+				return false
+			}
 			af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
 			af.transitiveDep = true
 
@@ -2727,13 +2743,13 @@
 	// Only override the minSdkVersion value on Apexes which already specify
 	// a min_sdk_version (it's optional for non-updatable apexes), and that its
 	// min_sdk_version value is lower than the one to override with.
-	minApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version))
+	minApiLevel := android.MinSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version))
 	if minApiLevel.IsNone() {
 		return ""
 	}
 
 	overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride()
-	overrideApiLevel := minSdkVersionFromValue(ctx, overrideMinSdkValue)
+	overrideApiLevel := android.MinSdkVersionFromValue(ctx, overrideMinSdkValue)
 	if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(minApiLevel) > 0 {
 		minApiLevel = overrideApiLevel
 	}
@@ -2748,20 +2764,7 @@
 
 // Returns apex's min_sdk_version ApiLevel, honoring overrides
 func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
-	return minSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
-}
-
-// Construct ApiLevel object from min_sdk_version string value
-func minSdkVersionFromValue(ctx android.EarlyModuleContext, value string) android.ApiLevel {
-	if value == "" {
-		return android.NoneApiLevel
-	}
-	apiLevel, err := android.ApiLevelFromUser(ctx, value)
-	if err != nil {
-		ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
-		return android.NoneApiLevel
-	}
-	return apiLevel
+	return android.MinSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
 }
 
 // Ensures that a lib providing stub isn't statically linked
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1717f3e..9475f5d 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7977,7 +7977,8 @@
 		apex {
 			name: "myapex",
 			key: "myapex.key",
-			jni_libs: ["mylib", "libfoo.rust"],
+			binaries: ["mybin"],
+			jni_libs: ["mylib", "mylib3", "libfoo.rust"],
 			updatable: false,
 		}
 
@@ -8004,6 +8005,24 @@
 			apex_available: [ "myapex" ],
 		}
 
+		// Used as both a JNI library and a regular shared library.
+		cc_library {
+			name: "mylib3",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			apex_available: [ "myapex" ],
+		}
+
+		cc_binary {
+			name: "mybin",
+			srcs: ["mybin.cpp"],
+			shared_libs: ["mylib3"],
+			system_shared_libs: [],
+			stl: "none",
+			apex_available: [ "myapex" ],
+		}
+
 		rust_ffi_shared {
 			name: "libfoo.rust",
 			crate_name: "foo",
@@ -8027,10 +8046,12 @@
 
 	rule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
 	// Notice mylib2.so (transitive dep) is not added as a jni_lib
-	ensureEquals(t, rule.Args["opt"], "-a jniLibs libfoo.rust.so mylib.so")
+	ensureEquals(t, rule.Args["opt"], "-a jniLibs libfoo.rust.so mylib.so mylib3.so")
 	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
+		"bin/mybin",
 		"lib64/mylib.so",
 		"lib64/mylib2.so",
+		"lib64/mylib3.so",
 		"lib64/libfoo.rust.so",
 		"lib64/libc++.so", // auto-added to libfoo.rust by Soong
 		"lib64/liblog.so", // auto-added to libfoo.rust by Soong
diff --git a/bazel/aquery.go b/bazel/aquery.go
index d77d59a..c355712 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -123,6 +123,7 @@
 	// Unlike most properties in BuildStatement, these paths must be relative to the root of
 	// the whole out/ folder, instead of relative to ctx.Config().BazelContext.OutputBase()
 	ImplicitDeps []string
+	IsExecutable bool
 }
 
 // A helper type for aquery processing which facilitates retrieval of path IDs from their
@@ -176,6 +177,21 @@
 		if err != nil {
 			return nil, err
 		}
+		if artifact.IsTreeArtifact &&
+			!strings.HasPrefix(artifactPath, "bazel-out/io_bazel_rules_go/") &&
+			!strings.HasPrefix(artifactPath, "bazel-out/rules_java_builtin/") {
+			// Since we're using ninja as an executor, we can't use tree artifacts. Ninja only
+			// considers a file/directory "dirty" when it's mtime changes. Directories' mtimes will
+			// only change when a file in the directory is added/removed, but not when files in
+			// the directory are changed, or when files in subdirectories are changed/added/removed.
+			// Bazel handles this by walking the directory and generating a hash for it after the
+			// action runs, which we would have to do as well if we wanted to support these
+			// artifacts in mixed builds.
+			//
+			// However, there are some bazel built-in rules that use tree artifacts. Allow those,
+			// but keep in mind that they'll have incrementality issues.
+			return nil, fmt.Errorf("tree artifacts are currently not supported in mixed builds: " + artifactPath)
+		}
 		artifactIdToPath[artifactId(artifact.Id)] = artifactPath
 	}
 
@@ -560,6 +576,7 @@
 		Mnemonic:          actionEntry.Mnemonic,
 		InputDepsetHashes: depsetHashes,
 		FileContents:      actionEntry.FileContents,
+		IsExecutable:      actionEntry.IsExecutable,
 	}, nil
 }
 
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index c104833..b675e5e 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -32,6 +32,7 @@
         "soong-genrule",
         "soong-linkerconfig",
         "soong-python",
+        "soong-rust",
         "soong-sh",
         "soong-shared",
         "soong-starlark-format",
@@ -61,7 +62,6 @@
         "cc_test_conversion_test.go",
         "cc_yasm_conversion_test.go",
         "conversion_test.go",
-        "droidstubs_conversion_test.go",
         "filegroup_conversion_test.go",
         "genrule_conversion_test.go",
         "gensrcs_conversion_test.go",
@@ -82,6 +82,10 @@
         "python_binary_conversion_test.go",
         "python_library_conversion_test.go",
         "python_test_conversion_test.go",
+        "rust_binary_conversion_test.go",
+        "rust_library_conversion_test.go",
+        "rust_proc_macro_conversion_test.go",
+        "rust_protobuf_conversion_test.go",
         "sh_conversion_test.go",
         "sh_test_conversion_test.go",
         "soong_config_module_type_conversion_test.go",
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index 25494a1..f2ee322 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -47,6 +47,11 @@
 		name: "TestApp",
 		srcs: ["app.java"],
 		sdk_version: "current",
+		optimize: {
+			shrink: true,
+			optimize: true,
+			obfuscate: true,
+		},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -75,17 +80,25 @@
 		},
 		Blueprint: simpleModuleDoNotConvertBp2build("android_app", "static_lib_dep") + `
 android_app {
-		name: "TestApp",
-		srcs: ["app.java"],
-		sdk_version: "current",
-		package_name: "com.google",
-		resource_dirs: ["resa", "resb"],
-		manifest: "manifest/AndroidManifest.xml",
-		static_libs: ["static_lib_dep"],
-		java_version: "7",
-		certificate: "foocert",
-		required: ["static_lib_dep"],
-		asset_dirs: ["assets_"],
+	name: "TestApp",
+	srcs: ["app.java"],
+	sdk_version: "current",
+	package_name: "com.google",
+	resource_dirs: ["resa", "resb"],
+	manifest: "manifest/AndroidManifest.xml",
+	static_libs: ["static_lib_dep"],
+	java_version: "7",
+	certificate: "foocert",
+	required: ["static_lib_dep"],
+	asset_dirs: ["assets_"],
+	optimize: {
+		enabled: true,
+		optimize: false,
+		proguard_flags_files: ["proguard.flags"],
+		shrink: false,
+		obfuscate: false,
+		ignore_warnings: true,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -103,6 +116,14 @@
 				"java_version":     `"7"`,
 				"sdk_version":      `"current"`,
 				"certificate_name": `"foocert"`,
+				"proguard_specs": `[
+        "proguard.flags",
+        ":TestApp_proguard_flags",
+    ]`,
+			}),
+			MakeBazelTarget("genrule", "TestApp_proguard_flags", AttrNameToString{
+				"outs": `["TestApp_proguard.flags"]`,
+				"cmd":  `"echo -ignorewarning -dontshrink -dontoptimize -dontobfuscate > $(OUTS)"`,
 			}),
 		}})
 }
@@ -129,7 +150,10 @@
 		x86: {
 			srcs: ["x86.java"],
 		}
-	}
+	},
+	optimize: {
+		enabled: false,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -142,6 +166,7 @@
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `["res/res.png"]`,
 				"sdk_version":    `"current"`,
+				"optimize":       `False`,
 			}),
 		}})
 }
@@ -157,6 +182,9 @@
 	name: "TestApp",
 	certificate: ":foocert",
 	sdk_version: "current",
+	optimize: {
+		enabled: false,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -165,6 +193,7 @@
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `[]`,
 				"sdk_version":    `"current"`, // use as default
+				"optimize":       `False`,
 			}),
 		}})
 }
@@ -182,6 +211,9 @@
 	name: "TestApp",
 	certificate: "foocert",
 	sdk_version: "current",
+	optimize: {
+		enabled: false,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -190,6 +222,7 @@
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `[]`,
 				"sdk_version":    `"current"`, // use as default
+				"optimize":       `False`,
 			}),
 		}})
 }
@@ -207,6 +240,9 @@
 	name: "TestApp",
 	certificate: "foocert",
 	sdk_version: "current",
+	optimize: {
+		enabled: false,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -215,6 +251,7 @@
 				"manifest":         `"AndroidManifest.xml"`,
 				"resource_files":   `[]`,
 				"sdk_version":      `"current"`, // use as default
+				"optimize":         `False`,
 			}),
 		}})
 }
@@ -225,12 +262,14 @@
 		ModuleTypeUnderTest:        "android_app",
 		ModuleTypeUnderTestFactory: java.AndroidAppFactory,
 		Filesystem:                 map[string]string{},
-		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") +
-			simpleModuleDoNotConvertBp2build("java_library", "barLib") + `
+		Blueprint: simpleModuleDoNotConvertBp2build("java_library", "barLib") + `
 android_app {
 	name: "foo",
 	libs: ["barLib"],
 	sdk_version: "current",
+	optimize: {
+		enabled: false,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -239,6 +278,7 @@
 				"resource_files": `[]`,
 				"deps":           `[":barLib-neverlink"]`,
 				"sdk_version":    `"current"`, // use as default
+				"optimize":       `False`,
 			}),
 		}})
 }
@@ -260,6 +300,9 @@
 	manifest: "fooManifest.xml",
 	libs: ["barLib"],
 	sdk_version: "current",
+	optimize: {
+		enabled: false,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -278,6 +321,7 @@
 				"certificate": `":foocert"`,
 				"manifest":    `"fooManifest.xml"`,
 				"sdk_version": `"current"`, // use as default
+				"optimize":    `False`,
 			}),
 		}})
 }
@@ -290,15 +334,17 @@
 		Filesystem: map[string]string{
 			"res/res.png": "",
 		},
-		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+		Blueprint: `
 android_app {
 	name: "foo",
 	srcs: ["a.java"],
 	common_srcs: ["b.kt"],
-	certificate: "foocert",
 	manifest: "fooManifest.xml",
 	libs:        ["barLib"],
 	sdk_version: "current",
+	optimize: {
+		enabled: false,
+	},
 }
 java_library{
 	name:   "barLib",
@@ -315,10 +361,10 @@
 				"sdk_version":    `"current"`, // use as default
 			}),
 			MakeBazelTarget("android_binary", "foo", AttrNameToString{
-				"deps":             `[":foo_kt"]`,
-				"certificate_name": `"foocert"`,
-				"manifest":         `"fooManifest.xml"`,
-				"sdk_version":      `"current"`, // use as default
+				"deps":        `[":foo_kt"]`,
+				"manifest":    `"fooManifest.xml"`,
+				"sdk_version": `"current"`, // use as default
+				"optimize":    `False`,
 			}),
 		}})
 }
@@ -331,14 +377,16 @@
 		Filesystem: map[string]string{
 			"res/res.png": "",
 		},
-		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+		Blueprint: `
 android_app {
 	name: "foo",
 	srcs: ["a.java", "b.kt"],
-	certificate: ":foocert",
 	manifest: "fooManifest.xml",
 	kotlincflags: ["-flag1", "-flag2"],
 	sdk_version: "current",
+	optimize: {
+		enabled: false,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -357,9 +405,9 @@
 			}),
 			MakeBazelTarget("android_binary", "foo", AttrNameToString{
 				"deps":        `[":foo_kt"]`,
-				"certificate": `":foocert"`,
 				"manifest":    `"fooManifest.xml"`,
 				"sdk_version": `"current"`,
+				"optimize":    `False`,
 			}),
 		}})
 }
@@ -370,13 +418,16 @@
 		ModuleTypeUnderTest:        "android_app",
 		ModuleTypeUnderTestFactory: java.AndroidAppFactory,
 		Filesystem:                 map[string]string{},
-		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+		Blueprint: `
 android_app {
 	name: "foo",
 	sdk_version: "current",
 	min_sdk_version: "24",
 	max_sdk_version: "30",
 	target_sdk_version: "29",
+	optimize: {
+		enabled: false,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -389,6 +440,7 @@
         "targetSdkVersion": "29",
     }`,
 				"sdk_version": `"current"`,
+				"optimize":    `False`,
 			}),
 		}})
 }
@@ -399,10 +451,13 @@
 		ModuleTypeUnderTest:        "android_app",
 		ModuleTypeUnderTestFactory: java.AndroidAppFactory,
 		Filesystem:                 map[string]string{},
-		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+		Blueprint: `
 android_app {
 	name: "foo",
 	sdk_version: "30",
+	optimize: {
+		enabled: false,
+	},
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -414,6 +469,7 @@
         "targetSdkVersion": "30",
     }`,
 				"sdk_version": `"30"`,
+				"optimize":    `False`,
 			}),
 		}})
 }
diff --git a/bp2build/api_domain_conversion_test.go b/bp2build/api_domain_conversion_test.go
deleted file mode 100644
index 224008f..0000000
--- a/bp2build/api_domain_conversion_test.go
+++ /dev/null
@@ -1,68 +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/android"
-	"android/soong/cc"
-)
-
-func registerApiDomainModuleTypes(ctx android.RegistrationContext) {
-	android.RegisterApiDomainBuildComponents(ctx)
-	cc.RegisterNdkModuleTypes(ctx)
-	cc.RegisterLibraryBuildComponents(ctx)
-}
-
-func TestApiDomainContributionsTest(t *testing.T) {
-	bp := `
-	api_domain {
-		name: "system",
-		cc_api_contributions: [
-			"libfoo.ndk",
-			"libbar",
-		],
-	}
-	`
-	fs := map[string]string{
-		"libfoo/Android.bp": `
-		ndk_library {
-			name: "libfoo",
-		}
-		`,
-		"libbar/Android.bp": `
-		cc_library {
-			name: "libbar",
-		}
-		`,
-	}
-	expectedBazelTarget := MakeBazelTargetNoRestrictions(
-		"api_domain",
-		"system",
-		AttrNameToString{
-			"cc_api_contributions": `[
-        "//libfoo:libfoo.ndk.contribution",
-        "//libbar:libbar.contribution",
-    ]`,
-			"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
-		},
-	)
-	RunApiBp2BuildTestCase(t, registerApiDomainModuleTypes, Bp2buildTestCase{
-		Blueprint:            bp,
-		ExpectedBazelTargets: []string{expectedBazelTarget},
-		Filesystem:           fs,
-	})
-}
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index e8c2ef7..0214941 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -1,9 +1,6 @@
 package bp2build
 
 import (
-	"android/soong/android"
-	"android/soong/android/soongconfig"
-	"android/soong/starlark_import"
 	"encoding/json"
 	"fmt"
 	"os"
@@ -11,6 +8,11 @@
 	"reflect"
 	"strings"
 
+	"android/soong/android"
+	"android/soong/android/soongconfig"
+	"android/soong/starlark_import"
+
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 	"go.starlark.net/starlark"
 )
@@ -44,6 +46,15 @@
 		return nil, nil, err
 	}
 
+	// Visit all modules to determine the list of ndk libraries
+	// This list will be used to add additional flags for cc stub generation
+	ndkLibsStringFormatted := []string{}
+	ctx.Context().VisitAllModules(func(m blueprint.Module) {
+		if ctx.Context().ModuleType(m) == "ndk_library" {
+			ndkLibsStringFormatted = append(ndkLibsStringFormatted, fmt.Sprintf(`"%s"`, m.Name())) // name will be `"libc.ndk"`
+		}
+	})
+
 	// TODO(b/249685973): the name is product_config_platforms because product_config
 	// was already used for other files. Deduplicate them.
 	currentProductFolder := fmt.Sprintf("product_config_platforms/products/%s-%s", targetProduct, targetBuildVariant)
@@ -153,6 +164,11 @@
 			productReplacer.Replace(`
 build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64
 `)),
+		newFile(
+			"cc_toolchain",
+			"ndk_libs.bzl",
+			fmt.Sprintf("ndk_libs = [%v]", strings.Join(ndkLibsStringFormatted, ", ")),
+		),
 	}
 	bp2buildDirFiles := []BazelFile{
 		newFile(
@@ -258,12 +274,16 @@
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:device_name=%s\n", proptools.String(productVariables.DeviceName)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:device_page_size_agnostic=%t\n", proptools.Bool(productVariables.DevicePageSizeAgnostic)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:device_product=%s\n", proptools.String(productVariables.DeviceProduct)))
+		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:device_platform=%s\n", label))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:enable_cfi=%t\n", proptools.BoolDefault(productVariables.EnableCFI, true)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:enforce_vintf_manifest=%t\n", proptools.Bool(productVariables.Enforce_vintf_manifest)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:eng=%t\n", proptools.Bool(productVariables.Eng)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:malloc_not_svelte=%t\n", proptools.Bool(productVariables.Malloc_not_svelte)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:malloc_pattern_fill_contents=%t\n", proptools.Bool(productVariables.Malloc_pattern_fill_contents)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:malloc_zero_contents=%t\n", proptools.Bool(productVariables.Malloc_zero_contents)))
+		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:memtag_heap_exclude_paths=%s\n", strings.Join(productVariables.MemtagHeapExcludePaths, ",")))
+		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:memtag_heap_async_include_paths=%s\n", strings.Join(productVariables.MemtagHeapAsyncIncludePaths, ",")))
+		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:memtag_heap_sync_include_paths=%s\n", strings.Join(productVariables.MemtagHeapSyncIncludePaths, ",")))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:manifest_package_name_overrides=%s\n", strings.Join(productVariables.ManifestPackageNameOverrides, ",")))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:native_coverage=%t\n", proptools.Bool(productVariables.Native_coverage)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:platform_version_name=%s\n", proptools.String(productVariables.Platform_version_name)))
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index cd1bc7f..9060363 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -175,9 +175,6 @@
 	// This mode is used for discovering and introspecting the existing Soong
 	// module graph.
 	QueryView
-
-	// ApiBp2build - generate BUILD files for API contribution targets
-	ApiBp2build
 )
 
 type unconvertedDepsMode int
@@ -196,8 +193,6 @@
 		return "Bp2Build"
 	case QueryView:
 		return "QueryView"
-	case ApiBp2build:
-		return "ApiBp2build"
 	default:
 		return fmt.Sprintf("%d", mode)
 	}
@@ -774,10 +769,6 @@
 				errs = append(errs, err)
 			}
 			targets = append(targets, t)
-		case ApiBp2build:
-			if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
-				targets, errs = generateBazelTargets(bpCtx, aModule)
-			}
 		default:
 			errs = append(errs, fmt.Errorf("Unknown code-generation mode: %s", ctx.Mode()))
 			return
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 8ee0439..3887c5d 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -1879,30 +1879,6 @@
 		})
 }
 
-func TestGenerateApiBazelTargets(t *testing.T) {
-	bp := `
-	custom {
-		name: "foo",
-		api: "foo.txt",
-	}
-	`
-	expectedBazelTarget := MakeBazelTarget(
-		"custom_api_contribution",
-		"foo",
-		AttrNameToString{
-			"api": `"foo.txt"`,
-		},
-	)
-	registerCustomModule := func(ctx android.RegistrationContext) {
-		ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
-	}
-	RunApiBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
-		Blueprint:            bp,
-		ExpectedBazelTargets: []string{expectedBazelTarget},
-		Description:          "Generating API contribution Bazel targets for custom module",
-	})
-}
-
 func TestGenerateConfigSetting(t *testing.T) {
 	bp := `
 	custom {
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 02ed57a..9bb1713 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -2839,205 +2839,6 @@
 	)
 }
 
-func TestCcApiContributionsWithHdrs(t *testing.T) {
-	bp := `
-	cc_library {
-		name: "libfoo",
-		stubs: { symbol_file: "libfoo.map.txt", versions: ["28", "29", "current"] },
-		llndk: { symbol_file: "libfoo.map.txt", override_export_include_dirs: ["dir2"]},
-		export_include_dirs: ["dir1"],
-	}
-	`
-	expectedBazelTargets := []string{
-		MakeBazelTarget(
-			"cc_api_library_headers",
-			"libfoo.module-libapi.headers",
-			AttrNameToString{
-				"export_includes": `["dir1"]`,
-			}),
-		MakeBazelTarget(
-			"cc_api_library_headers",
-			"libfoo.vendorapi.headers",
-			AttrNameToString{
-				"export_includes": `["dir2"]`,
-			}),
-		MakeBazelTarget(
-			"cc_api_contribution",
-			"libfoo.contribution",
-			AttrNameToString{
-				"api":          `"libfoo.map.txt"`,
-				"library_name": `"libfoo"`,
-				"api_surfaces": `[
-        "module-libapi",
-        "vendorapi",
-    ]`,
-				"hdrs": `[
-        ":libfoo.module-libapi.headers",
-        ":libfoo.vendorapi.headers",
-    ]`,
-			}),
-	}
-	RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{
-		Blueprint:            bp,
-		Description:          "cc API contributions to module-libapi and vendorapi",
-		ExpectedBazelTargets: expectedBazelTargets,
-	})
-}
-
-func TestCcApiSurfaceCombinations(t *testing.T) {
-	testCases := []struct {
-		bp                  string
-		expectedApi         string
-		expectedApiSurfaces string
-		description         string
-	}{
-		{
-			bp: `
-			cc_library {
-				name: "a",
-				stubs: {symbol_file: "a.map.txt"},
-			}`,
-			expectedApi:         `"a.map.txt"`,
-			expectedApiSurfaces: `["module-libapi"]`,
-			description:         "Library that contributes to module-libapi",
-		},
-		{
-			bp: `
-			cc_library {
-				name: "a",
-				llndk: {symbol_file: "a.map.txt"},
-			}`,
-			expectedApi:         `"a.map.txt"`,
-			expectedApiSurfaces: `["vendorapi"]`,
-			description:         "Library that contributes to vendorapi",
-		},
-		{
-			bp: `
-			cc_library {
-				name: "a",
-				llndk: {symbol_file: "a.map.txt"},
-				stubs: {symbol_file: "a.map.txt"},
-			}`,
-			expectedApi: `"a.map.txt"`,
-			expectedApiSurfaces: `[
-        "module-libapi",
-        "vendorapi",
-    ]`,
-			description: "Library that contributes to module-libapi and vendorapi",
-		},
-	}
-	for _, testCase := range testCases {
-		expectedBazelTargets := []string{
-			MakeBazelTarget(
-				"cc_api_contribution",
-				"a.contribution",
-				AttrNameToString{
-					"library_name": `"a"`,
-					"hdrs":         `[]`,
-					"api":          testCase.expectedApi,
-					"api_surfaces": testCase.expectedApiSurfaces,
-				},
-			),
-		}
-		RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{
-			Blueprint:            testCase.bp,
-			Description:          testCase.description,
-			ExpectedBazelTargets: expectedBazelTargets,
-		})
-	}
-}
-
-// llndk struct property in Soong provides users with several options to configure the exported include dirs
-// Test the generated bazel targets for the different configurations
-func TestCcVendorApiHeaders(t *testing.T) {
-	testCases := []struct {
-		bp                     string
-		expectedIncludes       string
-		expectedSystemIncludes string
-		description            string
-	}{
-		{
-			bp: `
-			cc_library {
-				name: "a",
-				export_include_dirs: ["include"],
-				export_system_include_dirs: ["base_system_include"],
-				llndk: {
-					symbol_file: "a.map.txt",
-					export_headers_as_system: true,
-				},
-			}
-			`,
-			expectedIncludes: "",
-			expectedSystemIncludes: `[
-        "base_system_include",
-        "include",
-    ]`,
-			description: "Headers are exported as system to API surface",
-		},
-		{
-			bp: `
-			cc_library {
-				name: "a",
-				export_include_dirs: ["include"],
-				export_system_include_dirs: ["base_system_include"],
-				llndk: {
-					symbol_file: "a.map.txt",
-					override_export_include_dirs: ["llndk_include"],
-				},
-			}
-			`,
-			expectedIncludes:       `["llndk_include"]`,
-			expectedSystemIncludes: `["base_system_include"]`,
-			description:            "Non-system Headers are ovverriden before export to API surface",
-		},
-		{
-			bp: `
-			cc_library {
-				name: "a",
-				export_include_dirs: ["include"],
-				export_system_include_dirs: ["base_system_include"],
-				llndk: {
-					symbol_file: "a.map.txt",
-					override_export_include_dirs: ["llndk_include"],
-					export_headers_as_system: true,
-				},
-			}
-			`,
-			expectedIncludes: "", // includes are set to nil
-			expectedSystemIncludes: `[
-        "base_system_include",
-        "llndk_include",
-    ]`,
-			description: "System Headers are extended before export to API surface",
-		},
-	}
-	for _, testCase := range testCases {
-		attrs := AttrNameToString{}
-		if testCase.expectedIncludes != "" {
-			attrs["export_includes"] = testCase.expectedIncludes
-		}
-		if testCase.expectedSystemIncludes != "" {
-			attrs["export_system_includes"] = testCase.expectedSystemIncludes
-		}
-
-		expectedBazelTargets := []string{
-			MakeBazelTarget("cc_api_library_headers", "a.vendorapi.headers", attrs),
-			// Create a target for cc_api_contribution target
-			MakeBazelTarget("cc_api_contribution", "a.contribution", AttrNameToString{
-				"api":          `"a.map.txt"`,
-				"api_surfaces": `["vendorapi"]`,
-				"hdrs":         `[":a.vendorapi.headers"]`,
-				"library_name": `"a"`,
-			}),
-		}
-		RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{
-			Blueprint:            testCase.bp,
-			ExpectedBazelTargets: expectedBazelTargets,
-		})
-	}
-}
-
 func TestCcLibraryStubsAcrossConfigsDuplicatesRemoved(t *testing.T) {
 	runCcLibraryTestCase(t, Bp2buildTestCase{
 		Description:                "stub target generation of the same lib across configs should not result in duplicates",
@@ -3066,7 +2867,6 @@
 		ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{
 			"implementation_dynamic_deps": `select({
         "//build/bazel/rules/apex:foo": ["@api_surfaces//module-libapi/current:barlib"],
-        "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:barlib"],
         "//conditions:default": [":barlib"],
     })`,
 			"local_includes": `["."]`,
@@ -3124,10 +2924,6 @@
             "@api_surfaces//module-libapi/current:barlib",
             "@api_surfaces//module-libapi/current:quxlib",
         ],
-        "//build/bazel/rules/apex:system": [
-            "@api_surfaces//module-libapi/current:barlib",
-            "@api_surfaces//module-libapi/current:quxlib",
-        ],
         "//conditions:default": [
             ":barlib",
             ":quxlib",
@@ -5241,3 +5037,96 @@
 	}
 	runCcLibraryTestCase(t, tc)
 }
+
+// `foo_device` and `bar_host` can depend on .proto files of a specific dir,
+// the dynamically generated proto_library should not have any target_compatible_with
+func TestProtoLibraryForIncludeDirsIsOsAgnostic(t *testing.T) {
+	tc := Bp2buildTestCase{
+		Description:                "proto_library generated for proto.include_dirs is compatible for all axes",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite") + `
+cc_library {
+	name: "foo_device",
+	device_supported: true, // this is the default behavior, but added explicitly here for illustration
+	host_supported: false,
+	proto: {include_dirs: ["dir"]},
+}
+cc_library {
+	name: "bar_host",
+	device_supported: false,
+	host_supported: true,
+	srcs: ["bar.proto"],
+	proto: {include_dirs: ["dir"]},
+}
+`,
+		Filesystem: map[string]string{
+			"dir/Android.bp": "",
+			"dir/dir.proto":  "",
+		},
+		Dir: "dir", // check for the generated proto_library
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("proto_library", "dir.include_dir_bp2build_generated_proto", AttrNameToString{
+				"srcs":                `["dir.proto"]`,
+				"strip_import_prefix": `""`,
+				"tags":                `["manual"]`,
+			}),
+		},
+	}
+	runCcLibraryTestCase(t, tc)
+}
+
+func TestCcCompileMultilibConversion(t *testing.T) {
+	tc := Bp2buildTestCase{
+		Description:                "cc_library with compile_multilib",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+cc_library {
+	name: "lib32",
+	compile_multilib: "32",
+}
+cc_library {
+	name: "lib64",
+	compile_multilib: "64",
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("cc_library_shared", "lib32", AttrNameToString{
+				"local_includes": `["."]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"] + select({
+        "//build/bazel/platforms/arch:arm64": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/arch:riscv64": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/arch:x86_64": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+			MakeBazelTargetNoRestrictions("cc_library_static", "lib32_bp2build_cc_library_static", AttrNameToString{
+				"local_includes": `["."]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"] + select({
+        "//build/bazel/platforms/arch:arm64": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/arch:riscv64": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/arch:x86_64": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+			MakeBazelTargetNoRestrictions("cc_library_shared", "lib64", AttrNameToString{
+				"local_includes": `["."]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"] + select({
+        "//build/bazel/platforms/arch:arm": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/arch:x86": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+			MakeBazelTargetNoRestrictions("cc_library_static", "lib64_bp2build_cc_library_static", AttrNameToString{
+				"local_includes": `["."]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"] + select({
+        "//build/bazel/platforms/arch:arm": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/arch:x86": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	}
+	runCcLibraryTestCase(t, tc)
+}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 072f5b3..a592ca9 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -123,69 +123,6 @@
 	})
 }
 
-func TestCcApiHeaders(t *testing.T) {
-	fs := map[string]string{
-		"bar/Android.bp": `cc_library_headers { name: "bar_headers", }`,
-	}
-	bp := `
-	cc_library_headers {
-		name: "foo_headers",
-		export_include_dirs: ["dir1", "dir2"],
-		export_header_lib_headers: ["bar_headers"],
-
-		arch: {
-			arm: {
-				export_include_dirs: ["dir_arm"],
-			},
-			x86: {
-				export_include_dirs: ["dir_x86"],
-			},
-		},
-
-		target: {
-			android: {
-				export_include_dirs: ["dir1", "dir_android"],
-			},
-			windows: {
-				export_include_dirs: ["dir_windows"],
-			},
-		}
-	}
-	`
-	expectedBazelTargets := []string{
-		MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.arm", AttrNameToString{
-			"export_includes": `["dir_arm"]`,
-			"arch":            `"arm"`,
-		}),
-		MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.x86", AttrNameToString{
-			"export_includes": `["dir_x86"]`,
-			"arch":            `"x86"`,
-		}),
-		MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.androidos", AttrNameToString{
-			"export_includes": `["dir_android"]`, // common includes are deduped
-		}),
-		// Windows headers are not exported
-		MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution", AttrNameToString{
-			"export_includes": `[
-        "dir1",
-        "dir2",
-    ]`,
-			"deps": `[
-        "//bar:bar_headers.contribution",
-        ":foo_headers.contribution.arm",
-        ":foo_headers.contribution.x86",
-        ":foo_headers.contribution.androidos",
-    ]`,
-		}),
-	}
-	RunApiBp2BuildTestCase(t, cc.RegisterLibraryHeadersBuildComponents, Bp2buildTestCase{
-		Blueprint:            bp,
-		Description:          "Header library contributions to API surfaces",
-		ExpectedBazelTargets: expectedBazelTargets,
-		Filesystem:           fs,
-	})
-}
-
 // header_libs has "variant_prepend" tag. In bp2build output,
 // variant info(select) should go before general info.
 func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) {
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 90b13b0..44b9722 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -661,7 +661,7 @@
             ":libapexfoo_stable",
         ],
         "//build/bazel/rules/apex:system": [
-            "@api_surfaces//module-libapi/current:libplatform_stable",
+            ":libplatform_stable",
             "@api_surfaces//module-libapi/current:libapexfoo_stable",
         ],
         "//conditions:default": [
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 35a1400..da4b5cf 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -145,7 +145,7 @@
 		targets.sort()
 
 		var content string
-		if mode == Bp2Build || mode == ApiBp2build {
+		if mode == Bp2Build {
 			content = `# READ THIS FIRST:
 # This file was automatically generated by bp2build for the Bazel migration project.
 # Feel free to edit or test it, but do *not* check it into your version control system.
diff --git a/bp2build/droidstubs_conversion_test.go b/bp2build/droidstubs_conversion_test.go
deleted file mode 100644
index 12c1cfe..0000000
--- a/bp2build/droidstubs_conversion_test.go
+++ /dev/null
@@ -1,104 +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/android"
-	"android/soong/java"
-)
-
-func registerJavaApiModules(ctx android.RegistrationContext) {
-	java.RegisterSdkLibraryBuildComponents(ctx)
-	java.RegisterStubsBuildComponents(ctx)
-}
-
-func TestDroidstubsApiContributions(t *testing.T) {
-	bp := `
-	droidstubs {
-		name: "framework-stubs",
-		check_api: {
-			current: {
-				api_file: "framework.current.txt",
-			},
-		},
-	}
-
-	// Modules without check_api should not generate a Bazel API target
-	droidstubs {
-		name: "framework-docs",
-	}
-
-	// java_sdk_library is a macro that creates droidstubs
-	java_sdk_library {
-		name: "module-stubs",
-		srcs: ["A.java"],
-
-		// These api surfaces are added by default, but add them explicitly to make
-		// this test hermetic
-		public: {
-			enabled: true,
-		},
-		system: {
-			enabled: true,
-		},
-
-		// Disable other api surfaces to keep unit test scope limited
-		module_lib: {
-			enabled: false,
-		},
-		test: {
-			enabled: false,
-		},
-	}
-	`
-	expectedBazelTargets := []string{
-		MakeBazelTargetNoRestrictions(
-			"java_api_contribution",
-			"framework-stubs.contribution",
-			AttrNameToString{
-				"api":                    `"framework.current.txt"`,
-				"api_surface":            `"publicapi"`,
-				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
-			}),
-		MakeBazelTargetNoRestrictions(
-			"java_api_contribution",
-			"module-stubs.stubs.source.contribution",
-			AttrNameToString{
-				"api":                    `"api/current.txt"`,
-				"api_surface":            `"publicapi"`,
-				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
-			}),
-		MakeBazelTargetNoRestrictions(
-			"java_api_contribution",
-			"module-stubs.stubs.source.system.contribution",
-			AttrNameToString{
-				"api":                    `"api/system-current.txt"`,
-				"api_surface":            `"systemapi"`,
-				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
-			}),
-	}
-	RunApiBp2BuildTestCase(t, registerJavaApiModules, Bp2buildTestCase{
-		Blueprint:            bp,
-		ExpectedBazelTargets: expectedBazelTargets,
-		Filesystem: map[string]string{
-			"api/current.txt":        "",
-			"api/removed.txt":        "",
-			"api/system-current.txt": "",
-			"api/system-removed.txt": "",
-		},
-	})
-}
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 7429ae6..512c1e1 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -441,12 +441,13 @@
 func TestJavaLibraryResourcesWithMultipleDirs(t *testing.T) {
 	runJavaLibraryTestCase(t, Bp2buildTestCase{
 		Filesystem: map[string]string{
-			"res/a.res":  "",
-			"res1/b.res": "",
+			"res/a.res":   "",
+			"res1/b.res":  "",
+			"res2/b.java": "",
 		},
 		Blueprint: `java_library {
 	name: "java-lib-1",
-	java_resource_dirs: ["res", "res1"],
+	java_resource_dirs: ["res", "res1", "res2"],
 	sdk_version: "current",
 }`,
 		ExpectedBazelTargets: []string{
@@ -1046,3 +1047,14 @@
 		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	})
 }
+
+func TestJavaSdkVersionCorePlatformDoesNotConvert(t *testing.T) {
+	runJavaLibraryTestCase(t, Bp2buildTestCase{
+		Blueprint: `java_library {
+    name: "java-lib-1",
+    sdk_version: "core_platform",
+    bazel_module: { bp2build_available: true },
+}`,
+		ExpectedBazelTargets: []string{},
+	})
+}
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go
index 5b2d609..e237303 100644
--- a/bp2build/prebuilt_etc_conversion_test.go
+++ b/bp2build/prebuilt_etc_conversion_test.go
@@ -346,3 +346,17 @@
 		ExpectedErr: fmt.Errorf("label attribute could not be collapsed"),
 	})
 }
+
+func TestPrebuiltEtcNoConversionIfSrcEqualsName(t *testing.T) {
+	runPrebuiltEtcTestCase(t, Bp2buildTestCase{
+		Description: "",
+		Filesystem:  map[string]string{},
+		Blueprint: `
+prebuilt_etc {
+    name: "foo",
+    filename: "fooFilename",
+		src: "foo",
+}`,
+		ExpectedBazelTargets: []string{},
+	})
+}
diff --git a/bp2build/rust_binary_conversion_test.go b/bp2build/rust_binary_conversion_test.go
index 3364401..a5abbdb 100644
--- a/bp2build/rust_binary_conversion_test.go
+++ b/bp2build/rust_binary_conversion_test.go
@@ -1,3 +1,17 @@
+// 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 (
diff --git a/bp2build/rust_library_conversion_test.go b/bp2build/rust_library_conversion_test.go
index b860b76..0bc80df 100644
--- a/bp2build/rust_library_conversion_test.go
+++ b/bp2build/rust_library_conversion_test.go
@@ -1,3 +1,17 @@
+// 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 (
diff --git a/bp2build/rust_proc_macro_conversion_test.go b/bp2build/rust_proc_macro_conversion_test.go
index 82e080d..7df37ec 100644
--- a/bp2build/rust_proc_macro_conversion_test.go
+++ b/bp2build/rust_proc_macro_conversion_test.go
@@ -1,3 +1,17 @@
+// 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 (
@@ -17,7 +31,7 @@
 }
 
 func TestRustProcMacroLibrary(t *testing.T) {
-	runRustLibraryTestCase(t, Bp2buildTestCase{
+	rustRustProcMacroTestCase(t, Bp2buildTestCase{
 		Dir:       "external/rust/crates/foo",
 		Blueprint: "",
 		Filesystem: map[string]string{
diff --git a/bp2build/rust_protobuf_conversion_test.go b/bp2build/rust_protobuf_conversion_test.go
index a779c36..cf256aa 100644
--- a/bp2build/rust_protobuf_conversion_test.go
+++ b/bp2build/rust_protobuf_conversion_test.go
@@ -1,3 +1,17 @@
+// 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 (
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 42d955e..997df64 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -108,15 +108,6 @@
 	runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
 }
 
-func RunApiBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
-	t.Helper()
-	apiBp2BuildSetup := android.GroupFixturePreparers(
-		android.FixtureRegisterWithContext(registerModuleTypes),
-		SetApiBp2BuildTestRunner,
-	)
-	runBp2BuildTestCaseWithSetup(t, apiBp2BuildSetup, tc)
-}
-
 func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePreparer, tc Bp2buildTestCase) {
 	t.Helper()
 	dir := "."
@@ -180,27 +171,14 @@
 }
 
 // SetBp2BuildTestRunner customizes the test fixture mechanism to run tests in Bp2Build mode.
-var SetBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{Bp2Build})
+var SetBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{})
 
-// SetApiBp2BuildTestRunner customizes the test fixture mechanism to run tests in ApiBp2build mode.
-var SetApiBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{ApiBp2build})
-
-// bazelTestRunner customizes the test fixture mechanism to run tests of the bp2build and
-// apiBp2build build modes.
-type bazelTestRunner struct {
-	mode CodegenMode
-}
+// bazelTestRunner customizes the test fixture mechanism to run tests of the bp2build build mode.
+type bazelTestRunner struct{}
 
 func (b *bazelTestRunner) FinalPreparer(result *android.TestResult) android.CustomTestResult {
 	ctx := result.TestContext
-	switch b.mode {
-	case Bp2Build:
-		ctx.RegisterForBazelConversion()
-	case ApiBp2build:
-		ctx.RegisterForApiBazelConversion()
-	default:
-		panic(fmt.Errorf("unknown build mode: %d", b.mode))
-	}
+	ctx.RegisterForBazelConversion()
 
 	return &BazelTestResult{TestResult: result}
 }
@@ -214,11 +192,7 @@
 		return
 	}
 
-	codegenMode := Bp2Build
-	if ctx.Config().BuildMode == android.ApiBp2build {
-		codegenMode = ApiBp2build
-	}
-	codegenCtx := NewCodegenContext(config, ctx.Context, codegenMode, "")
+	codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
 	res, errs := GenerateBazelTargets(codegenCtx, false)
 	if bazelResult.CollateErrs(errs) {
 		return
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 83553c8..62416f7 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -1624,6 +1624,11 @@
 				if linkable, ok := ctx.Module().(LinkableInterface); ok && linkable.Bootstrap() {
 					sameApiDomain = true
 				}
+				// If dependency has `apex_available: ["//apex_available:platform]`, then the platform variant of rdep should link against its impl.
+				// https://cs.android.com/android/_/android/platform/build/soong/+/main:cc/cc.go;l=3617;bpv=1;bpt=0;drc=c6a93d853b37ec90786e745b8d282145e6d3b589
+				if depApexAvailable := dep.(*Module).ApexAvailable(); len(depApexAvailable) == 1 && depApexAvailable[0] == android.AvailableToPlatform {
+					sameApiDomain = true
+				}
 			} else {
 				sameApiDomain = android.InList(apiDomain, dep.(*Module).ApexAvailable())
 			}
diff --git a/cc/config/OWNERS b/cc/config/OWNERS
index 580f215..c78b6d5 100644
--- a/cc/config/OWNERS
+++ b/cc/config/OWNERS
@@ -1,3 +1,3 @@
 per-file vndk.go = smoreland@google.com, victoryang@google.com
-per-file clang.go,global.go,tidy.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
+per-file clang.go,global.go,tidy.go = appujee@google.com, pirama@google.com, srhines@google.com, yabinc@google.com, yikong@google.com, zijunzhao@google.com
 
diff --git a/cc/config/global.go b/cc/config/global.go
index 23a05be..174b12c 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -45,7 +45,6 @@
 		"-UDEBUG",
 
 		"-fno-exceptions",
-		"-Wno-multichar",
 
 		"-O2",
 		"-fdebug-default-version=5",
@@ -140,6 +139,9 @@
 		"-Werror=format-security",
 		"-nostdlibinc",
 
+		// Enable MLGO for register allocation.
+		"-mllvm -regalloc-enable-advisor=release",
+
 		// Emit additional debug info for AutoFDO
 		"-fdebug-info-for-profiling",
 	}
@@ -167,6 +169,8 @@
 		"-Wl,--exclude-libs,libgcc_stripped.a",
 		"-Wl,--exclude-libs,libunwind_llvm.a",
 		"-Wl,--exclude-libs,libunwind.a",
+		// Enable MLGO for register allocation.
+		"-Wl,-mllvm,-regalloc-enable-advisor=release",
 	}
 
 	deviceGlobalLldflags = append(deviceGlobalLdflags, commonGlobalLldflags...)
@@ -251,9 +255,6 @@
 	noOverrideExternalGlobalCflags = []string{
 		// http://b/191699019
 		"-Wno-format-insufficient-args",
-		// http://b/296422292
-		// Usually signals a mistake and should be a hard error.
-		"-Wno-sizeof-array-div",
 		// http://b/296321145
 		// Indicates potential memory or stack corruption, so should be changed
 		// to a hard error. Currently triggered by some vendor code.
@@ -320,7 +321,7 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r498229"
+	ClangDefaultVersion      = "clang-r498229b"
 	ClangDefaultShortVersion = "17"
 
 	// Directories with warnings from Android.bp files.
diff --git a/cc/lto.go b/cc/lto.go
index 820c1f0..df9ca0a 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -162,7 +162,7 @@
 }
 
 func GlobalThinLTO(ctx android.BaseModuleContext) bool {
-	return ctx.Config().IsEnvTrue("GLOBAL_THINLTO")
+	return !ctx.Config().IsEnvFalse("GLOBAL_THINLTO")
 }
 
 // Propagate lto requirements down from binaries
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f37b5c7..0abdafc 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -553,7 +553,9 @@
 		}
 
 		if found, globalSanitizers = removeFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil {
-			s.Hwaddress = proptools.BoolPtr(true)
+			if !ctx.Config().HWASanDisabledForPath(ctx.ModuleDir()) {
+				s.Hwaddress = proptools.BoolPtr(true)
+			}
 		}
 
 		if found, globalSanitizers = removeFromList("writeonly", globalSanitizers); found && s.Writeonly == nil {
diff --git a/cc/test.go b/cc/test.go
index c643862..ae62128 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -395,7 +395,7 @@
 
 	useVendor := ctx.inVendor() || ctx.useVndk()
 	testInstallBase := getTestInstallBase(useVendor)
-	configs := getTradefedConfigOptions(ctx, &test.Properties, test.isolated(ctx))
+	configs := getTradefedConfigOptions(ctx, &test.Properties, test.isolated(ctx), ctx.Device())
 
 	test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
 		TestConfigProp:         test.Properties.Test_config,
@@ -435,22 +435,24 @@
 	return testInstallBase
 }
 
-func getTradefedConfigOptions(ctx android.EarlyModuleContext, properties *TestBinaryProperties, isolated bool) []tradefed.Config {
+func getTradefedConfigOptions(ctx android.EarlyModuleContext, properties *TestBinaryProperties, isolated bool, device bool) []tradefed.Config {
 	var configs []tradefed.Config
 
 	for _, module := range properties.Test_mainline_modules {
 		configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
 	}
-	if Bool(properties.Require_root) {
-		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
-	} else {
-		var options []tradefed.Option
-		options = append(options, tradefed.Option{Name: "force-root", Value: "false"})
-		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
-	}
-	if Bool(properties.Disable_framework) {
-		var options []tradefed.Option
-		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options})
+	if device {
+		if Bool(properties.Require_root) {
+			configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
+		} else {
+			var options []tradefed.Option
+			options = append(options, tradefed.Option{Name: "force-root", Value: "false"})
+			configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
+		}
+		if Bool(properties.Disable_framework) {
+			var options []tradefed.Option
+			configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options})
+		}
 	}
 	if isolated {
 		configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"})
@@ -760,7 +762,7 @@
 				p.Auto_gen_config,
 				p.Test_options.Test_suite_tag,
 				p.Test_config_template,
-				getTradefedConfigOptions(ctx, p, gtestIsolated),
+				getTradefedConfigOptions(ctx, p, gtestIsolated, true),
 				&testInstallBase,
 			)
 			testBinaryAttrs.TestConfigAttributes = testConfigAttributes
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 20e366e..626f076 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -27,7 +27,6 @@
 
 	"android/soong/android"
 	"android/soong/android/allowlists"
-	"android/soong/bazel"
 	"android/soong/bp2build"
 	"android/soong/shared"
 	"android/soong/ui/metrics/bp2build_metrics_proto"
@@ -76,7 +75,6 @@
 	flag.StringVar(&cmdlineArgs.ModuleActionsFile, "module_actions_file", "", "JSON file to output inputs/outputs of actions of modules")
 	flag.StringVar(&cmdlineArgs.DocFile, "soong_docs", "", "build documentation file to output")
 	flag.StringVar(&cmdlineArgs.BazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
-	flag.StringVar(&cmdlineArgs.BazelApiBp2buildDir, "bazel_api_bp2build_dir", "", "path to the bazel api_bp2build directory relative to --top")
 	flag.StringVar(&cmdlineArgs.Bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
 	flag.StringVar(&cmdlineArgs.SymlinkForestMarker, "symlink_forest_marker", "", "If set, create the bp2build symlink forest, touch the specified marker file, then exit")
 	flag.StringVar(&cmdlineArgs.OutFile, "o", "build.ninja", "the Ninja file to output")
@@ -169,120 +167,6 @@
 	touch(shared.JoinPath(topDir, queryviewMarker))
 }
 
-// Run the code-generation phase to convert API contributions to BUILD files.
-// Return marker file for the new synthetic workspace
-func runApiBp2build(ctx *android.Context, extraNinjaDeps []string) string {
-	ctx.EventHandler.Begin("api_bp2build")
-	defer ctx.EventHandler.End("api_bp2build")
-	// api_bp2build does not run the typical pipeline of soong mutators.
-	// Hoevever, it still runs the defaults mutator which can create dependencies.
-	// These dependencies might not always exist (e.g. in tests)
-	ctx.SetAllowMissingDependencies(ctx.Config().AllowMissingDependencies())
-	ctx.RegisterForApiBazelConversion()
-
-	// Register the Android.bp files in the tree
-	// Add them to the workspace's .d file
-	ctx.SetModuleListFile(cmdlineArgs.ModuleListFile)
-	if paths, err := ctx.ListModulePaths("."); err == nil {
-		extraNinjaDeps = append(extraNinjaDeps, paths...)
-	} else {
-		panic(err)
-	}
-
-	// Run the loading and analysis phase
-	ninjaDeps, err := bootstrap.RunBlueprint(cmdlineArgs.Args,
-		bootstrap.StopBeforePrepareBuildActions,
-		ctx.Context,
-		ctx.Config())
-	maybeQuit(err, "")
-	ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
-
-	// Add the globbed dependencies
-	ninjaDeps = append(ninjaDeps, writeBuildGlobsNinjaFile(ctx)...)
-
-	// Run codegen to generate BUILD files
-	codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.ApiBp2build, topDir)
-	absoluteApiBp2buildDir := shared.JoinPath(topDir, cmdlineArgs.BazelApiBp2buildDir)
-	// Always generate bp2build_all_srcs filegroups in api_bp2build.
-	// This is necessary to force each Android.bp file to create an equivalent BUILD file
-	// and prevent package boundray issues.
-	// e.g.
-	// Source
-	// f/b/Android.bp
-	// java_library{
-	//   name: "foo",
-	//   api: "api/current.txt",
-	// }
-	//
-	// f/b/api/Android.bp <- will cause package boundary issues
-	//
-	// Gen
-	// f/b/BUILD
-	// java_contribution{
-	//   name: "foo.contribution",
-	//   api: "//f/b/api:current.txt",
-	// }
-	//
-	// If we don't generate f/b/api/BUILD, foo.contribution will be unbuildable.
-	err = createBazelWorkspace(codegenContext, absoluteApiBp2buildDir, true)
-	maybeQuit(err, "")
-	ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
-
-	// Create soong_injection repository
-	soongInjectionFiles, workspaceFiles, err := bp2build.CreateSoongInjectionDirFiles(codegenContext, bp2build.CreateCodegenMetrics())
-	maybeQuit(err, "")
-	absoluteSoongInjectionDir := shared.JoinPath(topDir, ctx.Config().SoongOutDir(), bazel.SoongInjectionDirName)
-	for _, file := range soongInjectionFiles {
-		// The API targets in api_bp2build workspace do not have any dependency on api_bp2build.
-		// But we need to create these files to prevent errors during Bazel analysis.
-		// These need to be created in Read-Write mode.
-		// This is because the subsequent step (bp2build in api domain analysis) creates them in Read-Write mode
-		// to allow users to edit/experiment in the synthetic workspace.
-		writeReadWriteFile(absoluteSoongInjectionDir, file)
-	}
-	for _, file := range workspaceFiles {
-		writeReadWriteFile(absoluteApiBp2buildDir, file)
-	}
-
-	workspace := shared.JoinPath(ctx.Config().SoongOutDir(), "api_bp2build")
-	// Create the symlink forest
-	symlinkDeps, _, _ := bp2build.PlantSymlinkForest(
-		ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE"),
-		topDir,
-		workspace,
-		cmdlineArgs.BazelApiBp2buildDir,
-		apiBuildFileExcludes(ctx))
-	ninjaDeps = append(ninjaDeps, symlinkDeps...)
-
-	workspaceMarkerFile := workspace + ".marker"
-	writeDepFile(workspaceMarkerFile, ctx.EventHandler, ninjaDeps)
-	touch(shared.JoinPath(topDir, workspaceMarkerFile))
-	return workspaceMarkerFile
-}
-
-// With some exceptions, api_bp2build does not have any dependencies on the checked-in BUILD files
-// Exclude them from the generated workspace to prevent unrelated errors during the loading phase
-func apiBuildFileExcludes(ctx *android.Context) []string {
-	ret := bazelArtifacts()
-	srcs, err := getExistingBazelRelatedFiles(topDir)
-	maybeQuit(err, "Error determining existing Bazel-related files")
-	for _, src := range srcs {
-		// Exclude all src BUILD files
-		if src != "WORKSPACE" &&
-			src != "BUILD" &&
-			src != "BUILD.bazel" &&
-			!strings.HasPrefix(src, "build/bazel") &&
-			!strings.HasPrefix(src, "external/bazel-skylib") &&
-			!strings.HasPrefix(src, "prebuilts/clang") {
-			ret = append(ret, src)
-		}
-	}
-	// Android.bp files for api surfaces are mounted to out/, but out/ should not be a
-	// dep for api_bp2build. Otherwise, api_bp2build will be run every single time
-	ret = append(ret, ctx.Config().OutDir())
-	return ret
-}
-
 func writeNinjaHint(ctx *android.Context) error {
 	ctx.BeginEvent("ninja_hint")
 	defer ctx.EndEvent("ninja_hint")
@@ -551,9 +435,6 @@
 		// Run the alternate pipeline of bp2build mutators and singleton to convert
 		// Blueprint to BUILD files before everything else.
 		finalOutputFile = runBp2Build(ctx, extraNinjaDeps, metricsDir)
-	case android.ApiBp2build:
-		finalOutputFile = runApiBp2build(ctx, extraNinjaDeps)
-		writeMetrics(configuration, ctx.EventHandler, metricsDir)
 	default:
 		ctx.Register()
 		isMixedBuildsEnabled := configuration.IsMixedBuildsEnabled()
diff --git a/etc/Android.bp b/etc/Android.bp
index c670236..cefd717 100644
--- a/etc/Android.bp
+++ b/etc/Android.bp
@@ -14,10 +14,12 @@
     srcs: [
         "prebuilt_etc.go",
         "snapshot_etc.go",
+        "install_symlink.go",
     ],
     testSrcs: [
         "prebuilt_etc_test.go",
         "snapshot_etc_test.go",
+        "install_symlink_test.go",
     ],
     pluginFor: ["soong_build"],
 }
diff --git a/etc/install_symlink.go b/etc/install_symlink.go
new file mode 100644
index 0000000..2182b86
--- /dev/null
+++ b/etc/install_symlink.go
@@ -0,0 +1,92 @@
+// 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 etc
+
+import (
+	"android/soong/android"
+	"path/filepath"
+	"strings"
+)
+
+func init() {
+	RegisterInstallSymlinkBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterInstallSymlinkBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("install_symlink", InstallSymlinkFactory)
+}
+
+// install_symlink can be used to install an symlink with an arbitrary target to an arbitrary path
+// on the device.
+func InstallSymlinkFactory() android.Module {
+	module := &InstallSymlink{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	return module
+}
+
+type InstallSymlinkProperties struct {
+	// Where to install this symlink, relative to the partition it's installed on.
+	// Which partition it's installed on can be controlled by the vendor, system_ext, ramdisk, etc.
+	// properties.
+	Installed_location string
+	// The target of the symlink, aka where the symlink points.
+	Symlink_target string
+}
+
+type InstallSymlink struct {
+	android.ModuleBase
+	properties InstallSymlinkProperties
+
+	output        android.Path
+	installedPath android.InstallPath
+}
+
+func (m *InstallSymlink) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if filepath.Clean(m.properties.Symlink_target) != m.properties.Symlink_target {
+		ctx.PropertyErrorf("symlink_target", "Should be a clean filepath")
+		return
+	}
+	if filepath.Clean(m.properties.Installed_location) != m.properties.Installed_location {
+		ctx.PropertyErrorf("installed_location", "Should be a clean filepath")
+		return
+	}
+	if strings.HasPrefix(m.properties.Installed_location, "../") || strings.HasPrefix(m.properties.Installed_location, "/") {
+		ctx.PropertyErrorf("installed_location", "Should not start with / or ../")
+		return
+	}
+
+	out := android.PathForModuleOut(ctx, "out.txt")
+	android.WriteFileRuleVerbatim(ctx, out, "")
+	m.output = out
+
+	name := filepath.Base(m.properties.Installed_location)
+	installDir := android.PathForModuleInstall(ctx, filepath.Dir(m.properties.Installed_location))
+	m.installedPath = ctx.InstallAbsoluteSymlink(installDir, name, m.properties.Symlink_target)
+}
+
+func (m *InstallSymlink) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{{
+		Class: "FAKE",
+		// Need at least one output file in order for this to take effect.
+		OutputFile: android.OptionalPathForPath(m.output),
+		Include:    "$(BUILD_PHONY_PACKAGE)",
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+				entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", m.installedPath.String())
+			},
+		},
+	}}
+}
diff --git a/etc/install_symlink_test.go b/etc/install_symlink_test.go
new file mode 100644
index 0000000..d7165e5
--- /dev/null
+++ b/etc/install_symlink_test.go
@@ -0,0 +1,135 @@
+// 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 etc
+
+import (
+	"android/soong/android"
+	"strings"
+	"testing"
+)
+
+var prepareForInstallSymlinkTest = android.GroupFixturePreparers(
+	android.PrepareForTestWithArchMutator,
+	android.FixtureRegisterWithContext(RegisterInstallSymlinkBuildComponents),
+)
+
+func TestInstallSymlinkBasic(t *testing.T) {
+	result := prepareForInstallSymlinkTest.RunTestWithBp(t, `
+		install_symlink {
+			name: "foo",
+			installed_location: "bin/foo",
+			symlink_target: "/system/system_ext/bin/foo",
+		}
+	`)
+
+	foo_variants := result.ModuleVariantsForTests("foo")
+	if len(foo_variants) != 1 {
+		t.Fatalf("expected 1 variant, got %#v", foo_variants)
+	}
+
+	foo := result.ModuleForTests("foo", "android_common").Module()
+	androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo)
+	if len(androidMkEntries) != 1 {
+		t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries))
+	}
+
+	symlinks := androidMkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"]
+	if len(symlinks) != 1 {
+		t.Fatalf("Expected 1 symlink, got %d", len(symlinks))
+	}
+
+	if !strings.HasSuffix(symlinks[0], "system/bin/foo") {
+		t.Fatalf("Expected symlink install path to end in system/bin/foo, got: %s", symlinks[0])
+	}
+}
+
+func TestInstallSymlinkToRecovery(t *testing.T) {
+	result := prepareForInstallSymlinkTest.RunTestWithBp(t, `
+		install_symlink {
+			name: "foo",
+			installed_location: "bin/foo",
+			symlink_target: "/system/system_ext/bin/foo",
+			recovery: true,
+		}
+	`)
+
+	foo_variants := result.ModuleVariantsForTests("foo")
+	if len(foo_variants) != 1 {
+		t.Fatalf("expected 1 variant, got %#v", foo_variants)
+	}
+
+	foo := result.ModuleForTests("foo", "android_common").Module()
+	androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo)
+	if len(androidMkEntries) != 1 {
+		t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries))
+	}
+
+	symlinks := androidMkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"]
+	if len(symlinks) != 1 {
+		t.Fatalf("Expected 1 symlink, got %d", len(symlinks))
+	}
+
+	if !strings.HasSuffix(symlinks[0], "recovery/root/system/bin/foo") {
+		t.Fatalf("Expected symlink install path to end in recovery/root/system/bin/foo, got: %s", symlinks[0])
+	}
+}
+
+func TestErrorOnNonCleanTarget(t *testing.T) {
+	prepareForInstallSymlinkTest.
+		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should be a clean filepath")).
+		RunTestWithBp(t, `
+		install_symlink {
+			name: "foo",
+			installed_location: "bin/foo",
+			symlink_target: "/system/system_ext/../bin/foo",
+		}
+	`)
+}
+
+func TestErrorOnNonCleanInstalledLocation(t *testing.T) {
+	prepareForInstallSymlinkTest.
+		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should be a clean filepath")).
+		RunTestWithBp(t, `
+		install_symlink {
+			name: "foo",
+			installed_location: "bin/../foo",
+			symlink_target: "/system/system_ext/bin/foo",
+		}
+	`)
+}
+
+func TestErrorOnInstalledPathStartingWithDotDot(t *testing.T) {
+	prepareForInstallSymlinkTest.
+		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should not start with / or \\.\\./")).
+		RunTestWithBp(t, `
+		install_symlink {
+			name: "foo",
+			installed_location: "../bin/foo",
+			symlink_target: "/system/system_ext/bin/foo",
+		}
+	`)
+}
+
+func TestErrorOnInstalledPathStartingWithSlash(t *testing.T) {
+	prepareForInstallSymlinkTest.
+		ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should not start with / or \\.\\./")).
+		RunTestWithBp(t, `
+		install_symlink {
+			name: "foo",
+			installed_location: "/bin/foo",
+			symlink_target: "/system/system_ext/bin/foo",
+		}
+	`)
+}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 370a423..c48bafa 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -40,6 +40,7 @@
 	"android/soong/bazel"
 	"android/soong/bazel/cquery"
 	"android/soong/snapshot"
+	"android/soong/ui/metrics/bp2build_metrics_proto"
 )
 
 var pctx = android.NewPackageContext("android/soong/etc")
@@ -711,7 +712,7 @@
 // Bp2buildHelper returns a bazelPrebuiltFileAttributes used for the conversion
 // of prebuilt_*  modules. bazelPrebuiltFileAttributes has the common attributes
 // used by both prebuilt_etc_xml and other prebuilt_* moodules
-func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) *bazelPrebuiltFileAttributes {
+func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) (*bazelPrebuiltFileAttributes, bool) {
 	var src bazel.LabelAttribute
 	for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltEtcProperties{}) {
 		for config, p := range configToProps {
@@ -720,7 +721,12 @@
 				continue
 			}
 			if props.Src != nil {
-				label := android.BazelLabelForModuleSrcSingle(ctx, *props.Src)
+				srcStr := proptools.String(props.Src)
+				if srcStr == ctx.ModuleName() {
+					ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "src == name")
+					return &bazelPrebuiltFileAttributes{}, false
+				}
+				label := android.BazelLabelForModuleSrcSingle(ctx, srcStr)
 				src.SetSelectValue(axis, config, label)
 			}
 		}
@@ -779,8 +785,7 @@
 		attrs.Filename_from_src = bazel.BoolAttribute{Value: moduleProps.Filename_from_src}
 	}
 
-	return attrs
-
+	return attrs, true
 }
 
 // ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
@@ -793,7 +798,10 @@
 		return
 	}
 
-	attrs := module.Bp2buildHelper(ctx)
+	attrs, convertible := module.Bp2buildHelper(ctx)
+	if !convertible {
+		return
+	}
 
 	props := bazel.BazelTargetModuleProperties{
 		Rule_class:        "prebuilt_file",
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index df7664d..5c4e222 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -83,7 +83,7 @@
 
 	baz_variants := result.ModuleVariantsForTests("baz.conf")
 	if len(baz_variants) != 1 {
-		t.Errorf("expected 1, got %#v", bar_variants)
+		t.Errorf("expected 1, got %#v", baz_variants)
 	}
 }
 
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 8e3f278..d1c2f13 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -912,7 +912,7 @@
 	Out []string
 }
 
-type bazelGenruleAttributes struct {
+type BazelGenruleAttributes struct {
 	Srcs  bazel.LabelListAttribute
 	Outs  []string
 	Tools bazel.LabelListAttribute
@@ -1036,7 +1036,7 @@
 				break
 			}
 		}
-		attrs := &bazelGenruleAttributes{
+		attrs := &BazelGenruleAttributes{
 			Srcs:  srcs,
 			Outs:  outs,
 			Cmd:   cmdProp,
diff --git a/java/app.go b/java/app.go
index dadae48..d533b71 100755
--- a/java/app.go
+++ b/java/app.go
@@ -29,6 +29,7 @@
 	"android/soong/bazel"
 	"android/soong/cc"
 	"android/soong/dexpreopt"
+	"android/soong/genrule"
 	"android/soong/tradefed"
 )
 
@@ -315,6 +316,17 @@
 	a.generateJavaUsedByApex(ctx)
 }
 
+func (a *AndroidApp) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+	defaultMinSdkVersion := a.Module.MinSdkVersion(ctx)
+	if proptools.Bool(a.appProperties.Updatable) {
+		overrideApiLevel := android.MinSdkVersionFromValue(ctx, ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride())
+		if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(defaultMinSdkVersion) > 0 {
+			return overrideApiLevel
+		}
+	}
+	return defaultMinSdkVersion
+}
+
 func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
 	if a.Updatable() {
 		if !a.SdkVersion(ctx).Stable() {
@@ -1614,6 +1626,8 @@
 	Certificate      bazel.LabelAttribute
 	Certificate_name bazel.StringAttribute
 	Manifest_values  *manifestValueAttribute
+	Optimize         *bool
+	Proguard_specs   bazel.LabelListAttribute
 }
 
 // ConvertWithBp2build is used to convert android_app to Bazel.
@@ -1665,6 +1679,41 @@
 		Manifest_values:  manifestValues,
 	}
 
+	if !BoolDefault(a.dexProperties.Optimize.Enabled, true) {
+		appAttrs.Optimize = proptools.BoolPtr(false)
+	} else {
+		handCraftedFlags := ""
+		if Bool(a.dexProperties.Optimize.Ignore_warnings) {
+			handCraftedFlags += "-ignorewarning "
+		}
+		if !Bool(a.dexProperties.Optimize.Shrink) {
+			handCraftedFlags += "-dontshrink "
+		}
+		if !Bool(a.dexProperties.Optimize.Optimize) {
+			handCraftedFlags += "-dontoptimize "
+		}
+		if !Bool(a.dexProperties.Optimize.Obfuscate) {
+			handCraftedFlags += "-dontobfuscate "
+		}
+		appAttrs.Proguard_specs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, a.dexProperties.Optimize.Proguard_flags_files))
+		if handCraftedFlags != "" {
+			generatedFlagFileRuleName := a.Name() + "_proguard_flags"
+			ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
+				Rule_class: "genrule",
+			}, android.CommonAttributes{
+				Name:     generatedFlagFileRuleName,
+				SkipData: proptools.BoolPtr(true),
+			}, &genrule.BazelGenruleAttributes{
+				Outs: []string{a.Name() + "_proguard.flags"},
+				Cmd: bazel.StringAttribute{
+					Value: proptools.StringPtr("echo " + handCraftedFlags + "> $(OUTS)"),
+				},
+			})
+			appAttrs.Proguard_specs.Add(bazel.MakeLabelAttribute(":" + generatedFlagFileRuleName))
+		}
+
+	}
+
 	props := bazel.BazelTargetModuleProperties{
 		Rule_class:        "android_binary",
 		Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl",
diff --git a/java/app_import.go b/java/app_import.go
index ad1765e..1718d93 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -277,6 +277,14 @@
 		a.hideApexVariantFromMake = true
 	}
 
+	if Bool(a.properties.Preprocessed) {
+		if a.properties.Presigned != nil && !*a.properties.Presigned {
+			ctx.ModuleErrorf("Setting preprocessed: true implies presigned: true, so you cannot set presigned to false")
+		}
+		t := true
+		a.properties.Presigned = &t
+	}
+
 	numCertPropsSet := 0
 	if String(a.properties.Certificate) != "" {
 		numCertPropsSet++
@@ -288,11 +296,9 @@
 		numCertPropsSet++
 	}
 	if numCertPropsSet != 1 {
-		ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
+		ctx.ModuleErrorf("One and only one of certficate, presigned (implied by preprocessed), and default_dev_cert properties must be set")
 	}
 
-	_, _, certificates := collectAppDeps(ctx, a, false, false)
-
 	// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
 	// TODO: LOCAL_PACKAGE_SPLITS
 
@@ -365,6 +371,7 @@
 	} else if !Bool(a.properties.Presigned) {
 		// If the certificate property is empty at this point, default_dev_cert must be set to true.
 		// Which makes processMainCert's behavior for the empty cert string WAI.
+		_, _, certificates := collectAppDeps(ctx, a, false, false)
 		a.certificate, certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
 		signed := android.PathForModuleOut(ctx, "signed", apkFilename)
 		var lineageFile android.Path
@@ -377,8 +384,13 @@
 		SignAppPackage(ctx, signed, jnisUncompressed, certificates, nil, lineageFile, rotationMinSdkVersion)
 		a.outputFile = signed
 	} else {
+		// Presigned without Preprocessed shouldn't really be a thing, currently we disallow
+		// it for apps with targetSdk >= 30, because on those targetSdks you must be using signature
+		// v2 or later, and signature v2 would be wrecked by uncompressing libs / zipaligning.
+		// But ideally we would disallow it for all prebuilt apks, and remove the presigned property.
+		targetSdkCheck := a.validateTargetSdkLessThan30(ctx, srcApk)
 		alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
-		TransformZipAlign(ctx, alignedApk, jnisUncompressed)
+		TransformZipAlign(ctx, alignedApk, jnisUncompressed, []android.Path{targetSdkCheck})
 		a.outputFile = alignedApk
 		a.certificate = PresignedCertificate
 	}
@@ -432,6 +444,16 @@
 	})
 }
 
+func (a *AndroidAppImport) validateTargetSdkLessThan30(ctx android.ModuleContext, srcApk android.Path) android.Path {
+	alignmentStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "old_target_sdk.stamp")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   checkBelowTargetSdk30ForNonPreprocessedApks,
+		Input:  srcApk,
+		Output: alignmentStamp,
+	})
+	return alignmentStamp
+}
+
 func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
 	return &a.prebuilt
 }
diff --git a/java/app_import_test.go b/java/app_import_test.go
index bb8fab9..506c734 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -629,31 +629,21 @@
 			presigned: true,
 			preprocessed: true,
 		}
-
-		android_test_import {
-			name: "foo_cert",
-			apk: "prebuilts/apk/app.apk",
-			certificate: "cert/new_cert",
-			preprocessed: true,
-		}
 		`)
 
-	testModules := []string{"foo", "foo_cert"}
-	for _, m := range testModules {
-		apkName := m + ".apk"
-		variant := ctx.ModuleForTests(m, "android_common")
-		jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
-		if jniRule != android.Cp.String() {
-			t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
-		}
+	apkName := "foo.apk"
+	variant := ctx.ModuleForTests("foo", "android_common")
+	jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
+	if jniRule != android.Cp.String() {
+		t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
+	}
 
-		// Make sure signing and aligning were skipped.
-		if variant.MaybeOutput("signed/"+apkName).Rule != nil {
-			t.Errorf("signing rule shouldn't be included for preprocessed.")
-		}
-		if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil {
-			t.Errorf("aligning rule shouldn't be for preprocessed")
-		}
+	// Make sure signing and aligning were skipped.
+	if variant.MaybeOutput("signed/"+apkName).Rule != nil {
+		t.Errorf("signing rule shouldn't be included for preprocessed.")
+	}
+	if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil {
+		t.Errorf("aligning rule shouldn't be for preprocessed")
 	}
 }
 
diff --git a/java/app_test.go b/java/app_test.go
index 8474ea7..fc57f44 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -4137,3 +4137,49 @@
 		"\\S+soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/bar.xml",
 	)
 }
+
+func TestApexGlobalMinSdkVersionOverride(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		PrepareForTestWithJavaDefaultModules,
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.ApexGlobalMinSdkVersionOverride = proptools.StringPtr("Tiramisu")
+		}),
+	).RunTestWithBp(t, `
+		android_app {
+			name: "com.android.bar",
+			srcs: ["a.java"],
+			sdk_version: "current",
+		}
+		android_app {
+			name: "com.android.foo",
+			srcs: ["a.java"],
+			sdk_version: "current",
+			min_sdk_version: "S",
+			updatable: true,
+		}
+		override_android_app {
+			name: "com.android.go.foo",
+			base: "com.android.foo",
+		}
+	`)
+	foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
+	fooOverride := result.ModuleForTests("com.android.foo", "android_common_com.android.go.foo").Rule("manifestFixer")
+	bar := result.ModuleForTests("com.android.bar", "android_common").Rule("manifestFixer")
+
+	android.AssertStringDoesContain(t,
+		"expected manifest fixer to set com.android.bar minSdkVersion to S",
+		bar.BuildParams.Args["args"],
+		"--minSdkVersion  S",
+	)
+	android.AssertStringDoesContain(t,
+		"com.android.foo: expected manifest fixer to set minSdkVersion to T",
+		foo.BuildParams.Args["args"],
+		"--minSdkVersion  T",
+	)
+	android.AssertStringDoesContain(t,
+		"com.android.go.foo: expected manifest fixer to set minSdkVersion to T",
+		fooOverride.BuildParams.Args["args"],
+		"--minSdkVersion  T",
+	)
+
+}
diff --git a/java/base.go b/java/base.go
index 2c0b3ea..8f48398 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1608,7 +1608,7 @@
 					false, nil, nil)
 				if *j.dexProperties.Uncompress_dex {
 					combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
-					TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
+					TransformZipAlign(ctx, combinedAlignedJar, combinedJar, nil)
 					dexOutputFile = combinedAlignedJar
 				} else {
 					dexOutputFile = combinedJar
diff --git a/java/builder.go b/java/builder.go
index debf49a..bf91917 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -277,6 +277,14 @@
 			Command:     `${config.Zip2ZipCmd} -i ${in} -o ${out} -x 'META-INF/services/**/*'`,
 			CommandDeps: []string{"${config.Zip2ZipCmd}"},
 		})
+
+	checkBelowTargetSdk30ForNonPreprocessedApks = pctx.AndroidStaticRule("checkBelowTargetSdk30ForNonPreprocessedApks",
+		blueprint.RuleParams{
+			Command:     "build/soong/scripts/check_target_sdk_less_than_30.py ${config.Aapt2Cmd} $in $out",
+			CommandDeps: []string{"build/soong/scripts/check_target_sdk_less_than_30.py", "${config.Aapt2Cmd}"},
+			Description: "Check prebuilt target sdk version",
+		},
+	)
 )
 
 func init() {
@@ -689,12 +697,13 @@
 	android.WriteFileRule(ctx, outputFile, "Main-Class: "+mainClass+"\n")
 }
 
-func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) {
+func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path, validations android.Paths) {
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        zipalign,
 		Description: "align",
 		Input:       inputFile,
 		Output:      outputFile,
+		Validations: validations,
 	})
 }
 
diff --git a/java/dex.go b/java/dex.go
index 21937e1..5b8cf3d 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -450,7 +450,7 @@
 	}
 	if proptools.Bool(d.dexProperties.Uncompress_dex) {
 		alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", dexParams.jarName).OutputPath
-		TransformZipAlign(ctx, alignedJavalibJar, javalibJar)
+		TransformZipAlign(ctx, alignedJavalibJar, javalibJar, nil)
 		javalibJar = alignedJavalibJar
 	}
 
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 4d08b83..fe3fe7b 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -305,7 +305,7 @@
 	})
 
 	if uncompressDex {
-		TransformZipAlign(ctx, output, encodeRuleOutput)
+		TransformZipAlign(ctx, output, encodeRuleOutput, nil)
 	}
 
 	return output
diff --git a/java/java.go b/java/java.go
index 6c448a2..99bb1b3 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1735,7 +1735,6 @@
 
 	cmd.Flag("--color").
 		Flag("--quiet").
-		Flag("--format=v2").
 		Flag("--include-annotations").
 		// The flag makes nullability issues as warnings rather than errors by replacing
 		// @Nullable/@NonNull in the listed packages APIs with @RecentlyNullable/@RecentlyNonNull,
@@ -1747,14 +1746,13 @@
 		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.
+	// The main purpose of the `--api-class-resolution api` option is to force metalava to ignore
+	// classes on the classpath when an API file contains missing classes. However, as this command
+	// does not specify `--classpath` this is not needed for that. However, this is also used as a
+	// signal to the special metalava code for generating stubs from text files that it needs to add
+	// some additional items into the API (e.g. default constructors).
 	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
 }
 
@@ -1916,7 +1914,7 @@
 		FlagWithArg("-C ", stubsDir.String()).
 		FlagWithArg("-D ", stubsDir.String())
 
-	rule.Build("metalava", "metalava merged")
+	rule.Build("metalava", "metalava merged text")
 
 	if depApiSrcsStubsJar == nil {
 		var flags javaBuilderFlags
@@ -2828,7 +2826,7 @@
 			if resourceStripPrefix == nil && i == 0 {
 				resourceStripPrefix = resAttr.Resource_strip_prefix
 				resources = resAttr.Resources.Value
-			} else {
+			} else if !resAttr.Resources.IsEmpty() {
 				ctx.CreateBazelTargetModule(
 					bazel.BazelTargetModuleProperties{
 						Rule_class:        "java_resources",
@@ -2906,8 +2904,13 @@
 	var staticDeps bazel.LabelListAttribute
 
 	if proptools.String(m.deviceProperties.Sdk_version) == "" && m.DeviceSupported() {
+		// TODO(b/297356704): handle platform apis in bp2build
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "sdk_version unset")
 		return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false
+	} else if proptools.String(m.deviceProperties.Sdk_version) == "core_platform" {
+		// TODO(b/297356582): handle core_platform in bp2build
+		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "sdk_version core_platform")
+		return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false
 	}
 
 	archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
diff --git a/java/sdk_library.go b/java/sdk_library.go
index b1ddde0..d1620af 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1633,7 +1633,7 @@
 	}{}
 
 	props.Name = proptools.StringPtr(module.sourceStubLibraryModuleName(apiScope))
-	props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
+	props.Visibility = []string{"//visibility:override", "//visibility:private"}
 	// sources are generated from the droiddoc
 	props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
 	sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
@@ -1829,7 +1829,7 @@
 	}{}
 
 	props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
-	props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
+	props.Visibility = []string{"//visibility:override", "//visibility:private"}
 
 	apiContributions := []string{}
 
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 118f8b6..868d697 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -1474,3 +1474,32 @@
 		android.AssertStringEquals(t, "Module expected to contain full api surface api library", c.fullApiSurfaceStub, *m.properties.Full_api_surface_stub)
 	}
 }
+
+func TestStaticDepStubLibrariesVisibility(t *testing.T) {
+	android.GroupFixturePreparers(
+		prepareForJavaTest,
+		PrepareForTestWithJavaSdkLibraryFiles,
+		FixtureWithLastReleaseApis("foo"),
+		android.FixtureMergeMockFs(
+			map[string][]byte{
+				"A.java": nil,
+				"dir/Android.bp": []byte(
+					`
+					java_library {
+						name: "bar",
+						srcs: ["A.java"],
+						libs: ["foo.stubs.from-source"],
+					}
+					`),
+				"dir/A.java": nil,
+			},
+		).ExtendWithErrorHandler(
+			android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+				`module "bar" variant "android_common": depends on //.:foo.stubs.from-source which is not visible to this module`)),
+	).RunTestWithBp(t, `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["A.java"],
+		}
+	`)
+}
diff --git a/python/python.go b/python/python.go
index 8b31c6c..7d77ca7 100644
--- a/python/python.go
+++ b/python/python.go
@@ -462,8 +462,7 @@
 
 	// generate the zipfile of all source and data files
 	p.srcsZip = p.createSrcsZip(ctx, pkgPath)
-	// TODO(b/278602456): precompilation temporarily disabled for python3.11 upgrade
-	p.precompiledSrcsZip = p.srcsZip //p.precompileSrcs(ctx)
+	p.precompiledSrcsZip = p.precompileSrcs(ctx)
 }
 
 func isValidPythonPath(path string) error {
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 407f275..a80a587 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
 	defaultBindgenFlags = []string{""}
 
 	// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
-	bindgenClangVersion = "clang-r498229"
+	bindgenClangVersion = "clang-r498229b"
 
 	_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
 		if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
diff --git a/rust/sanitize.go b/rust/sanitize.go
index cc19e6e..2f5afd7 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -208,6 +208,11 @@
 		s.Memtag_heap = nil
 	}
 
+	// Disable sanitizers for musl x86 modules, rustc does not support any sanitizers.
+	if ctx.Os() == android.LinuxMusl && ctx.Arch().ArchType == android.X86 {
+		s.Never = boolPtr(true)
+	}
+
 	// TODO:(b/178369775)
 	// For now sanitizing is only supported on non-windows targets
 	if ctx.Os() != android.Windows && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap) || Bool(s.Fuzzer)) {
diff --git a/scripts/check_target_sdk_less_than_30.py b/scripts/check_target_sdk_less_than_30.py
new file mode 100755
index 0000000..69b0bf0
--- /dev/null
+++ b/scripts/check_target_sdk_less_than_30.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+
+import subprocess
+import argparse
+import re
+import sys
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('aapt2', help = "the path to the aapt2 executable")
+    parser.add_argument('apk', help = "the apk to check")
+    parser.add_argument('stampfile', help = "a file to touch if successful")
+    args = parser.parse_args()
+
+    regex = re.compile(r"targetSdkVersion: *'([0-9]+)'")
+    output = subprocess.check_output([args.aapt2, "dump", "badging", args.apk], text=True)
+    targetSdkVersion = None
+    for line in output.splitlines():
+        match = regex.fullmatch(line.strip())
+        if match:
+            targetSdkVersion = int(match.group(1))
+            break
+
+    if targetSdkVersion is None or targetSdkVersion >= 30:
+        sys.exit(args.apk + ": Prebuilt, presigned apks with targetSdkVersion >= 30 (or a codename targetSdkVersion) must set preprocessed: true in the Android.bp definition (because they must be signed with signature v2, and the build system would wreck that signature otherwise)")
+
+    subprocess.check_call(["touch", args.stampfile])
+
+if __name__ == "__main__":
+    main()
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index 7ccc114..3c0b8ae 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -86,6 +86,98 @@
 	)
 }
 
+func TestSnapshotWithPartialSystemServerClasspathFragment(t *testing.T) {
+	commonSdk := `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			min_sdk_version: "Tiramisu",
+			systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
+		}
+		systemserverclasspath_fragment {
+			name: "mysystemserverclasspathfragment",
+			apex_available: ["myapex"],
+			contents: [
+				"mysdklibrary",
+				"mysdklibrary-future",
+			],
+		}
+		java_sdk_library {
+			name: "mysdklibrary",
+			apex_available: ["myapex"],
+			srcs: ["Test.java"],
+			min_sdk_version: "33", // Tiramisu
+		}
+		java_sdk_library {
+			name: "mysdklibrary-future",
+			apex_available: ["myapex"],
+			srcs: ["Test.java"],
+			min_sdk_version: "34", // UpsideDownCake
+		}
+		sdk {
+			name: "mysdk",
+			apexes: ["myapex"],
+		}
+	`
+
+	result := android.GroupFixturePreparers(
+		prepareForSdkTestWithJava,
+		java.PrepareForTestWithJavaDefaultModules,
+		java.PrepareForTestWithJavaSdkLibraryFiles,
+		java.FixtureWithLastReleaseApis("mysdklibrary", "mysdklibrary-future"),
+		dexpreopt.FixtureSetApexSystemServerJars("myapex:mysdklibrary", "myapex:mysdklibrary-future"),
+		android.FixtureModifyEnv(func(env map[string]string) {
+			// targeting Tiramisu here means that we won't export mysdklibrary-future
+			env["SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE"] = "Tiramisu"
+		}),
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.Platform_version_active_codenames = []string{"UpsideDownCake"}
+		}),
+		prepareForSdkTestWithApex,
+		android.FixtureWithRootAndroidBp(commonSdk),
+	).RunTest(t)
+
+	CheckSnapshot(t, result, "mysdk", "", checkAndroidBpContents(
+		`// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+    name: "mysdklibrary",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["myapex"],
+    shared_library: true,
+    public: {
+        jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+        stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+        current_api: "sdk_library/public/mysdklibrary.txt",
+        removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+        sdk_version: "current",
+    },
+    system: {
+        jars: ["sdk_library/system/mysdklibrary-stubs.jar"],
+        stub_srcs: ["sdk_library/system/mysdklibrary_stub_sources"],
+        current_api: "sdk_library/system/mysdklibrary.txt",
+        removed_api: "sdk_library/system/mysdklibrary-removed.txt",
+        sdk_version: "system_current",
+    },
+    test: {
+        jars: ["sdk_library/test/mysdklibrary-stubs.jar"],
+        stub_srcs: ["sdk_library/test/mysdklibrary_stub_sources"],
+        current_api: "sdk_library/test/mysdklibrary.txt",
+        removed_api: "sdk_library/test/mysdklibrary-removed.txt",
+        sdk_version: "test_current",
+    },
+}
+
+prebuilt_systemserverclasspath_fragment {
+    name: "mysystemserverclasspathfragment",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["myapex"],
+    contents: ["mysdklibrary"],
+} `))
+}
+
 func TestSnapshotWithEmptySystemServerClasspathFragment(t *testing.T) {
 	commonSdk := `
 		apex {
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 090114b..8a64a56 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -407,38 +407,6 @@
   fi
 }
 
-# Smoke test to verify api_bp2build worksapce does not contain any errors
-function test_api_bp2build_empty_build() {
-  setup
-  run_soong api_bp2build
-  run_bazel build --config=android --config=api_bp2build //:empty
-}
-
-# Verify that an *_api_contribution target can refer to an api file from
-# another Bazel package.
-function test_api_export_from_another_bazel_package() {
-  setup
-  # Parent dir Android.bp
-  mkdir -p foo
-  cat > foo/Android.bp << 'EOF'
-cc_library {
-  name: "libfoo",
-  stubs: {
-    symbol_file: "api/libfoo.map.txt",
-  },
-}
-EOF
-  # Child dir Android.bp
-  mkdir -p foo/api
-  cat > foo/api/Android.bp << 'EOF'
-package{}
-EOF
-  touch foo/api/libfoo.map.txt
-  # Run test
-  run_soong api_bp2build
-  run_bazel build --config=android --config=api_bp2build //foo:libfoo.contribution
-}
-
 function test_bazel_standalone_output_paths_contain_product_name {
   setup
   mkdir -p a
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 9801a8e..73fbeab 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -47,13 +47,10 @@
 }
 
 function diff_files {
-  file_list_file="$1"; shift
-  files_in_spdx_file="$1"; shift
-  partition_name="$1"; shift
-  exclude=
-  if [ -v 'diff_excludes[$partition_name]' ]; then
-   exclude=${diff_excludes[$partition_name]}
-  fi
+  local file_list_file="$1"; shift
+  local files_in_spdx_file="$1"; shift
+  local partition_name="$1"; shift
+  local exclude="$1"; shift
 
   diff "$file_list_file" "$files_in_spdx_file" $exclude
   if [ $? != "0" ]; then
@@ -84,48 +81,6 @@
   dump_erofs=$out_dir/host/linux-x86/bin/dump.erofs
   lz4=$out_dir/host/linux-x86/bin/lz4
 
-  declare -A diff_excludes
-  diff_excludes[vendor]="\
-    -I /vendor/lib64/libkeystore2_crypto.so \
-    -I /vendor/lib64/libvsock_utils.so"
-  diff_excludes[system]="\
-    -I /system/bin/assemble_cvd \
-    -I /system/bin/console_forwarder \
-    -I /system/bin/kernel_log_monitor \
-    -I /system/bin/logcat_receiver \
-    -I /system/bin/mkenvimage_slim \
-    -I /system/bin/run_cvd \
-    -I /system/bin/simg2img \
-    -I /system/bin/log_tee \
-    -I /system/lib64/android.hardware.confirmationui@1.0.so \
-    -I /system/lib64/android.hardware.confirmationui-V1-ndk.so \
-    -I /system/lib64/android.hardware.keymaster@4.1.so \
-    -I /system/lib64/android.hardware.security.rkp-V3-ndk.so \
-    -I /system/lib64/android.hardware.security.sharedsecret-V1-ndk.so \
-    -I /system/lib64/android.security.compat-ndk.so \
-    -I /system/lib64/libcuttlefish_allocd_utils.so \
-    -I /system/lib64/libcuttlefish_device_config_proto.so \
-    -I /system/lib64/libcuttlefish_device_config.so \
-    -I /system/lib64/libcuttlefish_fs.so \
-    -I /system/lib64/libcuttlefish_kernel_log_monitor_utils.so \
-    -I /system/lib64/libcuttlefish_utils.so \
-    -I /system/lib64/libfruit.so \
-    -I /system/lib64/libgflags.so \
-    -I /system/lib64/libkeymaster4_1support.so \
-    -I /system/lib64/libkeymaster4support.so \
-    -I /system/lib64/libkeymint.so \
-    -I /system/lib64/libkeystore2_aaid.so \
-    -I /system/lib64/libkeystore2_apc_compat.so \
-    -I /system/lib64/libkeystore2_crypto.so \
-    -I /system/lib64/libkeystore-attestation-application-id.so \
-    -I /system/lib64/libkm_compat_service.so \
-    -I /system/lib64/libkm_compat.so \
-    -I /system/lib64/vndk-29 \
-    -I /system/lib64/vndk-sp-29 \
-    -I /system/lib/vndk-29 \
-    -I /system/lib/vndk-sp-29 \
-    -I /system/usr/icu"
-
   # Example output of dump.erofs is as below, and the data used in the test start
   # at line 11. Column 1 is inode id, column 2 is inode type and column 3 is name.
   # Each line is captured in variable "entry", awk is used to get type and name.
@@ -197,7 +152,7 @@
     sort -n -o "$files_in_spdx_file" "$files_in_spdx_file"
 
     echo ============ Diffing files in $f and SBOM
-    diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name"
+    diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name" ""
   done
 
   RAMDISK_IMAGES="$product_out/ramdisk.img"
@@ -215,7 +170,7 @@
     grep "FileName: /${partition_name}/" $product_out/sbom.spdx | sed 's/^FileName: //' | sort -n > "$files_in_spdx_file"
 
     echo ============ Diffing files in $f and SBOM
-    diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name"
+    diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name" ""
   done
 
   verify_package_verification_code "$product_out/sbom.spdx"
diff --git a/ui/build/config.go b/ui/build/config.go
index 5d1505a..084d28d 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -70,7 +70,6 @@
 	checkbuild               bool
 	dist                     bool
 	jsonModuleGraph          bool
-	apiBp2build              bool // Generate BUILD files for Soong modules that contribute APIs
 	bp2build                 bool
 	queryview                bool
 	reportMkMetrics          bool // Collect and report mk2bp migration progress metrics.
@@ -869,8 +868,6 @@
 			c.jsonModuleGraph = true
 		} else if arg == "bp2build" {
 			c.bp2build = true
-		} else if arg == "api_bp2build" {
-			c.apiBp2build = true
 		} else if arg == "queryview" {
 			c.queryview = true
 		} else if arg == "soong_docs" {
@@ -970,7 +967,7 @@
 		return true
 	}
 
-	if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() && !c.ApiBp2build() {
+	if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() {
 		// Command line was empty, the default Ninja target is built
 		return true
 	}
@@ -1068,10 +1065,6 @@
 	return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
 }
 
-func (c *configImpl) ApiBp2buildMarkerFile() string {
-	return shared.JoinPath(c.SoongOutDir(), "api_bp2build.marker")
-}
-
 func (c *configImpl) ModuleGraphFile() string {
 	return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
 }
@@ -1113,10 +1106,6 @@
 	return c.bp2build
 }
 
-func (c *configImpl) ApiBp2build() bool {
-	return c.apiBp2build
-}
-
 func (c *configImpl) Queryview() bool {
 	return c.queryview
 }
@@ -1308,7 +1297,7 @@
 
 func (c *configImpl) UseRBE() bool {
 	// These alternate modes of running Soong do not use RBE / reclient.
-	if c.Bp2Build() || c.Queryview() || c.ApiBp2build() || c.JsonModuleGraph() {
+	if c.Bp2Build() || c.Queryview() || c.JsonModuleGraph() {
 		return false
 	}
 
diff --git a/ui/build/soong.go b/ui/build/soong.go
index b8543d9..44c20a0 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -41,7 +41,6 @@
 	bp2buildWorkspaceTag = "bp2build_workspace"
 	jsonModuleGraphTag   = "modulegraph"
 	queryviewTag         = "queryview"
-	apiBp2buildTag       = "api_bp2build"
 	soongDocsTag         = "soong_docs"
 
 	// bootstrapEpoch is used to determine if an incremental build is incompatible with the current
@@ -264,7 +263,6 @@
 		config.NamedGlobFile(bp2buildFilesTag),
 		config.NamedGlobFile(jsonModuleGraphTag),
 		config.NamedGlobFile(queryviewTag),
-		config.NamedGlobFile(apiBp2buildTag),
 		config.NamedGlobFile(soongDocsTag),
 	}
 }
@@ -305,9 +303,6 @@
 	}
 
 	queryviewDir := filepath.Join(config.SoongOutDir(), "queryview")
-	// The BUILD files will be generated in out/soong/.api_bp2build (no symlinks to src files)
-	// The final workspace will be generated in out/soong/api_bp2build
-	apiBp2buildDir := filepath.Join(config.SoongOutDir(), ".api_bp2build")
 
 	pbfs := []PrimaryBuilderFactory{
 		{
@@ -355,15 +350,6 @@
 			),
 		},
 		{
-			name:        apiBp2buildTag,
-			description: fmt.Sprintf("generating BUILD files for API contributions at %s", apiBp2buildDir),
-			config:      config,
-			output:      config.ApiBp2buildMarkerFile(),
-			specificArgs: append(baseArgs,
-				"--bazel_api_bp2build_dir", apiBp2buildDir,
-			),
-		},
-		{
 			name:        soongDocsTag,
 			description: fmt.Sprintf("generating Soong docs at %s", config.SoongDocsHtml()),
 			config:      config,
@@ -533,10 +519,6 @@
 			checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(queryviewTag))
 		}
 
-		if config.ApiBp2build() {
-			checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(apiBp2buildTag))
-		}
-
 		if config.SoongDocs() {
 			checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(soongDocsTag))
 		}
@@ -608,10 +590,6 @@
 		targets = append(targets, config.QueryviewMarkerFile())
 	}
 
-	if config.ApiBp2build() {
-		targets = append(targets, config.ApiBp2buildMarkerFile())
-	}
-
 	if config.SoongDocs() {
 		targets = append(targets, config.SoongDocsHtml())
 	}
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index fb760ac..7b25d50 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -40,10 +40,11 @@
 	}
 
 	n := &NinjaReader{
-		status: status,
-		fifo:   fifo,
-		done:   make(chan bool),
-		cancel: make(chan bool),
+		status:     status,
+		fifo:       fifo,
+		forceClose: make(chan bool),
+		done:       make(chan bool),
+		cancelOpen: make(chan bool),
 	}
 
 	go n.run()
@@ -52,10 +53,11 @@
 }
 
 type NinjaReader struct {
-	status ToolStatus
-	fifo   string
-	done   chan bool
-	cancel chan bool
+	status     ToolStatus
+	fifo       string
+	forceClose chan bool
+	done       chan bool
+	cancelOpen chan bool
 }
 
 const NINJA_READER_CLOSE_TIMEOUT = 5 * time.Second
@@ -63,18 +65,34 @@
 // Close waits for NinjaReader to finish reading from the fifo, or 5 seconds.
 func (n *NinjaReader) Close() {
 	// Signal the goroutine to stop if it is blocking opening the fifo.
-	close(n.cancel)
+	close(n.cancelOpen)
 
+	// Ninja should already have exited or been killed, wait 5 seconds for the FIFO to be closed and any
+	// remaining messages to be processed through the NinjaReader.run goroutine.
 	timeoutCh := time.After(NINJA_READER_CLOSE_TIMEOUT)
-
 	select {
 	case <-n.done:
-		// Nothing
+		return
 	case <-timeoutCh:
-		n.status.Error(fmt.Sprintf("ninja fifo didn't finish after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
+		// Channel is not closed yet
 	}
 
-	return
+	n.status.Error(fmt.Sprintf("ninja fifo didn't finish after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
+
+	// Force close the reader even if the FIFO didn't close.
+	close(n.forceClose)
+
+	// Wait again for the reader thread to acknowledge the close before giving up and assuming it isn't going
+	// to send anything else.
+	timeoutCh = time.After(NINJA_READER_CLOSE_TIMEOUT)
+	select {
+	case <-n.done:
+		return
+	case <-timeoutCh:
+		// Channel is not closed yet
+	}
+
+	n.status.Verbose(fmt.Sprintf("ninja fifo didn't finish even after force closing after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
 }
 
 func (n *NinjaReader) run() {
@@ -98,7 +116,7 @@
 	select {
 	case f = <-fileCh:
 		// Nothing
-	case <-n.cancel:
+	case <-n.cancelOpen:
 		return
 	}
 
@@ -108,33 +126,58 @@
 
 	running := map[uint32]*Action{}
 
+	msgChan := make(chan *ninja_frontend.Status)
+
+	// Read from the ninja fifo and decode the protobuf in a goroutine so the main NinjaReader.run goroutine
+	// can listen
+	go func() {
+		defer close(msgChan)
+		for {
+			size, err := readVarInt(r)
+			if err != nil {
+				if err != io.EOF {
+					n.status.Error(fmt.Sprintf("Got error reading from ninja: %s", err))
+				}
+				return
+			}
+
+			buf := make([]byte, size)
+			_, err = io.ReadFull(r, buf)
+			if err != nil {
+				if err == io.EOF {
+					n.status.Print(fmt.Sprintf("Missing message of size %d from ninja\n", size))
+				} else {
+					n.status.Error(fmt.Sprintf("Got error reading from ninja: %s", err))
+				}
+				return
+			}
+
+			msg := &ninja_frontend.Status{}
+			err = proto.Unmarshal(buf, msg)
+			if err != nil {
+				n.status.Print(fmt.Sprintf("Error reading message from ninja: %v", err))
+				continue
+			}
+
+			msgChan <- msg
+		}
+	}()
+
 	for {
-		size, err := readVarInt(r)
-		if err != nil {
-			if err != io.EOF {
-				n.status.Error(fmt.Sprintf("Got error reading from ninja: %s", err))
-			}
-			return
+		var msg *ninja_frontend.Status
+		var msgOk bool
+		select {
+		case <-n.forceClose:
+			// Close() has been called, but the reader goroutine didn't get EOF after 5 seconds
+			break
+		case msg, msgOk = <-msgChan:
+			// msg is ready or closed
 		}
 
-		buf := make([]byte, size)
-		_, err = io.ReadFull(r, buf)
-		if err != nil {
-			if err == io.EOF {
-				n.status.Print(fmt.Sprintf("Missing message of size %d from ninja\n", size))
-			} else {
-				n.status.Error(fmt.Sprintf("Got error reading from ninja: %s", err))
-			}
-			return
+		if !msgOk {
+			// msgChan is closed
+			break
 		}
-
-		msg := &ninja_frontend.Status{}
-		err = proto.Unmarshal(buf, msg)
-		if err != nil {
-			n.status.Print(fmt.Sprintf("Error reading message from ninja: %v", err))
-			continue
-		}
-
 		// Ignore msg.BuildStarted
 		if msg.TotalEdges != nil {
 			n.status.SetTotalActions(int(msg.TotalEdges.GetTotalEdges()))
diff --git a/xml/xml.go b/xml/xml.go
index 8c0c072..20a26f5 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -146,7 +146,11 @@
 }
 
 func (p *prebuiltEtcXml) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
-	baseAttrs := p.PrebuiltEtc.Bp2buildHelper(ctx)
+	baseAttrs, convertible := p.PrebuiltEtc.Bp2buildHelper(ctx)
+
+	if !convertible {
+		return
+	}
 
 	var schema *string
 	if p.properties.Schema != nil {