Merge "Shard srcjars when sharding javac compilation" into main
diff --git a/README.md b/README.md
index 2d8f0af..22daa95 100644
--- a/README.md
+++ b/README.md
@@ -26,8 +26,6 @@
 [bug tracker](https://issuetracker.google.com/issues/new?component=381517) or
 or write us at android-building@googlegroups.com .
 
-For Googlers, see our [internal documentation](http://go/soong).
-
 ## Android.bp file format
 
 By design, Android.bp files are very simple.  There are no conditionals or
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index d2ddfdf..faa4ddb 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -32,6 +32,8 @@
         "aconfig_values_test.go",
         "aconfig_value_set_test.go",
         "java_aconfig_library_test.go",
+        "cc_aconfig_library_test.go",
+        "rust_aconfig_library_test.go",
     ],
     pluginFor: ["soong_build"],
 }
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 5cdf5b6..f19ddb8 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -15,16 +15,18 @@
 package aconfig
 
 import (
-	"android/soong/android"
 	"fmt"
 	"strings"
 
+	"android/soong/android"
+	"android/soong/bazel"
 	"github.com/google/blueprint"
 )
 
 type DeclarationsModule struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.BazelModuleBase
 
 	// Properties for "aconfig_declarations"
 	properties struct {
@@ -47,8 +49,7 @@
 	android.InitAndroidModule(module)
 	android.InitDefaultableModule(module)
 	module.AddProperties(&module.properties)
-	// TODO: bp2build
-	//android.InitBazelModule(module)
+	android.InitBazelModule(module)
 
 	return module
 }
@@ -73,7 +74,9 @@
 	// RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that
 	// match our package.
 	valuesFromConfig := ctx.Config().ReleaseAconfigValueSets()
-	ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
+	if valuesFromConfig != "" {
+		ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig)
+	}
 }
 
 func (module *DeclarationsModule) OutputFiles(tag string) (android.Paths, error) {
@@ -159,3 +162,26 @@
 	})
 
 }
+
+type bazelAconfigDeclarationsAttributes struct {
+	Srcs    bazel.LabelListAttribute
+	Package string
+}
+
+func (module *DeclarationsModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	if ctx.ModuleType() != "aconfig_declarations" {
+		return
+	}
+	srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, module.properties.Srcs))
+
+	attrs := bazelAconfigDeclarationsAttributes{
+		Srcs:    srcs,
+		Package: module.properties.Package,
+	}
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "aconfig_declarations",
+		Bzl_load_location: "//build/bazel/rules/aconfig:aconfig_declarations.bzl",
+	}
+
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, &attrs)
+}
diff --git a/aconfig/aconfig_value_set.go b/aconfig/aconfig_value_set.go
index 252908f..cd178d4 100644
--- a/aconfig/aconfig_value_set.go
+++ b/aconfig/aconfig_value_set.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
 	"github.com/google/blueprint"
 )
 
@@ -23,6 +24,7 @@
 type ValueSetModule struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.BazelModuleBase
 
 	properties struct {
 		// aconfig_values modules
@@ -36,8 +38,7 @@
 	android.InitAndroidModule(module)
 	android.InitDefaultableModule(module)
 	module.AddProperties(&module.properties)
-	// TODO: bp2build
-	//android.InitBazelModule(module)
+	android.InitBazelModule(module)
 
 	return module
 }
@@ -90,3 +91,23 @@
 		AvailablePackages: packages,
 	})
 }
+
+type bazelAconfigValueSetAttributes struct {
+	Values bazel.LabelListAttribute
+}
+
+func (module *ValueSetModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	if ctx.ModuleType() != "aconfig_value_set" {
+		return
+	}
+
+	attrs := bazelAconfigValueSetAttributes{
+		Values: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, module.properties.Values)),
+	}
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "aconfig_value_set",
+		Bzl_load_location: "//build/bazel/rules/aconfig:aconfig_value_set.bzl",
+	}
+
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, &attrs)
+}
diff --git a/aconfig/aconfig_values.go b/aconfig/aconfig_values.go
index 91f1c90..03a930d 100644
--- a/aconfig/aconfig_values.go
+++ b/aconfig/aconfig_values.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
 	"github.com/google/blueprint"
 )
 
@@ -23,6 +24,7 @@
 type ValuesModule struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.BazelModuleBase
 
 	properties struct {
 		// aconfig files, relative to this Android.bp file
@@ -39,8 +41,7 @@
 	android.InitAndroidModule(module)
 	android.InitDefaultableModule(module)
 	module.AddProperties(&module.properties)
-	// TODO: bp2build
-	//android.InitBazelModule(module)
+	android.InitBazelModule(module)
 
 	return module
 }
@@ -68,3 +69,27 @@
 	}
 	ctx.SetProvider(valuesProviderKey, providerData)
 }
+
+type bazelAconfigValuesAttributes struct {
+	Srcs    bazel.LabelListAttribute
+	Package string
+}
+
+func (module *ValuesModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	if ctx.ModuleType() != "aconfig_values" {
+		return
+	}
+
+	srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, module.properties.Srcs))
+
+	attrs := bazelAconfigValuesAttributes{
+		Srcs:    srcs,
+		Package: module.properties.Package,
+	}
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "aconfig_values",
+		Bzl_load_location: "//build/bazel/rules/aconfig:aconfig_values.bzl",
+	}
+
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, &attrs)
+}
diff --git a/aconfig/cc_aconfig_library.go b/aconfig/cc_aconfig_library.go
index 14090bc..0583bef 100644
--- a/aconfig/cc_aconfig_library.go
+++ b/aconfig/cc_aconfig_library.go
@@ -16,8 +16,11 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
 	"android/soong/cc"
+
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 
 	"fmt"
 	"strings"
@@ -29,9 +32,14 @@
 
 var ccDeclarationsTag = ccDeclarationsTagType{}
 
+const baseLibDep = "server_configurable_flags"
+
 type CcAconfigLibraryProperties struct {
 	// name of the aconfig_declarations module to generate a library for
 	Aconfig_declarations string
+
+	// whether to generate test mode version of the library
+	Test *bool
 }
 
 type CcAconfigLibraryCallbacks struct {
@@ -67,7 +75,7 @@
 	}
 
 	// Add a dependency for the aconfig flags base library
-	deps.SharedLibs = append(deps.SharedLibs, "server_configurable_flags")
+	deps.SharedLibs = append(deps.SharedLibs, baseLibDep)
 	// TODO: It'd be really nice if we could reexport this library and not make everyone do it.
 
 	return deps
@@ -113,6 +121,12 @@
 	}
 	declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
 
+	var mode string
+	if proptools.Bool(this.properties.Test) {
+		mode = "test"
+	} else {
+		mode = "production"
+	}
 	ctx.Build(pctx, android.BuildParams{
 		Rule:  cppRule,
 		Input: declarations.IntermediatePath,
@@ -123,6 +137,37 @@
 		Description: "cc_aconfig_library",
 		Args: map[string]string{
 			"gendir": this.generatedDir.String(),
+			"mode":   mode,
 		},
 	})
 }
+
+type bazelCcAconfigLibraryAttributes struct {
+	Aconfig_declarations bazel.LabelAttribute
+	Dynamic_deps         bazel.LabelListAttribute
+}
+
+// Convert the cc_aconfig_library module to bazel.
+//
+// This method is called from cc.ConvertWithBp2build to actually convert the
+// cc_aconfig_library module. This is necessary since the factory method of this
+// module type returns a cc library and the bp2build conversion is called on the
+// cc library type.
+
+func (this *CcAconfigLibraryCallbacks) GeneratorBp2build(ctx android.Bp2buildMutatorContext) bool {
+	if ctx.ModuleType() != "cc_aconfig_library" {
+		return false
+	}
+
+	attrs := bazelCcAconfigLibraryAttributes{
+		Aconfig_declarations: *bazel.MakeLabelAttribute(android.BazelLabelForModuleDepSingle(ctx, this.properties.Aconfig_declarations).Label),
+		Dynamic_deps:         bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, []string{baseLibDep})),
+	}
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "cc_aconfig_library",
+		Bzl_load_location: "//build/bazel/rules/cc:cc_aconfig_library.bzl",
+	}
+
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: ctx.ModuleName()}, &attrs)
+	return true
+}
diff --git a/aconfig/cc_aconfig_library_test.go b/aconfig/cc_aconfig_library_test.go
new file mode 100644
index 0000000..6f17c75
--- /dev/null
+++ b/aconfig/cc_aconfig_library_test.go
@@ -0,0 +1,67 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package aconfig
+
+import (
+	"fmt"
+	"testing"
+
+	"android/soong/android"
+	"android/soong/cc"
+)
+
+var codegenModeTestData = []struct {
+	setting, expected string
+}{
+	{"", "production"},
+	{"test: false,", "production"},
+	{"test: true,", "test"},
+}
+
+func TestCCCodegenMode(t *testing.T) {
+	for _, testData := range codegenModeTestData {
+		testCCCodegenModeHelper(t, testData.setting, testData.expected)
+	}
+}
+
+func testCCCodegenModeHelper(t *testing.T, bpMode string, ruleMode string) {
+	t.Helper()
+	result := android.GroupFixturePreparers(
+		PrepareForTestWithAconfigBuildComponents,
+		cc.PrepareForTestWithCcDefaultModules).
+		ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+		RunTestWithBp(t, fmt.Sprintf(`
+			aconfig_declarations {
+				name: "my_aconfig_declarations",
+				package: "com.example.package",
+				srcs: ["foo.aconfig"],
+			}
+
+			cc_library {
+    		name: "server_configurable_flags",
+    		srcs: ["server_configurable_flags.cc"],
+			}
+
+			cc_aconfig_library {
+				name: "my_cc_aconfig_library",
+				aconfig_declarations: "my_aconfig_declarations",
+				%s
+			}
+		`, bpMode))
+
+	module := result.ModuleForTests("my_cc_aconfig_library", "android_arm64_armv8-a_shared")
+	rule := module.Rule("cc_aconfig_library")
+	android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode)
+}
diff --git a/aconfig/init.go b/aconfig/init.go
index 797388d..3d62714 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -64,13 +64,14 @@
 			Command: `rm -rf ${gendir}` +
 				` && mkdir -p ${gendir}` +
 				` && ${aconfig} create-cpp-lib` +
+				`    --mode ${mode}` +
 				`    --cache ${in}` +
 				`    --out ${gendir}`,
 			CommandDeps: []string{
 				"$aconfig",
 				"$soong_zip",
 			},
-		}, "gendir")
+		}, "gendir", "mode")
 
 	rustRule = pctx.AndroidStaticRule("rust_aconfig_library",
 		blueprint.RuleParams{
@@ -97,12 +98,12 @@
 )
 
 func init() {
-	registerBuildComponents(android.InitRegistrationContext)
+	RegisterBuildComponents(android.InitRegistrationContext)
 	pctx.HostBinToolVariable("aconfig", "aconfig")
 	pctx.HostBinToolVariable("soong_zip", "soong_zip")
 }
 
-func registerBuildComponents(ctx android.RegistrationContext) {
+func RegisterBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("aconfig_declarations", DeclarationsFactory)
 	ctx.RegisterModuleType("aconfig_values", ValuesFactory)
 	ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
diff --git a/aconfig/testing.go b/aconfig/testing.go
index 60cefeb..f6489ec 100644
--- a/aconfig/testing.go
+++ b/aconfig/testing.go
@@ -20,7 +20,7 @@
 	"android/soong/android"
 )
 
-var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
+var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents)
 
 func runTest(t *testing.T, errorHandler android.FixtureErrorHandler, bp string) *android.TestResult {
 	return android.GroupFixturePreparers(PrepareForTestWithAconfigBuildComponents).
diff --git a/aidl_library/aidl_library.go b/aidl_library/aidl_library.go
index 7449d67..2c0aef7 100644
--- a/aidl_library/aidl_library.go
+++ b/aidl_library/aidl_library.go
@@ -64,7 +64,7 @@
 	Deps                bazel.LabelListAttribute
 }
 
-func (lib *AidlLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (lib *AidlLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	srcs := bazel.MakeLabelListAttribute(
 		android.BazelLabelForModuleSrc(
 			ctx,
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index fb2e0d7..a627d47 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -65,6 +65,7 @@
 
 		"build/bazel":                        Bp2BuildDefaultTrueRecursively,
 		"build/make/target/product/security": Bp2BuildDefaultTrue,
+		"build/make/tools":                   Bp2BuildDefaultTrue,
 		"build/make/tools/protos":            Bp2BuildDefaultTrue,
 		"build/make/tools/releasetools":      Bp2BuildDefaultTrue,
 		"build/make/tools/sbom":              Bp2BuildDefaultTrue,
@@ -79,6 +80,9 @@
 		"build/soong/scripts":                Bp2BuildDefaultTrueRecursively,
 
 		"cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
+		"cts/libs/json":                          Bp2BuildDefaultTrueRecursively,
+		"cts/tests/tests/gesture":                Bp2BuildDefaultTrueRecursively,
+		"platform_testing/libraries/annotations": Bp2BuildDefaultTrueRecursively,
 
 		"dalvik/tools/dexdeps": Bp2BuildDefaultTrueRecursively,
 
@@ -127,6 +131,7 @@
 		"external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
 		"external/auto/common":                   Bp2BuildDefaultTrueRecursively,
 		"external/auto/service":                  Bp2BuildDefaultTrueRecursively,
+		"external/auto/value":                    Bp2BuildDefaultTrueRecursively,
 		"external/boringssl":                     Bp2BuildDefaultTrueRecursively,
 		"external/bouncycastle":                  Bp2BuildDefaultTrue,
 		"external/brotli":                        Bp2BuildDefaultTrue,
@@ -178,6 +183,7 @@
 		"external/libjpeg-turbo":                 Bp2BuildDefaultTrueRecursively,
 		"external/libmpeg2":                      Bp2BuildDefaultTrueRecursively,
 		"external/libpng":                        Bp2BuildDefaultTrueRecursively,
+		"external/libphonenumber":                Bp2BuildDefaultTrueRecursively,
 		"external/libvpx":                        Bp2BuildDefaultTrueRecursively,
 		"external/libyuv":                        Bp2BuildDefaultTrueRecursively,
 		"external/lz4/lib":                       Bp2BuildDefaultTrue,
@@ -190,6 +196,7 @@
 		"external/openscreen":                    Bp2BuildDefaultTrueRecursively,
 		"external/ow2-asm":                       Bp2BuildDefaultTrueRecursively,
 		"external/pcre":                          Bp2BuildDefaultTrueRecursively,
+		"external/perfmark/api":                  Bp2BuildDefaultTrueRecursively,
 		"external/protobuf":                      Bp2BuildDefaultTrueRecursively,
 		"external/python/pyyaml/lib/yaml":        Bp2BuildDefaultTrueRecursively,
 		"external/python/six":                    Bp2BuildDefaultTrueRecursively,
@@ -221,6 +228,8 @@
 		"frameworks/av/media/module/foundation":              Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/module/minijail":                Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/services/minijail":                    Bp2BuildDefaultTrueRecursively,
+		"frameworks/base/apex/jobscheduler/service/jni":      Bp2BuildDefaultTrueRecursively,
+		"frameworks/base/core/java":                          Bp2BuildDefaultTrue,
 		"frameworks/base/libs/androidfw":                     Bp2BuildDefaultTrue,
 		"frameworks/base/libs/services":                      Bp2BuildDefaultTrue,
 		"frameworks/base/media/tests/MediaDump":              Bp2BuildDefaultTrue,
@@ -231,17 +240,22 @@
 		"frameworks/base/tools/aapt":                         Bp2BuildDefaultTrue,
 		"frameworks/base/tools/aapt2":                        Bp2BuildDefaultTrue,
 		"frameworks/base/tools/codegen":                      Bp2BuildDefaultTrueRecursively,
+		"frameworks/base/tools/locked_region_code_injection": Bp2BuildDefaultTrueRecursively,
 		"frameworks/base/tools/streaming_proto":              Bp2BuildDefaultTrueRecursively,
+		"frameworks/hardware/interfaces":                     Bp2BuildDefaultTrue,
+		"frameworks/hardware/interfaces/displayservice":      Bp2BuildDefaultTrueRecursively,
 		"frameworks/hardware/interfaces/stats/aidl":          Bp2BuildDefaultTrue,
 		"frameworks/libs/modules-utils/build":                Bp2BuildDefaultTrueRecursively,
-		"frameworks/libs/net/common/native":                  Bp2BuildDefaultTrueRecursively, // TODO(b/296014682): Remove this path
+		"frameworks/libs/modules-utils/java":                 Bp2BuildDefaultTrue,
 		"frameworks/native":                                  Bp2BuildDefaultTrue,
 		"frameworks/native/libs/adbd_auth":                   Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/arect":                       Bp2BuildDefaultTrueRecursively,
+		"frameworks/native/libs/binder":                      Bp2BuildDefaultTrue,
 		"frameworks/native/libs/gui":                         Bp2BuildDefaultTrue,
 		"frameworks/native/libs/math":                        Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/nativebase":                  Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/permission":                  Bp2BuildDefaultTrueRecursively,
+		"frameworks/native/libs/ui":                          Bp2BuildDefaultTrue,
 		"frameworks/native/libs/vr":                          Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/opengl/tests/gl2_cameraeye":       Bp2BuildDefaultTrue,
 		"frameworks/native/opengl/tests/gl2_java":            Bp2BuildDefaultTrue,
@@ -285,13 +299,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,
@@ -299,6 +309,9 @@
 		"hardware/interfaces/neuralnetworks/1.2/vts":              Bp2BuildDefaultFalseRecursively,
 		"hardware/interfaces/neuralnetworks/1.3/vts":              Bp2BuildDefaultFalseRecursively,
 		"hardware/interfaces/neuralnetworks/1.4/vts":              Bp2BuildDefaultFalseRecursively,
+		"hardware/interfaces/tests":                               Bp2BuildDefaultTrueRecursively,
+		"hardware/interfaces/tests/extension":                     Bp2BuildDefaultFalseRecursively, // missing deps
+		"hardware/interfaces/tests/msgq":                          Bp2BuildDefaultFalseRecursively, // missing deps
 
 		"libnativehelper": Bp2BuildDefaultTrueRecursively,
 
@@ -332,6 +345,7 @@
 		"prebuilts/clang/host/linux-x86":                   Bp2BuildDefaultTrueRecursively,
 		"prebuilts/gradle-plugin":                          Bp2BuildDefaultTrueRecursively,
 		"prebuilts/runtime/mainline/platform/sdk":          Bp2BuildDefaultTrueRecursively,
+		"prebuilts/module_sdk":                             Bp2BuildDefaultTrueRecursively,
 		"prebuilts/sdk":                                    Bp2BuildDefaultTrue,
 		"prebuilts/sdk/current/androidx":                   Bp2BuildDefaultTrue,
 		"prebuilts/sdk/current/androidx-legacy":            Bp2BuildDefaultTrue,
@@ -364,6 +378,7 @@
 		"system/core/libprocessgroup/cgrouprc":                   Bp2BuildDefaultTrue,
 		"system/core/libprocessgroup/cgrouprc_format":            Bp2BuildDefaultTrue,
 		"system/core/libsparse":                                  Bp2BuildDefaultTrueRecursively,
+		"system/core/libstats/expresslog":                        Bp2BuildDefaultTrueRecursively,
 		"system/core/libsuspend":                                 Bp2BuildDefaultTrue,
 		"system/core/libsystem":                                  Bp2BuildDefaultTrueRecursively,
 		"system/core/libsysutils":                                Bp2BuildDefaultTrueRecursively,
@@ -372,6 +387,7 @@
 		"system/core/mkbootfs":                                   Bp2BuildDefaultTrueRecursively,
 		"system/core/property_service/libpropertyinfoparser":     Bp2BuildDefaultTrueRecursively,
 		"system/core/property_service/libpropertyinfoserializer": Bp2BuildDefaultTrueRecursively,
+		"system/core/trusty/libtrusty":                           Bp2BuildDefaultTrue,
 		"system/extras/f2fs_utils":                               Bp2BuildDefaultTrueRecursively,
 		"system/extras/toolchain-extras":                         Bp2BuildDefaultTrue,
 		"system/extras/verity":                                   Bp2BuildDefaultTrueRecursively,
@@ -380,6 +396,7 @@
 		"system/libartpalette":                                   Bp2BuildDefaultTrueRecursively,
 		"system/libbase":                                         Bp2BuildDefaultTrueRecursively,
 		"system/libfmq":                                          Bp2BuildDefaultTrue,
+		"system/libhidl":                                         Bp2BuildDefaultTrue,
 		"system/libhidl/libhidlmemory":                           Bp2BuildDefaultTrue,
 		"system/libhidl/transport":                               Bp2BuildDefaultTrue,
 		"system/libhidl/transport/allocator/1.0":                 Bp2BuildDefaultTrue,
@@ -387,8 +404,7 @@
 		"system/libhidl/transport/manager/1.0":                   Bp2BuildDefaultTrue,
 		"system/libhidl/transport/manager/1.1":                   Bp2BuildDefaultTrue,
 		"system/libhidl/transport/manager/1.2":                   Bp2BuildDefaultTrue,
-		"system/libhidl/transport/memory/1.0":                    Bp2BuildDefaultTrue,
-		"system/libhidl/transport/memory/token/1.0":              Bp2BuildDefaultTrue,
+		"system/libhidl/transport/memory":                        Bp2BuildDefaultTrueRecursively,
 		"system/libhidl/transport/safe_union/1.0":                Bp2BuildDefaultTrue,
 		"system/libhidl/transport/token/1.0":                     Bp2BuildDefaultTrue,
 		"system/libhidl/transport/token/1.0/utils":               Bp2BuildDefaultTrue,
@@ -398,14 +414,14 @@
 		"system/libziparchive":                                   Bp2BuildDefaultTrueRecursively,
 		"system/logging":                                         Bp2BuildDefaultTrueRecursively,
 		"system/media":                                           Bp2BuildDefaultTrue,
-		"system/media/audio":                                     Bp2BuildDefaultTrueRecursively,
 		"system/media/alsa_utils":                                Bp2BuildDefaultTrueRecursively,
+		"system/media/audio":                                     Bp2BuildDefaultTrueRecursively,
 		"system/media/audio_utils":                               Bp2BuildDefaultTrueRecursively,
 		"system/media/camera":                                    Bp2BuildDefaultTrueRecursively,
 		"system/memory/libion":                                   Bp2BuildDefaultTrueRecursively,
 		"system/memory/libmemunreachable":                        Bp2BuildDefaultTrueRecursively,
-		"system/sepolicy/apex":                                   Bp2BuildDefaultTrueRecursively,
 		"system/security/fsverity":                               Bp2BuildDefaultTrueRecursively,
+		"system/sepolicy/apex":                                   Bp2BuildDefaultTrueRecursively,
 		"system/testing/gtest_extras":                            Bp2BuildDefaultTrueRecursively,
 		"system/timezone/apex":                                   Bp2BuildDefaultTrueRecursively,
 		"system/timezone/output_data":                            Bp2BuildDefaultTrueRecursively,
@@ -413,18 +429,22 @@
 		"system/timezone/testing":                                Bp2BuildDefaultTrueRecursively,
 		"system/tools/aidl/build/tests_bp2build":                 Bp2BuildDefaultTrue,
 		"system/tools/aidl/metadata":                             Bp2BuildDefaultTrue,
-		"system/tools/hidl/metadata":                             Bp2BuildDefaultTrue,
+		"system/tools/hidl":                                      Bp2BuildDefaultTrueRecursively,
 		"system/tools/mkbootimg":                                 Bp2BuildDefaultTrueRecursively,
 		"system/tools/sysprop":                                   Bp2BuildDefaultTrue,
 		"system/tools/xsdc/utils":                                Bp2BuildDefaultTrueRecursively,
 		"system/unwinding/libunwindstack":                        Bp2BuildDefaultTrueRecursively,
 
-		"tools/apifinder":                            Bp2BuildDefaultTrue,
-		"tools/apksig":                               Bp2BuildDefaultTrue,
-		"tools/external_updater":                     Bp2BuildDefaultTrueRecursively,
-		"tools/metalava":                             Bp2BuildDefaultTrue,
-		"tools/platform-compat/java/android/compat":  Bp2BuildDefaultTrueRecursively,
-		"tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
+		"test/vts/vts_hal_hidl_target": Bp2BuildDefaultTrueRecursively,
+
+		"tools/apifinder":                             Bp2BuildDefaultTrue,
+		"tools/apksig":                                Bp2BuildDefaultTrue,
+		"tools/dexter/slicer":                         Bp2BuildDefaultTrueRecursively,
+		"tools/external_updater":                      Bp2BuildDefaultTrueRecursively,
+		"tools/metalava":                              Bp2BuildDefaultTrueRecursively,
+		"tools/platform-compat/java/android/compat":   Bp2BuildDefaultTrueRecursively,
+		"tools/platform-compat/java/androidprocessor": Bp2BuildDefaultTrueRecursively,
+		"tools/tradefederation/prebuilts/filegroups":  Bp2BuildDefaultTrueRecursively,
 	}
 
 	Bp2buildKeepExistingBuildFile = map[string]bool{
@@ -547,6 +567,7 @@
 		"remote-color-resources-compile-colors",
 
 		// framework-minus-apex
+		"ImmutabilityAnnotationProcessor",
 		"android.mime.types.minimized",
 		"debian.mime.types.minimized",
 		"framework-javastream-protos",
@@ -556,10 +577,8 @@
 		"apache-commons-math",
 		"cbor-java",
 		"icu4j_calendar_astronomer",
-		"json",
 		"remote-color-resources-compile-public",
 		"statslog-art-java-gen",
-		"statslog-framework-java-gen",
 
 		"AndroidCommonLint",
 		"ImmutabilityAnnotation",
@@ -592,10 +611,6 @@
 		"libandroid_runtime_lazy",
 		"libandroid_runtime_vm_headers",
 		"libaudioclient_aidl_conversion_util",
-		"libbinder",
-		"libbinder_device_interface_sources",
-		"libbinder_aidl",
-		"libbinder_headers",
 		"libbinder_headers_platform_shared",
 		"libbinderthreadstateutils",
 		"libbluetooth-types-header",
@@ -628,9 +643,6 @@
 		"libtextclassifier_hash_static",
 		"libtflite_kernel_utils",
 		"libtinyxml2",
-		"libui",
-		"libui-types",
-		"libui_headers",
 		"libvorbisidec",
 		"media_ndk_headers",
 		"media_plugin_headers",
@@ -638,8 +650,6 @@
 		"mediaswcodec.xml",
 		"neuralnetworks_types",
 		"libneuralnetworks_common",
-		// packagemanager_aidl_interface is created implicitly in packagemanager_aidl module
-		"packagemanager_aidl_interface",
 		"philox_random",
 		"philox_random_headers",
 		"server_configurable_flags",
@@ -681,9 +691,6 @@
 		//external/fec
 		"libfec_rs",
 
-		//frameworks/base/core/java
-		"IDropBoxManagerService_aidl",
-
 		//system/extras/ext4_utils
 		"libext4_utils",
 		"mke2fs_conf",
@@ -704,10 +711,6 @@
 		"car-ui-androidx-lifecycle-common-nodeps",
 		"car-ui-androidx-constraintlayout-solver-nodeps",
 
-		//system/libhidl
-		"libhidlbase", // needed by cc_hidl_library
-		"libhidl_gtest_helper",
-
 		//frameworks/native/libs/input
 		"inputconstants_aidl",
 
@@ -716,11 +719,6 @@
 
 		"libusb",
 
-		// needed by liblogd
-		"ILogcatManagerService_aidl",
-		"libincremental_aidl-cpp",
-		"incremental_aidl",
-
 		//frameworks/native/cmds/cmd
 		"libcmd",
 
@@ -763,6 +761,7 @@
 		//system/core/fs_mgr
 		"libfs_mgr",
 
+		"libcodec2_aidl",
 		"libcodec2_hidl@1.0",
 		"libcodec2_hidl@1.1",
 		"libcodec2_hidl@1.2",
@@ -862,15 +861,14 @@
 
 		"libstagefright_headers",
 
+		// Apps with JNI libs
+		"SimpleJNI",
+		"libsimplejni",
+
 		// aidl
 		"aidl",
 		"libaidl-common",
 
-		// java_resources containing only a single filegroup
-		"libauto_value_plugin",
-		"auto_value_plugin_resources",
-		"auto_value_extension",
-
 		// Used by xsd_config
 		"xsdc",
 
@@ -910,24 +908,80 @@
 
 		"merge_annotation_zips_test",
 
-		// bouncycastle dep
-		"platform-test-annotations",
-
 		// java_resources with multiple resource_dirs
 		"emma",
+
+		// NDK STL
+		"ndk_libc++abi",
+		"ndk_libunwind",
+		"ndk_libc++_static",
+		"ndk_libc++_shared",
+		"ndk_system",
+
+		// allowlist //prebuilts/common/misc/androidx-test/...
+		"androidx.test.runner",
+		"androidx.test.runner-nodeps",
+		"androidx.test.services.storage",
+		"androidx.test.services.storage-nodeps",
+		"androidx.test.monitor",
+		"androidx.test.monitor-nodeps",
+		"androidx.test.annotation",
+		"androidx.test.annotation-nodeps",
+
+		// jni deps of an internal android_test (b/297405812)
+		"libdexmakerjvmtiagent",
+		"libopenjdkjvmti_headers",
+		"libstaticjvmtiagent",
+
+		// tradefed deps
+		"tradefed-protos",
+		"grpc-java",
+		"grpc-java-api",
+		"grpc-java-auth",
+		"grpc-java-context",
+		"grpc-java-core",
+		"grpc-java-core-inprocess",
+		"grpc-java-core-internal",
+		"grpc-java-core-util",
+		"grpc-java-protobuf",
+		"grpc-java-protobuf-lite",
+		"grpc-java-stub",
+		"grpc-java-annotation-stubs",
+		"grpc-java-annotation-stubs-srcjar",
+		"gen_annotations",
+		"opencensus-java-contrib-grpc-metrics",
+		"opencensus-java-api",
+		"gson",
+		"GsonBuildConfig.java",
+		"gson_version_generator",
+		"lab-resource-grpc",
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
+		// go/keep-sorted start
+		"aconfig_declarations",
+		"aconfig_value_set",
+		"aconfig_values",
 		"aidl_interface_headers",
 		"bpf",
+		"cc_aconfig_library",
+		"cc_prebuilt_library",
+		"cc_prebuilt_library_headers",
+		"cc_prebuilt_library_shared",
+		"cc_prebuilt_library_static",
 		"combined_apis",
-		"license",
-		"linker_config",
+		"droiddoc_exported_dir",
 		"java_import",
 		"java_import_host",
 		"java_sdk_library",
+		"java_sdk_library_import",
+		"license",
+		"linker_config",
+		"ndk_headers",
+		"ndk_library",
 		"sysprop_library",
 		"xsd_config",
+		// go/keep-sorted end
 	}
 
 	// Add the names of modules that bp2build should never convert, if it is
@@ -1003,8 +1057,6 @@
 		"conscrypt-for-host",               // TODO(b/210751803), we don't handle path property for filegroups
 		"host-libprotobuf-java-full",       // TODO(b/210751803), we don't handle path property for filegroups
 		"libprotobuf-internal-python-srcs", // TODO(b/210751803), we don't handle path property for filegroups
-		"libprotobuf-java-full",            // TODO(b/210751803), we don't handle path property for filegroups
-		"libprotobuf-java-util-full",       // TODO(b/210751803), we don't handle path property for filegroups
 
 		// go deps:
 		"analyze_bcpf",              // depends on bpmodify a blueprint_go_binary.
@@ -1016,30 +1068,32 @@
 		"libtombstoned_client_rust_bridge_code", "libtombstoned_client_wrapper", // rust conversions are not supported
 
 		// unconverted deps
-		"apexer_with_DCLA_preprocessing_test",                        // depends on unconverted modules: apexer_test_host_tools, com.android.example.apex
-		"adb",                                                        // depends on unconverted modules: AdbWinApi, libandroidfw, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi
-		"android_icu4j_srcgen",                                       // depends on unconverted modules: currysrc
-		"android_icu4j_srcgen_binary",                                // depends on unconverted modules: android_icu4j_srcgen, currysrc
-		"apex_compression_test",                                      // depends on unconverted modules: soong_zip, com.android.example.apex
-		"apex_manifest_proto_java",                                   // b/210751803, depends on libprotobuf-java-full
-		"art-script",                                                 // depends on unconverted modules: dalvikvm, dex2oat
-		"bin2c_fastdeployagent",                                      // depends on unconverted modules: deployagent
-		"CarHTMLViewer",                                              // depends on unconverted modules android.car-stubs, car-ui-lib
-		"com.android.runtime",                                        // depends on unconverted modules: bionic-linker-config, linkerconfig
-		"currysrc",                                                   // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9
-		"dex2oat-script",                                             // depends on unconverted modules: dex2oat
-		"generated_android_icu4j_resources",                          // depends on unconverted modules: android_icu4j_srcgen_binary
-		"generated_android_icu4j_test_resources",                     // depends on unconverted modules: android_icu4j_srcgen_binary
+		"CarHTMLViewer",                          // depends on unconverted modules android.car-stubs, car-ui-lib
+		"adb",                                    // depends on unconverted modules: AdbWinApi, libandroidfw, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi
+		"android_icu4j_srcgen",                   // depends on unconverted modules: currysrc
+		"android_icu4j_srcgen_binary",            // depends on unconverted modules: android_icu4j_srcgen, currysrc
+		"apex_compression_test",                  // depends on unconverted modules: soong_zip, com.android.example.apex
+		"apex_manifest_proto_java",               // b/210751803, depends on libprotobuf-java-full
+		"apexer_with_DCLA_preprocessing_test",    // depends on unconverted modules: apexer_test_host_tools, com.android.example.apex
+		"art-script",                             // depends on unconverted modules: dalvikvm, dex2oat
+		"bin2c_fastdeployagent",                  // depends on unconverted modules: deployagent
+		"com.android.runtime",                    // depends on unconverted modules: bionic-linker-config, linkerconfig
+		"currysrc",                               // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9
+		"dex2oat-script",                         // depends on unconverted modules: dex2oat
+		"generated_android_icu4j_resources",      // depends on unconverted modules: android_icu4j_srcgen_binary
+		"generated_android_icu4j_test_resources", // depends on unconverted modules: android_icu4j_srcgen_binary
+		"hidl_system_api_test",
+		"hidl_test_java",
 		"host-libprotobuf-java-nano",                                 // b/220869005, depends on libprotobuf-java-nano
 		"jacoco-stubs",                                               // b/245767077, depends on droidstubs
 		"libapexutil",                                                // depends on unconverted modules: apex-info-list-tinyxml
 		"libart",                                                     // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
+		"libart-runtime",                                             // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
+		"libart-runtime-for-test",                                    // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
 		"libart-runtime-gtest",                                       // depends on unconverted modules: libgtest_isolated, libart-compiler, libdexfile, libprofile, libartbase, libartbase-art-gtest
 		"libart_headers",                                             // depends on unconverted modules: art_libartbase_headers
 		"libartbase-art-gtest",                                       // depends on unconverted modules: libgtest_isolated, libart, libart-compiler, libdexfile, libprofile
 		"libartbased-art-gtest",                                      // depends on unconverted modules: libgtest_isolated, libartd, libartd-compiler, libdexfiled, libprofiled
-		"libart-runtime",                                             // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
-		"libart-runtime-for-test",                                    // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
 		"libartd",                                                    // depends on unconverted modules: art_operator_srcs, libcpu_features, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfiled, libnativebridge, libnativeloader, libsigchain, libartbased, libprofiled, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api
 		"libartd-runtime",                                            // depends on unconverted modules: art_operator_srcs, libcpu_features, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfiled, libnativebridge, libnativeloader, libsigchain, libartbased, libprofiled, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api
 		"libartd-runtime-gtest",                                      // depends on unconverted modules: libgtest_isolated, libartd-compiler, libdexfiled, libprofiled, libartbased, libartbased-art-gtest
@@ -1051,6 +1105,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_*
@@ -1611,6 +1666,7 @@
 
 		// python_test_host with test data
 		"sbom_writers_test",
+		"hidl_test",
 
 		// TODO(B/283193845): tradefed and its java_test_host dependents
 		"tradefed",
@@ -1636,10 +1692,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",
 
@@ -1650,6 +1702,30 @@
 
 		// Depends on the module defined in the directory not bp2build default allowed
 		"ota_from_raw_img",
+
+		// TODO(b/299924782): Fix linking error
+		"libbinder_on_trusty_mock",
+
+		// TODO(b/299943581): Depends on aidl filegroups with implicit headers
+		"libdataloader_aidl-cpp",
+		"libincremental_manager_aidl-cpp",
+
+		// TODO(b/299974637) Fix linking error
+		"libbinder_rpc_unstable",
+
+		// TODO(b/297356704) sdk_version is unset.
+		"VendorAtomCodeGenJavaTest",
+
+		// android_test from allowlisted packages, but with unconverted deps
+		"MtsLibnativehelperLazyTestCases",
+		"ObjenesisTck",
+		"DevCodelabTest",
+		"MtsTimeZoneDataTestCases",
+		"NanoAndroidTest",
+		"MtsLibnativehelperTestCases",
+
+		// android_test_helper_app from allowlisted packages, but with unconverted deps
+		"SharedLibraryInfoTestApp",
 	}
 
 	// Bazel prod-mode allowlist. Modules in this list are built by Bazel
@@ -1712,18 +1788,4 @@
 		"art_":        DEFAULT_PRIORITIZED_WEIGHT,
 		"ndk_library": DEFAULT_PRIORITIZED_WEIGHT,
 	}
-
-	BazelSandwichTargets = []struct {
-		Label string
-		Host  bool
-	}{
-		{
-			Label: "//build/bazel/examples/partitions:system_image",
-			Host:  false,
-		},
-		{
-			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/api_domain.go b/android/api_domain.go
index 587ceae..0603c70 100644
--- a/android/api_domain.go
+++ b/android/api_domain.go
@@ -107,24 +107,3 @@
 	bazelLabels := BazelLabelForModuleDepsWithFn(ctx, contributions, addSuffix)
 	return bazel.MakeLabelListAttribute(bazelLabels)
 }
-
-type bazelApiDomainAttributes struct {
-	Cc_api_contributions   bazel.LabelListAttribute
-	Java_api_contributions bazel.LabelListAttribute
-}
-
-var _ ApiProvider = (*apiDomain)(nil)
-
-func (a *apiDomain) ConvertWithApiBp2build(ctx TopDownMutatorContext) {
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class:        "api_domain",
-		Bzl_load_location: "//build/bazel/rules/apis:api_domain.bzl",
-	}
-	attrs := &bazelApiDomainAttributes{
-		Cc_api_contributions:   contributionBazelAttributes(ctx, a.properties.Cc_api_contributions),
-		Java_api_contributions: contributionBazelAttributes(ctx, a.properties.Java_api_contributions),
-	}
-	ctx.CreateBazelTargetModule(props, CommonAttributes{
-		Name: ctx.ModuleName(),
-	}, attrs)
-}
diff --git a/android/bazel.go b/android/bazel.go
index 94b36e3..4516396 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -162,7 +162,7 @@
 	// Modules must implement this function to be bp2build convertible. The function
 	// must either create at least one Bazel target module (using ctx.CreateBazelTargetModule or
 	// its related functions), or declare itself unconvertible using ctx.MarkBp2buildUnconvertible.
-	ConvertWithBp2build(ctx TopDownMutatorContext)
+	ConvertWithBp2build(ctx Bp2buildMutatorContext)
 
 	// namespacedVariableProps is a map from a soong config variable namespace
 	// (e.g. acme, android) to a map of interfaces{}, which are really
@@ -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
 	}
@@ -606,17 +600,10 @@
 }
 
 func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) {
-	ctx.TopDown("bp2build_conversion", bp2buildConversionMutator).Parallel()
+	ctx.BottomUp("bp2build_conversion", bp2buildConversionMutator).Parallel()
 }
 
-func bp2buildConversionMutator(ctx TopDownMutatorContext) {
-	if ctx.Config().HasBazelBuildTargetInSource(ctx) {
-		// Defer to the BUILD target. Generating an additional target would
-		// cause a BUILD file conflict.
-		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, "")
-		return
-	}
-
+func bp2buildConversionMutator(ctx BottomUpMutatorContext) {
 	bModule, ok := ctx.Module().(Bazelable)
 	if !ok {
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
@@ -640,21 +627,23 @@
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "")
 		return
 	}
+	if ctx.Module().base().GetUnconvertedReason() != nil {
+		return
+	}
+
 	bModule.ConvertWithBp2build(ctx)
 
-	if !ctx.Module().base().IsConvertedByBp2build() && ctx.Module().base().GetUnconvertedReason() == nil {
+	if len(ctx.Module().base().Bp2buildTargets()) == 0 && ctx.Module().base().GetUnconvertedReason() == nil {
 		panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", ctx.ModuleName()))
 	}
-}
 
-func registerApiBp2buildConversionMutator(ctx RegisterMutatorsContext) {
-	ctx.TopDown("apiBp2build_conversion", convertWithApiBp2build).Parallel()
-}
-
-// Generate API contribution targets if the Soong module provides APIs
-func convertWithApiBp2build(ctx TopDownMutatorContext) {
-	if m, ok := ctx.Module().(ApiProvider); ok {
-		m.ConvertWithApiBp2build(ctx)
+	for _, targetInfo := range ctx.Module().base().Bp2buildTargets() {
+		if ctx.Config().HasBazelBuildTargetInSource(targetInfo.TargetPackage(), targetInfo.TargetName()) {
+			// Defer to the BUILD target. Generating an additional target would
+			// cause a BUILD file conflict.
+			ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, targetInfo.TargetName())
+			return
+		}
 	}
 }
 
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 4b98345..51ce3c9 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -33,10 +33,10 @@
 	"android/soong/shared"
 	"android/soong/starlark_import"
 
+	"android/soong/bazel"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/metrics"
-
-	"android/soong/bazel"
 )
 
 var (
@@ -665,7 +665,8 @@
 		command.expression,
 		"--profile=" + shared.BazelMetricsFilename(context.paths, runName),
 
-		"--host_platform=@soong_injection//product_config_platforms:mixed_builds_product-" + context.targetBuildVariant + "_" + runtime.GOOS + "_x86_64",
+		"--host_platform=@soong_injection//product_config_platforms:mixed_builds_product_" + runtime.GOOS + "_x86_64",
+		"--//build/bazel/product_config:target_build_variant=" + context.targetBuildVariant,
 		// Don't specify --platforms, because on some products/branches (like kernel-build-tools)
 		// the main platform for mixed_builds_product-variant doesn't exist because an arch isn't
 		// specified in product config. The derivative platforms that config_node transitions into
@@ -720,9 +721,9 @@
 #####################################################
 def _config_node_transition_impl(settings, attr):
     if attr.os == "android" and attr.arch == "target":
-        target = "mixed_builds_product-{VARIANT}"
+        target = "mixed_builds_product"
     else:
-        target = "mixed_builds_product-{VARIANT}_%s_%s" % (attr.os, attr.arch)
+        target = "mixed_builds_product_%s_%s" % (attr.os, attr.arch)
     apex_name = ""
     if attr.within_apex:
         # //build/bazel/rules/apex:apex_name has to be set to a non_empty value,
@@ -794,11 +795,7 @@
 )
 `
 
-	productReplacer := strings.NewReplacer(
-		"{PRODUCT}", context.targetProduct,
-		"{VARIANT}", context.targetBuildVariant)
-
-	return []byte(productReplacer.Replace(contents))
+	return []byte(contents)
 }
 
 func (context *mixedBuildBazelContext) mainBuildFileContents() []byte {
@@ -972,9 +969,9 @@
   platform_name = platforms[0].name
   if platform_name == "host":
     return "HOST"
-  if not platform_name.startswith("mixed_builds_product-{TARGET_BUILD_VARIANT}"):
-    fail("expected platform name of the form 'mixed_builds_product-{TARGET_BUILD_VARIANT}_android_<arch>' or 'mixed_builds_product-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
-  platform_name = platform_name.removeprefix("mixed_builds_product-{TARGET_BUILD_VARIANT}").removeprefix("_")
+  if not platform_name.startswith("mixed_builds_product"):
+    fail("expected platform name of the form 'mixed_builds_product_android_<arch>' or 'mixed_builds_product_linux_<arch>', but was " + str(platforms))
+  platform_name = platform_name.removeprefix("mixed_builds_product").removeprefix("_")
   config_key = ""
   if not platform_name:
     config_key = "target|android"
@@ -983,7 +980,7 @@
   elif platform_name.startswith("linux_"):
     config_key = platform_name.removeprefix("linux_") + "|linux"
   else:
-    fail("expected platform name of the form 'mixed_builds_product-{TARGET_BUILD_VARIANT}_android_<arch>' or 'mixed_builds_product-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
+    fail("expected platform name of the form 'mixed_builds_product_android_<arch>' or 'mixed_builds_product_linux_<arch>', but was " + str(platforms))
 
   within_apex = buildoptions.get("//build/bazel/rules/apex:within_apex")
   apex_sdk_version = buildoptions.get("//build/bazel/rules/apex:min_sdk_version")
@@ -1012,8 +1009,6 @@
   return id_string + ">>NONE"
 `
 	replacer := strings.NewReplacer(
-		"{TARGET_PRODUCT}", context.targetProduct,
-		"{TARGET_BUILD_VARIANT}", context.targetBuildVariant,
 		"{LABEL_REGISTRATION_MAP_SECTION}", labelRegistrationMapSection,
 		"{FUNCTION_DEF_SECTION}", functionDefSection,
 		"{MAIN_SWITCH_SECTION}", mainSwitchSection)
@@ -1053,39 +1048,46 @@
 	allBazelCommands = []bazelCommand{aqueryCmd, cqueryCmd, buildCmd}
 )
 
+// This can't be part of bp2build_product_config.go because it would create a circular go package dependency
+func getLabelsForBazelSandwichPartitions(variables *ProductVariables) []string {
+	targetProduct := "unknown"
+	if variables.DeviceProduct != nil {
+		targetProduct = *variables.DeviceProduct
+	}
+	currentProductFolder := fmt.Sprintf("build/bazel/products/%s", targetProduct)
+	if len(variables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory) > 0 {
+		currentProductFolder = fmt.Sprintf("%s%s", variables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory, targetProduct)
+	}
+	var ret []string
+	if variables.PartitionVarsForBazelMigrationOnlyDoNotUse.PartitionQualifiedVariables["system"].BuildingImage {
+		ret = append(ret, "@//"+currentProductFolder+":system_image")
+		ret = append(ret, "@//"+currentProductFolder+":run_system_image_test")
+	}
+	return ret
+}
+
 func GetBazelSandwichCqueryRequests(config Config) ([]cqueryKey, error) {
-	result := make([]cqueryKey, 0, len(allowlists.BazelSandwichTargets))
+	partitionLabels := getLabelsForBazelSandwichPartitions(&config.productVariables)
+	result := make([]cqueryKey, 0, len(partitionLabels))
 	labelRegex := regexp.MustCompile("^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$")
 	// Note that bazel "targets" are different from soong "targets", the bazel targets are
 	// synonymous with soong modules, and soong targets are a configuration a module is built in.
-	for _, target := range allowlists.BazelSandwichTargets {
-		match := labelRegex.FindStringSubmatch(target.Label)
+	for _, target := range partitionLabels {
+		match := labelRegex.FindStringSubmatch(target)
 		if match == nil {
-			return nil, fmt.Errorf("invalid label, must match `^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$`: %s", target.Label)
-		}
-		if _, err := os.Stat(absolutePath(match[1])); err != nil {
-			if os.IsNotExist(err) {
-				// Ignore bazel sandwich targets that don't exist.
-				continue
-			} else {
-				return nil, err
-			}
+			return nil, fmt.Errorf("invalid label, must match `^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$`: %s", target)
 		}
 
-		var soongTarget Target
-		if target.Host {
-			soongTarget = config.BuildOSTarget
-		} else {
-			soongTarget = config.AndroidCommonTarget
-			if soongTarget.Os.Class != Device {
-				// kernel-build-tools seems to set the AndroidCommonTarget to a linux host
-				// target for some reason, disable device builds in that case.
-				continue
-			}
+		// change this to config.BuildOSTarget if we add host targets
+		soongTarget := config.AndroidCommonTarget
+		if soongTarget.Os.Class != Device {
+			// kernel-build-tools seems to set the AndroidCommonTarget to a linux host
+			// target for some reason, disable device builds in that case.
+			continue
 		}
 
 		result = append(result, cqueryKey{
-			label:       target.Label,
+			label:       target,
 			requestType: cquery.GetOutputFiles,
 			configKey: configKey{
 				arch:   soongTarget.Arch.String(),
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 86829ce..4ac5840 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -487,6 +487,9 @@
 	if moduleDir == Bp2BuildTopLevel {
 		moduleDir = ""
 	}
+	if a, ok := module.(Module); ok && IsModulePrebuilt(a) {
+		moduleName = RemoveOptionalPrebuiltPrefix(moduleName)
+	}
 	return fmt.Sprintf("//%s:%s", moduleDir, moduleName)
 }
 
@@ -585,7 +588,7 @@
 // For the first two cases, they are defined using the label attribute. For the third case,
 // it's defined with the string attribute.
 func BazelStringOrLabelFromProp(
-	ctx TopDownMutatorContext,
+	ctx Bp2buildMutatorContext,
 	propToDistinguish *string) (bazel.LabelAttribute, bazel.StringAttribute) {
 
 	var labelAttr bazel.LabelAttribute
diff --git a/android/bazel_test.go b/android/bazel_test.go
index 194a6b3..e0145b5 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",
@@ -469,7 +469,7 @@
 	return m
 }
 
-func (m *mixedBuildModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+func (m *mixedBuildModule) ConvertWithBp2build(ctx Bp2buildMutatorContext) {
 }
 
 func (m *mixedBuildModule) DepsMutator(ctx BottomUpMutatorContext) {
diff --git a/android/config.go b/android/config.go
index 1a3b539..b3ff86b 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
 
@@ -201,9 +197,22 @@
 	return c.config.productVariables.ReleaseVersion
 }
 
-// The flag values files passed to aconfig, derived from RELEASE_VERSION
-func (c Config) ReleaseAconfigValueSets() []string {
-	return c.config.productVariables.ReleaseAconfigValueSets
+// The aconfig value set passed to aconfig, derived from RELEASE_VERSION
+func (c Config) ReleaseAconfigValueSets() string {
+	// This logic to handle both Soong module name and bazel target is temporary in order to
+	// provide backward compatibility where aosp and internal both have the release
+	// aconfig value set but can't be updated at the same time to use bazel target
+	value := strings.Split(c.config.productVariables.ReleaseAconfigValueSets, ":")
+	value_len := len(value)
+	if value_len > 2 {
+		// This shouldn't happen as this should be either a module name or a bazel target path.
+		panic(fmt.Errorf("config file: invalid value for release aconfig value sets: %s",
+			c.config.productVariables.ReleaseAconfigValueSets))
+	}
+	if value_len > 0 {
+		return value[value_len-1]
+	}
+	return ""
 }
 
 // The flag default permission value passed to aconfig
@@ -641,7 +650,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 +1670,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 {
@@ -2007,10 +2022,9 @@
 	}
 }
 
-func (c *config) HasBazelBuildTargetInSource(ctx BaseModuleContext) bool {
-	moduleName := ctx.Module().Name()
-	for _, buildTarget := range c.bazelTargetsByDir[ctx.ModuleDir()] {
-		if moduleName == buildTarget {
+func (c *config) HasBazelBuildTargetInSource(dir string, target string) bool {
+	for _, existingTarget := range c.bazelTargetsByDir[dir] {
+		if target == existingTarget {
 			return true
 		}
 	}
@@ -2058,6 +2072,15 @@
 	return c.apiLibraries
 }
 
+// Bp2buildMode indicates whether the config is for bp2build mode of Soong
+func (c *config) Bp2buildMode() bool {
+	return c.BuildMode == Bp2build
+}
+
 func (c *deviceConfig) CheckVendorSeappViolations() bool {
 	return Bool(c.config.productVariables.CheckVendorSeappViolations)
 }
+
+func (c *deviceConfig) NextReleaseHideFlaggedApi() bool {
+	return Bool(c.config.productVariables.NextReleaseHideFlaggedApi)
+}
diff --git a/android/defaults.go b/android/defaults.go
index e0e6e5c..cc723f7 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -180,7 +180,7 @@
 
 // ConvertWithBp2build to fulfill Bazelable interface; however, at this time defaults module are
 // *NOT* converted with bp2build
-func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx TopDownMutatorContext) {
+func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx Bp2buildMutatorContext) {
 	// Defaults types are never convertible.
 	ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
 }
diff --git a/android/filegroup.go b/android/filegroup.go
index 6cc9232..5a8c4b9 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -86,14 +86,8 @@
 	Strip_import_prefix *string
 }
 
-// api srcs can be contained in filegroups.
-// this should be generated in api_bp2build workspace as well.
-func (fg *fileGroup) ConvertWithApiBp2build(ctx TopDownMutatorContext) {
-	fg.ConvertWithBp2build(ctx)
-}
-
 // ConvertWithBp2build performs bp2build conversion of filegroup
-func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
+func (fg *fileGroup) ConvertWithBp2build(ctx Bp2buildMutatorContext) {
 	srcs := bazel.MakeLabelListAttribute(
 		BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs))
 
@@ -209,10 +203,10 @@
 }
 
 type FileGroupPath interface {
-	GetPath(ctx TopDownMutatorContext) string
+	GetPath(ctx Bp2buildMutatorContext) string
 }
 
-func (fg *fileGroup) GetPath(ctx TopDownMutatorContext) string {
+func (fg *fileGroup) GetPath(ctx Bp2buildMutatorContext) string {
 	if fg.properties.Path != nil {
 		return *fg.properties.Path
 	}
diff --git a/android/fixture.go b/android/fixture.go
index 6660afd..5ad47e8 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -275,6 +275,15 @@
 	})
 }
 
+// Sync the mock filesystem with the current config, then modify the context,
+// This allows context modification that requires filesystem access.
+func FixtureModifyContextWithMockFs(mutator func(ctx *TestContext)) FixturePreparer {
+	return newSimpleFixturePreparer(func(f *fixture) {
+		f.config.mockFileSystem("", f.mockFS)
+		mutator(f.ctx)
+	})
+}
+
 func FixtureRegisterWithContext(registeringFunc func(ctx RegistrationContext)) FixturePreparer {
 	return FixtureModifyContext(func(ctx *TestContext) { registeringFunc(ctx) })
 }
diff --git a/android/license.go b/android/license.go
index a09422b..76f5115 100644
--- a/android/license.go
+++ b/android/license.go
@@ -71,7 +71,7 @@
 	Visibility       []string
 }
 
-func (m *licenseModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+func (m *licenseModule) ConvertWithBp2build(ctx Bp2buildMutatorContext) {
 	attrs := &bazelLicenseAttributes{
 		License_kinds:    m.properties.License_kinds,
 		Copyright_notice: m.properties.Copyright_notice,
diff --git a/android/license_kind.go b/android/license_kind.go
index 24b91e4..78df938 100644
--- a/android/license_kind.go
+++ b/android/license_kind.go
@@ -50,7 +50,7 @@
 	Visibility []string
 }
 
-func (m *licenseKindModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+func (m *licenseKindModule) ConvertWithBp2build(ctx Bp2buildMutatorContext) {
 	attrs := &bazelLicenseKindAttributes{
 		Conditions: m.properties.Conditions,
 		Url:        m.properties.Url,
diff --git a/android/module.go b/android/module.go
index f9ea897..74b8cb8 100644
--- a/android/module.go
+++ b/android/module.go
@@ -565,8 +565,8 @@
 	AddProperties(props ...interface{})
 	GetProperties() []interface{}
 
-	// IsConvertedByBp2build returns whether this module was converted via bp2build
-	IsConvertedByBp2build() bool
+	// If this module should not have bazel BUILD definitions generated by bp2build,
+	// GetUnconvertedReason returns a reason this is the case.
 	GetUnconvertedReason() *UnconvertedReason
 
 	// Bp2buildTargets returns the target(s) generated for Bazel via bp2build for this module
@@ -1272,7 +1272,7 @@
 	m.base().commonProperties.CreateCommonOSVariant = true
 }
 
-func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutatorContext,
+func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *bottomUpMutatorContext,
 	enabledPropertyOverrides bazel.BoolAttribute) constraintAttributes {
 
 	mod := ctx.Module().base()
@@ -1418,15 +1418,50 @@
 	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 *bottomUpMutatorContext, 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 {
+func productVariableConfigEnableAttribute(ctx *bottomUpMutatorContext) bazel.LabelListAttribute {
 	result := bazel.LabelListAttribute{}
-	productVariableProps := ProductVariableProperties(ctx, ctx.Module())
+	productVariableProps, errs := ProductVariableProperties(ctx, ctx.Module())
+	for _, err := range errs {
+		ctx.ModuleErrorf("ProductVariableProperties error: %s", err)
+	}
 	if productConfigProps, exists := productVariableProps["Enabled"]; exists {
 		for productConfigProp, prop := range productConfigProps {
 			flag, ok := prop.(*bool)
@@ -1604,27 +1639,16 @@
 }
 
 func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) {
-	if m.commonProperties.BazelConversionStatus.UnconvertedReason != nil {
-		panic(fmt.Errorf("bp2build: module '%s' marked unconvertible and also is converted", m.Name()))
-	}
 	m.commonProperties.BazelConversionStatus.Bp2buildInfo = append(m.commonProperties.BazelConversionStatus.Bp2buildInfo, info)
 }
 
 func (m *ModuleBase) setBp2buildUnconvertible(reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) {
-	if len(m.commonProperties.BazelConversionStatus.Bp2buildInfo) > 0 {
-		panic(fmt.Errorf("bp2build: module '%s' marked unconvertible and also is converted", m.Name()))
-	}
 	m.commonProperties.BazelConversionStatus.UnconvertedReason = &UnconvertedReason{
 		ReasonType: int(reasonType),
 		Detail:     detail,
 	}
 }
 
-// IsConvertedByBp2build returns whether this module was converted via bp2build.
-func (m *ModuleBase) IsConvertedByBp2build() bool {
-	return len(m.commonProperties.BazelConversionStatus.Bp2buildInfo) > 0
-}
-
 func (m *ModuleBase) GetUnconvertedReason() *UnconvertedReason {
 	return m.commonProperties.BazelConversionStatus.UnconvertedReason
 }
@@ -3057,11 +3081,21 @@
 	if !b.isBazelConversionMode() {
 		panic("cannot call ModuleFromName if not in bazel conversion mode")
 	}
+	var m blueprint.Module
+	var ok bool
 	if moduleName, _ := SrcIsModuleWithTag(name); moduleName != "" {
-		return b.bp.ModuleFromName(moduleName)
+		m, ok = b.bp.ModuleFromName(moduleName)
 	} else {
-		return b.bp.ModuleFromName(name)
+		m, ok = b.bp.ModuleFromName(name)
 	}
+	if !ok {
+		return m, ok
+	}
+	// If this module is not preferred, tried to get the prebuilt version instead
+	if a, aOk := m.(Module); aOk && !IsModulePrebuilt(a) && !IsModulePreferred(a) {
+		return b.ModuleFromName("prebuilt_" + name)
+	}
+	return m, ok
 }
 
 func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
diff --git a/android/mutator.go b/android/mutator.go
index 41477b8..57ff1e0 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,9 +15,10 @@
 package android
 
 import (
+	"path/filepath"
+
 	"android/soong/bazel"
 	"android/soong/ui/metrics/bp2build_metrics_proto"
-	"path/filepath"
 
 	"github.com/google/blueprint"
 )
@@ -37,13 +38,6 @@
 	registerMutatorsForBazelConversion(ctx, bp2buildMutators)
 }
 
-// RegisterMutatorsForApiBazelConversion is an alternate registration pipeline for api_bp2build
-// This pipeline restricts generation of Bazel targets to Soong modules that contribute APIs
-func RegisterMutatorsForApiBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
-	bp2buildMutators := append(preArchMutators, registerApiBp2buildConversionMutator)
-	registerMutatorsForBazelConversion(ctx, bp2buildMutators)
-}
-
 func registerMutatorsForBazelConversion(ctx *Context, bp2buildMutators []RegisterMutatorFunc) {
 	mctx := &registerMutatorsContext{
 		bazelConversionMode: true,
@@ -55,6 +49,7 @@
 		// TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should
 		// evaluate the impact on conversion.
 		RegisterPrebuiltsPreArchMutators,
+		RegisterPrebuiltsPostDepsMutators,
 	},
 		bp2buildMutators...)
 
@@ -229,37 +224,8 @@
 // A minimal context for Bp2build conversion
 type Bp2buildMutatorContext interface {
 	BazelConversionPathContext
-
-	CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{})
-	CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute)
-}
-
-// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
-// into Bazel BUILD targets that should run prior to deps and conversion.
-func PreArchBp2BuildMutators(f RegisterMutatorFunc) {
-	bp2buildPreArchMutators = append(bp2buildPreArchMutators, f)
-}
-
-type BaseMutatorContext interface {
-	BaseModuleContext
-
-	// MutatorName returns the name that this mutator was registered with.
-	MutatorName() string
-
-	// Rename all variants of a module.  The new name is not visible to calls to ModuleName,
-	// AddDependency or OtherModuleName until after this mutator pass is complete.
-	Rename(name string)
-}
-
-type TopDownMutator func(TopDownMutatorContext)
-
-type TopDownMutatorContext interface {
 	BaseMutatorContext
 
-	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
-	// the specified property structs to it as if the properties were set in a blueprint file.
-	CreateModule(ModuleFactory, ...interface{}) Module
-
 	// CreateBazelTargetModule creates a BazelTargetModule by calling the
 	// factory method, just like in CreateModule, but also requires
 	// BazelTargetModuleProperties containing additional metadata for the
@@ -290,6 +256,33 @@
 	CreateBazelConfigSetting(csa bazel.ConfigSettingAttributes, ca CommonAttributes, dir string)
 }
 
+// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
+// into Bazel BUILD targets that should run prior to deps and conversion.
+func PreArchBp2BuildMutators(f RegisterMutatorFunc) {
+	bp2buildPreArchMutators = append(bp2buildPreArchMutators, f)
+}
+
+type BaseMutatorContext interface {
+	BaseModuleContext
+
+	// MutatorName returns the name that this mutator was registered with.
+	MutatorName() string
+
+	// Rename all variants of a module.  The new name is not visible to calls to ModuleName,
+	// AddDependency or OtherModuleName until after this mutator pass is complete.
+	Rename(name string)
+}
+
+type TopDownMutator func(TopDownMutatorContext)
+
+type TopDownMutatorContext interface {
+	BaseMutatorContext
+
+	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
+	// the specified property structs to it as if the properties were set in a blueprint file.
+	CreateModule(ModuleFactory, ...interface{}) Module
+}
+
 type topDownMutatorContext struct {
 	bp blueprint.TopDownMutatorContext
 	baseModuleContext
@@ -299,6 +292,7 @@
 
 type BottomUpMutatorContext interface {
 	BaseMutatorContext
+	Bp2buildMutatorContext
 
 	// AddDependency adds a dependency to the given module.  It returns a slice of modules for each
 	// dependency (some entries may be nil).
@@ -710,14 +704,14 @@
 	ctx.BottomUp("deps", depsMutator).Parallel()
 }
 
-func (t *topDownMutatorContext) CreateBazelTargetModule(
+func (t *bottomUpMutatorContext) CreateBazelTargetModule(
 	bazelProps bazel.BazelTargetModuleProperties,
 	commonAttrs CommonAttributes,
 	attrs interface{}) {
 	t.createBazelTargetModule(bazelProps, commonAttrs, attrs, bazel.BoolAttribute{})
 }
 
-func (t *topDownMutatorContext) CreateBazelTargetModuleWithRestrictions(
+func (t *bottomUpMutatorContext) CreateBazelTargetModuleWithRestrictions(
 	bazelProps bazel.BazelTargetModuleProperties,
 	commonAttrs CommonAttributes,
 	attrs interface{},
@@ -725,7 +719,7 @@
 	t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty)
 }
 
-func (t *topDownMutatorContext) MarkBp2buildUnconvertible(
+func (t *bottomUpMutatorContext) MarkBp2buildUnconvertible(
 	reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) {
 	mod := t.Module()
 	mod.base().setBp2buildUnconvertible(reasonType, detail)
@@ -741,7 +735,7 @@
 	Actual *bazel.LabelAttribute
 }
 
-func (t *topDownMutatorContext) CreateBazelTargetAliasInDir(
+func (t *bottomUpMutatorContext) CreateBazelTargetAliasInDir(
 	dir string,
 	name string,
 	actual bazel.Label) {
@@ -762,7 +756,7 @@
 // Returns the directory in which the bazel target will be generated
 // If ca.Dir is not nil, use that
 // Otherwise default to the directory of the soong module
-func dirForBazelTargetGeneration(t *topDownMutatorContext, ca *CommonAttributes) string {
+func dirForBazelTargetGeneration(t *bottomUpMutatorContext, ca *CommonAttributes) string {
 	dir := t.OtherModuleDir(t.Module())
 	if ca.Dir != nil {
 		dir = *ca.Dir
@@ -780,7 +774,7 @@
 	return dir
 }
 
-func (t *topDownMutatorContext) CreateBazelConfigSetting(
+func (t *bottomUpMutatorContext) CreateBazelConfigSetting(
 	csa bazel.ConfigSettingAttributes,
 	ca CommonAttributes,
 	dir string) {
@@ -866,7 +860,7 @@
 	return ConvertApexAvailableToTags(noTestApexes)
 }
 
-func (t *topDownMutatorContext) createBazelTargetModule(
+func (t *bottomUpMutatorContext) createBazelTargetModule(
 	bazelProps bazel.BazelTargetModuleProperties,
 	commonAttrs CommonAttributes,
 	attrs interface{},
diff --git a/android/package.go b/android/package.go
index 7fbc700..ce0b150 100644
--- a/android/package.go
+++ b/android/package.go
@@ -54,7 +54,7 @@
 
 var _ Bazelable = &packageModule{}
 
-func (p *packageModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+func (p *packageModule) ConvertWithBp2build(ctx Bp2buildMutatorContext) {
 	defaultPackageMetadata := bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, p.properties.Default_applicable_licenses))
 	// If METADATA file exists in the package, add it to package(default_package_metadata=) using a
 	// filegroup(name="default_metadata_file") which can be accessed later on each module in Bazel
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 95b772d..e7b7979 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -483,20 +483,55 @@
 // usePrebuilt returns true if a prebuilt should be used instead of the source module.  The prebuilt
 // will be used if it is marked "prefer" or if the source module is disabled.
 func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module, prebuilt Module) bool {
-	if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 {
-		return false
-	}
+	if !ctx.Config().Bp2buildMode() {
+		if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 {
+			return false
+		}
 
-	// Skip prebuilt modules under unexported namespaces so that we won't
-	// end up shadowing non-prebuilt module when prebuilt module under same
-	// name happens to have a `Prefer` property set to true.
-	if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() {
-		return false
+		// Skip prebuilt modules under unexported namespaces so that we won't
+		// end up shadowing non-prebuilt module when prebuilt module under same
+		// name happens to have a `Prefer` property set to true.
+		if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() {
+			return false
+		}
 	}
 
 	// If source is not available or is disabled then always use the prebuilt.
 	if source == nil || !source.Enabled() {
-		return true
+		// If in bp2build mode, we need to check product variables & Soong config variables, which may
+		// have overridden the "enabled" property but have not been merged into the property value as
+		// they would in a non-bp2build mode invocation
+		if ctx.Config().Bp2buildMode() && source != nil {
+			productVariableProps, errs := ProductVariableProperties(ctx, source)
+			if productConfigProps, exists := productVariableProps["Enabled"]; len(errs) == 0 && exists && len(productConfigProps) == 1 {
+				var prop ProductConfigOrSoongConfigProperty
+				var value bool
+				for p, v := range productConfigProps {
+					prop = p
+					actual, ok := v.(*bool)
+					if ok {
+						value = proptools.Bool(actual)
+					}
+				}
+				if scv, ok := prop.(SoongConfigProperty); ok {
+					// If the product config var is enabled but the value of enabled is false still, the
+					// prebuilt is preferred. Otherwise, check if the prebulit is explicitly preferred
+					if ctx.Config().VendorConfig(scv.namespace).Bool(strings.ToLower(scv.name)) && !value {
+						return true
+					}
+				} else {
+					// TODO: b/300998219 - handle product vars
+					// We don't handle product variables yet, so return based on the non-product specific
+					// value of enabled
+					return true
+				}
+			} else {
+				// No "enabled" property override, return true since this module isn't enabled
+				return true
+			}
+		} else {
+			return true
+		}
 	}
 
 	// If the use_source_config_var property is set then it overrides the prefer property setting.
diff --git a/android/proto.go b/android/proto.go
index fc21d01..c449a87 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -289,7 +289,7 @@
 				attrs.Strip_import_prefix = proptools.StringPtr("")
 			}
 
-			tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module())
+			tags := ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module())
 
 			moduleDir := ctx.ModuleDir()
 			if !canonicalPathFromRoot {
diff --git a/android/register.go b/android/register.go
index 64b0207..f1c2986 100644
--- a/android/register.go
+++ b/android/register.go
@@ -15,9 +15,13 @@
 package android
 
 import (
+	"bufio"
 	"fmt"
+	"path/filepath"
 	"reflect"
+	"regexp"
 
+	"android/soong/shared"
 	"github.com/google/blueprint"
 )
 
@@ -197,11 +201,54 @@
 	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)
+// RegisterExistingBazelTargets reads Bazel BUILD.bazel and BUILD files under
+// the workspace, and returns a map containing names of Bazel targets defined in
+// these BUILD files.
+// For example, maps "//foo/bar" to ["baz", "qux"] if `//foo/bar:{baz,qux}` exist.
+func (c *Context) RegisterExistingBazelTargets(topDir string, existingBazelFiles []string) error {
+	result := map[string][]string{}
+
+	// Search for instances of `name = "$NAME"` (with arbitrary spacing).
+	targetNameRegex := regexp.MustCompile(`(?m)^\s*name\s*=\s*\"([^\"]+)\"`)
+
+	parseBuildFile := func(path string) error {
+		fullPath := shared.JoinPath(topDir, path)
+		sourceDir := filepath.Dir(path)
+
+		fileInfo, err := c.Config().fs.Stat(fullPath)
+		if err != nil {
+			return fmt.Errorf("Error accessing Bazel file '%s': %s", path, err)
+		}
+		if !fileInfo.IsDir() &&
+			(fileInfo.Name() == "BUILD" || fileInfo.Name() == "BUILD.bazel") {
+			f, err := c.Config().fs.Open(fullPath)
+			if err != nil {
+				return fmt.Errorf("Error reading Bazel file '%s': %s", path, err)
+			}
+			defer f.Close()
+			scanner := bufio.NewScanner(f)
+			for scanner.Scan() {
+				line := scanner.Text()
+				matches := targetNameRegex.FindAllStringSubmatch(line, -1)
+				for _, match := range matches {
+					result[sourceDir] = append(result[sourceDir], match[1])
+				}
+			}
+		}
+		return nil
+	}
+
+	for _, path := range existingBazelFiles {
+		if !c.Config().Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(filepath.Dir(path)) {
+			continue
+		}
+		err := parseBuildFile(path)
+		if err != nil {
+			return err
+		}
+	}
+	c.Config().SetBazelBuildFileTargets(result)
+	return nil
 }
 
 // Register the pipeline of singletons, module types, and mutators for
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 89ac915..44a8fd7 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"`
@@ -437,16 +438,17 @@
 
 	ShippingApiLevel *string `json:",omitempty"`
 
-	BuildBrokenPluginValidation        []string `json:",omitempty"`
-	BuildBrokenClangAsFlags            bool     `json:",omitempty"`
-	BuildBrokenClangCFlags             bool     `json:",omitempty"`
-	BuildBrokenClangProperty           bool     `json:",omitempty"`
-	GenruleSandboxing                  *bool    `json:",omitempty"`
-	BuildBrokenEnforceSyspropOwner     bool     `json:",omitempty"`
-	BuildBrokenTrebleSyspropNeverallow bool     `json:",omitempty"`
-	BuildBrokenUsesSoongPython2Modules bool     `json:",omitempty"`
-	BuildBrokenVendorPropertyNamespace bool     `json:",omitempty"`
-	BuildBrokenInputDirModules         []string `json:",omitempty"`
+	BuildBrokenPluginValidation         []string `json:",omitempty"`
+	BuildBrokenClangAsFlags             bool     `json:",omitempty"`
+	BuildBrokenClangCFlags              bool     `json:",omitempty"`
+	BuildBrokenClangProperty            bool     `json:",omitempty"`
+	GenruleSandboxing                   *bool    `json:",omitempty"`
+	BuildBrokenEnforceSyspropOwner      bool     `json:",omitempty"`
+	BuildBrokenTrebleSyspropNeverallow  bool     `json:",omitempty"`
+	BuildBrokenUsesSoongPython2Modules  bool     `json:",omitempty"`
+	BuildBrokenVendorPropertyNamespace  bool     `json:",omitempty"`
+	BuildBrokenIncorrectPartitionImages bool     `json:",omitempty"`
+	BuildBrokenInputDirModules          []string `json:",omitempty"`
 
 	BuildWarningBadOptionalUsesLibsAllowlist []string `json:",omitempty"`
 
@@ -474,14 +476,66 @@
 	ProductBrand        string   `json:",omitempty"`
 	BuildVersionTags    []string `json:",omitempty"`
 
-	ReleaseVersion          string   `json:",omitempty"`
-	ReleaseAconfigValueSets []string `json:",omitempty"`
+	ReleaseVersion          string `json:",omitempty"`
+	ReleaseAconfigValueSets string `json:",omitempty"`
 
 	ReleaseAconfigFlagDefaultPermission string `json:",omitempty"`
 
 	KeepVndk *bool `json:",omitempty"`
 
 	CheckVendorSeappViolations *bool `json:",omitempty"`
+
+	// PartitionVarsForBazelMigrationOnlyDoNotUse are extra variables that are used to define the
+	// partition images. They should not be read from soong modules.
+	PartitionVarsForBazelMigrationOnlyDoNotUse PartitionVariables `json:",omitempty"`
+
+	NextReleaseHideFlaggedApi *bool `json:",omitempty"`
+}
+
+type PartitionVariables struct {
+	ProductDirectory            string `json:",omitempty"`
+	PartitionQualifiedVariables map[string]struct {
+		BuildingImage               bool   `json:",omitempty"`
+		BoardErofsCompressor        string `json:",omitempty"`
+		BoardErofsCompressHints     string `json:",omitempty"`
+		BoardErofsPclusterSize      string `json:",omitempty"`
+		BoardExtfsInodeCount        string `json:",omitempty"`
+		BoardExtfsRsvPct            string `json:",omitempty"`
+		BoardF2fsSloadCompressFlags string `json:",omitempty"`
+		BoardFileSystemCompress     string `json:",omitempty"`
+		BoardFileSystemType         string `json:",omitempty"`
+		BoardJournalSize            string `json:",omitempty"`
+		BoardPartitionReservedSize  string `json:",omitempty"`
+		BoardPartitionSize          string `json:",omitempty"`
+		BoardSquashfsBlockSize      string `json:",omitempty"`
+		BoardSquashfsCompressor     string `json:",omitempty"`
+		BoardSquashfsCompressorOpt  string `json:",omitempty"`
+		BoardSquashfsDisable4kAlign string `json:",omitempty"`
+		ProductBaseFsPath           string `json:",omitempty"`
+		ProductHeadroom             string `json:",omitempty"`
+		ProductVerityPartition      string `json:",omitempty"`
+	}
+	TargetUserimagesUseExt2 bool `json:",omitempty"`
+	TargetUserimagesUseExt3 bool `json:",omitempty"`
+	TargetUserimagesUseExt4 bool `json:",omitempty"`
+
+	TargetUserimagesSparseExtDisabled      bool `json:",omitempty"`
+	TargetUserimagesSparseErofsDisabled    bool `json:",omitempty"`
+	TargetUserimagesSparseSquashfsDisabled bool `json:",omitempty"`
+	TargetUserimagesSparseF2fsDisabled     bool `json:",omitempty"`
+
+	BoardErofsCompressor                 string `json:",omitempty"`
+	BoardErofsCompressorHints            string `json:",omitempty"`
+	BoardErofsPclusterSize               string `json:",omitempty"`
+	BoardErofsShareDupBlocks             string `json:",omitempty"`
+	BoardErofsUseLegacyCompression       string `json:",omitempty"`
+	BoardExt4ShareDupBlocks              string `json:",omitempty"`
+	BoardFlashLogicalBlockSize           string `json:",omitempty"`
+	BoardFlashEraseBlockSize             string `json:",omitempty"`
+	BoardUsesRecoveryAsBoot              bool   `json:",omitempty"`
+	BoardBuildGkiBootImageWithoutRamdisk bool   `json:",omitempty"`
+	ProductUseDynamicPartitionSize       bool   `json:",omitempty"`
+	CopyImagesForTargetFilesZip          bool   `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
@@ -667,7 +721,8 @@
 
 // ProductVariableProperties returns a ProductConfigProperties containing only the properties which
 // have been set for the given module.
-func ProductVariableProperties(ctx ArchVariantContext, module Module) ProductConfigProperties {
+func ProductVariableProperties(ctx ArchVariantContext, module Module) (ProductConfigProperties, []error) {
+	var errs []error
 	moduleBase := module.base()
 
 	productConfigProperties := ProductConfigProperties{}
@@ -691,12 +746,15 @@
 		for namespace, namespacedVariableProps := range m.namespacedVariableProps() {
 			for _, namespacedVariableProp := range namespacedVariableProps {
 				variableValues := reflect.ValueOf(namespacedVariableProp).Elem().FieldByName(soongconfig.SoongConfigProperty)
-				productConfigProperties.AddSoongConfigProperties(namespace, variableValues)
+				err := productConfigProperties.AddSoongConfigProperties(namespace, variableValues)
+				if err != nil {
+					errs = append(errs, err)
+				}
 			}
 		}
 	}
 
-	return productConfigProperties
+	return productConfigProperties, errs
 }
 
 func (p *ProductConfigProperties) AddProductConfigProperty(
@@ -818,7 +876,7 @@
 
 }
 
-func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties(namespace string, soongConfigVariablesStruct reflect.Value) {
+func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties(namespace string, soongConfigVariablesStruct reflect.Value) error {
 	//
 	// Example of soong_config_variables:
 	//
@@ -915,7 +973,7 @@
 					if propertyName == "Target" {
 						productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), field.Field(k))
 					} else if propertyName == "Arch" || propertyName == "Multilib" {
-						panic("Arch/Multilib are not currently supported in soong config variable structs")
+						return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs")
 					} else {
 						productConfigProperties.AddSoongConfigProperty(propertyName, namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), "", field.Field(k).Interface())
 					}
@@ -926,13 +984,14 @@
 				if propertyOrValueName == "Target" {
 					productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, "", propertyOrStruct)
 				} else if propertyOrValueName == "Arch" || propertyOrValueName == "Multilib" {
-					panic("Arch/Multilib are not currently supported in soong config variable structs")
+					return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs")
 				} else {
 					productConfigProperties.AddSoongConfigProperty(propertyOrValueName, namespace, variableName, "", "", propertyOrStruct.Interface())
 				}
 			}
 		}
 	}
+	return nil
 }
 
 func (productConfigProperties *ProductConfigProperties) AddSoongConfigPropertiesFromTargetStruct(namespace, soongConfigVariableName string, soongConfigVariableValue string, targetStruct reflect.Value) {
diff --git a/apex/apex.go b/apex/apex.go
index 52a5e20..090d9c4 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
 
@@ -2607,7 +2623,7 @@
 	return m
 }
 
-func (o *OverrideApex) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (o *OverrideApex) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	if ctx.ModuleType() != "override_apex" {
 		return
 	}
@@ -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
@@ -3258,7 +3261,7 @@
 )
 
 // ConvertWithBp2build performs bp2build conversion of an apex
-func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (a *apexBundle) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	// We only convert apex and apex_test modules at this time
 	if ctx.ModuleType() != "apex" && ctx.ModuleType() != "apex_test" {
 		return
@@ -3269,7 +3272,7 @@
 	ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
 }
 
-func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties, android.CommonAttributes) {
+func convertWithBp2build(a *apexBundle, ctx android.Bp2buildMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties, android.CommonAttributes) {
 	var manifestLabelAttribute bazel.LabelAttribute
 	manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")))
 
@@ -3295,7 +3298,10 @@
 		cannedFsConfigAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.Canned_fs_config))
 	}
 
-	productVariableProps := android.ProductVariableProperties(ctx, a)
+	productVariableProps, errs := android.ProductVariableProperties(ctx, a)
+	for _, err := range errs {
+		ctx.ModuleErrorf("ProductVariableProperties error: %s", err)
+	}
 	// TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but
 	// given it's coming via config, we probably don't want to put it in here.
 	var minSdkVersion bazel.StringAttribute
@@ -3426,7 +3432,7 @@
 // both,                    32/32,     64/none,   32&64/32, 64/32
 // first,                   32/32,     64/none,   64/32,    64/32
 
-func convert32Libs(ctx android.TopDownMutatorContext, compileMultilb string,
+func convert32Libs(ctx android.Bp2buildMutatorContext, compileMultilb string,
 	libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
 	libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
 	switch compileMultilb {
@@ -3441,7 +3447,7 @@
 	}
 }
 
-func convert64Libs(ctx android.TopDownMutatorContext, compileMultilb string,
+func convert64Libs(ctx android.Bp2buildMutatorContext, compileMultilb string,
 	libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
 	libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
 	switch compileMultilb {
@@ -3454,7 +3460,7 @@
 	}
 }
 
-func convertBothLibs(ctx android.TopDownMutatorContext, compileMultilb string,
+func convertBothLibs(ctx android.Bp2buildMutatorContext, compileMultilb string,
 	libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
 	libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
 	switch compileMultilb {
@@ -3472,7 +3478,7 @@
 	}
 }
 
-func convertFirstLibs(ctx android.TopDownMutatorContext, compileMultilb string,
+func convertFirstLibs(ctx android.Bp2buildMutatorContext, compileMultilb string,
 	libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
 	libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
 	switch compileMultilb {
@@ -3515,7 +3521,7 @@
 	labelListAttr.Append(list)
 }
 
-func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) {
+func invalidCompileMultilib(ctx android.Bp2buildMutatorContext, value string) {
 	ctx.PropertyErrorf("compile_multilib", "Invalid value: %s", value)
 }
 
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/apex/builder.go b/apex/builder.go
index 4b42b74..729917f 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -17,6 +17,7 @@
 import (
 	"encoding/json"
 	"fmt"
+	"path"
 	"path/filepath"
 	"runtime"
 	"sort"
@@ -75,6 +76,8 @@
 	pctx.HostBinToolVariable("deapexer", "deapexer")
 	pctx.HostBinToolVariable("debugfs_static", "debugfs_static")
 	pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
+	pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config")
+	pctx.HostBinToolVariable("assemble_vintf", "assemble_vintf")
 }
 
 var (
@@ -222,6 +225,18 @@
 		CommandDeps: []string{"${apex_sepolicy_tests}", "${deapexer}", "${debugfs_static}"},
 		Description: "run apex_sepolicy_tests",
 	})
+
+	apexLinkerconfigValidationRule = pctx.StaticRule("apexLinkerconfigValidationRule", blueprint.RuleParams{
+		Command:     `${conv_linker_config} validate --type apex ${image_dir} && touch ${out}`,
+		CommandDeps: []string{"${conv_linker_config}"},
+		Description: "run apex_linkerconfig_validation",
+	}, "image_dir")
+
+	assembleVintfRule = pctx.StaticRule("assembleVintfRule", blueprint.RuleParams{
+		Command:     `rm -f $out && VINTF_IGNORE_TARGET_FCM_VERSION=true ${assemble_vintf} -i $in -o $out`,
+		CommandDeps: []string{"${assemble_vintf}"},
+		Description: "run assemble_vintf",
+	})
 )
 
 // buildManifest creates buile rules to modify the input apex_manifest.json to add information
@@ -444,6 +459,22 @@
 	})
 }
 
+func isVintfFragment(fi apexFile) bool {
+	isVintfFragment, _ := path.Match("etc/vintf/*.xml", fi.path())
+	return isVintfFragment
+}
+
+func runAssembleVintf(ctx android.ModuleContext, vintfFragment android.Path) android.Path {
+	processed := android.PathForModuleOut(ctx, "vintf", vintfFragment.Base())
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        assembleVintfRule,
+		Input:       vintfFragment,
+		Output:      processed,
+		Description: "run assemble_vintf for VINTF in APEX",
+	})
+	return processed
+}
+
 // buildApex creates build rules to build an APEX using apexer.
 func (a *apexBundle) buildApex(ctx android.ModuleContext) {
 	suffix := imageApexSuffix
@@ -481,7 +512,15 @@
 			copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
 		} else {
 			// Copy the file into APEX
-			copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+			if !a.testApex && isVintfFragment(fi) {
+				// copy the output of assemble_vintf instead of the original
+				vintfFragment := runAssembleVintf(ctx, fi.builtFile)
+				copyCommands = append(copyCommands, "cp -f "+vintfFragment.String()+" "+destPath)
+				implicitInputs = append(implicitInputs, vintfFragment)
+			} else {
+				copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+				implicitInputs = append(implicitInputs, fi.builtFile)
+			}
 
 			var installedPath android.InstallPath
 			if fi.class == appSet {
@@ -499,7 +538,6 @@
 					installedPath = ctx.InstallFile(apexDir.Join(ctx, fi.installDir), fi.stem(), fi.builtFile)
 				}
 			}
-			implicitInputs = append(implicitInputs, fi.builtFile)
 
 			// Create additional symlinks pointing the file inside the APEX (if any). Note that
 			// this is independent from the symlink optimization.
@@ -843,6 +881,7 @@
 		args["outCommaList"] = signedOutputFile.String()
 	}
 	var validations android.Paths
+	validations = append(validations, runApexLinkerconfigValidation(ctx, unsignedOutputFile.OutputPath, imageDir.OutputPath))
 	// TODO(b/279688635) deapexer supports [ext4]
 	if suffix == imageApexSuffix && ext4 == a.payloadFsType {
 		validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile.OutputPath))
@@ -1097,6 +1136,19 @@
 	return cannedFsConfig.OutputPath
 }
 
+func runApexLinkerconfigValidation(ctx android.ModuleContext, apexFile android.OutputPath, imageDir android.OutputPath) android.Path {
+	timestamp := android.PathForModuleOut(ctx, "apex_linkerconfig_validation.timestamp")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   apexLinkerconfigValidationRule,
+		Input:  apexFile,
+		Output: timestamp,
+		Args: map[string]string{
+			"image_dir": imageDir.String(),
+		},
+	})
+	return timestamp
+}
+
 // Runs apex_sepolicy_tests
 //
 // $ deapexer list -Z {apex_file} > {file_contexts}
diff --git a/apex/key.go b/apex/key.go
index 65e739a..fc1456b 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -208,11 +208,11 @@
 }
 
 // ConvertWithBp2build performs conversion apexKey for bp2build
-func (m *apexKey) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (m *apexKey) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	apexKeyBp2BuildInternal(ctx, m)
 }
 
-func apexKeyBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexKey) {
+func apexKeyBp2BuildInternal(ctx android.Bp2buildMutatorContext, module *apexKey) {
 	privateKeyLabelAttribute, privateKeyNameAttribute :=
 		android.BazelStringOrLabelFromProp(ctx, module.properties.Private_key)
 
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 76cd972..7195a97 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -18,14 +18,16 @@
 	"crypto/sha256"
 	"encoding/base64"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"path/filepath"
-	analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
 	"reflect"
 	"sort"
 	"strings"
 	"sync"
 
+	analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+
 	"github.com/google/blueprint/metrics"
 	"github.com/google/blueprint/proptools"
 	"google.golang.org/protobuf/proto"
@@ -177,6 +179,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
 	}
 
@@ -359,9 +376,14 @@
 		for i, actionEntry := range aqueryProto.Actions {
 			wg.Add(1)
 			go func(i int, actionEntry *analysis_v2_proto.Action) {
-				buildStatement, aErr := aqueryHandler.actionToBuildStatement(actionEntry)
-				if aErr != nil {
+				if buildStatement, aErr := aqueryHandler.actionToBuildStatement(actionEntry); aErr != nil {
 					errOnce.Do(func() {
+						for _, t := range aqueryProto.Targets {
+							if t.GetId() == actionEntry.GetTargetId() {
+								aErr = fmt.Errorf("%s: [%s] [%s]", aErr.Error(), actionEntry.GetMnemonic(), t.GetLabel())
+								break
+							}
+						}
 						err = aErr
 					})
 				} else {
@@ -767,7 +789,7 @@
 	}
 
 	if len(actionEntry.Arguments) < 1 {
-		return nil, fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic)
+		return nil, errors.New("received action with no command")
 	}
 	return a.normalActionBuildStatement(actionEntry)
 
diff --git a/bazel/configurability.go b/bazel/configurability.go
index 1fe8442..a28432c 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -71,6 +71,7 @@
 
 	AndroidAndInApex = "android-in_apex"
 	AndroidPlatform  = "system"
+	Unbundled_app    = "unbundled_app"
 
 	InApex  = "in_apex"
 	NonApex = "non_apex"
@@ -207,6 +208,7 @@
 	osAndInApexMap = map[string]string{
 		AndroidAndInApex:           "//build/bazel/rules/apex:android-in_apex",
 		AndroidPlatform:            "//build/bazel/rules/apex:system",
+		Unbundled_app:              "//build/bazel/rules/apex:unbundled_app",
 		OsDarwin:                   "//build/bazel/platforms/os:darwin",
 		OsLinux:                    "//build/bazel/platforms/os:linux_glibc",
 		osLinuxMusl:                "//build/bazel/platforms/os:linux_musl",
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 6b50a2e..e30e53d 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -44,6 +44,7 @@
         "aidl_library_conversion_test.go",
         "android_app_certificate_conversion_test.go",
         "android_app_conversion_test.go",
+        "android_test_conversion_test.go",
         "apex_conversion_test.go",
         "apex_key_conversion_test.go",
         "build_conversion_test.go",
@@ -62,7 +63,8 @@
         "cc_test_conversion_test.go",
         "cc_yasm_conversion_test.go",
         "conversion_test.go",
-        "droidstubs_conversion_test.go",
+        "droiddoc_exported_dir_conversion_test.go",
+        "fdo_profile_conversion_test.go",
         "filegroup_conversion_test.go",
         "genrule_conversion_test.go",
         "gensrcs_conversion_test.go",
@@ -73,6 +75,8 @@
         "java_library_host_conversion_test.go",
         "java_plugin_conversion_test.go",
         "java_proto_conversion_test.go",
+        "java_sdk_library_conversion_test.go",
+        "java_sdk_library_import_conversion_test.go",
         "license_conversion_test.go",
         "license_kind_conversion_test.go",
         "linker_config_conversion_test.go",
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
index a24378c..40356a1 100644
--- a/bp2build/aar_conversion_test.go
+++ b/bp2build/aar_conversion_test.go
@@ -15,11 +15,10 @@
 package bp2build
 
 import (
+	"testing"
+
 	"android/soong/android"
 	"android/soong/java"
-	"fmt"
-
-	"testing"
 )
 
 func TestConvertAndroidLibrary(t *testing.T) {
@@ -35,7 +34,8 @@
 			"res/res.png":                  "",
 			"manifest/AndroidManifest.xml": "",
 		},
-		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
+		StubbedBuildDefinitions: []string{"static_lib_dep"},
+		Blueprint: simpleModule("android_library", "static_lib_dep") + `
 android_library {
 	name: "TestLib",
 	srcs: ["lib.java"],
@@ -82,7 +82,7 @@
 			"res/res.png":         "",
 			"AndroidManifest.xml": "",
 		},
-		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "lib_dep") + `
+		Blueprint: simpleModule("android_library", "lib_dep") + `
 android_library {
 	name: "TestLib",
 	srcs: [],
@@ -91,7 +91,6 @@
 	sdk_version: "current",
 }
 `,
-		ExpectedErr:          fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."),
 		ExpectedBazelTargets: []string{},
 	})
 }
@@ -109,18 +108,25 @@
 			ModuleTypeUnderTestFactory: java.AARImportFactory,
 			Filesystem: map[string]string{
 				"import.aar": "",
+				"dep.aar":    "",
 			},
+			StubbedBuildDefinitions: []string{"static_lib_dep", "static_import_dep", "static_import_dep-neverlink"},
 			// Bazel's aar_import can only export *_import targets, so we expect
 			// only "static_import_dep" in exports, but both "static_lib_dep" and
 			// "static_import_dep" in deps
-			Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") +
-				simpleModuleDoNotConvertBp2build("android_library_import", "static_import_dep") + `
+			Blueprint: simpleModule("android_library", "static_lib_dep") + `
 android_library_import {
         name: "TestImport",
         aars: ["import.aar"],
         static_libs: ["static_lib_dep", "static_import_dep"],
     sdk_version: "current",
 }
+
+// TODO: b/301007952 - This dep is needed because android_library_import must have aars set.
+android_library_import {
+        name: "static_import_dep",
+        aars: ["import.aar"],
+}
 `,
 			ExpectedBazelTargets: []string{
 				MakeBazelTarget(
diff --git a/bp2build/aconfig_conversion_test.go b/bp2build/aconfig_conversion_test.go
new file mode 100644
index 0000000..cbf42ac
--- /dev/null
+++ b/bp2build/aconfig_conversion_test.go
@@ -0,0 +1,137 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+	"testing"
+
+	"android/soong/aconfig"
+	"android/soong/android"
+	"android/soong/cc"
+)
+
+func registerAconfigModuleTypes(ctx android.RegistrationContext) {
+	aconfig.RegisterBuildComponents(ctx)
+	ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
+}
+
+func TestAconfigDeclarations(t *testing.T) {
+	bp := `
+	aconfig_declarations {
+		name: "foo",
+		srcs: [
+			"foo1.aconfig",
+			"test/foo2.aconfig",
+		],
+		package: "com.android.foo",
+	}
+	`
+	expectedBazelTarget := MakeBazelTargetNoRestrictions(
+		"aconfig_declarations",
+		"foo",
+		AttrNameToString{
+			"srcs": `[
+        "foo1.aconfig",
+        "test/foo2.aconfig",
+    ]`,
+			"package": `"com.android.foo"`,
+		},
+	)
+	RunBp2BuildTestCase(t, registerAconfigModuleTypes, Bp2buildTestCase{
+		Blueprint:            bp,
+		ExpectedBazelTargets: []string{expectedBazelTarget},
+	})
+}
+
+func TestAconfigValues(t *testing.T) {
+	bp := `
+	aconfig_values {
+		name: "foo",
+		srcs: [
+			"foo1.textproto",
+		],
+		package: "com.android.foo",
+	}
+	aconfig_value_set {
+    name: "bar",
+    values: [
+        "foo"
+    ]
+	}
+	`
+	expectedBazelTargets := []string{
+		MakeBazelTargetNoRestrictions(
+			"aconfig_values",
+			"foo",
+			AttrNameToString{
+				"srcs":    `["foo1.textproto"]`,
+				"package": `"com.android.foo"`,
+			},
+		),
+		MakeBazelTargetNoRestrictions(
+			"aconfig_value_set",
+			"bar",
+			AttrNameToString{
+				"values": `[":foo"]`,
+			},
+		)}
+	RunBp2BuildTestCase(t, registerAconfigModuleTypes, Bp2buildTestCase{
+		Blueprint:            bp,
+		ExpectedBazelTargets: expectedBazelTargets,
+	})
+}
+
+func TestCcAconfigLibrary(t *testing.T) {
+	bp := `
+	aconfig_declarations {
+		name: "foo_aconfig_declarations",
+		srcs: [
+			"foo1.aconfig",
+		],
+		package: "com.android.foo",
+	}
+	cc_library {
+			name: "server_configurable_flags",
+			srcs: ["bar.cc"],
+			bazel_module: { bp2build_available: false },
+	}
+	cc_aconfig_library {
+			name: "foo",
+			aconfig_declarations: "foo_aconfig_declarations",
+	}
+	`
+	expectedBazelTargets := []string{
+		MakeBazelTargetNoRestrictions(
+			"aconfig_declarations",
+			"foo_aconfig_declarations",
+			AttrNameToString{
+				"srcs":    `["foo1.aconfig"]`,
+				"package": `"com.android.foo"`,
+			},
+		),
+		MakeBazelTargetNoRestrictions(
+			"cc_aconfig_library",
+			"foo",
+			AttrNameToString{
+				"aconfig_declarations":   `":foo_aconfig_declarations"`,
+				"dynamic_deps":           `[":server_configurable_flags"]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+			},
+		)}
+	RunBp2BuildTestCase(t, registerAconfigModuleTypes, Bp2buildTestCase{
+		Blueprint:            bp,
+		ExpectedBazelTargets: expectedBazelTargets,
+	})
+}
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index f2ee322..8ec4b35 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/cc"
 	"android/soong/java"
 
 	"testing"
@@ -29,6 +30,7 @@
 func registerAndroidAppModuleTypes(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	ctx.RegisterModuleType("java_library", java.LibraryFactory)
+	ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory)
 }
 
 func TestMinimalAndroidApp(t *testing.T) {
@@ -78,7 +80,9 @@
 			"manifest/AndroidManifest.xml": "",
 			"assets_/asset.png":            "",
 		},
-		Blueprint: simpleModuleDoNotConvertBp2build("android_app", "static_lib_dep") + `
+		StubbedBuildDefinitions: []string{"static_lib_dep", "jni_lib"},
+		Blueprint: simpleModule("android_app", "static_lib_dep") +
+			simpleModule("cc_library_shared", "jni_lib") + `
 android_app {
 	name: "TestApp",
 	srcs: ["app.java"],
@@ -99,6 +103,7 @@
 		obfuscate: false,
 		ignore_warnings: true,
 	},
+	jni_libs: ["jni_lib"],
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -109,10 +114,13 @@
         "resa/res.png",
         "resb/res.png",
     ]`,
-				"assets":           `["assets_/asset.png"]`,
-				"assets_dir":       `"assets_"`,
-				"custom_package":   `"com.google"`,
-				"deps":             `[":static_lib_dep"]`,
+				"assets":         `["assets_/asset.png"]`,
+				"assets_dir":     `"assets_"`,
+				"custom_package": `"com.google"`,
+				"deps": `[
+        ":static_lib_dep",
+        ":jni_lib",
+    ]`,
 				"java_version":     `"7"`,
 				"sdk_version":      `"current"`,
 				"certificate_name": `"foocert"`,
@@ -177,7 +185,8 @@
 		ModuleTypeUnderTest:        "android_app",
 		ModuleTypeUnderTestFactory: java.AndroidAppFactory,
 		Filesystem:                 map[string]string{},
-		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+		StubbedBuildDefinitions:    []string{"foocert"},
+		Blueprint: simpleModule("filegroup", "foocert") + `
 android_app {
 	name: "TestApp",
 	certificate: ":foocert",
@@ -262,7 +271,8 @@
 		ModuleTypeUnderTest:        "android_app",
 		ModuleTypeUnderTestFactory: java.AndroidAppFactory,
 		Filesystem:                 map[string]string{},
-		Blueprint: simpleModuleDoNotConvertBp2build("java_library", "barLib") + `
+		StubbedBuildDefinitions:    []string{"barLib"},
+		Blueprint: simpleModule("java_library", "barLib") + `
 android_app {
 	name: "foo",
 	libs: ["barLib"],
@@ -291,8 +301,9 @@
 		Filesystem: map[string]string{
 			"res/res.png": "",
 		},
-		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") +
-			simpleModuleDoNotConvertBp2build("java_library", "barLib") + `
+		StubbedBuildDefinitions: []string{"foocert", "barLib"},
+		Blueprint: simpleModule("filegroup", "foocert") +
+			simpleModule("java_library", "barLib") + `
 android_app {
 	name: "foo",
 	srcs: ["a.java", "b.kt"],
@@ -334,6 +345,7 @@
 		Filesystem: map[string]string{
 			"res/res.png": "",
 		},
+		StubbedBuildDefinitions: []string{"barLib"},
 		Blueprint: `
 android_app {
 	name: "foo",
@@ -348,7 +360,6 @@
 }
 java_library{
 	name:   "barLib",
-	bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -423,7 +434,6 @@
 	name: "foo",
 	sdk_version: "current",
 	min_sdk_version: "24",
-	max_sdk_version: "30",
 	target_sdk_version: "29",
 	optimize: {
 		enabled: false,
@@ -435,7 +445,6 @@
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `[]`,
 				"manifest_values": `{
-        "maxSdkVersion": "30",
         "minSdkVersion": "24",
         "targetSdkVersion": "29",
     }`,
@@ -464,12 +473,8 @@
 			MakeBazelTarget("android_binary", "foo", AttrNameToString{
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `[]`,
-				"manifest_values": `{
-        "minSdkVersion": "30",
-        "targetSdkVersion": "30",
-    }`,
-				"sdk_version": `"30"`,
-				"optimize":    `False`,
+				"sdk_version":    `"30"`,
+				"optimize":       `False`,
 			}),
 		}})
 }
diff --git a/bp2build/android_test_conversion_test.go b/bp2build/android_test_conversion_test.go
new file mode 100644
index 0000000..486f154
--- /dev/null
+++ b/bp2build/android_test_conversion_test.go
@@ -0,0 +1,178 @@
+// 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 (
+	"android/soong/android"
+	"android/soong/java"
+
+	"testing"
+)
+
+func runAndroidTestTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	RunBp2BuildTestCase(t, registerAndroidTestModuleTypes, tc)
+}
+
+func registerAndroidTestModuleTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	ctx.RegisterModuleType("java_library", java.LibraryFactory)
+}
+
+func TestMinimalAndroidTest(t *testing.T) {
+	runAndroidAppTestCase(t, Bp2buildTestCase{
+		Description:                "Android test - simple example",
+		ModuleTypeUnderTest:        "android_test",
+		ModuleTypeUnderTestFactory: java.AndroidTestFactory,
+		Filesystem: map[string]string{
+			"app.java":            "",
+			"res/res.png":         "",
+			"AndroidManifest.xml": "",
+			"assets/asset.png":    "",
+		},
+		Blueprint: `
+android_test {
+		name: "TestApp",
+		srcs: ["app.java"],
+		sdk_version: "current",
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("android_test", "TestApp", AttrNameToString{
+				"srcs":           `["app.java"]`,
+				"manifest":       `"AndroidManifest.xml"`,
+				"resource_files": `["res/res.png"]`,
+				"sdk_version":    `"current"`,
+				"assets":         `["assets/asset.png"]`,
+				"assets_dir":     `"assets"`,
+				// no need for optimize = False because it's false for
+				// android_test by default
+			}),
+		}})
+}
+
+func TestAndroidTest_OptimizationEnabled(t *testing.T) {
+	runAndroidAppTestCase(t, Bp2buildTestCase{
+		Description:                "Android test - simple example",
+		ModuleTypeUnderTest:        "android_test",
+		ModuleTypeUnderTestFactory: java.AndroidTestFactory,
+		Filesystem: map[string]string{
+			"app.java":            "",
+			"res/res.png":         "",
+			"AndroidManifest.xml": "",
+			"assets/asset.png":    "",
+		},
+		Blueprint: `
+android_test {
+		name: "TestApp",
+		srcs: ["app.java"],
+		sdk_version: "current",
+		optimize: {
+			enabled: true,
+			shrink: true,
+			optimize: true,
+			obfuscate: true,
+		},
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("android_test", "TestApp", AttrNameToString{
+				"srcs":           `["app.java"]`,
+				"manifest":       `"AndroidManifest.xml"`,
+				"resource_files": `["res/res.png"]`,
+				"sdk_version":    `"current"`,
+				"assets":         `["assets/asset.png"]`,
+				"assets_dir":     `"assets"`,
+				// optimize = True because it's false for android_test by
+				// default
+				"optimize": `True`,
+			}),
+		}})
+}
+
+func TestMinimalAndroidTestHelperApp(t *testing.T) {
+	runAndroidAppTestCase(t, Bp2buildTestCase{
+		Description:                "Android test helper app - simple example",
+		ModuleTypeUnderTest:        "android_test_helper_app",
+		ModuleTypeUnderTestFactory: java.AndroidTestHelperAppFactory,
+		Filesystem: map[string]string{
+			"app.java":            "",
+			"res/res.png":         "",
+			"AndroidManifest.xml": "",
+			"assets/asset.png":    "",
+		},
+		Blueprint: `
+android_test_helper_app {
+		name: "TestApp",
+		srcs: ["app.java"],
+		sdk_version: "current",
+		optimize: {
+			shrink: true,
+			optimize: true,
+			obfuscate: true,
+		},
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
+				"srcs":           `["app.java"]`,
+				"manifest":       `"AndroidManifest.xml"`,
+				"resource_files": `["res/res.png"]`,
+				"sdk_version":    `"current"`,
+				"assets":         `["assets/asset.png"]`,
+				"assets_dir":     `"assets"`,
+				"testonly":       `True`,
+				// no need for optimize = True because it's true for
+				// android_test_helper_app by default
+			}),
+		}})
+}
+
+func TestAndroidTestHelperApp_OptimizationDisabled(t *testing.T) {
+	runAndroidAppTestCase(t, Bp2buildTestCase{
+		Description:                "Android test helper app - simple example",
+		ModuleTypeUnderTest:        "android_test_helper_app",
+		ModuleTypeUnderTestFactory: java.AndroidTestHelperAppFactory,
+		Filesystem: map[string]string{
+			"app.java":            "",
+			"res/res.png":         "",
+			"AndroidManifest.xml": "",
+			"assets/asset.png":    "",
+		},
+		Blueprint: `
+android_test_helper_app {
+		name: "TestApp",
+		srcs: ["app.java"],
+		sdk_version: "current",
+		optimize: {
+			enabled: false,
+		},
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
+				"srcs":           `["app.java"]`,
+				"manifest":       `"AndroidManifest.xml"`,
+				"resource_files": `["res/res.png"]`,
+				"sdk_version":    `"current"`,
+				"assets":         `["assets/asset.png"]`,
+				"assets_dir":     `"assets"`,
+				"testonly":       `True`,
+				// optimize = False because it's true for
+				// android_test_helper_app by default
+				"optimize": `False`,
+			}),
+		}})
+}
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 2383247..5871d59 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -74,38 +74,34 @@
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions: []string{"com.android.apogee.key", "com.android.apogee.certificate", "native_shared_lib_1", "native_shared_lib_2",
+			"prebuilt_1", "prebuilt_2", "com.android.apogee-file_contexts", "cc_binary_1", "sh_binary_2"},
 		Blueprint: `
 apex_key {
 	name: "com.android.apogee.key",
 	public_key: "com.android.apogee.avbpubkey",
 	private_key: "com.android.apogee.pem",
-	bazel_module: { bp2build_available: false },
 }
 
 android_app_certificate {
 	name: "com.android.apogee.certificate",
 	certificate: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "native_shared_lib_1",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "native_shared_lib_2",
-	bazel_module: { bp2build_available: false },
 }
 
 prebuilt_etc {
 	name: "prebuilt_1",
-	bazel_module: { bp2build_available: false },
 }
 
 prebuilt_etc {
 	name: "prebuilt_2",
-	bazel_module: { bp2build_available: false },
 }
 
 filegroup {
@@ -113,11 +109,10 @@
 	srcs: [
 		"com.android.apogee-file_contexts",
 	],
-	bazel_module: { bp2build_available: false },
 }
 
-cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } }
-sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } }
+cc_binary { name: "cc_binary_1"}
+sh_binary { name: "sh_binary_2", src: "foo.sh"}
 
 apex {
 	name: "com.android.apogee",
@@ -202,6 +197,7 @@
 		Description:                "apex - file contexts is a module in another Android.bp",
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
+		StubbedBuildDefinitions:    []string{"//a/b:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"a/b/Android.bp": `
 filegroup {
@@ -209,7 +205,6 @@
 	srcs: [
 		"com.android.apogee-file_contexts",
 	],
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -252,6 +247,7 @@
 		Description:                "apex - file contexts is not specified",
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
+		StubbedBuildDefinitions:    []string{"//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
@@ -259,7 +255,6 @@
 	srcs: [
 		"com.android.apogee-file_contexts",
 	],
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -281,12 +276,12 @@
 		Description:                "apex - example with compile_multilib=both",
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
+		StubbedBuildDefinitions:    append(multilibStubNames(), "//system/sepolicy/apex:com.android.apogee-file_contexts"),
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -373,12 +368,12 @@
 			Description:                "apex - example with " + compileMultiLibProp,
 			ModuleTypeUnderTest:        "apex",
 			ModuleTypeUnderTestFactory: apex.BundleFactory,
+			StubbedBuildDefinitions:    append(multilibStubNames(), "//system/sepolicy/apex:com.android.apogee-file_contexts"),
 			Filesystem: map[string]string{
 				"system/sepolicy/apex/Android.bp": `
     filegroup {
         name: "com.android.apogee-file_contexts",
         srcs: [ "apogee-file_contexts", ],
-        bazel_module: { bp2build_available: false },
     }
     `,
 			},
@@ -393,12 +388,12 @@
 		Description:                "apex - example with compile_multilib=32",
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
+		StubbedBuildDefinitions:    append(multilibStubNames(), "//system/sepolicy/apex:com.android.apogee-file_contexts"),
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -425,12 +420,12 @@
 		Description:                "apex - example with compile_multilib=64",
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
+		StubbedBuildDefinitions:    append(multilibStubNames(), "//system/sepolicy/apex:com.android.apogee-file_contexts"),
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -458,31 +453,31 @@
 		}})
 }
 
+func multilibStubNames() []string {
+	return []string{"native_shared_lib_for_both", "native_shared_lib_for_first", "native_shared_lib_for_lib32", "native_shared_lib_for_lib64",
+		"native_shared_lib_for_lib64", "unnested_native_shared_lib"}
+}
+
 func createMultilibBlueprint(compile_multilib string) string {
 	return fmt.Sprintf(`
 cc_library {
 	name: "native_shared_lib_for_both",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "native_shared_lib_for_first",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "native_shared_lib_for_lib32",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "native_shared_lib_for_lib64",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "unnested_native_shared_lib",
-	bazel_module: { bp2build_available: false },
 }
 
 apex {
@@ -519,12 +514,12 @@
 		Description:                "apex - default property values",
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
+		StubbedBuildDefinitions:    []string{"//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -546,12 +541,12 @@
 		Description:                "apex - has bazel module props",
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
+		StubbedBuildDefinitions:    []string{"//system/sepolicy/apex:apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -575,38 +570,35 @@
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions: []string{"com.android.apogee.key", "com.android.apogee.certificate", "native_shared_lib_1",
+			"native_shared_lib_2", "prebuilt_1", "prebuilt_2", "com.android.apogee-file_contexts", "cc_binary_1",
+			"sh_binary_2", "com.android.apogee", "com.google.android.apogee.key", "com.google.android.apogee.certificate"},
 		Blueprint: `
 apex_key {
 	name: "com.android.apogee.key",
 	public_key: "com.android.apogee.avbpubkey",
 	private_key: "com.android.apogee.pem",
-	bazel_module: { bp2build_available: false },
 }
 
 android_app_certificate {
 	name: "com.android.apogee.certificate",
 	certificate: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "native_shared_lib_1",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "native_shared_lib_2",
-	bazel_module: { bp2build_available: false },
 }
 
 prebuilt_etc {
 	name: "prebuilt_1",
-	bazel_module: { bp2build_available: false },
 }
 
 prebuilt_etc {
 	name: "prebuilt_2",
-	bazel_module: { bp2build_available: false },
 }
 
 filegroup {
@@ -614,11 +606,10 @@
 	srcs: [
 		"com.android.apogee-file_contexts",
 	],
-	bazel_module: { bp2build_available: false },
 }
 
-cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } }
-sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } }
+cc_binary { name: "cc_binary_1" }
+sh_binary { name: "sh_binary_2", src: "foo.sh"}
 
 apex {
 	name: "com.android.apogee",
@@ -643,20 +634,17 @@
 	    "prebuilt_1",
 	    "prebuilt_2",
 	],
-	bazel_module: { bp2build_available: false },
 }
 
 apex_key {
 	name: "com.google.android.apogee.key",
 	public_key: "com.google.android.apogee.avbpubkey",
 	private_key: "com.google.android.apogee.pem",
-	bazel_module: { bp2build_available: false },
 }
 
 android_app_certificate {
 	name: "com.google.android.apogee.certificate",
 	certificate: "com.google.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -717,28 +705,27 @@
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions: []string{"com.android.apogee.certificate", "native_shared_lib_1",
+			"prebuilt_1", "com.android.apogee-file_contexts", "cc_binary_1", "sh_binary_2",
+			"com.android.apogee", "com.google.android.apogee.key", "com.google.android.apogee.certificate", "com.android.apogee.key"},
 		Blueprint: `
 apex_key {
 	name: "com.android.apogee.key",
 	public_key: "com.android.apogee.avbpubkey",
 	private_key: "com.android.apogee.pem",
-	bazel_module: { bp2build_available: false },
 }
 
 android_app_certificate {
 	name: "com.android.apogee.certificate",
 	certificate: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "native_shared_lib_1",
-	bazel_module: { bp2build_available: false },
 }
 
 prebuilt_etc {
 	name: "prebuilt_1",
-	bazel_module: { bp2build_available: false },
 }
 
 filegroup {
@@ -746,11 +733,10 @@
 	srcs: [
 		"com.android.apogee-file_contexts",
 	],
-	bazel_module: { bp2build_available: false },
 }
 
-cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } }
-sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } }
+cc_binary { name: "cc_binary_1"}
+sh_binary { name: "sh_binary_2", src: "foo.sh"}
 
 apex_test {
 	name: "com.android.apogee",
@@ -773,20 +759,17 @@
 	prebuilts: [
 	    "prebuilt_1",
 	],
-	bazel_module: { bp2build_available: false },
 }
 
 apex_key {
 	name: "com.google.android.apogee.key",
 	public_key: "com.google.android.apogee.avbpubkey",
 	private_key: "com.google.android.apogee.pem",
-	bazel_module: { bp2build_available: false },
 }
 
 android_app_certificate {
 	name: "com.google.android.apogee.certificate",
 	certificate: "com.google.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -835,17 +818,16 @@
 		Description:                "override_apex - manifest of base apex is empty, base apex and override_apex is in different Android.bp",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"//a/b:com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 			"a/b/Android.bp": `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -869,18 +851,17 @@
 		Description:                "override_apex - manifest of base apex is set, base apex and override_apex is in different Android.bp",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"//a/b:com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 			"a/b/Android.bp": `
 apex {
 	name: "com.android.apogee",
   manifest: "apogee_manifest.json",
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -904,18 +885,17 @@
 		Description:                "override_apex - manifest of base apex is empty, base apex and override_apex is in same Android.bp",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 		},
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -937,19 +917,18 @@
 		Description:                "override_apex - manifest of base apex is set, base apex and override_apex is in same Android.bp",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 		},
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
   manifest: "apogee_manifest.json",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -971,18 +950,17 @@
 		Description:                "override_apex - override package name",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 		},
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -1006,24 +984,22 @@
 		Description:                "override_apex - no override",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"prebuilt_file", "com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 		},
 		Blueprint: `
 prebuilt_etc {
 	name: "prebuilt_file",
-	bazel_module: { bp2build_available: false },
 }
 
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
-    prebuilts: ["prebuilt_file"]
+	prebuilts: ["prebuilt_file"]
 }
 
 override_apex {
@@ -1046,35 +1022,32 @@
 		Description:                "override_apex - ooverride",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"prebuilt_file", "prebuilt_file2", "com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 		},
 		Blueprint: `
 prebuilt_etc {
 	name: "prebuilt_file",
-	bazel_module: { bp2build_available: false },
 }
 
 prebuilt_etc {
 	name: "prebuilt_file2",
-	bazel_module: { bp2build_available: false },
 }
 
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
-    prebuilts: ["prebuilt_file"]
+	prebuilts: ["prebuilt_file"]
 }
 
 override_apex {
 	name: "com.google.android.apogee",
 	base: ":com.android.apogee",
-    prebuilts: ["prebuilt_file2"]
+	prebuilts: ["prebuilt_file2"]
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -1092,24 +1065,22 @@
 		Description:                "override_apex - override with empty list",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"prebuilt_file", "com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 		},
 		Blueprint: `
 prebuilt_etc {
 	name: "prebuilt_file",
-	bazel_module: { bp2build_available: false },
 }
 
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
-    prebuilts: ["prebuilt_file"]
+	prebuilts: ["prebuilt_file"]
 }
 
 override_apex {
@@ -1133,18 +1104,17 @@
 		Description:                "override_apex - logging_parent - no override",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 		},
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 	logging_parent: "foo.bar.baz",
 }
 
@@ -1168,18 +1138,17 @@
 		Description:                "override_apex - logging_parent - override",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
 	name: "com.android.apogee-file_contexts",
 	srcs: [ "apogee-file_contexts", ],
-	bazel_module: { bp2build_available: false },
 }`,
 		},
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 	logging_parent: "foo.bar.baz",
 }
 
@@ -1205,11 +1174,11 @@
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions:    []string{"com.android.apogee.certificate", "com.android.apogee-file_contexts", "com.android.apogee"},
 		Blueprint: `
 android_app_certificate {
 	name: "com.android.apogee.certificate",
 	certificate: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 filegroup {
@@ -1217,7 +1186,6 @@
 	srcs: [
 		"com.android.apogee-file_contexts",
 	],
-	bazel_module: { bp2build_available: false },
 }
 
 apex {
@@ -1225,7 +1193,6 @@
 	manifest: "apogee_manifest.json",
 	file_contexts: ":com.android.apogee-file_contexts",
 	certificate: ":com.android.apogee.certificate",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -1250,11 +1217,11 @@
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions:    []string{"com.android.apogee-file_contexts", "com.android.apogee.certificate"},
 		Blueprint: `
 android_app_certificate {
 	name: "com.android.apogee.certificate",
 	certificate: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 apex {
@@ -1263,7 +1230,7 @@
 	file_contexts: ":com.android.apogee-file_contexts",
 	certificate: ":com.android.apogee.certificate",
 }
-` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee-file_contexts"),
+` + simpleModule("filegroup", "com.android.apogee-file_contexts"),
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
 				"certificate":   `":com.android.apogee.certificate"`,
@@ -1279,6 +1246,7 @@
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions:    []string{"myapex-file_contexts"},
 		Blueprint: `
 cc_library{
 	name: "foo",
@@ -1299,7 +1267,7 @@
 	binaries: ["bar"],
 	native_shared_libs: ["foo"],
 }
-` + simpleModuleDoNotConvertBp2build("filegroup", "myapex-file_contexts"),
+` + simpleModule("filegroup", "myapex-file_contexts"),
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_binary", "bar", AttrNameToString{
 				"local_includes": `["."]`,
@@ -1315,6 +1283,7 @@
 				"tags":              `["apex_available=myapex"]`,
 			}),
 			MakeBazelTarget("cc_stub_suite", "foo_stub_libs", AttrNameToString{
+				"api_surface":          `"module-libapi"`,
 				"soname":               `"foo.so"`,
 				"source_library_label": `"//:foo"`,
 				"symbol_file":          `"foo.map.txt"`,
@@ -1349,6 +1318,7 @@
 		ModuleTypeUnderTest:        "apex",
 		ModuleTypeUnderTestFactory: apex.BundleFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions:    []string{"com.android.apogee-file_contexts"},
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
@@ -1356,7 +1326,7 @@
 	file_contexts: ":com.android.apogee-file_contexts",
 	certificate: "com.android.apogee.certificate",
 }
-` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee-file_contexts"),
+` + simpleModule("filegroup", "com.android.apogee-file_contexts"),
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
 				"certificate_name": `"com.android.apogee.certificate"`,
@@ -1372,11 +1342,12 @@
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions: []string{"com.android.apogee.certificate", "com.android.apogee-file_contexts",
+			"com.android.apogee", "com.google.android.apogee.certificate"},
 		Blueprint: `
 android_app_certificate {
 	name: "com.android.apogee.certificate",
 	certificate: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 filegroup {
@@ -1384,7 +1355,6 @@
 	srcs: [
 		"com.android.apogee-file_contexts",
 	],
-	bazel_module: { bp2build_available: false },
 }
 
 apex {
@@ -1392,13 +1362,11 @@
 	manifest: "apogee_manifest.json",
 	file_contexts: ":com.android.apogee-file_contexts",
 	certificate: ":com.android.apogee.certificate",
-	bazel_module: { bp2build_available: false },
 }
 
 android_app_certificate {
 	name: "com.google.android.apogee.certificate",
 	certificate: "com.google.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -1423,11 +1391,11 @@
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "com.android.apogee.certificate", "com.android.apogee", "com.android.apogee-file_contexts"},
 		Blueprint: `
 android_app_certificate {
 	name: "com.android.apogee.certificate",
 	certificate: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 filegroup {
@@ -1435,7 +1403,6 @@
 	srcs: [
 		"com.android.apogee-file_contexts",
 	],
-	bazel_module: { bp2build_available: false },
 }
 
 apex {
@@ -1443,7 +1410,6 @@
 	manifest: "apogee_manifest.json",
 	file_contexts: ":com.android.apogee-file_contexts",
 	certificate: ":com.android.apogee.certificate",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -1468,8 +1434,9 @@
 		ModuleTypeUnderTest:        "apex_test",
 		ModuleTypeUnderTestFactory: apex.TestApexBundleFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions:    []string{"cc_test_1"},
 		Blueprint: `
-cc_test { name: "cc_test_1", bazel_module: { bp2build_available: false } }
+cc_test { name: "cc_test_1"}
 
 apex_test {
 	name: "test_com.android.apogee",
@@ -1496,6 +1463,7 @@
 		Description:                "apex - overriding a module that uses product vars",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		StubbedBuildDefinitions:    []string{"foo-file_contexts"},
 		Blueprint: `
 soong_config_string_variable {
     name: "library_linking_strategy",
@@ -1534,7 +1502,6 @@
 	srcs: [
 		"com.android.apogee-file_contexts",
 	],
-	bazel_module: { bp2build_available: false },
 }
 
 apex {
diff --git a/bp2build/apex_key_conversion_test.go b/bp2build/apex_key_conversion_test.go
index 1230a48..140afb7 100644
--- a/bp2build/apex_key_conversion_test.go
+++ b/bp2build/apex_key_conversion_test.go
@@ -83,14 +83,15 @@
 		ModuleTypeUnderTest:        "apex_key",
 		ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions:    []string{"com.android.apogee.avbpubkey", "com.android.apogee.pem"},
 		Blueprint: `
 apex_key {
         name: "com.android.apogee.key",
         public_key: ":com.android.apogee.avbpubkey",
         private_key: ":com.android.apogee.pem",
 }
-` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.avbpubkey") +
-			simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.pem"),
+` + simpleModule("filegroup", "com.android.apogee.avbpubkey") +
+			simpleModule("filegroup", "com.android.apogee.pem"),
 		ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{
 			"private_key":            `":com.android.apogee.pem"`,
 			"public_key":             `":com.android.apogee.avbpubkey"`,
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.go b/bp2build/bp2build.go
index 5f7b382..6c9d903 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -82,15 +82,25 @@
 		os.Exit(1)
 	}
 	var bp2buildFiles []BazelFile
+	productConfig, err := createProductConfigFiles(ctx, res.metrics)
 	ctx.Context().EventHandler.Do("CreateBazelFile", func() {
-		bp2buildFiles = CreateBazelFiles(nil, res.buildFileToTargets, ctx.mode)
+		allTargets := make(map[string]BazelTargets)
+		for k, v := range res.buildFileToTargets {
+			allTargets[k] = append(allTargets[k], v...)
+		}
+		for k, v := range productConfig.bp2buildTargets {
+			allTargets[k] = append(allTargets[k], v...)
+		}
+		bp2buildFiles = CreateBazelFiles(nil, allTargets, ctx.mode)
 	})
-	injectionFiles, additionalBp2buildFiles, err := CreateSoongInjectionDirFiles(ctx, res.metrics)
+	bp2buildFiles = append(bp2buildFiles, productConfig.bp2buildFiles...)
+	injectionFiles, err := createSoongInjectionDirFiles(ctx, res.metrics)
 	if err != nil {
 		fmt.Printf("%s\n", err.Error())
 		os.Exit(1)
 	}
-	bp2buildFiles = append(bp2buildFiles, additionalBp2buildFiles...)
+	injectionFiles = append(injectionFiles, productConfig.injectionFiles...)
+
 	writeFiles(ctx, bp2buildDir, bp2buildFiles)
 	// Delete files under the bp2build root which weren't just written. An
 	// alternative would have been to delete the whole directory and write these
@@ -109,26 +119,6 @@
 	return &res.metrics
 }
 
-// Wrapper function that will be responsible for all files in soong_injection directory
-// This includes
-// 1. config value(s) that are hardcoded in Soong
-// 2. product_config variables
-func CreateSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, []BazelFile, error) {
-	var ret []BazelFile
-
-	productConfigInjectionFiles, productConfigBp2BuildDirFiles, err := CreateProductConfigFiles(ctx, metrics)
-	if err != nil {
-		return nil, nil, err
-	}
-	ret = append(ret, productConfigInjectionFiles...)
-	injectionFiles, err := soongInjectionFiles(ctx.Config(), metrics)
-	if err != nil {
-		return nil, nil, err
-	}
-	ret = append(injectionFiles, ret...)
-	return ret, productConfigBp2BuildDirFiles, nil
-}
-
 // Get the output directory and create it if it doesn't exist.
 func getOrCreateOutputDir(outputDir android.OutputPath, ctx android.PathContext, dir string) android.OutputPath {
 	dirPath := outputDir.Join(ctx, dir)
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index e8c2ef7..b724f57 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,13 +8,33 @@
 	"reflect"
 	"strings"
 
+	"android/soong/android"
+	"android/soong/android/soongconfig"
+	"android/soong/starlark_import"
+
 	"github.com/google/blueprint/proptools"
 	"go.starlark.net/starlark"
 )
 
-func CreateProductConfigFiles(
+type createProductConfigFilesResult struct {
+	injectionFiles  []BazelFile
+	bp2buildFiles   []BazelFile
+	bp2buildTargets map[string]BazelTargets
+}
+
+type bazelLabel struct {
+	repo   string
+	pkg    string
+	target string
+}
+
+func (l *bazelLabel) String() string {
+	return fmt.Sprintf("@%s//%s:%s", l.repo, l.pkg, l.target)
+}
+
+func createProductConfigFiles(
 	ctx *CodegenContext,
-	metrics CodegenMetrics) ([]BazelFile, []BazelFile, error) {
+	metrics CodegenMetrics) (createProductConfigFilesResult, error) {
 	cfg := &ctx.config
 	targetProduct := "unknown"
 	if cfg.HasDeviceProduct() {
@@ -30,68 +47,93 @@
 		targetBuildVariant = "userdebug"
 	}
 
+	var res createProductConfigFilesResult
+
 	productVariablesFileName := cfg.ProductVariablesFileName
 	if !strings.HasPrefix(productVariablesFileName, "/") {
 		productVariablesFileName = filepath.Join(ctx.topDir, productVariablesFileName)
 	}
 	productVariablesBytes, err := os.ReadFile(productVariablesFileName)
 	if err != nil {
-		return nil, nil, err
+		return res, err
 	}
 	productVariables := android.ProductVariables{}
 	err = json.Unmarshal(productVariablesBytes, &productVariables)
 	if err != nil {
-		return nil, nil, err
+		return res, err
 	}
 
-	// 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)
+	currentProductFolder := fmt.Sprintf("build/bazel/products/%s", targetProduct)
+	if len(productVariables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory) > 0 {
+		currentProductFolder = fmt.Sprintf("%s%s", productVariables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory, targetProduct)
+	}
 
 	productReplacer := strings.NewReplacer(
 		"{PRODUCT}", targetProduct,
 		"{VARIANT}", targetBuildVariant,
 		"{PRODUCT_FOLDER}", currentProductFolder)
 
-	platformMappingContent, err := platformMappingContent(
-		productReplacer.Replace("@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}"),
-		&productVariables,
-		ctx.Config().Bp2buildSoongConfigDefinitions,
-		metrics.convertedModulePathMap)
-	if err != nil {
-		return nil, nil, err
-	}
-
 	productsForTestingMap, err := starlark_import.GetStarlarkValue[map[string]map[string]starlark.Value]("products_for_testing")
 	if err != nil {
-		return nil, nil, err
+		return res, err
 	}
 	productsForTesting := android.SortedKeys(productsForTestingMap)
 	for i := range productsForTesting {
 		productsForTesting[i] = fmt.Sprintf("  \"@//build/bazel/tests/products:%s\",", productsForTesting[i])
 	}
 
-	injectionDirFiles := []BazelFile{
-		newFile(
-			currentProductFolder,
-			"soong.variables.bzl",
-			`variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`),
-		newFile(
-			currentProductFolder,
-			"BUILD",
-			productReplacer.Replace(`
-package(default_visibility=[
-    "@soong_injection//product_config_platforms:__subpackages__",
-    "@//build/bazel/product_config:__subpackages__",
-])
-load(":soong.variables.bzl", _soong_variables = "variables")
-load("@//build/bazel/product_config:android_product.bzl", "android_product")
+	productLabelsToVariables := make(map[bazelLabel]*android.ProductVariables)
+	productLabelsToVariables[bazelLabel{
+		repo:   "",
+		pkg:    currentProductFolder,
+		target: targetProduct,
+	}] = &productVariables
+	for product, productVariablesStarlark := range productsForTestingMap {
+		productVariables, err := starlarkMapToProductVariables(productVariablesStarlark)
+		if err != nil {
+			return res, err
+		}
+		productLabelsToVariables[bazelLabel{
+			repo:   "",
+			pkg:    "build/bazel/tests/products",
+			target: product,
+		}] = &productVariables
+	}
 
-android_product(
-    name = "{PRODUCT}-{VARIANT}",
+	res.bp2buildTargets = make(map[string]BazelTargets)
+	res.bp2buildTargets[currentProductFolder] = append(res.bp2buildTargets[currentProductFolder], BazelTarget{
+		name:        productReplacer.Replace("{PRODUCT}"),
+		packageName: currentProductFolder,
+		content: productReplacer.Replace(`android_product(
+    name = "{PRODUCT}",
     soong_variables = _soong_variables,
-)
-`)),
+)`),
+		ruleClass: "android_product",
+		loads: []BazelLoad{
+			{
+				file: ":soong.variables.bzl",
+				symbols: []BazelLoadSymbol{{
+					symbol: "variables",
+					alias:  "_soong_variables",
+				}},
+			},
+			{
+				file:    "//build/bazel/product_config:android_product.bzl",
+				symbols: []BazelLoadSymbol{{symbol: "android_product"}},
+			},
+		},
+	})
+	createTargets(productLabelsToVariables, res.bp2buildTargets)
+
+	platformMappingContent, err := platformMappingContent(
+		productLabelsToVariables,
+		ctx.Config().Bp2buildSoongConfigDefinitions,
+		metrics.convertedModulePathMap)
+	if err != nil {
+		return res, err
+	}
+
+	res.injectionFiles = []BazelFile{
 		newFile(
 			"product_config_platforms",
 			"BUILD.bazel",
@@ -101,7 +143,7 @@
 	"@soong_injection//product_config_platforms:__subpackages__",
 ])
 
-load("//{PRODUCT_FOLDER}:soong.variables.bzl", _soong_variables = "variables")
+load("@//{PRODUCT_FOLDER}:soong.variables.bzl", _soong_variables = "variables")
 load("@//build/bazel/product_config:android_product.bzl", "android_product")
 
 # Bazel will qualify its outputs by the platform name. When switching between products, this
@@ -110,7 +152,7 @@
 # extra rebuilding, make mixed builds always use a single platform so that the bazel artifacts
 # are always under the same path.
 android_product(
-    name = "mixed_builds_product-{VARIANT}",
+    name = "mixed_builds_product",
     soong_variables = _soong_variables,
     extra_constraints = ["@//build/bazel/platforms:mixed_builds"],
 )
@@ -124,54 +166,55 @@
 # TODO: When we start generating the platforms for more than just the
 # currently lunched product, they should all be listed here
 product_labels = [
-  "@soong_injection//product_config_platforms:mixed_builds_product-{VARIANT}",
-  "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}",
+  "@soong_injection//product_config_platforms:mixed_builds_product",
+  "@//{PRODUCT_FOLDER}:{PRODUCT}",
 `)+strings.Join(productsForTesting, "\n")+"\n]\n"),
 		newFile(
 			"product_config_platforms",
 			"common.bazelrc",
 			productReplacer.Replace(`
 build --platform_mappings=platform_mappings
-build --platforms @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
+build --platforms @//{PRODUCT_FOLDER}:{PRODUCT}_linux_x86_64
+build --//build/bazel/product_config:target_build_variant={VARIANT}
 
-build:android --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
-build:linux_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86
-build:linux_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
-build:linux_bionic_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_bionic_x86_64
-build:linux_musl_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86
-build:linux_musl_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86_64
+build:android --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}
+build:linux_x86 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_x86
+build:linux_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_x86_64
+build:linux_bionic_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_bionic_x86_64
+build:linux_musl_x86 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_musl_x86
+build:linux_musl_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_musl_x86_64
 `)),
 		newFile(
 			"product_config_platforms",
 			"linux.bazelrc",
 			productReplacer.Replace(`
-build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
+build --host_platform @//{PRODUCT_FOLDER}:{PRODUCT}_linux_x86_64
 `)),
 		newFile(
 			"product_config_platforms",
 			"darwin.bazelrc",
 			productReplacer.Replace(`
-build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64
+build --host_platform @//{PRODUCT_FOLDER}:{PRODUCT}_darwin_x86_64
 `)),
 	}
-	bp2buildDirFiles := []BazelFile{
+	res.bp2buildFiles = []BazelFile{
 		newFile(
 			"",
 			"platform_mappings",
 			platformMappingContent),
+		newFile(
+			currentProductFolder,
+			"soong.variables.bzl",
+			`variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`),
 	}
-	return injectionDirFiles, bp2buildDirFiles, nil
+
+	return res, nil
 }
 
 func platformMappingContent(
-	mainProductLabel string,
-	mainProductVariables *android.ProductVariables,
+	productLabelToVariables map[bazelLabel]*android.ProductVariables,
 	soongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions,
 	convertedModulePathMap map[string]string) (string, error) {
-	productsForTesting, err := starlark_import.GetStarlarkValue[map[string]map[string]starlark.Value]("products_for_testing")
-	if err != nil {
-		return "", err
-	}
 	var result strings.Builder
 
 	mergedConvertedModulePathMap := make(map[string]string)
@@ -187,13 +230,8 @@
 	}
 
 	result.WriteString("platforms:\n")
-	platformMappingSingleProduct(mainProductLabel, mainProductVariables, soongConfigDefinitions, mergedConvertedModulePathMap, &result)
-	for product, productVariablesStarlark := range productsForTesting {
-		productVariables, err := starlarkMapToProductVariables(productVariablesStarlark)
-		if err != nil {
-			return "", err
-		}
-		platformMappingSingleProduct("@//build/bazel/tests/products:"+product, &productVariables, soongConfigDefinitions, mergedConvertedModulePathMap, &result)
+	for productLabel, productVariables := range productLabelToVariables {
+		platformMappingSingleProduct(productLabel, productVariables, soongConfigDefinitions, mergedConvertedModulePathMap, &result)
 	}
 	return result.String(), nil
 }
@@ -213,17 +251,11 @@
 }
 
 func platformMappingSingleProduct(
-	label string,
+	label bazelLabel,
 	productVariables *android.ProductVariables,
 	soongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions,
 	convertedModulePathMap map[string]string,
 	result *strings.Builder) {
-	targetBuildVariant := "user"
-	if proptools.Bool(productVariables.Eng) {
-		targetBuildVariant = "eng"
-	} else if proptools.Bool(productVariables.Debuggable) {
-		targetBuildVariant = "userdebug"
-	}
 
 	platform_sdk_version := -1
 	if productVariables.Platform_sdk_version != nil {
@@ -232,12 +264,12 @@
 
 	defaultAppCertificateFilegroup := "//build/bazel/utils:empty_filegroup"
 	if proptools.String(productVariables.DefaultAppCertificate) != "" {
-		defaultAppCertificateFilegroup = "@//" + filepath.Dir(proptools.String(productVariables.DefaultAppCertificate)) + ":android_certificate_directory"
+		defaultAppCertificateFilegroup = "@//" + filepath.Dir(proptools.String(productVariables.DefaultAppCertificate)) + ":generated_android_certificate_directory"
 	}
 
 	for _, suffix := range bazelPlatformSuffixes {
 		result.WriteString("  ")
-		result.WriteString(label)
+		result.WriteString(label.String())
 		result.WriteString(suffix)
 		result.WriteString("\n")
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:always_use_prebuilt_sdks=%t\n", proptools.Bool(productVariables.Always_use_prebuilt_sdks)))
@@ -245,12 +277,12 @@
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:apex_global_min_sdk_version_override=%s\n", proptools.String(productVariables.ApexGlobalMinSdkVersionOverride)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:binder32bit=%t\n", proptools.Bool(productVariables.Binder32bit)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:build_from_text_stub=%t\n", proptools.Bool(productVariables.Build_from_text_stub)))
+		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:build_broken_incorrect_partition_images=%t\n", productVariables.BuildBrokenIncorrectPartitionImages))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:build_id=%s\n", proptools.String(productVariables.BuildId)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:build_version_tags=%s\n", strings.Join(productVariables.BuildVersionTags, ",")))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:cfi_exclude_paths=%s\n", strings.Join(productVariables.CFIExcludePaths, ",")))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:cfi_include_paths=%s\n", strings.Join(productVariables.CFIIncludePaths, ",")))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:compressed_apex=%t\n", proptools.Bool(productVariables.CompressedApex)))
-		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:debuggable=%t\n", proptools.Bool(productVariables.Debuggable)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:default_app_certificate=%s\n", proptools.String(productVariables.DefaultAppCertificate)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:default_app_certificate_filegroup=%s\n", defaultAppCertificateFilegroup))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:device_abi=%s\n", strings.Join(productVariables.DeviceAbi, ",")))
@@ -258,20 +290,29 @@
 		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.String()))
 		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_sdk_final=%t\n", proptools.Bool(productVariables.Platform_sdk_final)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:platform_version_name=%s\n", proptools.String(productVariables.Platform_version_name)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:product_brand=%s\n", productVariables.ProductBrand))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:product_manufacturer=%s\n", productVariables.ProductManufacturer))
+		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:release_aconfig_flag_default_permission=%s\n", productVariables.ReleaseAconfigFlagDefaultPermission))
+		// Empty string can't be used as label_flag on the bazel side
+		if len(productVariables.ReleaseAconfigValueSets) > 0 {
+			result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:release_aconfig_value_sets=%s\n", productVariables.ReleaseAconfigValueSets))
+		}
+		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:release_version=%s\n", productVariables.ReleaseVersion))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:platform_sdk_version=%d\n", platform_sdk_version))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:safestack=%t\n", proptools.Bool(productVariables.Safestack)))
-		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:target_build_variant=%s\n", targetBuildVariant))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:treble_linker_namespaces=%t\n", proptools.Bool(productVariables.Treble_linker_namespaces)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:tidy_checks=%s\n", proptools.String(productVariables.TidyChecks)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:uml=%t\n", proptools.Bool(productVariables.Uml)))
@@ -398,3 +439,303 @@
 
 	return result, nil
 }
+
+func createTargets(productLabelsToVariables map[bazelLabel]*android.ProductVariables, res map[string]BazelTargets) {
+	createGeneratedAndroidCertificateDirectories(productLabelsToVariables, res)
+	for label, variables := range productLabelsToVariables {
+		createSystemPartition(label, &variables.PartitionVarsForBazelMigrationOnlyDoNotUse, res)
+	}
+}
+
+func createGeneratedAndroidCertificateDirectories(productLabelsToVariables map[bazelLabel]*android.ProductVariables, targets map[string]BazelTargets) {
+	var allDefaultAppCertificateDirs []string
+	for _, productVariables := range productLabelsToVariables {
+		if proptools.String(productVariables.DefaultAppCertificate) != "" {
+			d := filepath.Dir(proptools.String(productVariables.DefaultAppCertificate))
+			if !android.InList(d, allDefaultAppCertificateDirs) {
+				allDefaultAppCertificateDirs = append(allDefaultAppCertificateDirs, d)
+			}
+		}
+	}
+	for _, dir := range allDefaultAppCertificateDirs {
+		content := `filegroup(
+    name = "generated_android_certificate_directory",
+    srcs = glob([
+        "*.pk8",
+        "*.pem",
+        "*.avbpubkey",
+    ]),
+    visibility = ["//visibility:public"],
+)`
+		targets[dir] = append(targets[dir], BazelTarget{
+			name:        "generated_android_certificate_directory",
+			packageName: dir,
+			content:     content,
+			ruleClass:   "filegroup",
+		})
+	}
+}
+
+func createSystemPartition(platformLabel bazelLabel, variables *android.PartitionVariables, targets map[string]BazelTargets) {
+	if !variables.PartitionQualifiedVariables["system"].BuildingImage {
+		return
+	}
+
+	imageProps := generateImagePropDictionary(variables, "system")
+	imageProps["skip_fsck"] = "true"
+
+	var properties strings.Builder
+	for _, prop := range android.SortedKeys(imageProps) {
+		properties.WriteString(prop)
+		properties.WriteRune('=')
+		properties.WriteString(imageProps[prop])
+		properties.WriteRune('\n')
+	}
+
+	targets[platformLabel.pkg] = append(targets[platformLabel.pkg], BazelTarget{
+		name:        "system_image",
+		packageName: platformLabel.pkg,
+		content: fmt.Sprintf(`partition(
+    name = "system_image",
+    base_staging_dir = "//build/bazel/bazel_sandwich:system_staging_dir",
+    base_staging_dir_file_list = "//build/bazel/bazel_sandwich:system_staging_dir_file_list",
+    root_dir = "//build/bazel/bazel_sandwich:root_staging_dir",
+    image_properties = """
+%s
+""",
+    type = "system",
+)`, properties.String()),
+		ruleClass: "partition",
+		loads: []BazelLoad{{
+			file: "//build/bazel/rules/partitions:partition.bzl",
+			symbols: []BazelLoadSymbol{{
+				symbol: "partition",
+			}},
+		}},
+	}, BazelTarget{
+		name:        "system_image_test",
+		packageName: platformLabel.pkg,
+		content: `partition_diff_test(
+    name = "system_image_test",
+    partition1 = "//build/bazel/bazel_sandwich:make_system_image",
+    partition2 = ":system_image",
+)`,
+		ruleClass: "partition_diff_test",
+		loads: []BazelLoad{{
+			file: "//build/bazel/rules/partitions/diff:partition_diff.bzl",
+			symbols: []BazelLoadSymbol{{
+				symbol: "partition_diff_test",
+			}},
+		}},
+	}, BazelTarget{
+		name:        "run_system_image_test",
+		packageName: platformLabel.pkg,
+		content: `run_test_in_build(
+    name = "run_system_image_test",
+    test = ":system_image_test",
+)`,
+		ruleClass: "run_test_in_build",
+		loads: []BazelLoad{{
+			file: "//build/bazel/bazel_sandwich:run_test_in_build.bzl",
+			symbols: []BazelLoadSymbol{{
+				symbol: "run_test_in_build",
+			}},
+		}},
+	})
+}
+
+var allPartitionTypes = []string{
+	"system",
+	"vendor",
+	"cache",
+	"userdata",
+	"product",
+	"system_ext",
+	"oem",
+	"odm",
+	"vendor_dlkm",
+	"odm_dlkm",
+	"system_dlkm",
+}
+
+// An equivalent of make's generate-image-prop-dictionary function
+func generateImagePropDictionary(variables *android.PartitionVariables, partitionType string) map[string]string {
+	partitionQualifiedVariables, ok := variables.PartitionQualifiedVariables[partitionType]
+	if !ok {
+		panic("Unknown partitionType: " + partitionType)
+	}
+	ret := map[string]string{}
+	if partitionType == "system" {
+		if len(variables.PartitionQualifiedVariables["system_other"].BoardPartitionSize) > 0 {
+			ret["system_other_size"] = variables.PartitionQualifiedVariables["system_other"].BoardPartitionSize
+		}
+		if len(partitionQualifiedVariables.ProductHeadroom) > 0 {
+			ret["system_headroom"] = partitionQualifiedVariables.ProductHeadroom
+		}
+		addCommonRoFlagsToImageProps(variables, partitionType, ret)
+	}
+	// TODO: other partition-specific logic
+	if variables.TargetUserimagesUseExt2 {
+		ret["fs_type"] = "ext2"
+	} else if variables.TargetUserimagesUseExt3 {
+		ret["fs_type"] = "ext3"
+	} else if variables.TargetUserimagesUseExt4 {
+		ret["fs_type"] = "ext4"
+	}
+
+	if !variables.TargetUserimagesSparseExtDisabled {
+		ret["extfs_sparse_flag"] = "-s"
+	}
+	if !variables.TargetUserimagesSparseErofsDisabled {
+		ret["erofs_sparse_flag"] = "-s"
+	}
+	if !variables.TargetUserimagesSparseSquashfsDisabled {
+		ret["squashfs_sparse_flag"] = "-s"
+	}
+	if !variables.TargetUserimagesSparseF2fsDisabled {
+		ret["f2fs_sparse_flag"] = "-S"
+	}
+	erofsCompressor := variables.BoardErofsCompressor
+	if len(erofsCompressor) == 0 && hasErofsPartition(variables) {
+		if len(variables.BoardErofsUseLegacyCompression) > 0 {
+			erofsCompressor = "lz4"
+		} else {
+			erofsCompressor = "lz4hc,9"
+		}
+	}
+	if len(erofsCompressor) > 0 {
+		ret["erofs_default_compressor"] = erofsCompressor
+	}
+	if len(variables.BoardErofsCompressorHints) > 0 {
+		ret["erofs_default_compress_hints"] = variables.BoardErofsCompressorHints
+	}
+	if len(variables.BoardErofsCompressorHints) > 0 {
+		ret["erofs_default_compress_hints"] = variables.BoardErofsCompressorHints
+	}
+	if len(variables.BoardErofsPclusterSize) > 0 {
+		ret["erofs_pcluster_size"] = variables.BoardErofsPclusterSize
+	}
+	if len(variables.BoardErofsShareDupBlocks) > 0 {
+		ret["erofs_share_dup_blocks"] = variables.BoardErofsShareDupBlocks
+	}
+	if len(variables.BoardErofsUseLegacyCompression) > 0 {
+		ret["erofs_use_legacy_compression"] = variables.BoardErofsUseLegacyCompression
+	}
+	if len(variables.BoardExt4ShareDupBlocks) > 0 {
+		ret["ext4_share_dup_blocks"] = variables.BoardExt4ShareDupBlocks
+	}
+	if len(variables.BoardFlashLogicalBlockSize) > 0 {
+		ret["flash_logical_block_size"] = variables.BoardFlashLogicalBlockSize
+	}
+	if len(variables.BoardFlashEraseBlockSize) > 0 {
+		ret["flash_erase_block_size"] = variables.BoardFlashEraseBlockSize
+	}
+	if len(variables.BoardExt4ShareDupBlocks) > 0 {
+		ret["ext4_share_dup_blocks"] = variables.BoardExt4ShareDupBlocks
+	}
+	if len(variables.BoardExt4ShareDupBlocks) > 0 {
+		ret["ext4_share_dup_blocks"] = variables.BoardExt4ShareDupBlocks
+	}
+	for _, partitionType := range allPartitionTypes {
+		if qualifiedVariables, ok := variables.PartitionQualifiedVariables[partitionType]; ok && len(qualifiedVariables.ProductVerityPartition) > 0 {
+			ret[partitionType+"_verity_block_device"] = qualifiedVariables.ProductVerityPartition
+		}
+	}
+	// TODO: Vboot
+	// TODO: AVB
+	if variables.BoardUsesRecoveryAsBoot {
+		ret["recovery_as_boot"] = "true"
+	}
+	if variables.BoardBuildGkiBootImageWithoutRamdisk {
+		ret["gki_boot_image_without_ramdisk"] = "true"
+	}
+	if variables.ProductUseDynamicPartitionSize {
+		ret["use_dynamic_partition_size"] = "true"
+	}
+	if variables.CopyImagesForTargetFilesZip {
+		ret["use_fixed_timestamp"] = "true"
+	}
+	return ret
+}
+
+// Soong equivalent of make's add-common-ro-flags-to-image-props
+func addCommonRoFlagsToImageProps(variables *android.PartitionVariables, partitionType string, ret map[string]string) {
+	partitionQualifiedVariables, ok := variables.PartitionQualifiedVariables[partitionType]
+	if !ok {
+		panic("Unknown partitionType: " + partitionType)
+	}
+	if len(partitionQualifiedVariables.BoardErofsCompressor) > 0 {
+		ret[partitionType+"_erofs_compressor"] = partitionQualifiedVariables.BoardErofsCompressor
+	}
+	if len(partitionQualifiedVariables.BoardErofsCompressHints) > 0 {
+		ret[partitionType+"_erofs_compress_hints"] = partitionQualifiedVariables.BoardErofsCompressHints
+	}
+	if len(partitionQualifiedVariables.BoardErofsPclusterSize) > 0 {
+		ret[partitionType+"_erofs_pcluster_size"] = partitionQualifiedVariables.BoardErofsPclusterSize
+	}
+	if len(partitionQualifiedVariables.BoardExtfsRsvPct) > 0 {
+		ret[partitionType+"_extfs_rsv_pct"] = partitionQualifiedVariables.BoardExtfsRsvPct
+	}
+	if len(partitionQualifiedVariables.BoardF2fsSloadCompressFlags) > 0 {
+		ret[partitionType+"_f2fs_sldc_flags"] = partitionQualifiedVariables.BoardF2fsSloadCompressFlags
+	}
+	if len(partitionQualifiedVariables.BoardFileSystemCompress) > 0 {
+		ret[partitionType+"_f2fs_compress"] = partitionQualifiedVariables.BoardFileSystemCompress
+	}
+	if len(partitionQualifiedVariables.BoardFileSystemType) > 0 {
+		ret[partitionType+"_fs_type"] = partitionQualifiedVariables.BoardFileSystemType
+	}
+	if len(partitionQualifiedVariables.BoardJournalSize) > 0 {
+		ret[partitionType+"_journal_size"] = partitionQualifiedVariables.BoardJournalSize
+	}
+	if len(partitionQualifiedVariables.BoardPartitionReservedSize) > 0 {
+		ret[partitionType+"_reserved_size"] = partitionQualifiedVariables.BoardPartitionReservedSize
+	}
+	if len(partitionQualifiedVariables.BoardPartitionSize) > 0 {
+		ret[partitionType+"_size"] = partitionQualifiedVariables.BoardPartitionSize
+	}
+	if len(partitionQualifiedVariables.BoardSquashfsBlockSize) > 0 {
+		ret[partitionType+"_squashfs_block_size"] = partitionQualifiedVariables.BoardSquashfsBlockSize
+	}
+	if len(partitionQualifiedVariables.BoardSquashfsCompressor) > 0 {
+		ret[partitionType+"_squashfs_compressor"] = partitionQualifiedVariables.BoardSquashfsCompressor
+	}
+	if len(partitionQualifiedVariables.BoardSquashfsCompressorOpt) > 0 {
+		ret[partitionType+"_squashfs_compressor_opt"] = partitionQualifiedVariables.BoardSquashfsCompressorOpt
+	}
+	if len(partitionQualifiedVariables.BoardSquashfsDisable4kAlign) > 0 {
+		ret[partitionType+"_squashfs_disable_4k_align"] = partitionQualifiedVariables.BoardSquashfsDisable4kAlign
+	}
+	if len(partitionQualifiedVariables.BoardPartitionSize) == 0 && len(partitionQualifiedVariables.BoardPartitionReservedSize) == 0 && len(partitionQualifiedVariables.ProductHeadroom) == 0 {
+		ret[partitionType+"_disable_sparse"] = "true"
+	}
+	addCommonFlagsToImageProps(variables, partitionType, ret)
+}
+
+func hasErofsPartition(variables *android.PartitionVariables) bool {
+	return variables.PartitionQualifiedVariables["product"].BoardFileSystemType == "erofs" ||
+		variables.PartitionQualifiedVariables["system_ext"].BoardFileSystemType == "erofs" ||
+		variables.PartitionQualifiedVariables["odm"].BoardFileSystemType == "erofs" ||
+		variables.PartitionQualifiedVariables["vendor"].BoardFileSystemType == "erofs" ||
+		variables.PartitionQualifiedVariables["system"].BoardFileSystemType == "erofs" ||
+		variables.PartitionQualifiedVariables["vendor_dlkm"].BoardFileSystemType == "erofs" ||
+		variables.PartitionQualifiedVariables["odm_dlkm"].BoardFileSystemType == "erofs" ||
+		variables.PartitionQualifiedVariables["system_dlkm"].BoardFileSystemType == "erofs"
+}
+
+// Soong equivalent of make's add-common-flags-to-image-props
+func addCommonFlagsToImageProps(variables *android.PartitionVariables, partitionType string, ret map[string]string) {
+	// The selinux_fc will be handled separately
+	partitionQualifiedVariables, ok := variables.PartitionQualifiedVariables[partitionType]
+	if !ok {
+		panic("Unknown partitionType: " + partitionType)
+	}
+	ret["building_"+partitionType+"_image"] = boolToMakeString(partitionQualifiedVariables.BuildingImage)
+}
+
+func boolToMakeString(b bool) string {
+	if b {
+		return "true"
+	}
+	return ""
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index cd1bc7f..ce2a955 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -39,18 +39,24 @@
 	Attrs map[string]string
 }
 
-type BazelTarget struct {
-	name            string
-	packageName     string
-	content         string
-	ruleClass       string
-	bzlLoadLocation string
+type BazelLoadSymbol struct {
+	// The name of the symbol in the file being loaded
+	symbol string
+	// The name the symbol wil have in this file. Can be left blank to use the same name as symbol.
+	alias string
 }
 
-// IsLoadedFromStarlark determines if the BazelTarget's rule class is loaded from a .bzl file,
-// as opposed to a native rule built into Bazel.
-func (t BazelTarget) IsLoadedFromStarlark() bool {
-	return t.bzlLoadLocation != ""
+type BazelLoad struct {
+	file    string
+	symbols []BazelLoadSymbol
+}
+
+type BazelTarget struct {
+	name        string
+	packageName string
+	content     string
+	ruleClass   string
+	loads       []BazelLoad
 }
 
 // Label is the fully qualified Bazel label constructed from the BazelTarget's
@@ -110,30 +116,62 @@
 // LoadStatements return the string representation of the sorted and deduplicated
 // Starlark rule load statements needed by a group of BazelTargets.
 func (targets BazelTargets) LoadStatements() string {
-	bzlToLoadedSymbols := map[string][]string{}
+	// First, merge all the load statements from all the targets onto one list
+	bzlToLoadedSymbols := map[string][]BazelLoadSymbol{}
 	for _, target := range targets {
-		if target.IsLoadedFromStarlark() {
-			bzlToLoadedSymbols[target.bzlLoadLocation] =
-				append(bzlToLoadedSymbols[target.bzlLoadLocation], target.ruleClass)
+		for _, load := range target.loads {
+		outer:
+			for _, symbol := range load.symbols {
+				alias := symbol.alias
+				if alias == "" {
+					alias = symbol.symbol
+				}
+				for _, otherSymbol := range bzlToLoadedSymbols[load.file] {
+					otherAlias := otherSymbol.alias
+					if otherAlias == "" {
+						otherAlias = otherSymbol.symbol
+					}
+					if symbol.symbol == otherSymbol.symbol && alias == otherAlias {
+						continue outer
+					} else if alias == otherAlias {
+						panic(fmt.Sprintf("Conflicting destination (%s) for loads of %s and %s", alias, symbol.symbol, otherSymbol.symbol))
+					}
+				}
+				bzlToLoadedSymbols[load.file] = append(bzlToLoadedSymbols[load.file], symbol)
+			}
 		}
 	}
 
-	var loadStatements []string
-	for bzl, ruleClasses := range bzlToLoadedSymbols {
-		loadStatement := "load(\""
-		loadStatement += bzl
-		loadStatement += "\", "
-		ruleClasses = android.SortedUniqueStrings(ruleClasses)
-		for i, ruleClass := range ruleClasses {
-			loadStatement += "\"" + ruleClass + "\""
-			if i != len(ruleClasses)-1 {
-				loadStatement += ", "
+	var loadStatements strings.Builder
+	for i, bzl := range android.SortedKeys(bzlToLoadedSymbols) {
+		symbols := bzlToLoadedSymbols[bzl]
+		loadStatements.WriteString("load(\"")
+		loadStatements.WriteString(bzl)
+		loadStatements.WriteString("\", ")
+		sort.Slice(symbols, func(i, j int) bool {
+			if symbols[i].symbol < symbols[j].symbol {
+				return true
+			}
+			return symbols[i].alias < symbols[j].alias
+		})
+		for j, symbol := range symbols {
+			if symbol.alias != "" && symbol.alias != symbol.symbol {
+				loadStatements.WriteString(symbol.alias)
+				loadStatements.WriteString(" = ")
+			}
+			loadStatements.WriteString("\"")
+			loadStatements.WriteString(symbol.symbol)
+			loadStatements.WriteString("\"")
+			if j != len(symbols)-1 {
+				loadStatements.WriteString(", ")
 			}
 		}
-		loadStatement += ")"
-		loadStatements = append(loadStatements, loadStatement)
+		loadStatements.WriteString(")")
+		if i != len(bzlToLoadedSymbols)-1 {
+			loadStatements.WriteString("\n")
+		}
 	}
-	return strings.Join(android.SortedUniqueStrings(loadStatements), "\n")
+	return loadStatements.String()
 }
 
 type bpToBuildContext interface {
@@ -175,9 +213,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 +231,6 @@
 		return "Bp2Build"
 	case QueryView:
 		return "QueryView"
-	case ApiBp2build:
-		return "ApiBp2build"
 	default:
 		return fmt.Sprintf("%d", mode)
 	}
@@ -254,9 +287,9 @@
 	return r.buildFileToTargets
 }
 
-// struct to store state of go bazel targets
+// struct to store state of b bazel targets (e.g. go targets which do not implement android.Module)
 // this implements bp2buildModule interface and is passed to generateBazelTargets
-type goBazelTarget struct {
+type bTarget struct {
 	targetName            string
 	targetPackage         string
 	bazelRuleClass        string
@@ -264,26 +297,26 @@
 	bazelAttributes       []interface{}
 }
 
-var _ bp2buildModule = (*goBazelTarget)(nil)
+var _ bp2buildModule = (*bTarget)(nil)
 
-func (g goBazelTarget) TargetName() string {
-	return g.targetName
+func (b bTarget) TargetName() string {
+	return b.targetName
 }
 
-func (g goBazelTarget) TargetPackage() string {
-	return g.targetPackage
+func (b bTarget) TargetPackage() string {
+	return b.targetPackage
 }
 
-func (g goBazelTarget) BazelRuleClass() string {
-	return g.bazelRuleClass
+func (b bTarget) BazelRuleClass() string {
+	return b.bazelRuleClass
 }
 
-func (g goBazelTarget) BazelRuleLoadLocation() string {
-	return g.bazelRuleLoadLocation
+func (b bTarget) BazelRuleLoadLocation() string {
+	return b.bazelRuleLoadLocation
 }
 
-func (g goBazelTarget) BazelAttributes() []interface{} {
-	return g.bazelAttributes
+func (b bTarget) BazelAttributes() []interface{} {
+	return b.bazelAttributes
 }
 
 // Creates a target_compatible_with entry that is *not* compatible with android
@@ -388,7 +421,7 @@
 		Target_compatible_with: targetNotCompatibleWithAndroid(),
 	}
 
-	libTest := goBazelTarget{
+	libTest := bTarget{
 		targetName:            gp.name,
 		targetPackage:         gp.dir,
 		bazelRuleClass:        "go_test",
@@ -481,7 +514,7 @@
 		Target_compatible_with: targetNotCompatibleWithAndroid(),
 	}
 
-	lib := goBazelTarget{
+	lib := bTarget{
 		targetName:            g.Name(),
 		targetPackage:         ctx.ModuleDir(g),
 		bazelRuleClass:        "go_library",
@@ -522,23 +555,35 @@
 	Deps []string
 }
 
+type buildConversionMetadata struct {
+	nameToGoLibraryModule nameToGoLibraryModule
+	ndkHeaders            []blueprint.Module
+}
+
 type nameToGoLibraryModule map[string]goLibraryModule
 
-// Visit each module in the graph
+// Visit each module in the graph, and collect metadata about the build graph
 // If a module is of type `bootstrap_go_package`, return a map containing metadata like its dir and deps
-func createGoLibraryModuleMap(ctx *android.Context) nameToGoLibraryModule {
-	ret := nameToGoLibraryModule{}
+// If a module is of type `ndk_headers`, add it to a list and return the list
+func createBuildConversionMetadata(ctx *android.Context) buildConversionMetadata {
+	goMap := nameToGoLibraryModule{}
+	ndkHeaders := []blueprint.Module{}
 	ctx.VisitAllModules(func(m blueprint.Module) {
 		moduleType := ctx.ModuleType(m)
 		// We do not need to store information about blueprint_go_binary since it does not have any rdeps
 		if moduleType == "bootstrap_go_package" {
-			ret[m.Name()] = goLibraryModule{
+			goMap[m.Name()] = goLibraryModule{
 				Dir:  ctx.ModuleDir(m),
 				Deps: m.(*bootstrap.GoPackage).Deps(),
 			}
+		} else if moduleType == "ndk_headers" {
+			ndkHeaders = append(ndkHeaders, m)
 		}
 	})
-	return ret
+	return buildConversionMetadata{
+		nameToGoLibraryModule: goMap,
+		ndkHeaders:            ndkHeaders,
+	}
 }
 
 // Returns the deps in the transitive closure of a go target
@@ -587,7 +632,7 @@
 			Deps:                   goDepLabels(transitiveDeps, goModulesMap),
 			Target_compatible_with: targetNotCompatibleWithAndroid(),
 		}
-		libTestSource := goBazelTarget{
+		libTestSource := bTarget{
 			targetName:            goSource,
 			targetPackage:         ctx.ModuleDir(g),
 			bazelRuleClass:        "go_source",
@@ -636,7 +681,7 @@
 		ga.Srcs = goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs())
 	}
 
-	bin := goBazelTarget{
+	bin := bTarget{
 		targetName:            g.Name(),
 		targetPackage:         ctx.ModuleDir(g),
 		bazelRuleClass:        "go_binary",
@@ -667,7 +712,9 @@
 
 	// Visit go libraries in a pre-run and store its state in a map
 	// The time complexity remains O(N), and this does not add significant wall time.
-	nameToGoLibMap := createGoLibraryModuleMap(ctx.Context())
+	meta := createBuildConversionMetadata(ctx.Context())
+	nameToGoLibMap := meta.nameToGoLibraryModule
+	ndkHeaders := meta.ndkHeaders
 
 	bpCtx := ctx.Context()
 	bpCtx.VisitAllModules(func(m blueprint.Module) {
@@ -680,27 +727,32 @@
 
 		switch ctx.Mode() {
 		case Bp2Build:
-			// There are two main ways of converting a Soong module to Bazel:
-			// 1) Manually handcrafting a Bazel target and associating the module with its label
-			// 2) Automatically generating with bp2build converters
-			//
-			// bp2build converters are used for the majority of modules.
-			if b, ok := m.(android.Bazelable); ok && b.HasHandcraftedLabel() {
-				if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
-					panic(fmt.Errorf("module %q [%s] [%s] was both converted with bp2build and has a handcrafted label", bpCtx.ModuleName(m), moduleType, dir))
-				}
-				// Handle modules converted to handcrafted targets.
-				//
-				// Since these modules are associated with some handcrafted
-				// target in a BUILD file, we don't autoconvert them.
+			if aModule, ok := m.(android.Module); ok {
+				reason := aModule.GetUnconvertedReason()
+				if reason != nil {
+					// If this module was force-enabled, cause an error.
+					if _, ok := ctx.Config().BazelModulesForceEnabledByFlag()[m.Name()]; ok && m.Name() != "" {
+						err := fmt.Errorf("Force Enabled Module %s not converted", m.Name())
+						errs = append(errs, err)
+					}
 
-				// Log the module.
-				metrics.AddUnconvertedModule(m, moduleType, dir,
-					android.UnconvertedReason{
-						ReasonType: int(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE),
-					})
-			} else if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
+					// Log the module isn't to be converted by bp2build.
+					// TODO: b/291598248 - Log handcrafted modules differently than other unconverted modules.
+					metrics.AddUnconvertedModule(m, moduleType, dir, *reason)
+					return
+				}
+				if len(aModule.Bp2buildTargets()) == 0 {
+					panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", aModule.Name()))
+				}
+
 				// Handle modules converted to generated targets.
+				targets, targetErrs = generateBazelTargets(bpCtx, aModule)
+				errs = append(errs, targetErrs...)
+				for _, t := range targets {
+					// A module can potentially generate more than 1 Bazel
+					// target, each of a different rule class.
+					metrics.IncrementRuleClassCount(t.ruleClass)
+				}
 
 				// Log the module.
 				metrics.AddConvertedModule(aModule, moduleType, dir)
@@ -728,24 +780,6 @@
 						return
 					}
 				}
-				targets, targetErrs = generateBazelTargets(bpCtx, aModule)
-				errs = append(errs, targetErrs...)
-				for _, t := range targets {
-					// A module can potentially generate more than 1 Bazel
-					// target, each of a different rule class.
-					metrics.IncrementRuleClassCount(t.ruleClass)
-				}
-			} else if _, ok := ctx.Config().BazelModulesForceEnabledByFlag()[m.Name()]; ok && m.Name() != "" {
-				err := fmt.Errorf("Force Enabled Module %s not converted", m.Name())
-				errs = append(errs, err)
-			} else if aModule, ok := m.(android.Module); ok {
-				reason := aModule.GetUnconvertedReason()
-				if reason == nil {
-					panic(fmt.Errorf("module '%s' was neither converted nor marked unconvertible with bp2build", aModule.Name()))
-				} else {
-					metrics.AddUnconvertedModule(m, moduleType, dir, *reason)
-				}
-				return
 			} else if glib, ok := m.(*bootstrap.GoPackage); ok {
 				targets, targetErrs = generateBazelTargetsGoPackage(bpCtx, glib, nameToGoLibMap)
 				errs = append(errs, targetErrs...)
@@ -774,10 +808,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
@@ -789,6 +819,39 @@
 		}
 	})
 
+	// Create an ndk_sysroot target that has a dependency edge on every target corresponding to Soong's ndk_headers
+	// This root target will provide headers to sdk variants of jni libraries
+	if ctx.Mode() == Bp2Build {
+		var depLabels bazel.LabelList
+		for _, ndkHeader := range ndkHeaders {
+			depLabel := bazel.Label{
+				Label: "//" + bpCtx.ModuleDir(ndkHeader) + ":" + ndkHeader.Name(),
+			}
+			depLabels.Add(&depLabel)
+		}
+		a := struct {
+			Deps                bazel.LabelListAttribute
+			System_dynamic_deps bazel.LabelListAttribute
+		}{
+			Deps:                bazel.MakeLabelListAttribute(bazel.UniqueSortedBazelLabelList(depLabels)),
+			System_dynamic_deps: bazel.MakeLabelListAttribute(bazel.MakeLabelList([]bazel.Label{})),
+		}
+		ndkSysroot := bTarget{
+			targetName:            "ndk_sysroot",
+			targetPackage:         "build/bazel/rules/cc", // The location is subject to change, use build/bazel for now
+			bazelRuleClass:        "cc_library_headers",
+			bazelRuleLoadLocation: "//build/bazel/rules/cc:cc_library_headers.bzl",
+			bazelAttributes:       []interface{}{&a},
+		}
+
+		if t, err := generateBazelTarget(bpCtx, ndkSysroot); err == nil {
+			dir := ndkSysroot.targetPackage
+			buildFileToTargets[dir] = append(buildFileToTargets[dir], t)
+		} else {
+			errs = append(errs, err)
+		}
+	}
+
 	if len(errs) > 0 {
 		return conversionResults{}, errs
 	}
@@ -808,7 +871,7 @@
 		for dir := range dirs {
 			buildFileToTargets[dir] = append(buildFileToTargets[dir], BazelTarget{
 				name:      "bp2build_all_srcs",
-				content:   `filegroup(name = "bp2build_all_srcs", srcs = glob(["**/*"]))`,
+				content:   `filegroup(name = "bp2build_all_srcs", srcs = glob(["**/*"]), tags = ["manual"])`,
 				ruleClass: "filegroup",
 			})
 		}
@@ -866,12 +929,19 @@
 	} else {
 		content = fmt.Sprintf(unnamedRuleTargetTemplate, ruleClass, attributes)
 	}
+	var loads []BazelLoad
+	if bzlLoadLocation != "" {
+		loads = append(loads, BazelLoad{
+			file:    bzlLoadLocation,
+			symbols: []BazelLoadSymbol{{symbol: ruleClass}},
+		})
+	}
 	return BazelTarget{
-		name:            targetName,
-		packageName:     m.TargetPackage(),
-		ruleClass:       ruleClass,
-		bzlLoadLocation: bzlLoadLocation,
-		content:         content,
+		name:        targetName,
+		packageName: m.TargetPackage(),
+		ruleClass:   ruleClass,
+		loads:       loads,
+		content:     content,
 	}, nil
 }
 
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 8ee0439..afbfffa 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -773,9 +773,12 @@
 		{
 			bazelTargets: BazelTargets{
 				BazelTarget{
-					name:            "foo",
-					ruleClass:       "cc_library",
-					bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+					name:      "foo",
+					ruleClass: "cc_library",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:cc.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
+					}},
 				},
 			},
 			expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
@@ -783,14 +786,20 @@
 		{
 			bazelTargets: BazelTargets{
 				BazelTarget{
-					name:            "foo",
-					ruleClass:       "cc_library",
-					bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+					name:      "foo",
+					ruleClass: "cc_library",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:cc.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
+					}},
 				},
 				BazelTarget{
-					name:            "bar",
-					ruleClass:       "cc_library",
-					bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+					name:      "bar",
+					ruleClass: "cc_library",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:cc.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
+					}},
 				},
 			},
 			expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
@@ -798,14 +807,20 @@
 		{
 			bazelTargets: BazelTargets{
 				BazelTarget{
-					name:            "foo",
-					ruleClass:       "cc_library",
-					bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+					name:      "foo",
+					ruleClass: "cc_library",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:cc.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
+					}},
 				},
 				BazelTarget{
-					name:            "bar",
-					ruleClass:       "cc_binary",
-					bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+					name:      "bar",
+					ruleClass: "cc_binary",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:cc.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "cc_binary"}},
+					}},
 				},
 			},
 			expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`,
@@ -813,19 +828,28 @@
 		{
 			bazelTargets: BazelTargets{
 				BazelTarget{
-					name:            "foo",
-					ruleClass:       "cc_library",
-					bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+					name:      "foo",
+					ruleClass: "cc_library",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:cc.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
+					}},
 				},
 				BazelTarget{
-					name:            "bar",
-					ruleClass:       "cc_binary",
-					bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+					name:      "bar",
+					ruleClass: "cc_binary",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:cc.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "cc_binary"}},
+					}},
 				},
 				BazelTarget{
-					name:            "baz",
-					ruleClass:       "java_binary",
-					bzlLoadLocation: "//build/bazel/rules:java.bzl",
+					name:      "baz",
+					ruleClass: "java_binary",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:java.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "java_binary"}},
+					}},
 				},
 			},
 			expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")
@@ -834,19 +858,25 @@
 		{
 			bazelTargets: BazelTargets{
 				BazelTarget{
-					name:            "foo",
-					ruleClass:       "cc_binary",
-					bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+					name:      "foo",
+					ruleClass: "cc_binary",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:cc.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "cc_binary"}},
+					}},
 				},
 				BazelTarget{
-					name:            "bar",
-					ruleClass:       "java_binary",
-					bzlLoadLocation: "//build/bazel/rules:java.bzl",
+					name:      "bar",
+					ruleClass: "java_binary",
+					loads: []BazelLoad{{
+						file:    "//build/bazel/rules:java.bzl",
+						symbols: []BazelLoadSymbol{{symbol: "java_binary"}},
+					}},
 				},
 				BazelTarget{
 					name:      "baz",
 					ruleClass: "genrule",
-					// Note: no bzlLoadLocation for native rules
+					// Note: no loads for native rules
 				},
 			},
 			expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary")
@@ -1743,7 +1773,8 @@
 			Description:                "Required into data test",
 			ModuleTypeUnderTest:        "filegroup",
 			ModuleTypeUnderTestFactory: android.FileGroupFactory,
-			Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
+			StubbedBuildDefinitions:    []string{"reqd"},
+			Blueprint: simpleModule("filegroup", "reqd") + `
 filegroup {
     name: "fg_foo",
     required: ["reqd"],
@@ -1759,7 +1790,8 @@
 			Description:                "Required into data test, cyclic self reference is filtered out",
 			ModuleTypeUnderTest:        "filegroup",
 			ModuleTypeUnderTestFactory: android.FileGroupFactory,
-			Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
+			StubbedBuildDefinitions:    []string{"reqd"},
+			Blueprint: simpleModule("filegroup", "reqd") + `
 filegroup {
     name: "fg_foo",
     required: ["reqd", "fg_foo"],
@@ -1775,8 +1807,9 @@
 			Description:                "Required via arch into data test",
 			ModuleTypeUnderTest:        "python_library",
 			ModuleTypeUnderTestFactory: python.PythonLibraryFactory,
-			Blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqdx86") +
-				simpleModuleDoNotConvertBp2build("python_library", "reqdarm") + `
+			StubbedBuildDefinitions:    []string{"reqdx86", "reqdarm"},
+			Blueprint: simpleModule("python_library", "reqdx86") +
+				simpleModule("python_library", "reqdarm") + `
 python_library {
     name: "fg_foo",
     arch: {
@@ -1809,7 +1842,8 @@
 				"data.bin": "",
 				"src.py":   "",
 			},
-			Blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqd") + `
+			StubbedBuildDefinitions: []string{"reqd"},
+			Blueprint: simpleModule("python_library", "reqd") + `
 python_library {
     name: "fg_foo",
     data: ["data.bin"],
@@ -1831,7 +1865,8 @@
 			Description:                "All props-to-attrs at once together test",
 			ModuleTypeUnderTest:        "filegroup",
 			ModuleTypeUnderTestFactory: android.FileGroupFactory,
-			Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
+			StubbedBuildDefinitions:    []string{"reqd"},
+			Blueprint: simpleModule("filegroup", "reqd") + `
 filegroup {
     name: "fg_foo",
     required: ["reqd"],
@@ -1879,30 +1914,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 {
@@ -1950,6 +1961,104 @@
 	android.AssertStringEquals(t, "Print the common value if all keys in an axis have the same value", `[":libfoo.impl"]`, actual)
 }
 
+func TestAlreadyPresentBuildTarget(t *testing.T) {
+	bp := `
+	custom {
+		name: "foo",
+	}
+	custom {
+		name: "bar",
+	}
+	`
+	alreadyPresentBuildFile :=
+		MakeBazelTarget(
+			"custom",
+			"foo",
+			AttrNameToString{},
+		)
+	expectedBazelTargets := []string{
+		MakeBazelTarget(
+			"custom",
+			"bar",
+			AttrNameToString{},
+		),
+	}
+	registerCustomModule := func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+	}
+	RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+		AlreadyExistingBuildContents: alreadyPresentBuildFile,
+		Blueprint:                    bp,
+		ExpectedBazelTargets:         expectedBazelTargets,
+		Description:                  "Not duplicating work for an already-present BUILD target.",
+	})
+}
+
+func TestAlreadyPresentOneToManyBuildTarget(t *testing.T) {
+	bp := `
+	custom {
+		name: "foo",
+    one_to_many_prop: true,
+	}
+	custom {
+		name: "bar",
+	}
+	`
+	alreadyPresentBuildFile :=
+		MakeBazelTarget(
+			"custom",
+			// one_to_many_prop ensures that foo generates "foo_proto_library_deps".
+			"foo_proto_library_deps",
+			AttrNameToString{},
+		)
+	expectedBazelTargets := []string{
+		MakeBazelTarget(
+			"custom",
+			"bar",
+			AttrNameToString{},
+		),
+	}
+	registerCustomModule := func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+	}
+	RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+		AlreadyExistingBuildContents: alreadyPresentBuildFile,
+		Blueprint:                    bp,
+		ExpectedBazelTargets:         expectedBazelTargets,
+		Description:                  "Not duplicating work for an already-present BUILD target (different generated name)",
+	})
+}
+
+// Verifies that if a module is defined in pkg1/Android.bp, that a target present
+// in pkg2/BUILD.bazel does not result in the module being labeled "already defined
+// in a BUILD file".
+func TestBuildTargetPresentOtherDirectory(t *testing.T) {
+	bp := `
+	custom {
+		name: "foo",
+	}
+	`
+	expectedBazelTargets := []string{
+		MakeBazelTarget(
+			"custom",
+			"foo",
+			AttrNameToString{},
+		),
+	}
+	registerCustomModule := func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+	}
+	RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+		KeepBuildFileForDirs: []string{"other_pkg"},
+		Filesystem: map[string]string{
+			"other_pkg/BUILD.bazel": MakeBazelTarget("custom", "foo", AttrNameToString{}),
+		},
+		Blueprint:            bp,
+		ExpectedBazelTargets: expectedBazelTargets,
+		Description:          "Not treating a BUILD target as the bazel definition for a module in another package",
+	})
+}
+
 // If CommonAttributes.Dir is set, the bazel target should be created in that dir
 func TestCreateBazelTargetInDifferentDir(t *testing.T) {
 	t.Parallel()
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 90db365..c679703 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -44,10 +44,11 @@
 }
 
 type ccBinaryBp2buildTestCase struct {
-	description string
-	filesystem  map[string]string
-	blueprint   string
-	targets     []testBazelTarget
+	description             string
+	filesystem              map[string]string
+	blueprint               string
+	targets                 []testBazelTarget
+	stubbedBuildDefinitions []string
 }
 
 func registerCcBinaryModuleTypes(ctx android.RegistrationContext) {
@@ -81,6 +82,7 @@
 			Description:                description,
 			Blueprint:                  binaryReplacer.Replace(testCase.blueprint),
 			Filesystem:                 testCase.filesystem,
+			StubbedBuildDefinitions:    testCase.stubbedBuildDefinitions,
 		})
 	})
 }
@@ -97,6 +99,7 @@
 			Description:                description,
 			Blueprint:                  hostBinaryReplacer.Replace(testCase.blueprint),
 			Filesystem:                 testCase.filesystem,
+			StubbedBuildDefinitions:    testCase.stubbedBuildDefinitions,
 		})
 	})
 }
@@ -107,6 +110,7 @@
 		filesystem: map[string]string{
 			soongCcVersionLibBpPath: soongCcVersionLibBp,
 		},
+		stubbedBuildDefinitions: []string{"//build/soong/cc/libbuildversion:libbuildversion"},
 		blueprint: `
 {rule_name} {
     name: "foo",
@@ -264,7 +268,8 @@
 
 func TestCcBinarySplitSrcsByLang(t *testing.T) {
 	runCcHostBinaryTestCase(t, ccBinaryBp2buildTestCase{
-		description: "split srcs by lang",
+		description:             "split srcs by lang",
+		stubbedBuildDefinitions: []string{"fg_foo"},
 		blueprint: `
 {rule_name} {
     name: "foo",
@@ -276,7 +281,7 @@
     ],
     include_build_directory: false,
 }
-` + simpleModuleDoNotConvertBp2build("filegroup", "fg_foo"),
+` + simpleModule("filegroup", "fg_foo"),
 		targets: []testBazelTarget{
 			{"cc_binary", "foo", AttrNameToString{
 				"srcs": `[
@@ -300,17 +305,17 @@
 func TestCcBinaryDoNotDistinguishBetweenDepsAndImplementationDeps(t *testing.T) {
 	runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
 		description: "no implementation deps",
+		stubbedBuildDefinitions: []string{"generated_hdr", "export_generated_hdr", "static_dep", "implementation_static_dep",
+			"whole_static_dep", "not_explicitly_exported_whole_static_dep", "shared_dep", "implementation_shared_dep"},
 		blueprint: `
 genrule {
     name: "generated_hdr",
     cmd: "nothing to see here",
-    bazel_module: { bp2build_available: false },
 }
 
 genrule {
     name: "export_generated_hdr",
     cmd: "nothing to see here",
-    bazel_module: { bp2build_available: false },
 }
 
 {rule_name} {
@@ -326,12 +331,12 @@
     export_generated_headers: ["export_generated_hdr"],
 }
 ` +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep") +
-			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep") +
-			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep"),
+			simpleModule("cc_library_static", "static_dep") +
+			simpleModule("cc_library_static", "implementation_static_dep") +
+			simpleModule("cc_library_static", "whole_static_dep") +
+			simpleModule("cc_library_static", "not_explicitly_exported_whole_static_dep") +
+			simpleModule("cc_library", "shared_dep") +
+			simpleModule("cc_library", "implementation_shared_dep"),
 		targets: []testBazelTarget{
 			{"cc_binary", "foo", AttrNameToString{
 				"deps": `[
@@ -502,6 +507,7 @@
 
 func TestCcBinarySharedProto(t *testing.T) {
 	runCcBinaryTests(t, ccBinaryBp2buildTestCase{
+		stubbedBuildDefinitions: []string{"libprotobuf-cpp-full", "libprotobuf-cpp-lite"},
 		blueprint: soongCcProtoLibraries + `{rule_name} {
 	name: "foo",
 	srcs: ["foo.proto"],
@@ -524,6 +530,7 @@
 
 func TestCcBinaryStaticProto(t *testing.T) {
 	runCcBinaryTests(t, ccBinaryBp2buildTestCase{
+		stubbedBuildDefinitions: []string{"libprotobuf-cpp-full", "libprotobuf-cpp-lite"},
 		blueprint: soongCcProtoLibraries + `{rule_name} {
 	name: "foo",
 	srcs: ["foo.proto"],
@@ -1224,13 +1231,13 @@
 
 func TestCcBinaryStatic_SystemSharedLibUsedAsDep(t *testing.T) {
 	runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
-		description: "cc_library_static system_shared_lib empty for linux_bionic variant",
+		stubbedBuildDefinitions: []string{"libm", "libc"},
+		description:             "cc_library_static system_shared_lib empty for linux_bionic variant",
 		blueprint: soongCcLibraryStaticPreamble +
-			simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
+			simpleModule("cc_library", "libc") + `
 
 cc_library {
     name: "libm",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_binary {
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index e50c710..c2b65a1 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -35,19 +35,16 @@
 	soongCcVersionLibBp     = `
 cc_library_static {
 	name: "libbuildversion",
-	bazel_module: { bp2build_available: false },
 }
 `
 
 	soongCcProtoLibraries = `
 cc_library {
 	name: "libprotobuf-cpp-lite",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
 	name: "libprotobuf-cpp-full",
-	bazel_module: { bp2build_available: false },
 }`
 
 	soongCcProtoPreamble = soongCcLibraryPreamble + soongCcProtoLibraries
@@ -55,6 +52,7 @@
 
 func runCcLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
 	t.Helper()
+	tc.StubbedBuildDefinitions = append(tc.StubbedBuildDefinitions, "libprotobuf-cpp-lite", "libprotobuf-cpp-full")
 	RunBp2BuildTestCase(t, registerCcLibraryModuleTypes, tc)
 }
 
@@ -65,6 +63,7 @@
 	ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
 	ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
 	ctx.RegisterModuleType("aidl_library", aidl_library.AidlLibraryFactory)
+	ctx.RegisterModuleType("ndk_library", cc.NdkLibraryFactory)
 }
 
 func TestCcLibrarySimple(t *testing.T) {
@@ -72,6 +71,7 @@
 		Description:                "cc_library - simple example",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"//build/soong/cc/libbuildversion:libbuildversion", "some-headers"},
 		Filesystem: map[string]string{
 			soongCcVersionLibBpPath: soongCcVersionLibBp,
 			"android.cpp":           "",
@@ -94,7 +94,7 @@
 			"foo-dir/a.h":      "",
 		},
 		Blueprint: soongCcLibraryPreamble +
-			simpleModuleDoNotConvertBp2build("cc_library_headers", "some-headers") + `
+			simpleModule("cc_library_headers", "some-headers") + `
 cc_library {
     name: "foo-lib",
     srcs: ["impl.cpp"],
@@ -159,6 +159,10 @@
 			"min_sdk_version":    `"29"`,
 			"use_version_lib":    `True`,
 			"whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
+			"deps": `select({
+        "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"],
+        "//conditions:default": [],
+    })`,
 		}),
 	})
 }
@@ -168,6 +172,7 @@
 		Description:                "cc_library - trimmed example of //bionic/linker:ld-android",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"libc_headers"},
 		Filesystem: map[string]string{
 			"ld-android.cpp":           "",
 			"linked_list.h":            "",
@@ -176,7 +181,7 @@
 			"linker_cfi.h":             "",
 		},
 		Blueprint: soongCcLibraryPreamble +
-			simpleModuleDoNotConvertBp2build("cc_library_headers", "libc_headers") + `
+			simpleModule("cc_library_headers", "libc_headers") + `
 cc_library {
     name: "fake-ld-android",
     srcs: ["ld_android.cpp"],
@@ -319,54 +324,49 @@
 
 cc_library_static {
     name: "static_dep_for_shared",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "static_dep_for_static",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "static_dep_for_both",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_static_lib_for_shared",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_static_lib_for_static",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_static_lib_for_both",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_and_static_lib_for_both",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "shared_dep_for_shared",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "shared_dep_for_static",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "shared_dep_for_both",
-    bazel_module: { bp2build_available: false },
 }
 `,
+		StubbedBuildDefinitions: []string{"static_dep_for_shared", "static_dep_for_static",
+			"static_dep_for_both", "whole_static_lib_for_shared", "whole_static_lib_for_static",
+			"whole_static_lib_for_both", "whole_and_static_lib_for_both", "shared_dep_for_shared",
+			"shared_dep_for_static", "shared_dep_for_both",
+		},
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
 				"copts": `[
@@ -457,24 +457,34 @@
     },
     include_build_directory: false,
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_shared") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_shared") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_static") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_static") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_both") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_both") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_shared") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_shared") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_static") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_static") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_both") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_both") +
-			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_shared") +
-			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_shared") +
-			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_static") +
-			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_static") +
-			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_both") +
-			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_both"),
+` + simpleModule("cc_library_static", "static_dep_for_shared") +
+			simpleModule("cc_library_static", "implementation_static_dep_for_shared") +
+			simpleModule("cc_library_static", "static_dep_for_static") +
+			simpleModule("cc_library_static", "implementation_static_dep_for_static") +
+			simpleModule("cc_library_static", "static_dep_for_both") +
+			simpleModule("cc_library_static", "implementation_static_dep_for_both") +
+			simpleModule("cc_library_static", "whole_static_dep_for_shared") +
+			simpleModule("cc_library_static", "not_explicitly_exported_whole_static_dep_for_shared") +
+			simpleModule("cc_library_static", "whole_static_dep_for_static") +
+			simpleModule("cc_library_static", "not_explicitly_exported_whole_static_dep_for_static") +
+			simpleModule("cc_library_static", "whole_static_dep_for_both") +
+			simpleModule("cc_library_static", "not_explicitly_exported_whole_static_dep_for_both") +
+			simpleModule("cc_library", "shared_dep_for_shared") +
+			simpleModule("cc_library", "implementation_shared_dep_for_shared") +
+			simpleModule("cc_library", "shared_dep_for_static") +
+			simpleModule("cc_library", "implementation_shared_dep_for_static") +
+			simpleModule("cc_library", "shared_dep_for_both") +
+			simpleModule("cc_library", "implementation_shared_dep_for_both"),
+		StubbedBuildDefinitions: []string{"static_dep_for_shared", "implementation_static_dep_for_shared",
+			"static_dep_for_static", "implementation_static_dep_for_static", "static_dep_for_both",
+			"implementation_static_dep_for_both", "whole_static_dep_for_shared",
+			"not_explicitly_exported_whole_static_dep_for_shared", "whole_static_dep_for_static",
+			"not_explicitly_exported_whole_static_dep_for_static", "whole_static_dep_for_both",
+			"not_explicitly_exported_whole_static_dep_for_both", "shared_dep_for_shared",
+			"implementation_shared_dep_for_shared", "shared_dep_for_static",
+			"implementation_shared_dep_for_static", "shared_dep_for_both",
+			"implementation_shared_dep_for_both",
+		},
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
 				"copts": `[
@@ -549,6 +559,8 @@
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
 		Dir:                        "foo/bar",
+		StubbedBuildDefinitions: []string{"//foo/bar:prebuilt_whole_static_lib_for_shared", "//foo/bar:prebuilt_whole_static_lib_for_static",
+			"//foo/bar:prebuilt_whole_static_lib_for_both"},
 		Filesystem: map[string]string{
 			"foo/bar/Android.bp": `
 cc_library {
@@ -665,6 +677,10 @@
 cc_library_static { name: "android_dep_for_shared" }
 `,
 		},
+		StubbedBuildDefinitions: []string{"//foo/bar:static_dep_for_shared", "//foo/bar:static_dep_for_static",
+			"//foo/bar:static_dep_for_both", "//foo/bar:arm_static_dep_for_shared", "//foo/bar:arm_whole_static_dep_for_shared",
+			"//foo/bar:arm_shared_dep_for_shared", "//foo/bar:x86_dep_for_static", "//foo/bar:android_dep_for_shared",
+		},
 		Blueprint: soongCcLibraryPreamble,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
@@ -746,6 +762,7 @@
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
 		Dir:                        "foo/bar",
+		StubbedBuildDefinitions:    []string{"//foo/bar:shared_filegroup", "//foo/bar:static_filegroup", "//foo/bar:both_filegroup"},
 		Filesystem: map[string]string{
 			"foo/bar/both_source.cpp":   "",
 			"foo/bar/both_source.cc":    "",
@@ -1017,10 +1034,10 @@
 		Description:                "cc_library shared_libs",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"mylib"},
 		Blueprint: soongCcLibraryPreamble + `
 cc_library {
     name: "mylib",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
@@ -1181,6 +1198,10 @@
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions: []string{"arm_whole_static_lib_excludes", "malloc_not_svelte_whole_static_lib",
+			"arm_static_lib_excludes", "malloc_not_svelte_whole_static_lib_excludes", "arm_shared_lib_excludes",
+			"malloc_not_svelte_static_lib_excludes", "arm_shared_lib_excludes", "malloc_not_svelte_shared_lib",
+		},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library {
     name: "foo_static",
@@ -1222,37 +1243,30 @@
 
 cc_library {
     name: "arm_whole_static_lib_excludes",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "malloc_not_svelte_whole_static_lib",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "malloc_not_svelte_whole_static_lib_excludes",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "arm_static_lib_excludes",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "malloc_not_svelte_static_lib_excludes",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "arm_shared_lib_excludes",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "malloc_not_svelte_shared_lib",
-    bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: makeCcLibraryTargets("foo_static", AttrNameToString{
@@ -1288,6 +1302,7 @@
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
 		Filesystem:                 map[string]string{},
+		StubbedBuildDefinitions:    []string{"malloc_not_svelte_header_lib"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library {
     name: "foo_static",
@@ -1302,7 +1317,6 @@
 
 cc_library {
     name: "malloc_not_svelte_header_lib",
-    bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: makeCcLibraryTargets("foo_static", AttrNameToString{
@@ -1812,10 +1826,10 @@
 		Description:                "cc_library system_shared_libs empty for linux_bionic variant",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"libc_musl"},
 		Blueprint: soongCcLibraryPreamble + `
 cc_library {
 	name: "libc_musl",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
@@ -1843,10 +1857,10 @@
 		Description:                "cc_library system_shared_libs empty for bionic variant",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"libc_musl"},
 		Blueprint: soongCcLibraryPreamble + `
 cc_library {
 	name: "libc_musl",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
@@ -1874,10 +1888,10 @@
 		Description:                "cc_library system_shared_lib empty for musl variant",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"libc_musl"},
 		Blueprint: soongCcLibraryPreamble + `
 cc_library {
 		name: "libc_musl",
-		bazel_module: { bp2build_available: false },
 }
 
 cc_library {
@@ -1901,10 +1915,10 @@
 		Description:                "cc_library system_shared_lib empty for linux_musl variant",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"libc_musl"},
 		Blueprint: soongCcLibraryPreamble + `
 cc_library {
 		name: "libc_musl",
-		bazel_module: { bp2build_available: false },
 }
 
 cc_library {
@@ -1927,14 +1941,13 @@
 		Description:                "cc_library system_shared_libs set for shared and root",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"libc", "libm"},
 		Blueprint: soongCcLibraryPreamble + `
 cc_library {
     name: "libc",
-    bazel_module: { bp2build_available: false },
 }
 cc_library {
     name: "libm",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
@@ -2505,6 +2518,7 @@
 	runCcLibraryTestCase(t, Bp2buildTestCase{
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"//path/to/A:a_fg_proto"},
 		Filesystem: map[string]string{
 			"path/to/A/Android.bp": `
 filegroup {
@@ -2548,11 +2562,12 @@
 	runCcLibraryTestCase(t, Bp2buildTestCase{
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"a_fg_proto", "b_protos", "c-proto-srcs", "proto-srcs-d"},
 		Blueprint: soongCcProtoPreamble +
-			simpleModuleDoNotConvertBp2build("filegroup", "a_fg_proto") +
-			simpleModuleDoNotConvertBp2build("filegroup", "b_protos") +
-			simpleModuleDoNotConvertBp2build("filegroup", "c-proto-srcs") +
-			simpleModuleDoNotConvertBp2build("filegroup", "proto-srcs-d") + `
+			simpleModule("filegroup", "a_fg_proto") +
+			simpleModule("filegroup", "b_protos") +
+			simpleModule("filegroup", "c-proto-srcs") +
+			simpleModule("filegroup", "proto-srcs-d") + `
 cc_library {
 	name: "a",
 	srcs: [":a_fg_proto"],
@@ -2809,6 +2824,7 @@
 		"stubs_symbol_file": `"a.map.txt"`,
 	})
 	expectedBazelTargets = append(expectedBazelTargets, makeCcStubSuiteTargets("a", AttrNameToString{
+		"api_surface":          `"module-libapi"`,
 		"soname":               `"a.so"`,
 		"source_library_label": `"//foo/bar:a"`,
 		"stubs_symbol_file":    `"a.map.txt"`,
@@ -2839,205 +2855,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",
@@ -3046,11 +2863,11 @@
 		Filesystem: map[string]string{
 			"bar.map.txt": "",
 		},
+		StubbedBuildDefinitions: []string{"barlib"},
 		Blueprint: `
 cc_library {
 	name: "barlib",
 	stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 }
 cc_library {
 	name: "foolib",
@@ -3066,7 +2883,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": `["."]`,
@@ -3082,16 +2898,15 @@
 		Filesystem: map[string]string{
 			"bar.map.txt": "",
 		},
-		Blueprint: simpleModuleDoNotConvertBp2build("cc_library", "bazlib") + `
+		StubbedBuildDefinitions: []string{"bazlib", "quxlib", "barlib"},
+		Blueprint: simpleModule("cc_library", "bazlib") + `
 cc_library {
 	name: "quxlib",
 	stubs: { symbol_file: "bar.map.txt", versions: ["current"] },
-	bazel_module: { bp2build_available: false },
 }
 cc_library {
 	name: "barlib",
 	stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 }
 cc_library {
 	name: "foolib",
@@ -3124,10 +2939,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",
@@ -3209,18 +3020,18 @@
 
 cc_library {
   name: "foo",
-  runtime_libs: ["foo"],
+  runtime_libs: ["bar"],
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{
 				"local_includes": `["."]`,
 			}),
 			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
-				"runtime_deps":   `[":foo"]`,
+				"runtime_deps":   `[":bar"]`,
 				"local_includes": `["."]`,
 			}),
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"runtime_deps":   `[":foo"]`,
+				"runtime_deps":   `[":bar"]`,
 				"local_includes": `["."]`,
 			}),
 		},
@@ -3431,6 +3242,7 @@
 		Description:                "cc_library with non aidl filegroup",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"//path/to/A:A_aidl"},
 		Filesystem: map[string]string{
 			"path/to/A/Android.bp": `
 filegroup {
@@ -3720,6 +3532,7 @@
 		Description:                "cc_aidl_library depends on libs from parent cc_library_static",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"bar-static", "baz-static", "bar-shared", "baz-shared"},
 		Blueprint: `
 cc_library_static {
 	name: "foo",
@@ -3741,10 +3554,10 @@
 		"baz-shared",
 	],
 }` +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "bar-static") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "baz-static") +
-			simpleModuleDoNotConvertBp2build("cc_library", "bar-shared") +
-			simpleModuleDoNotConvertBp2build("cc_library", "baz-shared"),
+			simpleModule("cc_library_static", "bar-static") +
+			simpleModule("cc_library_static", "baz-static") +
+			simpleModule("cc_library", "bar-shared") +
+			simpleModule("cc_library", "baz-shared"),
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
 				"srcs": `["Foo.aidl"]`,
@@ -3843,8 +3656,8 @@
 		{
 			description: "cc_library with afdo enabled and existing profile",
 			filesystem: map[string]string{
-				"vendor/google_data/pgo_profile/sampling/BUILD":    "",
-				"vendor/google_data/pgo_profile/sampling/foo.afdo": "",
+				"vendor/google_data/pgo_profile/sampling/Android.bp": "",
+				"vendor/google_data/pgo_profile/sampling/foo.afdo":   "",
 			},
 			expectedBazelTargets: []string{
 				MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
@@ -3856,8 +3669,8 @@
 		{
 			description: "cc_library with afdo enabled and existing profile in AOSP",
 			filesystem: map[string]string{
-				"toolchain/pgo-profiles/sampling/BUILD":    "",
-				"toolchain/pgo-profiles/sampling/foo.afdo": "",
+				"toolchain/pgo-profiles/sampling/Android.bp": "",
+				"toolchain/pgo-profiles/sampling/foo.afdo":   "",
 			},
 			expectedBazelTargets: []string{
 				MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
@@ -3869,8 +3682,8 @@
 		{
 			description: "cc_library with afdo enabled but profile filename doesn't match with module name",
 			filesystem: map[string]string{
-				"toolchain/pgo-profiles/sampling/BUILD":    "",
-				"toolchain/pgo-profiles/sampling/bar.afdo": "",
+				"toolchain/pgo-profiles/sampling/Android.bp": "",
+				"toolchain/pgo-profiles/sampling/bar.afdo":   "",
 			},
 			expectedBazelTargets: []string{
 				MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
@@ -4288,17 +4101,16 @@
 		Description:                "cc_library with in apex with stub shared_libs and export_shared_lib_headers",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"barlib", "bazlib"},
 		Blueprint: `
 cc_library {
 	name: "barlib",
 	stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 	apex_available: ["//apex_available:platform",],
 }
 cc_library {
 	name: "bazlib",
 	stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 	apex_available: ["//apex_available:platform",],
 }
 cc_library {
@@ -4674,6 +4486,7 @@
 		Description:                "cc_library is built from .y/.yy files",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"staticlib", "sharedlib"},
 		Blueprint: soongCcLibraryPreamble + `cc_library {
     name: "a",
     srcs: [
@@ -4690,11 +4503,9 @@
 }
 cc_library_static {
 	name: "staticlib",
-	bazel_module: { bp2build_available: false },
 }
 cc_library {
 	name: "sharedlib",
-	bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -4948,7 +4759,7 @@
 		canonical_path_from_root: true,
 	}
 }
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+` + simpleModule("cc_library", "libprotobuf-cpp-lite"),
 		Filesystem: map[string]string{
 			"bar/Android.bp":        "",
 			"baz/subbaz/Android.bp": "",
@@ -5016,7 +4827,7 @@
 		canonical_path_from_root: false,
 	}
 }
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+` + simpleModule("cc_library", "libprotobuf-cpp-lite"),
 		Filesystem: map[string]string{
 			"bar/Android.bp":        "",
 			"baz/subbaz/Android.bp": "",
@@ -5086,7 +4897,7 @@
 		include_dirs: ["bar"],
 	}
 }
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+` + simpleModule("cc_library", "libprotobuf-cpp-lite"),
 		Filesystem: map[string]string{
 			"bar/Android.bp":     "",
 			"bar/bar.proto":      "",
@@ -5157,7 +4968,7 @@
 		include_dirs: ["baz"],
 	}
 }
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+` + simpleModule("cc_library", "libprotobuf-cpp-lite"),
 		Filesystem: map[string]string{
 			"bar/Android.bp": "", // package boundary
 			"baz/Android.bp": "",
@@ -5192,7 +5003,14 @@
 		Description:                "cc_library depends on .proto files using proto.local_include_dirs",
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
-		Blueprint:                  simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+		Blueprint: `
+cc_library {
+	name: "libprotobuf-cpp-lite",
+  // TODO: b/285631638 - A stubbed proto library dependency does not work as a protolib
+  // dependency of cc_library_static.
+	bazel_module: { bp2build_available: false },
+}
+`,
 		Filesystem: map[string]string{
 			"foo/Android.bp": `cc_library_static {
 	name: "foo",
@@ -5249,7 +5067,7 @@
 		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") + `
+		Blueprint: simpleModule("cc_library", "libprotobuf-cpp-lite") + `
 cc_library {
 	name: "foo_device",
 	device_supported: true, // this is the default behavior, but added explicitly here for illustration
@@ -5279,3 +5097,120 @@
 	}
 	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)
+}
+
+func TestNdkLibraryConversion(t *testing.T) {
+	tc := Bp2buildTestCase{
+		Description:                "ndk_library conversion",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+cc_library {
+	name: "libfoo",
+	bazel_module: { bp2build_available: false },
+}
+ndk_library {
+	name: "libfoo",
+	first_version: "29",
+	symbol_file: "libfoo.map.txt",
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_stub_suite", "libfoo.ndk_stub_libs", AttrNameToString{
+				"api_surface":          `"publicapi"`,
+				"soname":               `"libfoo.so"`,
+				"source_library_label": `"//:libfoo"`,
+				"symbol_file":          `"libfoo.map.txt"`,
+				"versions": `[
+        "29",
+        "30",
+        "S",
+        "Tiramisu",
+        "current",
+    ]`,
+			}),
+		},
+	}
+	runCcLibraryTestCase(t, tc)
+}
+
+func TestNdkHeadersConversion(t *testing.T) {
+	tc := Bp2buildTestCase{
+		Description:                "ndk_headers conversion",
+		ModuleTypeUnderTest:        "ndk_headers",
+		ModuleTypeUnderTestFactory: cc.NdkHeadersFactory,
+		Blueprint: `
+ndk_headers {
+	name: "libfoo_headers",
+	from: "from",
+	to: "to",
+	srcs: ["foo.h", "foo_other.h"]
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("ndk_headers", "libfoo_headers", AttrNameToString{
+				"strip_import_prefix": `"from"`,
+				"import_prefix":       `"to"`,
+				"hdrs": `[
+        "foo.h",
+        "foo_other.h",
+    ]`,
+			}),
+		},
+	}
+	runCcLibraryTestCase(t, tc)
+}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 072f5b3..e54f051 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -57,6 +57,8 @@
 
 func registerCcLibraryHeadersModuleTypes(ctx android.RegistrationContext) {
 	cc.RegisterCCBuildComponents(ctx)
+	cc.RegisterLibraryHeadersBuildComponents(ctx)
+	ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory)
 }
 
 func runCcLibraryHeadersTestCase(t *testing.T, tc Bp2buildTestCase) {
@@ -66,9 +68,7 @@
 
 func TestCcLibraryHeadersSimple(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library_headers test",
-		ModuleTypeUnderTest:        "cc_library_headers",
-		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+		Description: "cc_library_headers test",
 		Filesystem: map[string]string{
 			"lib-1/lib1a.h":                        "",
 			"lib-1/lib1b.h":                        "",
@@ -118,106 +118,41 @@
     ]`,
 				"sdk_version":     `"current"`,
 				"min_sdk_version": `"29"`,
+				"deps": `select({
+        "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"],
+        "//conditions:default": [],
+    })`,
 			}),
 		},
 	})
 }
 
-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) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library_headers test with os-specific header_libs props",
-		ModuleTypeUnderTest:        "cc_library_headers",
-		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
-		Filesystem:                 map[string]string{},
+		Description: "cc_library_headers test with os-specific header_libs props",
+		Filesystem:  map[string]string{},
+		StubbedBuildDefinitions: []string{"android-lib", "base-lib", "darwin-lib",
+			"linux-lib", "linux_bionic-lib", "windows-lib"},
 		Blueprint: soongCcLibraryPreamble + `
 cc_library_headers {
     name: "android-lib",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_headers {
     name: "base-lib",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_headers {
     name: "darwin-lib",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_headers {
     name: "linux-lib",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_headers {
     name: "linux_bionic-lib",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_headers {
     name: "windows-lib",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_headers {
     name: "foo_headers",
@@ -264,18 +199,15 @@
 
 func TestCcLibraryHeadersOsSpecficHeaderLibsExportHeaderLibHeaders(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library_headers test with os-specific header_libs and export_header_lib_headers props",
-		ModuleTypeUnderTest:        "cc_library_headers",
-		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
-		Filesystem:                 map[string]string{},
+		Description:             "cc_library_headers test with os-specific header_libs and export_header_lib_headers props",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"android-lib", "exported-lib"},
 		Blueprint: soongCcLibraryPreamble + `
 cc_library_headers {
     name: "android-lib",
-    bazel_module: { bp2build_available: false },
   }
 cc_library_headers {
     name: "exported-lib",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_headers {
     name: "foo_headers",
@@ -300,10 +232,8 @@
 
 func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library_headers test with arch-specific and target-specific export_system_include_dirs props",
-		ModuleTypeUnderTest:        "cc_library_headers",
-		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
-		Filesystem:                 map[string]string{},
+		Description: "cc_library_headers test with arch-specific and target-specific export_system_include_dirs props",
+		Filesystem:  map[string]string{},
 		Blueprint: soongCcLibraryPreamble + `cc_library_headers {
     name: "foo_headers",
     export_system_include_dirs: [
@@ -359,9 +289,7 @@
 
 func TestCcLibraryHeadersNoCrtIgnored(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library_headers test",
-		ModuleTypeUnderTest:        "cc_library_headers",
-		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+		Description: "cc_library_headers test",
 		Filesystem: map[string]string{
 			"lib-1/lib1a.h":                        "",
 			"lib-1/lib1b.h":                        "",
@@ -392,10 +320,9 @@
 
 func TestCcLibraryHeadersExportedStaticLibHeadersReexported(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library_headers exported_static_lib_headers is reexported",
-		ModuleTypeUnderTest:        "cc_library_headers",
-		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
-		Filesystem:                 map[string]string{},
+		Description:             "cc_library_headers exported_static_lib_headers is reexported",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"foo_export"},
 		Blueprint: soongCcLibraryHeadersPreamble + `
 cc_library_headers {
 		name: "foo_headers",
@@ -403,7 +330,7 @@
 		static_libs: ["foo_export", "foo_no_reexport"],
     bazel_module: { bp2build_available: true },
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
+` + simpleModule("cc_library_headers", "foo_export"),
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
 				"deps": `[":foo_export"]`,
@@ -414,10 +341,9 @@
 
 func TestCcLibraryHeadersExportedSharedLibHeadersReexported(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library_headers exported_shared_lib_headers is reexported",
-		ModuleTypeUnderTest:        "cc_library_headers",
-		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
-		Filesystem:                 map[string]string{},
+		Description:             "cc_library_headers exported_shared_lib_headers is reexported",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"foo_export"},
 		Blueprint: soongCcLibraryHeadersPreamble + `
 cc_library_headers {
 		name: "foo_headers",
@@ -425,7 +351,7 @@
 		shared_libs: ["foo_export", "foo_no_reexport"],
     bazel_module: { bp2build_available: true },
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
+` + simpleModule("cc_library_headers", "foo_export"),
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
 				"deps": `[":foo_export"]`,
@@ -436,10 +362,9 @@
 
 func TestCcLibraryHeadersExportedHeaderLibHeadersReexported(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library_headers exported_header_lib_headers is reexported",
-		ModuleTypeUnderTest:        "cc_library_headers",
-		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
-		Filesystem:                 map[string]string{},
+		Description:             "cc_library_headers exported_header_lib_headers is reexported",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"foo_export"},
 		Blueprint: soongCcLibraryHeadersPreamble + `
 cc_library_headers {
 		name: "foo_headers",
@@ -447,7 +372,7 @@
 		header_libs: ["foo_export", "foo_no_reexport"],
     bazel_module: { bp2build_available: true },
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
+` + simpleModule("cc_library_headers", "foo_export"),
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
 				"deps": `[":foo_export"]`,
@@ -458,17 +383,16 @@
 
 func TestCcLibraryHeadersWholeStaticLibsReexported(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
-		Description:                "cc_library_headers whole_static_libs is reexported",
-		ModuleTypeUnderTest:        "cc_library_headers",
-		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
-		Filesystem:                 map[string]string{},
+		Description:             "cc_library_headers whole_static_libs is reexported",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"foo_export"},
 		Blueprint: soongCcLibraryHeadersPreamble + `
 cc_library_headers {
 		name: "foo_headers",
 		whole_static_libs: ["foo_export"],
     bazel_module: { bp2build_available: true },
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
+` + simpleModule("cc_library_headers", "foo_export"),
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
 				"deps": `[":foo_export"]`,
@@ -476,3 +400,89 @@
 		},
 	})
 }
+
+func TestPrebuiltCcLibraryHeadersWholeStaticLibsReexported(t *testing.T) {
+	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
+		Description: "cc_library_headers whole_static_libs is reexported",
+		Filesystem: map[string]string{
+			"foo/bar/Android.bp": simpleModule("cc_library_headers", "foo_headers"),
+		},
+		StubbedBuildDefinitions: []string{"foo_export"},
+		Blueprint: soongCcLibraryHeadersPreamble + `
+cc_prebuilt_library_headers {
+		name: "foo_headers",
+		whole_static_libs: ["foo_export"],
+    bazel_module: { bp2build_available: true },
+}
+` + simpleModule("cc_library_headers", "foo_export"),
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
+				"deps": `[":foo_export"]`,
+			}),
+		},
+	})
+}
+
+func TestPrebuiltCcLibraryHeadersPreferredRdepUpdated(t *testing.T) {
+	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
+		Description:             "cc_library_headers prebuilt preferred is used as rdep",
+		StubbedBuildDefinitions: []string{"foo_export"},
+		Filesystem: map[string]string{
+			"foo/bar/Android.bp": simpleModule("cc_library_headers", "foo_headers"),
+		},
+		Blueprint: soongCcLibraryHeadersPreamble + `
+cc_prebuilt_library_headers {
+		name: "foo_headers",
+		whole_static_libs: ["foo_export"],
+		bazel_module: { bp2build_available: true },
+		prefer: true,
+}
+
+cc_library_shared {
+	name: "foo",
+	header_libs: ["foo_headers"],
+	include_build_directory: false,
+}
+` + simpleModule("cc_library_headers", "foo_export"),
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
+				"deps": `[":foo_export"]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"implementation_deps": `[":foo_headers"]`,
+			}),
+		},
+	})
+}
+
+func TestPrebuiltCcLibraryHeadersRdepUpdated(t *testing.T) {
+	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
+		Description:             "cc_library_headers not preferred is not used for rdep",
+		StubbedBuildDefinitions: []string{"foo_export"},
+		Filesystem: map[string]string{
+			"foo/bar/Android.bp": simpleModule("cc_library_headers", "foo_headers"),
+		},
+		Blueprint: soongCcLibraryHeadersPreamble + `
+cc_prebuilt_library_headers {
+		name: "foo_headers",
+		whole_static_libs: ["foo_export"],
+		bazel_module: { bp2build_available: true },
+		prefer: false,
+}
+
+cc_library_shared {
+	name: "foo",
+	header_libs: ["foo_headers"],
+	include_build_directory: false,
+}
+` + simpleModule("cc_library_headers", "foo_export"),
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
+				"deps": `[":foo_export"]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"implementation_deps": `["//foo/bar:foo_headers"]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 90b13b0..2c5305f 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -32,11 +32,13 @@
 	ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
 	ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
 	ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
+	ctx.RegisterModuleType("ndk_library", cc.NdkLibraryFactory)
 }
 
 func runCcLibrarySharedTestCase(t *testing.T, tc Bp2buildTestCase) {
 	t.Helper()
 	t.Parallel()
+	tc.StubbedBuildDefinitions = append(tc.StubbedBuildDefinitions, "libbuildversion", "libprotobuf-cpp-lite", "libprotobuf-cpp-full")
 	(&tc).ModuleTypeUnderTest = "cc_library_shared"
 	(&tc).ModuleTypeUnderTestFactory = cc.LibrarySharedFactory
 	RunBp2BuildTestCase(t, registerCcLibrarySharedModuleTypes, tc)
@@ -44,7 +46,8 @@
 
 func TestCcLibrarySharedSimple(t *testing.T) {
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_shared simple overall test",
+		Description:             "cc_library_shared simple overall test",
+		StubbedBuildDefinitions: []string{"header_lib_1", "header_lib_2", "whole_static_lib_1", "whole_static_lib_2", "shared_lib_1", "shared_lib_2"},
 		Filesystem: map[string]string{
 			// NOTE: include_dir headers *should not* appear in Bazel hdrs later (?)
 			"include_dir_1/include_dir_1_a.h": "",
@@ -69,37 +72,31 @@
 cc_library_headers {
     name: "header_lib_1",
     export_include_dirs: ["header_lib_1"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_headers {
     name: "header_lib_2",
     export_include_dirs: ["header_lib_2"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_shared {
     name: "shared_lib_1",
     srcs: ["shared_lib_1.cc"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_shared {
     name: "shared_lib_2",
     srcs: ["shared_lib_2.cc"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_static_lib_1",
     srcs: ["whole_static_lib_1.cc"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_static_lib_2",
     srcs: ["whole_static_lib_2.cc"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_shared {
@@ -178,6 +175,10 @@
     ]`,
 				"sdk_version":     `"current"`,
 				"min_sdk_version": `"29"`,
+				"deps": `select({
+        "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"],
+        "//conditions:default": [],
+    })`,
 			}),
 		},
 	})
@@ -185,16 +186,15 @@
 
 func TestCcLibrarySharedArchSpecificSharedLib(t *testing.T) {
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_shared arch-specific shared_libs with whole_static_libs",
-		Filesystem:  map[string]string{},
+		Description:             "cc_library_shared arch-specific shared_libs with whole_static_libs",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"static_dep", "shared_dep"},
 		Blueprint: soongCcLibrarySharedPreamble + `
 cc_library_static {
     name: "static_dep",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_shared {
     name: "shared_dep",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_shared {
     name: "foo_shared",
@@ -218,12 +218,12 @@
 
 func TestCcLibrarySharedOsSpecificSharedLib(t *testing.T) {
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_shared os-specific shared_libs",
-		Filesystem:  map[string]string{},
+		StubbedBuildDefinitions: []string{"shared_dep"},
+		Description:             "cc_library_shared os-specific shared_libs",
+		Filesystem:              map[string]string{},
 		Blueprint: soongCcLibrarySharedPreamble + `
 cc_library_shared {
     name: "shared_dep",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_shared {
     name: "foo_shared",
@@ -243,20 +243,18 @@
 
 func TestCcLibrarySharedBaseArchOsSpecificSharedLib(t *testing.T) {
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_shared base, arch, and os-specific shared_libs",
-		Filesystem:  map[string]string{},
+		StubbedBuildDefinitions: []string{"shared_dep", "shared_dep2", "shared_dep3"},
+		Description:             "cc_library_shared base, arch, and os-specific shared_libs",
+		Filesystem:              map[string]string{},
 		Blueprint: soongCcLibrarySharedPreamble + `
 cc_library_shared {
     name: "shared_dep",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_shared {
     name: "shared_dep2",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_shared {
     name: "shared_dep3",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_shared {
     name: "foo_shared",
@@ -511,6 +509,7 @@
 		Filesystem: map[string]string{
 			soongCcVersionLibBpPath: soongCcVersionLibBp,
 		},
+		StubbedBuildDefinitions: []string{"//build/soong/cc/libbuildversion:libbuildversion"},
 		Blueprint: soongCcProtoPreamble + `cc_library_shared {
         name: "foo",
         use_version_lib: true,
@@ -543,6 +542,7 @@
 		},
 		Blueprint: soongCcLibraryPreamble,
 		ExpectedBazelTargets: []string{makeCcStubSuiteTargets("a", AttrNameToString{
+			"api_surface":          `"module-libapi"`,
 			"soname":               `"a.so"`,
 			"source_library_label": `"//foo/bar:a"`,
 			"stubs_symbol_file":    `"a.map.txt"`,
@@ -564,11 +564,11 @@
 		Description:                "cc_library_shared stubs",
 		ModuleTypeUnderTest:        "cc_library_shared",
 		ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+		StubbedBuildDefinitions:    []string{"a"},
 		Blueprint: soongCcLibrarySharedPreamble + `
 cc_library_shared {
 	name: "a",
 	stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 	include_build_directory: false,
 	apex_available: ["made_up_apex"],
 }
@@ -593,11 +593,11 @@
 		Description:                "cc_library_shared stubs",
 		ModuleTypeUnderTest:        "cc_library_shared",
 		ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+		StubbedBuildDefinitions:    []string{"a"},
 		Blueprint: soongCcLibrarySharedPreamble + `
 cc_library_shared {
 	name: "a",
 	stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 	include_build_directory: false,
 	apex_available: ["apex_a"],
 }
@@ -627,19 +627,18 @@
 		Description:                "cc_library_shared stubs",
 		ModuleTypeUnderTest:        "cc_library_shared",
 		ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+		StubbedBuildDefinitions:    []string{"libplatform_stable", "libapexfoo_stable"},
 		Blueprint: soongCcLibrarySharedPreamble + `
 cc_library_shared {
 	name: "libplatform_stable",
 	stubs: { symbol_file: "libplatform_stable.map.txt", versions: ["28", "29", "current"] },
 	apex_available: ["//apex_available:platform"],
-	bazel_module: { bp2build_available: false },
 	include_build_directory: false,
 }
 cc_library_shared {
 	name: "libapexfoo_stable",
 	stubs: { symbol_file: "libapexfoo_stable.map.txt", versions: ["28", "29", "current"] },
 	apex_available: ["apexfoo"],
-	bazel_module: { bp2build_available: false },
 	include_build_directory: false,
 }
 cc_library_shared {
@@ -661,7 +660,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": [
@@ -684,11 +683,11 @@
 		Description:                "cc_library_shared stubs",
 		ModuleTypeUnderTest:        "cc_library_shared",
 		ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+		StubbedBuildDefinitions:    []string{"a"},
 		Blueprint: soongCcLibrarySharedPreamble + `
 cc_library_shared {
 	name: "a",
 	stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 	include_build_directory: false,
 	apex_available: ["//apex_available:platform", "apex_a"],
 }
@@ -720,11 +719,11 @@
 		Description:                "cc_library depeends on impl for all configurations",
 		ModuleTypeUnderTest:        "cc_library_shared",
 		ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+		StubbedBuildDefinitions:    []string{"a"},
 		Blueprint: soongCcLibrarySharedPreamble + `
 cc_library_shared {
 	name: "a",
 	stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 	apex_available: ["//apex_available:platform"],
 }
 cc_library_shared {
@@ -747,11 +746,11 @@
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
 		ModuleTypeUnderTest:        "cc_library_shared",
 		ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+		StubbedBuildDefinitions:    []string{"a"},
 		Blueprint: soongCcLibrarySharedPreamble + `
 cc_library_shared {
 	name: "a",
 	stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 	include_build_directory: false,
 	apex_available: ["//apex_available:platform", "apex_a", "apex_b"],
 }
@@ -929,14 +928,14 @@
 
 cc_library_shared {
   name: "foo",
-  runtime_libs: ["foo"],
+  runtime_libs: ["bar"],
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{
 				"local_includes": `["."]`,
 			}),
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"runtime_deps":   `[":foo"]`,
+				"runtime_deps":   `[":bar"]`,
 				"local_includes": `["."]`,
 			}),
 		},
@@ -1442,6 +1441,7 @@
 `,
 		ExpectedBazelTargets: []string{
 			makeCcStubSuiteTargets("a", AttrNameToString{
+				"api_surface":          `"module-libapi"`,
 				"soname":               `"a.so"`,
 				"source_library_label": `"//:a"`,
 				"stubs_symbol_file":    `"a.map.txt"`,
@@ -1456,6 +1456,7 @@
 				"stubs_symbol_file": `"a.map.txt"`,
 			}),
 			makeCcStubSuiteTargets("b", AttrNameToString{
+				"api_surface":          `"module-libapi"`,
 				"soname":               `"b.so"`,
 				"source_library_label": `"//:b"`,
 				"stubs_symbol_file":    `"b.map.txt"`,
@@ -1592,3 +1593,64 @@
     ]`,
 			})}})
 }
+
+func TestCcLibrarySdkVariantUsesStubs(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library_shared stubs",
+		ModuleTypeUnderTest:        "cc_library_shared",
+		ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+		StubbedBuildDefinitions:    []string{"libNoStubs", "libHasApexStubs", "libHasApexAndNdkStubs", "libHasApexAndNdkStubs.ndk_stub_libs"},
+		Blueprint: soongCcLibrarySharedPreamble + `
+cc_library_shared {
+	name: "libUsesSdk",
+	sdk_version: "current",
+	shared_libs: [
+		"libNoStubs",
+		"libHasApexStubs",
+		"libHasApexAndNdkStubs",
+	]
+}
+cc_library_shared {
+	name: "libNoStubs",
+}
+cc_library_shared {
+	name: "libHasApexStubs",
+	stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
+	apex_available: ["apex_a"],
+}
+cc_library_shared {
+	name: "libHasApexAndNdkStubs",
+	stubs: { symbol_file: "b.map.txt", versions: ["28", "29", "current"] },
+	apex_available: ["apex_b"],
+}
+ndk_library {
+	name: "libHasApexAndNdkStubs",
+	first_version: "28",
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_shared", "libUsesSdk", AttrNameToString{
+				"implementation_dynamic_deps": `[":libNoStubs"] + select({
+        "//build/bazel/rules/apex:system": [
+            "@api_surfaces//module-libapi/current:libHasApexStubs",
+            "@api_surfaces//module-libapi/current:libHasApexAndNdkStubs",
+        ],
+        "//build/bazel/rules/apex:unbundled_app": [
+            ":libHasApexStubs",
+            "//.:libHasApexAndNdkStubs.ndk_stub_libs-current",
+        ],
+        "//conditions:default": [
+            ":libHasApexStubs",
+            ":libHasApexAndNdkStubs",
+        ],
+    })`,
+				"local_includes": `["."]`,
+				"sdk_version":    `"current"`,
+				"deps": `select({
+        "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 89ec8f9..09e40ed 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -96,41 +96,37 @@
 			"implicit_include_1.h": "",
 			"implicit_include_2.h": "",
 		},
+		StubbedBuildDefinitions: []string{"header_lib_1", "header_lib_2",
+			"static_lib_1", "static_lib_2", "whole_static_lib_1", "whole_static_lib_2"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library_headers {
     name: "header_lib_1",
     export_include_dirs: ["header_lib_1"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_headers {
     name: "header_lib_2",
     export_include_dirs: ["header_lib_2"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "static_lib_1",
     srcs: ["static_lib_1.cc"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "static_lib_2",
     srcs: ["static_lib_2.cc"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_static_lib_1",
     srcs: ["whole_static_lib_1.cc"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_static_lib_2",
     srcs: ["whole_static_lib_2.cc"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -207,6 +203,10 @@
     ]`,
 				"sdk_version":     `"current"`,
 				"min_sdk_version": `"29"`,
+				"deps": `select({
+        "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"],
+        "//conditions:default": [],
+    })`,
 			}),
 		},
 	})
@@ -392,16 +392,15 @@
 
 func TestCcLibraryStaticArchSpecificStaticLib(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static arch-specific static_libs",
-		Filesystem:  map[string]string{},
+		Description:             "cc_library_static arch-specific static_libs",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"static_dep", "static_dep2"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library_static {
     name: "static_dep",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_static {
     name: "static_dep2",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_static {
     name: "foo_static",
@@ -425,16 +424,15 @@
 
 func TestCcLibraryStaticOsSpecificStaticLib(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static os-specific static_libs",
-		Filesystem:  map[string]string{},
+		Description:             "cc_library_static os-specific static_libs",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"static_dep", "static_dep2"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library_static {
     name: "static_dep",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_static {
     name: "static_dep2",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_static {
     name: "foo_static",
@@ -460,22 +458,20 @@
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
 		Description: "cc_library_static base, arch and os-specific static_libs",
 		Filesystem:  map[string]string{},
+		StubbedBuildDefinitions: []string{"static_dep", "static_dep2", "static_dep3",
+			"static_dep4"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library_static {
     name: "static_dep",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_static {
     name: "static_dep2",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_static {
     name: "static_dep3",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_static {
     name: "static_dep4",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_static {
     name: "foo_static",
@@ -756,12 +752,12 @@
 
 func TestCcLibraryStaticMultipleDepSameName(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static multiple dep same name panic",
-		Filesystem:  map[string]string{},
+		Description:             "cc_library_static multiple dep same name panic",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"static_dep"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library_static {
     name: "static_dep",
-    bazel_module: { bp2build_available: false },
 }
 cc_library_static {
     name: "foo_static",
@@ -961,17 +957,16 @@
 
 func TestCcLibraryStaticGeneratedHeadersAllPartitions(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		StubbedBuildDefinitions: []string{"generated_hdr", "export_generated_hdr"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 genrule {
     name: "generated_hdr",
     cmd: "nothing to see here",
-    bazel_module: { bp2build_available: false },
 }
 
 genrule {
     name: "export_generated_hdr",
     cmd: "nothing to see here",
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -1005,19 +1000,18 @@
 
 func TestCcLibraryStaticGeneratedHeadersMultipleExports(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		StubbedBuildDefinitions: []string{"generated_hdr", "export_generated_hdr"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 genrule {
     name: "generated_hdr",
     cmd: "nothing to see here",
     export_include_dirs: ["foo", "bar"],
-    bazel_module: { bp2build_available: false },
 }
 
 genrule {
     name: "export_generated_hdr",
     cmd: "nothing to see here",
     export_include_dirs: ["a", "b"],
-    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -1040,22 +1034,26 @@
 func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
 		Description: "cc_library_static arch srcs/exclude_srcs with generated files",
+		StubbedBuildDefinitions: []string{"//dep:generated_src_other_pkg", "//dep:generated_hdr_other_pkg",
+			"//dep:generated_src_other_pkg_x86", "//dep:generated_hdr_other_pkg_x86", "//dep:generated_hdr_other_pkg_android",
+			"generated_src", "generated_src_not_x86", "generated_src_android", "generated_hdr",
+		},
 		Filesystem: map[string]string{
 			"common.cpp":             "",
 			"for-x86.cpp":            "",
 			"not-for-x86.cpp":        "",
 			"not-for-everything.cpp": "",
-			"dep/Android.bp": simpleModuleDoNotConvertBp2build("genrule", "generated_src_other_pkg") +
-				simpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg") +
-				simpleModuleDoNotConvertBp2build("genrule", "generated_src_other_pkg_x86") +
-				simpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg_x86") +
-				simpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg_android"),
+			"dep/Android.bp": simpleModule("genrule", "generated_src_other_pkg") +
+				simpleModule("genrule", "generated_hdr_other_pkg") +
+				simpleModule("genrule", "generated_src_other_pkg_x86") +
+				simpleModule("genrule", "generated_hdr_other_pkg_x86") +
+				simpleModule("genrule", "generated_hdr_other_pkg_android"),
 		},
 		Blueprint: soongCcLibraryStaticPreamble +
-			simpleModuleDoNotConvertBp2build("genrule", "generated_src") +
-			simpleModuleDoNotConvertBp2build("genrule", "generated_src_not_x86") +
-			simpleModuleDoNotConvertBp2build("genrule", "generated_src_android") +
-			simpleModuleDoNotConvertBp2build("genrule", "generated_hdr") + `
+			simpleModule("genrule", "generated_src") +
+			simpleModule("genrule", "generated_src_not_x86") +
+			simpleModule("genrule", "generated_src_android") +
+			simpleModule("genrule", "generated_hdr") + `
 cc_library_static {
     name: "foo_static",
     srcs: ["common.cpp", "not-for-*.cpp"],
@@ -1340,11 +1338,11 @@
 
 func TestStaticLibrary_SystemSharedLibsBionicEmpty(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static system_shared_lib empty for bionic variant",
+		Description:             "cc_library_static system_shared_lib empty for bionic variant",
+		StubbedBuildDefinitions: []string{"libc_musl"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library {
 		name: "libc_musl",
-		bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -1374,11 +1372,11 @@
 	// only for linux_bionic, but `android` had `["libc", "libdl", "libm"].
 	// b/195791252 tracks the fix.
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static system_shared_lib empty for linux_bionic variant",
+		Description:             "cc_library_static system_shared_lib empty for linux_bionic variant",
+		StubbedBuildDefinitions: []string{"libc_musl"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library {
 		name: "libc_musl",
-		bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -1404,11 +1402,11 @@
 
 func TestStaticLibrary_SystemSharedLibsMuslEmpty(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static system_shared_lib empty for musl variant",
+		Description:             "cc_library_static system_shared_lib empty for musl variant",
+		StubbedBuildDefinitions: []string{"libc_musl"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library {
 		name: "libc_musl",
-		bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -1431,11 +1429,11 @@
 
 func TestStaticLibrary_SystemSharedLibsLinuxMuslEmpty(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static system_shared_lib empty for linux_musl variant",
+		Description:             "cc_library_static system_shared_lib empty for linux_musl variant",
+		StubbedBuildDefinitions: []string{"libc_musl"},
 		Blueprint: soongCcLibraryStaticPreamble + `
 cc_library {
 		name: "libc_musl",
-		bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -1458,12 +1456,12 @@
 
 func TestStaticLibrary_SystemSharedLibsBionic(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static system_shared_libs set for bionic variant",
+		Description:             "cc_library_static system_shared_libs set for bionic variant",
+		StubbedBuildDefinitions: []string{"libc", "libc_musl"},
 		Blueprint: soongCcLibraryStaticPreamble +
-			simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
+			simpleModule("cc_library", "libc") + `
 cc_library {
 	name: "libc_musl",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -1491,13 +1489,13 @@
 
 func TestStaticLibrary_SystemSharedLibsLinuxRootAndLinuxBionic(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static system_shared_libs set for root and linux_bionic variant",
+		Description:             "cc_library_static system_shared_libs set for root and linux_bionic variant",
+		StubbedBuildDefinitions: []string{"libc", "libm", "libc_musl"},
 		Blueprint: soongCcLibraryStaticPreamble +
-			simpleModuleDoNotConvertBp2build("cc_library", "libc") +
-			simpleModuleDoNotConvertBp2build("cc_library", "libm") + `
+			simpleModule("cc_library", "libc") +
+			simpleModule("cc_library", "libm") + `
 cc_library {
 	name: "libc_musl",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -1525,9 +1523,10 @@
 
 func TestCcLibrarystatic_SystemSharedLibUsedAsDep(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static system_shared_lib empty for linux_bionic variant",
+		Description:             "cc_library_static system_shared_lib empty for linux_bionic variant",
+		StubbedBuildDefinitions: []string{"libc", "libm"},
 		Blueprint: soongCcLibraryStaticPreamble +
-			simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
+			simpleModule("cc_library", "libc") + `
 
 cc_library {
     name: "libm",
@@ -1535,7 +1534,6 @@
         symbol_file: "libm.map.txt",
         versions: ["current"],
     },
-    bazel_module: { bp2build_available: false },
     apex_available: ["com.android.runtime"],
 }
 
@@ -1613,6 +1611,7 @@
 
 func TestCcLibraryStaticProto(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		StubbedBuildDefinitions: []string{"libprotobuf-cpp-full", "libprotobuf-cpp-lite"},
 		Blueprint: soongCcProtoPreamble + `cc_library_static {
 	name: "foo",
 	srcs: ["foo.proto"],
@@ -1639,6 +1638,7 @@
 		Filesystem: map[string]string{
 			soongCcVersionLibBpPath: soongCcVersionLibBp,
 		},
+		StubbedBuildDefinitions: []string{"//build/soong/cc/libbuildversion:libbuildversion", "libprotobuf-cpp-full", "libprotobuf-cpp-lite"},
 		Blueprint: soongCcProtoPreamble + `cc_library_static {
 	name: "foo",
 	use_version_lib: true,
@@ -1658,6 +1658,8 @@
 		Filesystem: map[string]string{
 			soongCcVersionLibBpPath: soongCcVersionLibBp,
 		},
+		StubbedBuildDefinitions: []string{"//build/soong/cc/libbuildversion:libbuildversion", "libprotobuf-cpp-full", "libprotobuf-cpp-lite"},
+
 		Blueprint: soongCcProtoPreamble + `cc_library_static {
 	name: "foo",
 	use_version_lib: true,
@@ -1674,6 +1676,7 @@
 
 func TestCcLibraryStaticStdInFlags(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		StubbedBuildDefinitions: []string{"libprotobuf-cpp-full", "libprotobuf-cpp-lite"},
 		Blueprint: soongCcProtoPreamble + `cc_library_static {
 	name: "foo",
 	cflags: ["-std=candcpp"],
@@ -1767,14 +1770,14 @@
 
 cc_library_static {
   name: "foo",
-  runtime_libs: ["foo"],
+  runtime_libs: ["bar"],
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{
 				"local_includes": `["."]`,
 			}),
 			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
-				"runtime_deps":   `[":foo"]`,
+				"runtime_deps":   `[":bar"]`,
 				"local_includes": `["."]`,
 			}),
 		},
@@ -2260,6 +2263,7 @@
 		Description:                "cc_library with a .proto file generated from a genrule",
 		ModuleTypeUnderTest:        "cc_library_static",
 		ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
+		StubbedBuildDefinitions:    []string{"libprotobuf-cpp-lite"},
 		Blueprint: soongCcLibraryPreamble + `
 cc_library_static {
 	name: "mylib",
@@ -2269,7 +2273,7 @@
 	name: "myprotogen",
 	out: ["myproto.proto"],
 }
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+` + simpleModule("cc_library", "libprotobuf-cpp-lite"),
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "mylib", AttrNameToString{
 				"local_includes":                    `["."]`,
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index ecfcb5a..e1e2f43 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -317,7 +317,8 @@
 
 func TestCcObjectDepsAndLinkerScriptSelects(t *testing.T) {
 	runCcObjectTestCase(t, Bp2buildTestCase{
-		Description: "cc_object setting deps and linker_script across archs",
+		Description:             "cc_object setting deps and linker_script across archs",
+		StubbedBuildDefinitions: []string{"x86_obj", "x86_64_obj", "arm_obj"},
 		Blueprint: `cc_object {
     name: "foo",
     srcs: ["base.cpp"],
@@ -343,7 +344,6 @@
     system_shared_libs: [],
     srcs: ["x86.cpp"],
     include_build_directory: false,
-    bazel_module: { bp2build_available: false },
 }
 
 cc_object {
@@ -351,7 +351,6 @@
     system_shared_libs: [],
     srcs: ["x86_64.cpp"],
     include_build_directory: false,
-    bazel_module: { bp2build_available: false },
 }
 
 cc_object {
@@ -359,7 +358,6 @@
     system_shared_libs: [],
     srcs: ["arm.cpp"],
     include_build_directory: false,
-    bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
diff --git a/bp2build/cc_prebuilt_library_conversion_test.go b/bp2build/cc_prebuilt_library_conversion_test.go
index b88960e..8c33be3 100644
--- a/bp2build/cc_prebuilt_library_conversion_test.go
+++ b/bp2build/cc_prebuilt_library_conversion_test.go
@@ -17,6 +17,7 @@
 	"fmt"
 	"testing"
 
+	"android/soong/android"
 	"android/soong/cc"
 )
 
@@ -360,3 +361,52 @@
 		},
 	})
 }
+
+func TestPrebuiltNdkStlConversion(t *testing.T) {
+	registerNdkStlModuleTypes := func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("ndk_prebuilt_static_stl", cc.NdkPrebuiltStaticStlFactory)
+		ctx.RegisterModuleType("ndk_prebuilt_shared_stl", cc.NdkPrebuiltSharedStlFactory)
+	}
+	RunBp2BuildTestCase(t, registerNdkStlModuleTypes, Bp2buildTestCase{
+		Description: "TODO",
+		Blueprint: `
+ndk_prebuilt_static_stl {
+	name: "ndk_libfoo_static",
+	export_include_dirs: ["dir1", "dir2"],
+}
+ndk_prebuilt_shared_stl {
+	name: "ndk_libfoo_shared",
+	export_include_dirs: ["dir1", "dir2"],
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_prebuilt_library_static", "ndk_libfoo_static", AttrNameToString{
+				"static_library": `select({
+        "//build/bazel/platforms/os_arch:android_arm": "current/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libfoo_static.a",
+        "//build/bazel/platforms/os_arch:android_arm64": "current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libfoo_static.a",
+        "//build/bazel/platforms/os_arch:android_riscv64": "current/sources/cxx-stl/llvm-libc++/libs/riscv64/libfoo_static.a",
+        "//build/bazel/platforms/os_arch:android_x86": "current/sources/cxx-stl/llvm-libc++/libs/x86/libfoo_static.a",
+        "//build/bazel/platforms/os_arch:android_x86_64": "current/sources/cxx-stl/llvm-libc++/libs/x86_64/libfoo_static.a",
+        "//conditions:default": None,
+    })`,
+				"export_system_includes": `[
+        "dir1",
+        "dir2",
+    ]`,
+			}),
+			MakeBazelTarget("cc_prebuilt_library_shared", "ndk_libfoo_shared", AttrNameToString{
+				"shared_library": `select({
+        "//build/bazel/platforms/os_arch:android_arm": "current/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libfoo_shared.so",
+        "//build/bazel/platforms/os_arch:android_arm64": "current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libfoo_shared.so",
+        "//build/bazel/platforms/os_arch:android_riscv64": "current/sources/cxx-stl/llvm-libc++/libs/riscv64/libfoo_shared.so",
+        "//build/bazel/platforms/os_arch:android_x86": "current/sources/cxx-stl/llvm-libc++/libs/x86/libfoo_shared.so",
+        "//build/bazel/platforms/os_arch:android_x86_64": "current/sources/cxx-stl/llvm-libc++/libs/x86_64/libfoo_shared.so",
+        "//conditions:default": None,
+    })`,
+				"export_system_includes": `[
+        "dir1",
+        "dir2",
+    ]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go
index 9639ab9..392a962 100644
--- a/bp2build/cc_test_conversion_test.go
+++ b/bp2build/cc_test_conversion_test.go
@@ -24,10 +24,11 @@
 )
 
 type ccTestBp2buildTestCase struct {
-	description string
-	blueprint   string
-	filesystem  map[string]string
-	targets     []testBazelTarget
+	description             string
+	blueprint               string
+	filesystem              map[string]string
+	targets                 []testBazelTarget
+	stubbedBuildDefinitions []string
 }
 
 func registerCcTestModuleTypes(ctx android.RegistrationContext) {
@@ -52,6 +53,7 @@
 			ModuleTypeUnderTestFactory: cc.TestFactory,
 			Description:                description,
 			Blueprint:                  testCase.blueprint,
+			StubbedBuildDefinitions:    testCase.stubbedBuildDefinitions,
 		})
 	})
 }
@@ -59,6 +61,8 @@
 func TestBasicCcTest(t *testing.T) {
 	runCcTestTestCase(t, ccTestBp2buildTestCase{
 		description: "basic cc_test with commonly used attributes",
+		stubbedBuildDefinitions: []string{"libbuildversion", "libprotobuf-cpp-lite", "libprotobuf-cpp-full",
+			"foolib", "hostlib", "data_mod", "cc_bin", "cc_lib", "cc_test_lib2", "libgtest_main", "libgtest"},
 		blueprint: `
 cc_test {
     name: "mytest",
@@ -89,14 +93,14 @@
     host_supported: true,
     include_build_directory: false,
 }
-` + simpleModuleDoNotConvertBp2build("cc_library", "foolib") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "hostlib") +
-			simpleModuleDoNotConvertBp2build("genrule", "data_mod") +
-			simpleModuleDoNotConvertBp2build("cc_binary", "cc_bin") +
-			simpleModuleDoNotConvertBp2build("cc_library", "cc_lib") +
-			simpleModuleDoNotConvertBp2build("cc_test_library", "cc_test_lib2") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
+` + simpleModule("cc_library", "foolib") +
+			simpleModule("cc_library_static", "hostlib") +
+			simpleModule("genrule", "data_mod") +
+			simpleModule("cc_binary", "cc_bin") +
+			simpleModule("cc_library", "cc_lib") +
+			simpleModule("cc_test_library", "cc_test_lib2") +
+			simpleModule("cc_library_static", "libgtest_main") +
+			simpleModule("cc_library_static", "libgtest"),
 		targets: []testBazelTarget{
 			{"cc_library_shared", "cc_test_lib1", AttrNameToString{}},
 			{"cc_library_static", "cc_test_lib1_bp2build_cc_library_static", AttrNameToString{}},
@@ -188,7 +192,8 @@
 
 func TestCcTest_TestOptions_Tags(t *testing.T) {
 	runCcTestTestCase(t, ccTestBp2buildTestCase{
-		description: "cc test with test_options.tags converted to tags",
+		description:             "cc test with test_options.tags converted to tags",
+		stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"},
 		blueprint: `
 cc_test {
     name: "mytest",
@@ -196,8 +201,8 @@
     srcs: ["test.cpp"],
     test_options: { tags: ["no-remote"] },
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
+` + simpleModule("cc_library_static", "libgtest_main") +
+			simpleModule("cc_library_static", "libgtest"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"tags":           `["no-remote"]`,
@@ -230,14 +235,15 @@
 		filesystem: map[string]string{
 			"test_config.xml": "",
 		},
+		stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"},
 		blueprint: `
 cc_test {
 	name: "mytest",
 	srcs: ["test.cpp"],
 	test_config: "test_config.xml",
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
+` + simpleModule("cc_library_static", "libgtest_main") +
+			simpleModule("cc_library_static", "libgtest"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"local_includes":         `["."]`,
@@ -269,13 +275,14 @@
 			"AndroidTest.xml":   "",
 			"DynamicConfig.xml": "",
 		},
+		stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"},
 		blueprint: `
 cc_test {
 	name: "mytest",
 	srcs: ["test.cpp"],
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
+` + simpleModule("cc_library_static", "libgtest_main") +
+			simpleModule("cc_library_static", "libgtest"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"local_includes":         `["."]`,
@@ -307,6 +314,7 @@
 		filesystem: map[string]string{
 			"test_config_template.xml": "",
 		},
+		stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"},
 		blueprint: `
 cc_test {
 	name: "mytest",
@@ -315,8 +323,8 @@
 	auto_gen_config: true,
 	isolated: true,
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
-			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+` + simpleModule("cc_library_static", "libgtest_isolated_main") +
+			simpleModule("cc_library", "liblog"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"auto_generate_test_config": "True",
@@ -347,15 +355,16 @@
 
 func TestCcTest_WithExplicitGTestDepInAndroidBp(t *testing.T) {
 	runCcTestTestCase(t, ccTestBp2buildTestCase{
-		description: "cc test that lists libgtest in Android.bp should not have dups of libgtest in BUILD file",
+		description:             "cc test that lists libgtest in Android.bp should not have dups of libgtest in BUILD file",
+		stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"},
 		blueprint: `
 cc_test {
 	name: "mytest",
 	srcs: ["test.cpp"],
 	static_libs: ["libgtest"],
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
+` + simpleModule("cc_library_static", "libgtest_main") +
+			simpleModule("cc_library_static", "libgtest"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"local_includes":         `["."]`,
@@ -382,15 +391,16 @@
 
 func TestCcTest_WithIsolatedTurnedOn(t *testing.T) {
 	runCcTestTestCase(t, ccTestBp2buildTestCase{
-		description: "cc test that sets `isolated: true` should run with ligtest_isolated_main instead of libgtest_main",
+		description:             "cc test that sets `isolated: true` should run with ligtest_isolated_main instead of libgtest_main",
+		stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"},
 		blueprint: `
 cc_test {
 	name: "mytest",
 	srcs: ["test.cpp"],
 	isolated: true,
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
-			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+` + simpleModule("cc_library_static", "libgtest_isolated_main") +
+			simpleModule("cc_library", "liblog"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"local_includes":         `["."]`,
@@ -415,7 +425,8 @@
 
 func TestCcTest_GtestExplicitlySpecifiedInAndroidBp(t *testing.T) {
 	runCcTestTestCase(t, ccTestBp2buildTestCase{
-		description: "If `gtest` is explicit in Android.bp, it should be explicit in BUILD files as well",
+		description:             "If `gtest` is explicit in Android.bp, it should be explicit in BUILD files as well",
+		stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"},
 		blueprint: `
 cc_test {
 	name: "mytest_with_gtest",
@@ -425,8 +436,8 @@
 	name: "mytest_with_no_gtest",
 	gtest: false,
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
-			simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
+` + simpleModule("cc_library_static", "libgtest_main") +
+			simpleModule("cc_library_static", "libgtest"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest_with_gtest", AttrNameToString{
 				"local_includes": `["."]`,
@@ -466,7 +477,8 @@
 
 func TestCcTest_DisableMemtagHeap(t *testing.T) {
 	runCcTestTestCase(t, ccTestBp2buildTestCase{
-		description: "cc test that disable memtag_heap",
+		description:             "cc test that disable memtag_heap",
+		stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"},
 		blueprint: `
 cc_test {
 	name: "mytest",
@@ -477,8 +489,8 @@
 		memtag_heap: false,
 	},
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
-			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+` + simpleModule("cc_library_static", "libgtest_isolated_main") +
+			simpleModule("cc_library", "liblog"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"local_includes":         `["."]`,
@@ -499,7 +511,8 @@
 
 func TestCcTest_RespectArm64MemtagHeap(t *testing.T) {
 	runCcTestTestCase(t, ccTestBp2buildTestCase{
-		description: "cc test that disable memtag_heap",
+		description:             "cc test that disable memtag_heap",
+		stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"},
 		blueprint: `
 cc_test {
 	name: "mytest",
@@ -513,8 +526,8 @@
 		}
 	},
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
-			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+` + simpleModule("cc_library_static", "libgtest_isolated_main") +
+			simpleModule("cc_library", "liblog"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"local_includes":         `["."]`,
@@ -535,7 +548,8 @@
 
 func TestCcTest_IgnoreNoneArm64MemtagHeap(t *testing.T) {
 	runCcTestTestCase(t, ccTestBp2buildTestCase{
-		description: "cc test that disable memtag_heap",
+		description:             "cc test that disable memtag_heap",
+		stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"},
 		blueprint: `
 cc_test {
 	name: "mytest",
@@ -549,8 +563,8 @@
 		}
 	},
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
-			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+` + simpleModule("cc_library_static", "libgtest_isolated_main") +
+			simpleModule("cc_library", "liblog"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"local_includes":         `["."]`,
@@ -574,7 +588,8 @@
 
 func TestCcTest_Arm64MemtagHeapOverrideNoConfigOne(t *testing.T) {
 	runCcTestTestCase(t, ccTestBp2buildTestCase{
-		description: "cc test that disable memtag_heap",
+		description:             "cc test that disable memtag_heap",
+		stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"},
 		blueprint: `
 cc_test {
 	name: "mytest",
@@ -594,8 +609,8 @@
 		}
 	},
 }
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
-			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+` + simpleModule("cc_library_static", "libgtest_isolated_main") +
+			simpleModule("cc_library", "liblog"),
 		targets: []testBazelTarget{
 			{"cc_test", "mytest", AttrNameToString{
 				"local_includes":         `["."]`,
@@ -616,3 +631,23 @@
 		},
 	})
 }
+
+func TestCcTest_UnitTestFalse(t *testing.T) {
+	runCcTestTestCase(t, ccTestBp2buildTestCase{
+		description: "cc test with test_options.tags converted to tags",
+		blueprint: `
+cc_test {
+    name: "mytest",
+    host_supported: true,
+    srcs: ["test.cpp"],
+    test_options: { unit_test: false },
+}
+` + simpleModule("cc_library_static", "libgtest_main") +
+			simpleModule("cc_library_static", "libgtest"),
+		stubbedBuildDefinitions: []string{
+			"libgtest_main",
+			"libgtest",
+		},
+		targets: []testBazelTarget{},
+	})
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 35a1400..c697235 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -15,6 +15,7 @@
 	rust_config "android/soong/rust/config"
 	"android/soong/starlark_fmt"
 
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -24,16 +25,28 @@
 	Contents string
 }
 
-// PRIVATE: Use CreateSoongInjectionDirFiles instead
-func soongInjectionFiles(cfg android.Config, metrics CodegenMetrics) ([]BazelFile, error) {
+// createSoongInjectionDirFiles returns most of the files to write to the soong_injection directory.
+// Some other files also come from CreateProductConfigFiles
+func createSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, error) {
+	cfg := ctx.Config()
 	var files []BazelFile
 
 	files = append(files, newFile("android", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
 	files = append(files, newFile("android", "constants.bzl", android.BazelCcToolchainVars(cfg)))
 
+	// 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"`
+		}
+	})
+
 	files = append(files, newFile("cc_toolchain", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
 	files = append(files, newFile("cc_toolchain", "config_constants.bzl", cc_config.BazelCcToolchainVars(cfg)))
 	files = append(files, newFile("cc_toolchain", "sanitizer_constants.bzl", cc.BazelCcSanitizerToolchainVars(cfg)))
+	files = append(files, newFile("cc_toolchain", "ndk_libs.bzl", fmt.Sprintf("ndk_libs = [%v]", strings.Join(ndkLibsStringFormatted, ", "))))
 
 	files = append(files, newFile("java_toolchain", GeneratedBuildFileName, "")) // Creates a //java_toolchain package.
 	files = append(files, newFile("java_toolchain", "constants.bzl", java_config.BazelJavaToolchainVars(cfg)))
@@ -145,7 +158,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/conversion_test.go b/bp2build/conversion_test.go
index 89dd38e..6b10077 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -83,7 +83,8 @@
 
 func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) {
 	testConfig := android.TestConfig("", make(map[string]string), "", make(map[string][]byte))
-	files, err := soongInjectionFiles(testConfig, CreateCodegenMetrics())
+	codegenCtx := NewCodegenContext(testConfig, android.NewTestContext(testConfig).Context, Bp2Build, "")
+	files, err := createSoongInjectionDirFiles(codegenCtx, CreateCodegenMetrics())
 	if err != nil {
 		t.Error(err)
 	}
@@ -106,6 +107,10 @@
 		},
 		{
 			dir:      "cc_toolchain",
+			basename: "ndk_libs.bzl",
+		},
+		{
+			dir:      "cc_toolchain",
 			basename: "sanitizer_constants.bzl",
 		},
 		{
@@ -182,15 +187,45 @@
 		},
 	}
 
-	if len(files) != len(expectedFilePaths) {
-		t.Errorf("Expected %d file, got %d", len(expectedFilePaths), len(files))
+	less := func(a bazelFilepath, b bazelFilepath) bool {
+		return a.dir+"/"+a.basename < b.dir+"/"+b.basename
 	}
 
-	for i := range files {
-		actualFile, expectedFile := files[i], expectedFilePaths[i]
+	fileToFilepath := func(a BazelFile) bazelFilepath {
+		return bazelFilepath{basename: a.Basename, dir: a.Dir}
+	}
 
-		if actualFile.Dir != expectedFile.dir || actualFile.Basename != expectedFile.basename {
-			t.Errorf("Did not find expected file %s/%s", actualFile.Dir, actualFile.Basename)
+	sort.Slice(expectedFilePaths, func(i, j int) bool {
+		return less(expectedFilePaths[i], expectedFilePaths[j])
+	})
+	sort.Slice(files, func(i, j int) bool {
+		return less(fileToFilepath(files[i]), fileToFilepath(files[j]))
+	})
+
+	i := 0
+	j := 0
+	for i < len(expectedFilePaths) && j < len(files) {
+		expectedFile, actualFile := expectedFilePaths[i], files[j]
+
+		if actualFile.Dir == expectedFile.dir && actualFile.Basename == expectedFile.basename {
+			i++
+			j++
+		} else if less(expectedFile, fileToFilepath(actualFile)) {
+			t.Errorf("Did not find expected file %s/%s", expectedFile.dir, expectedFile.basename)
+			i++
+		} else {
+			t.Errorf("Found unexpected file %s/%s", actualFile.Dir, actualFile.Basename)
+			j++
 		}
 	}
+	for i < len(expectedFilePaths) {
+		expectedFile := expectedFilePaths[i]
+		t.Errorf("Did not find expected file %s/%s", expectedFile.dir, expectedFile.basename)
+		i++
+	}
+	for j < len(files) {
+		actualFile := files[j]
+		t.Errorf("Found unexpected file %s/%s", actualFile.Dir, actualFile.Basename)
+		j++
+	}
 }
diff --git a/bp2build/droiddoc_exported_dir_conversion_test.go b/bp2build/droiddoc_exported_dir_conversion_test.go
new file mode 100644
index 0000000..dee67f4
--- /dev/null
+++ b/bp2build/droiddoc_exported_dir_conversion_test.go
@@ -0,0 +1,60 @@
+// 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 (
+	"regexp"
+	"testing"
+
+	"android/soong/java"
+)
+
+func TestDroiddocExportedDir(t *testing.T) {
+	bp := `
+	droiddoc_exported_dir {
+		name: "test-module",
+		path: "docs",
+	}
+	`
+	p := regexp.MustCompile(`\t*\|`)
+	dedent := func(s string) string {
+		return p.ReplaceAllString(s, "")
+	}
+	expectedBazelTargets := []string{
+		MakeBazelTargetNoRestrictions(
+			"droiddoc_exported_dir",
+			"test-module",
+			AttrNameToString{
+				"dir": `"docs"`,
+				"srcs": dedent(`[
+				|        "docs/android/1.txt",
+				|        "docs/android/nested-1/2.txt",
+				|        "//docs/android/nested-2:3.txt",
+				|        "//docs/android/nested-2:Android.bp",
+				|    ]`),
+			}),
+		//note we are not excluding Android.bp files from subpackages for now
+	}
+	RunBp2BuildTestCase(t, java.RegisterDocsBuildComponents, Bp2buildTestCase{
+		Blueprint:            bp,
+		ExpectedBazelTargets: expectedBazelTargets,
+		Filesystem: map[string]string{
+			"docs/android/1.txt":               "",
+			"docs/android/nested-1/2.txt":      "",
+			"docs/android/nested-2/Android.bp": "",
+			"docs/android/nested-2/3.txt":      "",
+		},
+	})
+}
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/fdo_profile_conversion_test.go b/bp2build/fdo_profile_conversion_test.go
new file mode 100644
index 0000000..4d04283
--- /dev/null
+++ b/bp2build/fdo_profile_conversion_test.go
@@ -0,0 +1,85 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+	"testing"
+
+	"android/soong/android"
+	"android/soong/cc"
+)
+
+func runFdoProfileTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	(&tc).ModuleTypeUnderTest = "fdo_profile"
+	(&tc).ModuleTypeUnderTestFactory = cc.FdoProfileFactory
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+}
+
+func TestFdoProfile(t *testing.T) {
+	testcases := []struct {
+		name               string
+		bp                 string
+		expectedBazelAttrs AttrNameToString
+	}{
+		{
+			name: "fdo_profile with arch-specific profiles",
+			bp: `
+fdo_profile {
+	name: "foo",
+	arch: {
+		arm: {
+			profile: "foo_arm.afdo",
+		},
+		arm64: {
+			profile: "foo_arm64.afdo",
+		}
+	}
+}`,
+			expectedBazelAttrs: AttrNameToString{
+				"profile": `select({
+        "//build/bazel/platforms/arch:arm": "foo_arm.afdo",
+        "//build/bazel/platforms/arch:arm64": "foo_arm64.afdo",
+        "//conditions:default": None,
+    })`,
+			},
+		},
+		{
+			name: "fdo_profile with arch-agnostic profile",
+			bp: `
+fdo_profile {
+	name: "foo",
+	profile: "foo.afdo",
+}`,
+			expectedBazelAttrs: AttrNameToString{
+				"profile": `"foo.afdo"`,
+			},
+		},
+	}
+
+	for _, test := range testcases {
+		t.Run(test.name, func(t *testing.T) {
+			expectedBazelTargets := []string{
+				// TODO(b/276287371): Add device-only restriction back to fdo_profile targets
+				MakeBazelTargetNoRestrictions("fdo_profile", "foo", test.expectedBazelAttrs),
+			}
+			runFdoProfileTestCase(t, Bp2buildTestCase{
+				Description:          test.name,
+				Blueprint:            test.bp,
+				ExpectedBazelTargets: expectedBazelTargets,
+			})
+		})
+	}
+}
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index 2a10a14..7e9b17b 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -93,7 +93,6 @@
     out: ["foo_tool.out"],
     srcs: ["foo_tool.in"],
     cmd: "cp $(in) $(out)",
-    bazel_module: { bp2build_available: false },
 }
 
 %s {
@@ -124,6 +123,7 @@
 					ModuleTypeUnderTestFactory: tc.factory,
 					Blueprint:                  fmt.Sprintf(bp, tc.moduleType, tc.moduleType),
 					ExpectedBazelTargets:       expectedBazelTargets,
+					StubbedBuildDefinitions:    []string{"foo.tool", "other.tool"},
 				})
 		})
 	}
@@ -262,6 +262,7 @@
 					Blueprint:                  fmt.Sprintf(bp, tc.moduleType),
 					ExpectedBazelTargets:       expectedBazelTargets,
 					Filesystem:                 otherGenruleBp(tc.moduleType),
+					StubbedBuildDefinitions:    []string{"//other:foo.tool"},
 				})
 		})
 	}
@@ -326,6 +327,7 @@
 					Blueprint:                  fmt.Sprintf(bp, tc.moduleType),
 					ExpectedBazelTargets:       expectedBazelTargets,
 					Filesystem:                 otherGenruleBp(tc.moduleType),
+					StubbedBuildDefinitions:    []string{"//other:foo.tool", "//other:other.tool"},
 				})
 		})
 	}
@@ -390,6 +392,7 @@
 					Blueprint:                  fmt.Sprintf(bp, tc.moduleType),
 					ExpectedBazelTargets:       expectedBazelTargets,
 					Filesystem:                 otherGenruleBp(tc.moduleType),
+					StubbedBuildDefinitions:    []string{"//other:foo.tool", "//other:other.tool"},
 				})
 		})
 	}
@@ -454,6 +457,7 @@
 					Blueprint:                  fmt.Sprintf(bp, tc.moduleType),
 					ExpectedBazelTargets:       expectedBazelTargets,
 					Filesystem:                 otherGenruleBp(tc.moduleType),
+					StubbedBuildDefinitions:    []string{"//other:foo.tool", "//other:other.tool"},
 				})
 		})
 	}
@@ -948,6 +952,7 @@
 			ModuleTypeUnderTest:        "genrule",
 			ModuleTypeUnderTestFactory: genrule.GenRuleFactory,
 			ExpectedBazelTargets:       expectedBazelTargets,
+			StubbedBuildDefinitions:    []string{"//mynamespace/dir:mymodule"},
 		})
 	})
 
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
index 39e55c4..4271f76 100644
--- a/bp2build/java_binary_host_conversion_test.go
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -26,6 +26,7 @@
 	t.Helper()
 	(&tc).ModuleTypeUnderTest = "java_binary_host"
 	(&tc).ModuleTypeUnderTestFactory = java.BinaryHostFactory
+	tc.StubbedBuildDefinitions = append(tc.StubbedBuildDefinitions, "//other:jni-lib-1")
 	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
 		ctx.RegisterModuleType("cc_library_host_shared", cc.LibraryHostSharedFactory)
 		ctx.RegisterModuleType("java_library", java.LibraryFactory)
@@ -81,8 +82,9 @@
 
 func TestJavaBinaryHostRuntimeDeps(t *testing.T) {
 	runJavaBinaryHostTestCase(t, Bp2buildTestCase{
-		Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
-		Filesystem:  testFs,
+		Description:             "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
+		Filesystem:              testFs,
+		StubbedBuildDefinitions: []string{"java-dep-1"},
 		Blueprint: `java_binary_host {
     name: "java-binary-host-1",
     static_libs: ["java-dep-1"],
@@ -93,7 +95,6 @@
 java_library {
     name: "java-dep-1",
     srcs: ["a.java"],
-    bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -111,8 +112,9 @@
 
 func TestJavaBinaryHostLibs(t *testing.T) {
 	runJavaBinaryHostTestCase(t, Bp2buildTestCase{
-		Description: "java_binary_host with srcs, libs.",
-		Filesystem:  testFs,
+		Description:             "java_binary_host with srcs, libs.",
+		Filesystem:              testFs,
+		StubbedBuildDefinitions: []string{"java-lib-dep-1", "java-lib-dep-1-neverlink"},
 		Blueprint: `java_binary_host {
     name: "java-binary-host-libs",
     libs: ["java-lib-dep-1"],
@@ -123,7 +125,6 @@
 java_import_host{
     name: "java-lib-dep-1",
     jars: ["foo.jar"],
-    bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 7429ae6..7e4e44e 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -15,7 +15,6 @@
 package bp2build
 
 import (
-	"fmt"
 	"testing"
 
 	"android/soong/android"
@@ -70,6 +69,7 @@
 
 func TestJavaLibraryConvertsStaticLibsToDepsAndExports(t *testing.T) {
 	runJavaLibraryTestCase(t, Bp2buildTestCase{
+		StubbedBuildDefinitions: []string{"java-lib-2", "java-lib-3"},
 		Blueprint: `java_library {
     name: "java-lib-1",
     srcs: ["a.java"],
@@ -83,14 +83,12 @@
     name: "java-lib-2",
     srcs: ["b.java"],
     sdk_version: "current",
-    bazel_module: { bp2build_available: false },
 }
 
 java_library {
     name: "java-lib-3",
     srcs: ["c.java"],
     sdk_version: "current",
-    bazel_module: { bp2build_available: false },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
@@ -109,6 +107,7 @@
 
 func TestJavaLibraryConvertsStaticLibsToExportsIfNoSrcs(t *testing.T) {
 	runJavaLibraryTestCase(t, Bp2buildTestCase{
+		StubbedBuildDefinitions: []string{"java-lib-2"},
 		Blueprint: `java_library {
     name: "java-lib-1",
     static_libs: ["java-lib-2"],
@@ -119,7 +118,6 @@
 java_library {
     name: "java-lib-2",
     srcs: ["a.java"],
-    bazel_module: { bp2build_available: false },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
@@ -143,28 +141,9 @@
 	})
 }
 
-func TestJavaLibraryFailsToConvertLibsWithNoSrcs(t *testing.T) {
-	runJavaLibraryTestCase(t, Bp2buildTestCase{
-		ExpectedErr: fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."),
-		Blueprint: `java_library {
-    name: "java-lib-1",
-    libs: ["java-lib-2"],
-    sdk_version: "current",
-    bazel_module: { bp2build_available: true },
-}
-
-java_library {
-    name: "java-lib-2",
-    srcs: ["a.java"],
-    sdk_version: "current",
-    bazel_module: { bp2build_available: false },
-}`,
-		ExpectedBazelTargets: []string{},
-	})
-}
-
 func TestJavaLibraryPlugins(t *testing.T) {
 	runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
+		StubbedBuildDefinitions: []string{"java-plugin-1"},
 		Blueprint: `java_library {
     name: "java-lib-1",
     plugins: ["java-plugin-1"],
@@ -175,7 +154,6 @@
 java_plugin {
     name: "java-plugin-1",
     srcs: ["a.java"],
-    bazel_module: { bp2build_available: false },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
@@ -216,6 +194,7 @@
 
 func TestJavaLibraryErrorproneEnabledManually(t *testing.T) {
 	runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
+		StubbedBuildDefinitions: []string{"plugin2"},
 		Blueprint: `java_library {
     name: "java-lib-1",
     srcs: ["a.java"],
@@ -230,7 +209,6 @@
 java_plugin {
     name: "plugin2",
     srcs: ["a.java"],
-    bazel_module: { bp2build_available: false },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
@@ -639,6 +617,7 @@
 		Description:                "java_library with non adjacent aidl filegroup",
 		ModuleTypeUnderTest:        "java_library",
 		ModuleTypeUnderTestFactory: java.LibraryFactory,
+		StubbedBuildDefinitions:    []string{"A_aidl"},
 		Filesystem: map[string]string{
 			"path/to/A/Android.bp": `
 filegroup {
@@ -676,7 +655,7 @@
 		Description:                "Android Library - simple arch feature",
 		ModuleTypeUnderTest:        "android_library",
 		ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
-		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
+		Blueprint: simpleModule("android_library", "static_lib_dep") + `
 android_library {
   name: "TestLib",
   manifest: "manifest/AndroidManifest.xml",
@@ -714,7 +693,7 @@
 		Description:                "Android Library - multiple arch features",
 		ModuleTypeUnderTest:        "android_library",
 		ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
-		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
+		Blueprint: simpleModule("android_library", "static_lib_dep") + `
 android_library {
   name: "TestLib",
   manifest: "manifest/AndroidManifest.xml",
@@ -760,7 +739,7 @@
 		Description:                "Android Library - exclude_srcs with arch feature",
 		ModuleTypeUnderTest:        "android_library",
 		ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
-		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
+		Blueprint: simpleModule("android_library", "static_lib_dep") + `
 android_library {
   name: "TestLib",
   manifest: "manifest/AndroidManifest.xml",
@@ -870,7 +849,8 @@
 
 func TestJavaLibraryArchVariantDeps(t *testing.T) {
 	runJavaLibraryTestCase(t, Bp2buildTestCase{
-		Description: "java_library with arch variant libs",
+		Description:             "java_library with arch variant libs",
+		StubbedBuildDefinitions: []string{"java-lib-2", "java-lib-3", "java-lib-4"},
 		Blueprint: `java_library {
     name: "java-lib-1",
     srcs: ["a.java"],
@@ -887,17 +867,14 @@
 
   java_library{
     name: "java-lib-2",
-    bazel_module: { bp2build_available: false },
 }
 
   java_library{
     name: "java-lib-3",
-    bazel_module: { bp2build_available: false },
 }
 
   java_library{
     name: "java-lib-4",
-    bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
diff --git a/bp2build/java_plugin_conversion_test.go b/bp2build/java_plugin_conversion_test.go
index f2b6f20..dcc17b5 100644
--- a/bp2build/java_plugin_conversion_test.go
+++ b/bp2build/java_plugin_conversion_test.go
@@ -32,7 +32,8 @@
 
 func TestJavaPlugin(t *testing.T) {
 	runJavaPluginTestCase(t, Bp2buildTestCase{
-		Description: "java_plugin with srcs, libs, static_libs",
+		Description:             "java_plugin with srcs, libs, static_libs",
+		StubbedBuildDefinitions: []string{"java-lib-1", "java-lib-2"},
 		Blueprint: `java_plugin {
     name: "java-plug-1",
     srcs: ["a.java", "b.java"],
@@ -45,13 +46,11 @@
 java_library {
     name: "java-lib-1",
     srcs: ["b.java"],
-    bazel_module: { bp2build_available: false },
 }
 
 java_library {
     name: "java-lib-2",
     srcs: ["c.java"],
-    bazel_module: { bp2build_available: false },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{
@@ -75,7 +74,8 @@
 
 func TestJavaPluginNoSrcs(t *testing.T) {
 	runJavaPluginTestCase(t, Bp2buildTestCase{
-		Description: "java_plugin without srcs converts (static) libs to deps",
+		Description:             "java_plugin without srcs converts (static) libs to deps",
+		StubbedBuildDefinitions: []string{"java-lib-1", "java-lib-2"},
 		Blueprint: `java_plugin {
     name: "java-plug-1",
     libs: ["java-lib-1"],
@@ -86,13 +86,11 @@
 java_library {
     name: "java-lib-1",
     srcs: ["b.java"],
-    bazel_module: { bp2build_available: false },
 }
 
 java_library {
     name: "java-lib-2",
     srcs: ["c.java"],
-    bazel_module: { bp2build_available: false },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{
diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go
index 5d6b088..4e96efe 100644
--- a/bp2build/java_proto_conversion_test.go
+++ b/bp2build/java_proto_conversion_test.go
@@ -137,3 +137,59 @@
 		},
 	})
 }
+
+func TestJavaLibsAndOnlyProtoSrcs(t *testing.T) {
+	runJavaProtoTestCase(t, Bp2buildTestCase{
+		Description:             "java_library that has only proto srcs",
+		StubbedBuildDefinitions: []string{"java-lib-1", "java-lib-2"},
+		Blueprint: `java_library_static {
+    name: "java-protos",
+    srcs: ["a.proto"],
+    libs: ["java-lib-1"],
+    static_libs: ["java-lib-2"],
+    java_version: "7",
+    sdk_version: "current",
+}
+
+java_library_static {
+    name: "java-lib-1",
+}
+
+java_library_static {
+    name: "java-lib-2",
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("proto_library", "java-protos_proto", AttrNameToString{
+				"srcs": `["a.proto"]`,
+			}),
+			MakeBazelTarget(
+				"java_lite_proto_library",
+				"java-protos_java_proto_lite",
+				AttrNameToString{
+					"deps": `[":java-protos_proto"]`,
+					"additional_proto_deps": `[
+        ":java-lib-1-neverlink",
+        ":java-lib-2",
+    ]`,
+					"java_version": `"7"`,
+					"sdk_version":  `"current"`,
+				}),
+			MakeBazelTarget("java_library", "java-protos", AttrNameToString{
+				"exports": `[
+        ":java-lib-2",
+        ":java-protos_java_proto_lite",
+    ]`,
+				"java_version": `"7"`,
+				"sdk_version":  `"current"`,
+			}),
+			MakeNeverlinkDuplicateTargetWithAttrs(
+				"java_library",
+				"java-protos",
+				AttrNameToString{
+					"java_version": `"7"`,
+					"sdk_version":  `"current"`,
+				}),
+		},
+	})
+}
diff --git a/bp2build/java_sdk_library_import_conversion_test.go b/bp2build/java_sdk_library_import_conversion_test.go
new file mode 100644
index 0000000..456f872
--- /dev/null
+++ b/bp2build/java_sdk_library_import_conversion_test.go
@@ -0,0 +1,84 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+	"testing"
+
+	"android/soong/java"
+)
+
+func runJavaSdkLibraryImportTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	RunBp2BuildTestCase(t, java.RegisterSdkLibraryBuildComponents, tc)
+}
+
+func TestJavaSdkLibraryImport(t *testing.T) {
+	runJavaSdkLibraryImportTestCase(t, Bp2buildTestCase{
+		Blueprint: `
+java_sdk_library_import {
+	name : "foo",
+	public: {
+		current_api: "foo_current.txt",
+	},
+	system: {
+		current_api: "system_foo_current.txt",
+	},
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_sdk_library", "foo", AttrNameToString{
+				"public": `"foo_current.txt"`,
+				"system": `"system_foo_current.txt"`,
+			}),
+		},
+	})
+}
+
+func TestJavaSdkLibraryImportPrebuiltPrefixRemoved(t *testing.T) {
+	runJavaSdkLibraryImportTestCase(t, Bp2buildTestCase{
+		Filesystem: map[string]string{
+			"foobar/Android.bp": `
+java_sdk_library {
+	name: "foo",
+	srcs: ["**/*.java"],
+}
+`,
+			"foobar/api/current.txt":        "",
+			"foobar/api/system-current.txt": "",
+			"foobar/api/test-current.txt":   "",
+			"foobar/api/removed.txt":        "",
+			"foobar/api/system-removed.txt": "",
+			"foobar/api/test-removed.txt":   "",
+		},
+		Blueprint: `
+java_sdk_library_import {
+	name : "foo",
+	public: {
+		current_api: "foo_current.txt",
+	},
+	system: {
+		current_api: "system_foo_current.txt",
+	},
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_sdk_library", "foo", AttrNameToString{
+				"public": `"foo_current.txt"`,
+				"system": `"system_foo_current.txt"`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/java_test_host_conversion_test.go b/bp2build/java_test_host_conversion_test.go
index f41345e..95c239d 100644
--- a/bp2build/java_test_host_conversion_test.go
+++ b/bp2build/java_test_host_conversion_test.go
@@ -32,8 +32,9 @@
 
 func TestJavaTestHostGeneral(t *testing.T) {
 	runJavaTestHostTestCase(t, Bp2buildTestCase{
-		Description: "java_test_host general",
-		Filesystem:  map[string]string{},
+		Description:             "java_test_host general",
+		Filesystem:              map[string]string{},
+		StubbedBuildDefinitions: []string{"lib_a", "lib_b"},
 		Blueprint: `
 java_test_host {
     name: "java_test_host-1",
@@ -47,12 +48,10 @@
 
 java_library {
     name: "lib_a",
-    bazel_module: { bp2build_available: false },
 }
 
 java_library {
     name: "static_libs_a",
-    bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
diff --git a/bp2build/platform_compat_config_conversion_test.go b/bp2build/platform_compat_config_conversion_test.go
index 4dfcce3..d74db5d 100644
--- a/bp2build/platform_compat_config_conversion_test.go
+++ b/bp2build/platform_compat_config_conversion_test.go
@@ -37,6 +37,7 @@
 			name: "foo",
 			src: ":lib",
 		}`,
+		StubbedBuildDefinitions: []string{"//a/b:lib"},
 		Filesystem: map[string]string{
 			"a/b/Android.bp": `
 			java_library {
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/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index 1b538d0..b69c4ea 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -30,6 +30,7 @@
 			"b/e.py":         "",
 			"files/data.txt": "",
 		},
+		StubbedBuildDefinitions: []string{"bar"},
 		Blueprint: `python_binary_host {
     name: "foo",
     main: "a.py",
@@ -42,7 +43,6 @@
     python_library_host {
       name: "bar",
       srcs: ["b/e.py"],
-      bazel_module: { bp2build_available: false },
     }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("py_binary", "foo", AttrNameToString{
@@ -196,6 +196,7 @@
 		Description:                "python_binary_host main label in same package",
 		ModuleTypeUnderTest:        "python_binary_host",
 		ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+		StubbedBuildDefinitions:    []string{"a"},
 		Blueprint: `python_binary_host {
     name: "foo",
     main: ":a",
@@ -204,7 +205,6 @@
 
 genrule {
 		name: "a",
-		bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -282,6 +282,7 @@
 		Description:                "python_binary_host duplicates in required attribute of the module and its defaults",
 		ModuleTypeUnderTest:        "python_binary_host",
 		ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+		StubbedBuildDefinitions:    []string{"r1", "r2"},
 		Blueprint: `python_binary_host {
     name: "foo",
     main: "a.py",
@@ -298,8 +299,8 @@
         "r1",
         "r2",
     ],
-}` + simpleModuleDoNotConvertBp2build("genrule", "r1") +
-			simpleModuleDoNotConvertBp2build("genrule", "r2"),
+}` + simpleModule("genrule", "r1") +
+			simpleModule("genrule", "r2"),
 
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("py_binary", "foo", AttrNameToString{
diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go
index 595acd2..497df80 100644
--- a/bp2build/python_library_conversion_test.go
+++ b/bp2build/python_library_conversion_test.go
@@ -13,12 +13,13 @@
 type PythonLibBp2Build func(ctx android.TopDownMutatorContext)
 
 type pythonLibBp2BuildTestCase struct {
-	description          string
-	filesystem           map[string]string
-	blueprint            string
-	expectedBazelTargets []testBazelTarget
-	dir                  string
-	expectedError        error
+	description             string
+	filesystem              map[string]string
+	blueprint               string
+	expectedBazelTargets    []testBazelTarget
+	dir                     string
+	expectedError           error
+	stubbedBuildDefinitions []string
 }
 
 func convertPythonLibTestCaseToBp2build_Host(tc pythonLibBp2BuildTestCase) Bp2buildTestCase {
@@ -44,12 +45,13 @@
 		filesystemCopy[k] = v
 	}
 	return Bp2buildTestCase{
-		Description:          tc.description,
-		Filesystem:           filesystemCopy,
-		Blueprint:            tc.blueprint,
-		ExpectedBazelTargets: bp2BuildTargets,
-		Dir:                  tc.dir,
-		ExpectedErr:          tc.expectedError,
+		Description:             tc.description,
+		Filesystem:              filesystemCopy,
+		Blueprint:               tc.blueprint,
+		ExpectedBazelTargets:    bp2BuildTargets,
+		Dir:                     tc.dir,
+		ExpectedErr:             tc.expectedError,
+		StubbedBuildDefinitions: tc.stubbedBuildDefinitions,
 	}
 }
 
@@ -104,6 +106,7 @@
 				"b/e.py":         "",
 				"files/data.txt": "",
 			},
+			stubbedBuildDefinitions: []string{"bar"},
 			blueprint: `%s {
     name: "foo",
     srcs: ["**/*.py"],
@@ -115,7 +118,6 @@
     python_library {
       name: "bar",
       srcs: ["b/e.py"],
-      bazel_module: { bp2build_available: false },
     }`,
 			expectedBazelTargets: []testBazelTarget{
 				{
diff --git a/bp2build/python_test_conversion_test.go b/bp2build/python_test_conversion_test.go
index 4ff1fa1..fa2e485 100644
--- a/bp2build/python_test_conversion_test.go
+++ b/bp2build/python_test_conversion_test.go
@@ -15,8 +15,9 @@
 package bp2build
 
 import (
-	"android/soong/python"
 	"testing"
+
+	"android/soong/python"
 )
 
 func TestPythonTestHostSimple(t *testing.T) {
@@ -31,6 +32,7 @@
 			"b/e.py":         "",
 			"files/data.txt": "",
 		},
+		StubbedBuildDefinitions: []string{"bar"},
 		Blueprint: `python_test_host {
     name: "foo",
     main: "a.py",
@@ -43,7 +45,6 @@
     python_library_host {
       name: "bar",
       srcs: ["b/e.py"],
-      bazel_module: { bp2build_available: false },
     }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("py_test", "foo", AttrNameToString{
diff --git a/bp2build/rust_protobuf_conversion_test.go b/bp2build/rust_protobuf_conversion_test.go
index cf256aa..bd4f54b 100644
--- a/bp2build/rust_protobuf_conversion_test.go
+++ b/bp2build/rust_protobuf_conversion_test.go
@@ -27,7 +27,7 @@
 
 func registerRustProtobufModuleTypes(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("rust_protobuf_host", rust.RustProtobufHostFactory)
-
+	ctx.RegisterModuleType("rust_protobuf", rust.RustProtobufHostFactory)
 }
 
 func TestRustProtobufHostTestCase(t *testing.T) {
@@ -58,3 +58,32 @@
 	},
 	)
 }
+
+func TestRustProtobufTestCase(t *testing.T) {
+	runRustProtobufTestCase(t, Bp2buildTestCase{
+		Dir:       "external/rust/crates/foo",
+		Blueprint: "",
+		Filesystem: map[string]string{
+			"external/rust/crates/foo/src/lib.rs":    "",
+			"external/rust/crates/foo/src/helper.rs": "",
+			"external/rust/crates/foo/Android.bp": `
+rust_protobuf {
+	name: "libfoo",
+	crate_name: "foo",
+	protos: ["src/foo.proto"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+		},
+		ExpectedBazelTargets: []string{
+			makeBazelTargetHostOrDevice("proto_library", "libfoo_proto", AttrNameToString{
+				"srcs": `["src/foo.proto"]`,
+			}, android.HostSupported),
+			makeBazelTargetHostOrDevice("rust_proto_library", "libfoo", AttrNameToString{
+				"crate_name": `"foo"`,
+				"deps":       `[":libfoo_proto"]`,
+			}, android.HostSupported),
+		},
+	},
+	)
+}
diff --git a/bp2build/soong_config_module_type_conversion_test.go b/bp2build/soong_config_module_type_conversion_test.go
index 8302ce8..5ec6bab 100644
--- a/bp2build/soong_config_module_type_conversion_test.go
+++ b/bp2build/soong_config_module_type_conversion_test.go
@@ -15,10 +15,11 @@
 package bp2build
 
 import (
-	"android/soong/android"
-	"android/soong/cc"
 	"fmt"
 	"testing"
+
+	"android/soong/android"
+	"android/soong/cc"
 )
 
 func runSoongConfigModuleTypeTest(t *testing.T, tc Bp2buildTestCase) {
@@ -364,9 +365,9 @@
 }`
 
 	otherDeps := `
-cc_library_static { name: "soc_a_dep", bazel_module: { bp2build_available: false } }
-cc_library_static { name: "soc_b_dep", bazel_module: { bp2build_available: false } }
-cc_library_static { name: "soc_default_static_dep", bazel_module: { bp2build_available: false } }
+cc_library_static { name: "soc_a_dep"}
+cc_library_static { name: "soc_b_dep"}
+cc_library_static { name: "soc_default_static_dep"}
 `
 
 	runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
@@ -377,6 +378,7 @@
 		Filesystem: map[string]string{
 			"foo/bar/Android.bp": otherDeps,
 		},
+		StubbedBuildDefinitions: []string{"//foo/bar:soc_a_dep", "//foo/bar:soc_b_dep", "//foo/bar:soc_default_static_dep"},
 		ExpectedBazelTargets: []string{`cc_library_static(
     name = "foo",
     copts = select({
@@ -763,9 +765,9 @@
 }`
 
 	otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_default", bazel_module: { bp2build_available: false } }
+cc_library { name: "lib_a"}
+cc_library { name: "lib_b"}
+cc_library { name: "lib_default"}
 `
 
 	runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
@@ -773,6 +775,7 @@
 		ModuleTypeUnderTest:        "cc_binary",
 		ModuleTypeUnderTestFactory: cc.BinaryFactory,
 		Blueprint:                  bp,
+		StubbedBuildDefinitions:    []string{"//foo/bar:lib_a", "//foo/bar:lib_b", "//foo/bar:lib_default"},
 		Filesystem: map[string]string{
 			"foo/bar/Android.bp": otherDeps,
 		},
@@ -852,15 +855,16 @@
 }`
 
 	otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_c", bazel_module: { bp2build_available: false } }
+cc_library { name: "lib_a"}
+cc_library { name: "lib_b"}
+cc_library { name: "lib_c"}
 `
 
 	runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
 		Description:                "soong config variables - generates selects for library_linking_strategy",
 		ModuleTypeUnderTest:        "cc_binary",
 		ModuleTypeUnderTestFactory: cc.BinaryFactory,
+		StubbedBuildDefinitions:    []string{"//foo/bar:lib_a", "//foo/bar:lib_b", "//foo/bar:lib_c"},
 		Blueprint:                  bp,
 		Filesystem: map[string]string{
 			"foo/bar/Android.bp": otherDeps,
@@ -949,9 +953,9 @@
 }`
 
 	otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_default", bazel_module: { bp2build_available: false } }
+cc_library { name: "lib_a"}
+cc_library { name: "lib_b"}
+cc_library { name: "lib_default"}
 `
 
 	runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
@@ -962,6 +966,7 @@
 		Filesystem: map[string]string{
 			"foo/bar/Android.bp": otherDeps,
 		},
+		StubbedBuildDefinitions: []string{"//foo/bar:lib_a", "//foo/bar:lib_b", "//foo/bar:lib_default"},
 		ExpectedBazelTargets: []string{`cc_binary(
     name = "library_linking_strategy_sample_binary",
     deps = select({
@@ -1031,8 +1036,8 @@
 }`
 
 	otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
+cc_library { name: "lib_a"}
+cc_library { name: "lib_b"}
 `
 
 	runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
@@ -1040,6 +1045,7 @@
 		ModuleTypeUnderTest:        "cc_binary",
 		ModuleTypeUnderTestFactory: cc.BinaryFactory,
 		Blueprint:                  bp,
+		StubbedBuildDefinitions:    []string{"//foo/bar:lib_a", "//foo/bar:lib_b"},
 		Filesystem: map[string]string{
 			"foo/bar/Android.bp": otherDeps,
 		},
@@ -1118,9 +1124,9 @@
 }`
 
 	otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_default", bazel_module: { bp2build_available: false } }
+cc_library { name: "lib_a"}
+cc_library { name: "lib_b"}
+cc_library { name: "lib_default"}
 `
 
 	runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
@@ -1131,6 +1137,7 @@
 		Filesystem: map[string]string{
 			"foo/bar/Android.bp": otherDeps,
 		},
+		StubbedBuildDefinitions: []string{"//foo/bar:lib_a", "//foo/bar:lib_b", "//foo/bar:lib_default"},
 		ExpectedBazelTargets: []string{`cc_binary(
     name = "alphabet_binary",
     deps = select({
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index 5c33308..966b94a 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -43,7 +43,7 @@
 // clean the whole symlink forest and recreate it. This number can be bumped whenever there's
 // an incompatible change to the forest layout or a bug in incrementality that needs to be fixed
 // on machines that may still have the bug present in their forest.
-const symlinkForestVersion = 1
+const symlinkForestVersion = 2
 
 type instructionsNode struct {
 	name     string
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 42d955e..dfd4d57 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -21,6 +21,8 @@
 
 import (
 	"fmt"
+	"path/filepath"
+	"regexp"
 	"sort"
 	"strings"
 	"testing"
@@ -36,6 +38,9 @@
 	buildDir string
 )
 
+var labelRegex = regexp.MustCompile(`^//([^: ]+):([^ ]+)$`)
+var simpleModuleNameRegex = regexp.MustCompile(`^[^: /]+$`)
+
 func checkError(t *testing.T, errs []error, expectedErr error) bool {
 	t.Helper()
 
@@ -82,7 +87,19 @@
 	// ExpectedBazelTargets compares the BazelTargets generated in `Dir` (if not empty).
 	// Otherwise, it checks the BazelTargets generated by `Blueprint` in the root directory.
 	ExpectedBazelTargets []string
-	Filesystem           map[string]string
+	// AlreadyExistingBuildContents, if non-empty, simulates an already-present source BUILD file
+	// in the directory under test. The BUILD file has the given contents. This BUILD file
+	// will also be treated as "BUILD file to keep" by the simulated bp2build environment.
+	AlreadyExistingBuildContents string
+
+	// StubbedBuildDefinitions, if non-empty, adds stub definitions to already-present source
+	// BUILD files for each bazel label given. The BUILD files with these stub definitions
+	// are added to the BUILD file given in AlreadyExistingBuildContents.
+	// Labels may be of the form //pkg/to:target_name (which would be defined in pkg/to/BUILD.bazel)
+	// or `target_name` (which would be defined in ./BUILD.bazel).
+	StubbedBuildDefinitions []string
+
+	Filesystem map[string]string
 	// Dir sets the directory which will be compared against the targets in ExpectedBazelTargets.
 	// This should used in conjunction with the Filesystem property to check for targets
 	// generated from a directory that is not the root.
@@ -108,23 +125,53 @@
 	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 := "."
+	if tc.Filesystem == nil {
+		tc.Filesystem = map[string]string{}
+	}
+	checkDir := "."
+	if tc.Dir != "" {
+		checkDir = tc.Dir
+	}
+	keepExistingBuildDirs := tc.KeepBuildFileForDirs
+	buildFilesToParse := []string{}
+
+	if len(tc.StubbedBuildDefinitions) > 0 {
+		for _, buildDef := range tc.StubbedBuildDefinitions {
+			globalLabelMatch := labelRegex.FindStringSubmatch(buildDef)
+			var dir, targetName string
+			if len(globalLabelMatch) > 0 {
+				dir = globalLabelMatch[1]
+				targetName = globalLabelMatch[2]
+			} else {
+				if !simpleModuleNameRegex.MatchString(buildDef) {
+					t.Errorf("Stubbed build definition '%s' must be either a simple module name or of global target syntax (//foo/bar:baz).", buildDef)
+					return
+				}
+				dir = "."
+				targetName = buildDef
+			}
+			buildFilePath := filepath.Join(dir, "BUILD")
+			tc.Filesystem[buildFilePath] +=
+				MakeBazelTarget(
+					"bp2build_test_stub",
+					targetName,
+					AttrNameToString{})
+			keepExistingBuildDirs = append(keepExistingBuildDirs, dir)
+			buildFilesToParse = append(buildFilesToParse, buildFilePath)
+		}
+	}
+	if len(tc.AlreadyExistingBuildContents) > 0 {
+		buildFilePath := filepath.Join(checkDir, "BUILD")
+		tc.Filesystem[buildFilePath] += tc.AlreadyExistingBuildContents
+		keepExistingBuildDirs = append(keepExistingBuildDirs, checkDir)
+		buildFilesToParse = append(buildFilesToParse, buildFilePath)
+	}
 	filesystem := make(map[string][]byte)
 	for f, content := range tc.Filesystem {
 		filesystem[f] = []byte(content)
 	}
-
 	preparers := []android.FixturePreparer{
 		extraPreparer,
 		android.FixtureMergeMockFs(filesystem),
@@ -132,7 +179,7 @@
 		android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
 			ctx.RegisterModuleType(tc.ModuleTypeUnderTest, tc.ModuleTypeUnderTestFactory)
 		}),
-		android.FixtureModifyContext(func(ctx *android.TestContext) {
+		android.FixtureModifyContextWithMockFs(func(ctx *android.TestContext) {
 			// A default configuration for tests to not have to specify bp2build_available on top level
 			// targets.
 			bp2buildConfig := android.NewBp2BuildAllowlist().SetDefaultConfig(
@@ -140,7 +187,7 @@
 					android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
 				},
 			)
-			for _, f := range tc.KeepBuildFileForDirs {
+			for _, f := range keepExistingBuildDirs {
 				bp2buildConfig.SetKeepExistingBuildFile(map[string]bool{
 					f: /*recursive=*/ false,
 				})
@@ -150,6 +197,10 @@
 			// from cloning modules to their original state after mutators run. This
 			// would lose some data intentionally set by these mutators.
 			ctx.SkipCloneModulesAfterMutators = true
+			err := ctx.RegisterExistingBazelTargets(".", buildFilesToParse)
+			if err != nil {
+				t.Errorf("error parsing build files in test setup: %s", err)
+			}
 		}),
 		android.FixtureModifyEnv(func(env map[string]string) {
 			if tc.UnconvertedDepsMode == errorModulesUnconvertedDeps {
@@ -168,10 +219,6 @@
 		return
 	}
 
-	checkDir := dir
-	if tc.Dir != "" {
-		checkDir = tc.Dir
-	}
 	expectedTargets := map[string][]string{
 		checkDir: tc.ExpectedBazelTargets,
 	}
@@ -180,27 +227,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 +248,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
@@ -467,7 +497,7 @@
 	return m.props.Dir
 }
 
-func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (m *customModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	if p := m.props.One_to_many_prop; p != nil && *p {
 		customBp2buildOneToMany(ctx, m)
 		return
@@ -487,7 +517,10 @@
 			}
 		}
 	}
-	productVariableProps := android.ProductVariableProperties(ctx, ctx.Module())
+	productVariableProps, errs := android.ProductVariableProperties(ctx, ctx.Module())
+	for _, err := range errs {
+		ctx.ModuleErrorf("ProductVariableProperties error: %s", err)
+	}
 	if props, ok := productVariableProps["String_literal_prop"]; ok {
 		for c, p := range props {
 			if val, ok := p.(*string); ok {
@@ -522,7 +555,7 @@
 
 }
 
-func (m *customModule) createConfigSetting(ctx android.TopDownMutatorContext) {
+func (m *customModule) createConfigSetting(ctx android.Bp2buildMutatorContext) {
 	csa := bazel.ConfigSettingAttributes{
 		Flag_values: bazel.StringMapAttribute{
 			"//build/bazel/rules/my_string_setting": m.Name(),
@@ -538,26 +571,9 @@
 	)
 }
 
-var _ android.ApiProvider = (*customModule)(nil)
-
-func (c *customModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class: "custom_api_contribution",
-	}
-	apiAttribute := bazel.MakeLabelAttribute(
-		android.BazelLabelForModuleSrcSingle(ctx, proptools.String(c.props.Api)).Label,
-	)
-	attrs := &customBazelModuleAttributes{
-		Api: *apiAttribute,
-	}
-	ctx.CreateBazelTargetModule(props,
-		android.CommonAttributes{Name: c.Name()},
-		attrs)
-}
-
 // A bp2build mutator that uses load statements and creates a 1:M mapping from
 // module to target.
-func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) {
+func customBp2buildOneToMany(ctx android.Bp2buildMutatorContext, m *customModule) {
 
 	baseName := m.Name()
 	attrs := &customBazelModuleAttributes{}
@@ -596,11 +612,10 @@
 	ctx.RegisterForBazelConversion()
 }
 
-func simpleModuleDoNotConvertBp2build(typ, name string) string {
+func simpleModule(typ, name string) string {
 	return fmt.Sprintf(`
 %s {
 		name: "%s",
-		bazel_module: { bp2build_available: false },
 }`, typ, name)
 }
 
@@ -670,6 +685,7 @@
 		return ""
 	}
 	STUB_SUITE_ATTRS := map[string]string{
+		"api_surface":          "api_surface",
 		"stubs_symbol_file":    "symbol_file",
 		"stubs_versions":       "versions",
 		"soname":               "soname",
diff --git a/bpf/bpf.go b/bpf/bpf.go
index d135d5f..ba825cf 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -153,8 +153,6 @@
 		// The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
 		"-isystem bionic/libc/kernel/uapi/asm-arm64",
 		"-isystem bionic/libc/kernel/android/uapi",
-		// TODO(b/296014682): Remove after the bpf_headers is moved to Connectivity
-		"-I       frameworks/libs/net/common/native/bpf_headers/include/bpf",
 		"-I       packages/modules/Connectivity/staticlibs/native/bpf_headers/include/bpf",
 		// TODO(b/149785767): only give access to specific file with AID_* constants
 		"-I       system/core/libcutils/include",
@@ -313,7 +311,7 @@
 }
 
 // bpf bp2build converter
-func (b *bpf) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (b *bpf) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	if ctx.ModuleType() != "bpf" {
 		return
 	}
diff --git a/cc/binary.go b/cc/binary.go
index 4606b62..0722f81 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -599,7 +599,7 @@
 	handler.module.setAndroidMkVariablesFromCquery(info.CcAndroidMkInfo)
 }
 
-func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes {
+func binaryBp2buildAttrs(ctx android.Bp2buildMutatorContext, m *Module) binaryAttributes {
 	baseAttrs := bp2BuildParseBaseProps(ctx, m)
 	binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m)
 
@@ -661,7 +661,7 @@
 	return attrs
 }
 
-func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+func binaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) {
 	// shared with cc_test
 	binaryAttrs := binaryBp2buildAttrs(ctx, m)
 
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 83553c8..7738487 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -223,7 +223,7 @@
 }
 
 // bp2BuildParseLibProps returns the attributes for a variant of a cc_library.
-func bp2BuildParseLibProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) staticOrSharedAttributes {
+func bp2BuildParseLibProps(ctx android.Bp2buildMutatorContext, module *Module, isStatic bool) staticOrSharedAttributes {
 	lib, ok := module.compiler.(*libraryDecorator)
 	if !ok {
 		return staticOrSharedAttributes{}
@@ -232,12 +232,12 @@
 }
 
 // bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library.
-func bp2BuildParseSharedProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes {
+func bp2BuildParseSharedProps(ctx android.Bp2buildMutatorContext, module *Module) staticOrSharedAttributes {
 	return bp2BuildParseLibProps(ctx, module, false)
 }
 
 // bp2buildParseStaticProps returns the attributes for the static variant of a cc_library.
-func bp2BuildParseStaticProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes {
+func bp2BuildParseStaticProps(ctx android.Bp2buildMutatorContext, module *Module) staticOrSharedAttributes {
 	return bp2BuildParseLibProps(ctx, module, true)
 }
 
@@ -288,7 +288,7 @@
 }
 
 // Parses properties common to static and shared libraries. Also used for prebuilt libraries.
-func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
+func bp2buildParseStaticOrSharedProps(ctx android.Bp2buildMutatorContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
 	attrs := staticOrSharedAttributes{}
 
 	setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
@@ -334,7 +334,7 @@
 	attrs.Srcs_c = partitionedSrcs[cSrcPartition]
 	attrs.Srcs_as = partitionedSrcs[asSrcPartition]
 
-	attrs.Apex_available = android.ConvertApexAvailableToTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), apexAvailable)
+	attrs.Apex_available = android.ConvertApexAvailableToTagsWithoutTestApexes(ctx, apexAvailable)
 
 	attrs.Features.Append(convertHiddenVisibilityToFeatureStaticOrShared(ctx, module, isStatic))
 
@@ -944,7 +944,10 @@
 		nativeCoverage = BoolPtr(false)
 	}
 
-	productVariableProps := android.ProductVariableProperties(ctx, ctx.Module())
+	productVariableProps, errs := android.ProductVariableProperties(ctx, ctx.Module())
+	for _, err := range errs {
+		ctx.ModuleErrorf("ProductVariableProperties error: %s", err)
+	}
 
 	(&compilerAttrs).convertProductVariables(ctx, productVariableProps)
 	(&linkerAttrs).convertProductVariables(ctx, productVariableProps)
@@ -1000,6 +1003,8 @@
 	if module.afdo != nil && module.afdo.Properties.Afdo {
 		fdoProfileDep := bp2buildFdoProfile(ctx, module)
 		if fdoProfileDep != nil {
+			// TODO(b/276287371): Only set fdo_profile for android platform
+			// https://cs.android.com/android/platform/superproject/main/+/main:build/soong/cc/afdo.go;l=105;drc=2dbe160d1af445de32725098570ec594e3944fc5
 			(&compilerAttrs).fdoProfile.SetValue(*fdoProfileDep)
 		}
 	}
@@ -1109,22 +1114,15 @@
 	ctx android.Bp2buildMutatorContext,
 	m *Module,
 ) *bazel.Label {
+	// TODO(b/267229066): Convert to afdo boolean attribute and let Bazel handles finding
+	// fdo_profile target from AfdoProfiles product var
 	for _, project := range globalAfdoProfileProjects {
-		// Ensure handcrafted BUILD file exists in the project
-		BUILDPath := android.ExistentPathForSource(ctx, project, "BUILD")
-		if BUILDPath.Valid() {
-			// We handcraft a BUILD file with fdo_profile targets that use the existing profiles in the project
-			// This implementation is assuming that every afdo profile in globalAfdoProfileProjects already has
-			// an associated fdo_profile target declared in the same package.
+		// Ensure it's a Soong package
+		bpPath := android.ExistentPathForSource(ctx, project, "Android.bp")
+		if bpPath.Valid() {
 			// TODO(b/260714900): Handle arch-specific afdo profiles (e.g. `<module-name>-arm<64>.afdo`)
 			path := android.ExistentPathForSource(ctx, project, m.Name()+".afdo")
 			if path.Valid() {
-				// FIXME: Some profiles only exist internally and are not released to AOSP.
-				// When generated BUILD files are checked in, we'll run into merge conflict.
-				// The cc_library_shared target in AOSP won't have reference to an fdo_profile target because
-				// the profile doesn't exist. Internally, the same cc_library_shared target will
-				// have reference to the fdo_profile.
-				// For more context, see b/258682955#comment2
 				fdoProfileLabel := "//" + strings.TrimSuffix(project, "/") + ":" + m.Name()
 				return &bazel.Label{
 					Label: fdoProfileLabel,
@@ -1145,7 +1143,7 @@
 	compilerAttrs compilerAttributes,
 ) *bazel.LabelAttribute {
 	var aidlLibsFromSrcs, aidlFiles bazel.LabelListAttribute
-	apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
+	apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module())
 
 	if !aidlSrcs.IsEmpty() {
 		aidlLibsFromSrcs, aidlFiles = aidlSrcs.Partition(func(src bazel.Label) bool {
@@ -1285,7 +1283,7 @@
 	la.implementationDeps.Append(staticExcludesLabelList)
 }
 
-func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, module *Module, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
+func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.Bp2buildMutatorContext, module *Module, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
 	isBinary := module.Binary()
 	// Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
 	var axisFeatures []string
@@ -1380,10 +1378,10 @@
 		// having stubs or not, so Bazel select() statement can be used to choose
 		// source/stub variants of them.
 		apexAvailable := module.ApexAvailable()
-		setStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.export, &la.dynamicDeps, 0, false)
-		setStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.implementation, &la.implementationDynamicDeps, 1, false)
+		SetStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.export, &la.dynamicDeps, &la.deps, 0, false)
+		SetStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.implementation, &la.implementationDynamicDeps, &la.deps, 1, false)
 		if len(systemSharedLibs) > 0 {
-			setStubsForDynamicDeps(ctx, axis, config, apexAvailable, bazelLabelForSharedDeps(ctx, systemSharedLibs), &la.systemDynamicDeps, 2, true)
+			SetStubsForDynamicDeps(ctx, axis, config, apexAvailable, bazelLabelForSharedDeps(ctx, systemSharedLibs), &la.systemDynamicDeps, &la.deps, 2, true)
 		}
 	}
 
@@ -1492,7 +1490,7 @@
 // Note that this is an anti-pattern: The config_setting should be created from the apex definition
 // and not from a cc_library.
 // This anti-pattern is needed today since not all apexes have been allowlisted.
-func createInApexConfigSetting(ctx android.TopDownMutatorContext, apexName string) {
+func createInApexConfigSetting(ctx android.Bp2buildMutatorContext, apexName string) {
 	if apexName == android.AvailableToPlatform || apexName == android.AvailableToAnyApex {
 		// These correspond to android-non_apex and android-in_apex
 		return
@@ -1583,13 +1581,19 @@
 	}
 }
 
-func setStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis,
-	config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) {
+// hasNdkStubs returns true for libfoo if there exists a libfoo.ndk of type ndk_library
+func hasNdkStubs(ctx android.BazelConversionPathContext, c *Module) bool {
+	mod, exists := ctx.ModuleFromName(c.Name() + ndkLibrarySuffix)
+	return exists && ctx.OtherModuleType(mod) == "ndk_library"
+}
+
+func SetStubsForDynamicDeps(ctx android.Bp2buildMutatorContext, axis bazel.ConfigurationAxis,
+	config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, deps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) {
 
 	// Create a config_setting for each apex_available.
 	// This will be used to select impl of a dep if dep is available to the same apex.
 	for _, aa := range apexAvailable {
-		createInApexConfigSetting(ctx.(android.TopDownMutatorContext), aa)
+		createInApexConfigSetting(ctx, aa)
 	}
 
 	apiDomainForSelects := []string{}
@@ -1624,6 +1628,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())
 			}
@@ -1638,8 +1647,43 @@
 			useStubOrImplInApexWithName(ssi)
 		}
 	}
+
+	// If the library has an sdk variant, create additional selects to build this variant against the ndk
+	// The config setting for this variant will be //build/bazel/rules/apex:unbundled_app
+	if c, ok := ctx.Module().(*Module); ok && c.Properties.Sdk_version != nil {
+		for _, l := range dynamicLibs.Includes {
+			dep, _ := ctx.ModuleFromName(l.OriginalModuleName)
+			label := l // use the implementation by default
+			if depC, ok := dep.(*Module); ok && hasNdkStubs(ctx, depC) {
+				// If the dependency has ndk stubs, build against the ndk stubs
+				// https://cs.android.com/android/_/android/platform/build/soong/+/main:cc/cc.go;l=2642-2643;drc=e12d252e22dd8afa654325790d3298a0d67bd9d6;bpv=1;bpt=0
+				ver := proptools.String(c.Properties.Sdk_version)
+				// TODO - b/298085502: Add bp2build support for sdk_version: "minimum"
+				ndkLibModule, _ := ctx.ModuleFromName(dep.Name() + ndkLibrarySuffix)
+				label = bazel.Label{
+					Label: "//" + ctx.OtherModuleDir(ndkLibModule) + ":" + ndkLibModule.Name() + "_stub_libs-" + ver,
+				}
+			}
+			// add the ndk lib label to this axis
+			existingValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, "unbundled_app")
+			existingValue.Append(bazel.MakeLabelList([]bazel.Label{label}))
+			dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, "unbundled_app", bazel.FirstUniqueBazelLabelList(existingValue))
+		}
+
+		// Add ndk_sysroot to deps.
+		// ndk_sysroot has a dependency edge on all ndk_headers, and will provide the .h files of _every_ ndk library
+		existingValue := deps.SelectValue(bazel.OsAndInApexAxis, "unbundled_app")
+		existingValue.Append(bazel.MakeLabelList([]bazel.Label{ndkSysrootLabel}))
+		deps.SetSelectValue(bazel.OsAndInApexAxis, "unbundled_app", bazel.FirstUniqueBazelLabelList(existingValue))
+	}
 }
 
+var (
+	ndkSysrootLabel = bazel.Label{
+		Label: "//build/bazel/rules/cc:ndk_sysroot",
+	}
+)
+
 func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {
 	bp2BuildPropParseHelper(ctx, module, &StripProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
 		if stripProperties, ok := props.(*StripProperties); ok {
diff --git a/cc/cc.go b/cc/cc.go
index 3b92696..1896766 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -589,6 +589,7 @@
 	GeneratorFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags
 	GeneratorSources(ctx ModuleContext) GeneratedSource
 	GeneratorBuildActions(ctx ModuleContext, flags Flags, deps PathDeps)
+	GeneratorBp2build(ctx android.Bp2buildMutatorContext) bool
 }
 
 // compiler is the interface for a compiler helper object. Different module decorators may implement
@@ -879,16 +880,16 @@
 	installer    installer
 	bazelHandler BazelHandler
 
-	features []feature
-	stl      *stl
-	sanitize *sanitize
-	coverage *coverage
-	fuzzer   *fuzzer
-	sabi     *sabi
-	vndkdep  *vndkdep
-	lto      *lto
-	afdo     *afdo
-	pgo      *pgo
+	features  []feature
+	stl       *stl
+	sanitize  *sanitize
+	coverage  *coverage
+	fuzzer    *fuzzer
+	sabi      *sabi
+	vndkdep   *vndkdep
+	lto       *lto
+	afdo      *afdo
+	pgo       *pgo
 	orderfile *orderfile
 
 	library libraryInterface
@@ -1104,6 +1105,16 @@
 	return false
 }
 
+func (c *Module) IsNdkPrebuiltStl() bool {
+	if c.linker == nil {
+		return false
+	}
+	if _, ok := c.linker.(*ndkPrebuiltStlLinker); ok {
+		return true
+	}
+	return false
+}
+
 func (c *Module) RlibStd() bool {
 	panic(fmt.Errorf("RlibStd called on non-Rust module: %q", c.BaseModuleName()))
 }
@@ -4158,6 +4169,7 @@
 	headerLibrary
 	testBin // testBinary already declared
 	ndkLibrary
+	ndkPrebuiltStl
 )
 
 func (c *Module) typ() moduleType {
@@ -4196,12 +4208,24 @@
 		return sharedLibrary
 	} else if c.isNDKStubLibrary() {
 		return ndkLibrary
+	} else if c.IsNdkPrebuiltStl() {
+		return ndkPrebuiltStl
 	}
 	return unknownType
 }
 
 // ConvertWithBp2build converts Module to Bazel for bp2build.
-func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (c *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	if len(c.generators) > 0 {
+		allConverted := true
+		for _, generator := range c.generators {
+			allConverted = allConverted && generator.GeneratorBp2build(ctx)
+		}
+		if allConverted {
+			return
+		}
+	}
+
 	prebuilt := c.IsPrebuilt()
 	switch c.typ() {
 	case binary:
@@ -4240,29 +4264,15 @@
 		} else {
 			sharedOrStaticLibraryBp2Build(ctx, c, false)
 		}
+	case ndkPrebuiltStl:
+		ndkPrebuiltStlBp2build(ctx, c)
+	case ndkLibrary:
+		ndkLibraryBp2build(ctx, c)
 	default:
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
 	}
 }
 
-var _ android.ApiProvider = (*Module)(nil)
-
-func (c *Module) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
-	if c.IsPrebuilt() {
-		return
-	}
-	switch c.typ() {
-	case fullLibrary:
-		apiContributionBp2Build(ctx, c)
-	case sharedLibrary:
-		apiContributionBp2Build(ctx, c)
-	case headerLibrary:
-		// Aggressively generate api targets for all header modules
-		// This is necessary since the header module does not know if it is a dep of API surface stub library
-		apiLibraryHeadersBp2Build(ctx, c)
-	}
-}
-
 // Defaults
 type Defaults struct {
 	android.ModuleBase
diff --git a/cc/config/global.go b/cc/config/global.go
index 34e0aa7..a586a3f 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",
@@ -68,10 +67,6 @@
 		// not emit the table by default on Android since NDK still uses GNU binutils.
 		"-faddrsig",
 
-		// Turn on -fcommon explicitly, since Clang now defaults to -fno-common. The cleanup bug
-		// tracking this is http://b/151457797.
-		"-fcommon",
-
 		// Help catch common 32/64-bit errors.
 		"-Werror=int-conversion",
 
@@ -254,6 +249,8 @@
 	// (anything for which IsThirdPartyPath() in build/soong/android/paths.go
 	// returns true - includes external/, most of vendor/ and most of hardware/)
 	noOverrideExternalGlobalCflags = []string{
+		// http://b/151457797
+		"-fcommon",
 		// http://b/191699019
 		"-Wno-format-insufficient-args",
 		// http://b/296321145
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 40919c0..e048622 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -26,14 +26,14 @@
 		// Help catch common 32/64-bit errors.
 		"-Werror=implicit-function-declaration",
 		"-fno-emulated-tls",
-		"-march=rv64gc_zba_zbb_zbs",
+		"-march=rv64gcv_zba_zbb_zbs",
 	}
 
 	riscv64ArchVariantCflags = map[string][]string{}
 
 	riscv64Ldflags = []string{
 		"-Wl,--hash-style=gnu",
-		"-march=rv64gc_zba_zbb_zbs",
+		"-march=rv64gcv_zba_zbb_zbs",
 	}
 
 	riscv64Lldflags = append(riscv64Ldflags,
diff --git a/cc/fdo_profile.go b/cc/fdo_profile.go
index 7fbe719..05a8f46 100644
--- a/cc/fdo_profile.go
+++ b/cc/fdo_profile.go
@@ -16,8 +16,10 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 )
 
 func init() {
@@ -25,11 +27,12 @@
 }
 
 func RegisterFdoProfileBuildComponents(ctx android.RegistrationContext) {
-	ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
+	ctx.RegisterModuleType("fdo_profile", FdoProfileFactory)
 }
 
 type fdoProfile struct {
 	android.ModuleBase
+	android.BazelModuleBase
 
 	properties fdoProfileProperties
 }
@@ -38,6 +41,49 @@
 	Profile *string `android:"arch_variant"`
 }
 
+type bazelFdoProfileAttributes struct {
+	Profile bazel.StringAttribute
+}
+
+func (fp *fdoProfile) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	var profileAttr bazel.StringAttribute
+
+	archVariantProps := fp.GetArchVariantProperties(ctx, &fdoProfileProperties{})
+	for axis, configToProps := range archVariantProps {
+		for config, _props := range configToProps {
+			if archProps, ok := _props.(*fdoProfileProperties); ok {
+				if axis.String() == "arch" || axis.String() == "no_config" {
+					if archProps.Profile != nil {
+						profileAttr.SetSelectValue(axis, config, archProps.Profile)
+					}
+				}
+			}
+		}
+	}
+
+	// Ideally, cc_library_shared's fdo_profile attr can be a select statement so that we
+	// don't lift the restriction here. However, in cc_library_shared macro, fdo_profile
+	// is used as a string, we need to temporarily lift the host restriction until we can
+	// pass use fdo_profile attr with select statement
+	// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/cc_library_shared.bzl;l=127;drc=cc01bdfd39857eddbab04ef69ab6db22dcb1858a
+	// TODO(b/276287371): Drop the restriction override after fdo_profile path is handled properly
+	var noRestriction bazel.BoolAttribute
+	noRestriction.SetSelectValue(bazel.NoConfigAxis, "", proptools.BoolPtr(true))
+
+	ctx.CreateBazelTargetModuleWithRestrictions(
+		bazel.BazelTargetModuleProperties{
+			Rule_class: "fdo_profile",
+		},
+		android.CommonAttributes{
+			Name: fp.Name(),
+		},
+		&bazelFdoProfileAttributes{
+			Profile: profileAttr,
+		},
+		noRestriction,
+	)
+}
+
 // FdoProfileInfo is provided by FdoProfileProvider
 type FdoProfileInfo struct {
 	Path android.Path
@@ -77,9 +123,10 @@
 	}
 }
 
-func fdoProfileFactory() android.Module {
+func FdoProfileFactory() android.Module {
 	m := &fdoProfile{}
 	m.AddProperties(&m.properties)
 	android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibBoth)
+	android.InitBazelModule(m)
 	return m
 }
diff --git a/cc/generated_cc_library.go b/cc/generated_cc_library.go
index 55e19f9..8428e94 100644
--- a/cc/generated_cc_library.go
+++ b/cc/generated_cc_library.go
@@ -28,9 +28,8 @@
 		staticAndSharedLibrarySdkMemberType,
 	}
 
-	//	TODO: Need to be bazelable
-	//	module.bazelable = true
-	//	module.bazelHandler = &ccLibraryBazelHandler{module: module}
+	module.bazelable = true
+	module.bazelHandler = &ccLibraryBazelHandler{module: module}
 
 	module.generators = append(module.generators, callbacks)
 
diff --git a/cc/library.go b/cc/library.go
index 2d4d604..e66ce08 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -308,7 +308,7 @@
 	}
 }
 
-func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
+func libraryBp2Build(ctx android.Bp2buildMutatorContext, m *Module) {
 	sharedAttrs := bp2BuildParseSharedProps(ctx, m)
 	staticAttrs := bp2BuildParseStaticProps(ctx, m)
 	baseAttributes := bp2BuildParseBaseProps(ctx, m)
@@ -480,7 +480,7 @@
 	createStubsBazelTargetIfNeeded(ctx, m, compilerAttrs, exportedIncludes, baseAttributes)
 }
 
-func createStubsBazelTargetIfNeeded(ctx android.TopDownMutatorContext, m *Module, compilerAttrs compilerAttributes, exportedIncludes BazelIncludes, baseAttributes baseAttributes) {
+func createStubsBazelTargetIfNeeded(ctx android.Bp2buildMutatorContext, m *Module, compilerAttrs compilerAttributes, exportedIncludes BazelIncludes, baseAttributes baseAttributes) {
 	if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
 		stubSuitesProps := bazel.BazelTargetModuleProperties{
 			Rule_class:        "cc_stub_suite",
@@ -494,6 +494,7 @@
 			Soname:               &soname,
 			Source_library_label: proptools.StringPtr(m.GetBazelLabel(ctx, m)),
 			Deps:                 baseAttributes.deps,
+			Api_surface:          proptools.StringPtr("module-libapi"),
 		}
 		ctx.CreateBazelTargetModule(stubSuitesProps,
 			android.CommonAttributes{Name: m.Name() + "_stub_libs"},
@@ -516,70 +517,6 @@
 	}
 }
 
-func apiContributionBp2Build(ctx android.TopDownMutatorContext, module *Module) {
-	apiSurfaces := make([]string, 0)
-	apiHeaders := make([]string, 0)
-	// module-libapi for apexes (non-null `stubs` property)
-	if module.HasStubsVariants() {
-		apiSurfaces = append(apiSurfaces, android.ModuleLibApi.String())
-		apiIncludes := getModuleLibApiIncludes(ctx, module)
-		if !apiIncludes.isEmpty() {
-			createApiHeaderTarget(ctx, apiIncludes)
-			apiHeaders = append(apiHeaders, apiIncludes.name)
-		}
-	}
-	// vendorapi (non-null `llndk` property)
-	if module.HasLlndkStubs() {
-		apiSurfaces = append(apiSurfaces, android.VendorApi.String())
-		apiIncludes := getVendorApiIncludes(ctx, module)
-		if !apiIncludes.isEmpty() {
-			createApiHeaderTarget(ctx, apiIncludes)
-			apiHeaders = append(apiHeaders, apiIncludes.name)
-		}
-	}
-	// create a target only if this module contributes to an api surface
-	// TODO: Currently this does not distinguish modulelibapi-only headers and vendrorapi-only headers
-	// TODO: Update so that modulelibapi-only headers do not get exported to vendorapi (and vice-versa)
-	if len(apiSurfaces) > 0 {
-		props := bazel.BazelTargetModuleProperties{
-			Rule_class:        "cc_api_contribution",
-			Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
-		}
-		attrs := &bazelCcApiContributionAttributes{
-			Library_name: module.Name(),
-			Api_surfaces: bazel.MakeStringListAttribute(apiSurfaces),
-			Api:          apiLabelAttribute(ctx, module),
-			Hdrs: bazel.MakeLabelListAttribute(
-				bazel.MakeLabelListFromTargetNames(apiHeaders),
-			),
-		}
-		ctx.CreateBazelTargetModule(
-			props,
-			android.CommonAttributes{
-				Name:     android.ApiContributionTargetName(module.Name()),
-				SkipData: proptools.BoolPtr(true),
-			},
-			attrs,
-		)
-	}
-}
-
-// Native apis are versioned in a single .map.txt for all api surfaces
-// Pick any one of the .map.txt files
-func apiLabelAttribute(ctx android.TopDownMutatorContext, module *Module) bazel.LabelAttribute {
-	var apiFile *string
-	linker := module.linker.(*libraryDecorator)
-	if llndkApi := linker.Properties.Llndk.Symbol_file; llndkApi != nil {
-		apiFile = llndkApi
-	} else if moduleLibApi := linker.Properties.Stubs.Symbol_file; moduleLibApi != nil {
-		apiFile = moduleLibApi
-	} else {
-		ctx.ModuleErrorf("API surface library does not have any API file")
-	}
-	apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label
-	return *bazel.MakeLabelAttribute(apiLabel)
-}
-
 // wrapper struct to flatten the arch and os specific export_include_dirs
 // flattening is necessary since we want to export apis of all arches even when we build for x86 (e.g.)
 type bazelCcApiLibraryHeadersAttributes struct {
@@ -2885,7 +2822,7 @@
 	return outputFile
 }
 
-func bp2buildParseAbiCheckerProps(ctx android.TopDownMutatorContext, module *Module) bazelCcHeaderAbiCheckerAttributes {
+func bp2buildParseAbiCheckerProps(ctx android.Bp2buildMutatorContext, module *Module) bazelCcHeaderAbiCheckerAttributes {
 	lib, ok := module.linker.(*libraryDecorator)
 	if !ok {
 		return bazelCcHeaderAbiCheckerAttributes{}
@@ -2908,7 +2845,7 @@
 	return abiCheckerAttrs
 }
 
-func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module, isStatic bool) {
+func sharedOrStaticLibraryBp2Build(ctx android.Bp2buildMutatorContext, module *Module, isStatic bool) {
 	baseAttributes := bp2BuildParseBaseProps(ctx, module)
 	compilerAttrs := baseAttributes.compilerAttributes
 	linkerAttrs := baseAttributes.linkerAttributes
@@ -3121,6 +3058,7 @@
 	Source_library_label *string
 	Soname               *string
 	Deps                 bazel.LabelListAttribute
+	Api_surface          *string
 }
 
 type bazelCcHeaderAbiCheckerAttributes struct {
diff --git a/cc/library_headers.go b/cc/library_headers.go
index ce9c4aa..fccdf99 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -15,8 +15,6 @@
 package cc
 
 import (
-	"github.com/google/blueprint/proptools"
-
 	"android/soong/android"
 	"android/soong/bazel"
 	"android/soong/bazel/cquery"
@@ -129,7 +127,7 @@
 	sdkAttributes
 }
 
-func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+func libraryHeadersBp2Build(ctx android.Bp2buildMutatorContext, module *Module) {
 	baseAttributes := bp2BuildParseBaseProps(ctx, module)
 	exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, &baseAttributes.includes)
 	linkerAttrs := baseAttributes.linkerAttributes
@@ -153,8 +151,13 @@
 
 	tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
 
+	name := module.Name()
+	if module.IsPrebuilt() {
+		name = android.RemoveOptionalPrebuiltPrefix(name)
+	}
+
 	ctx.CreateBazelTargetModule(props, android.CommonAttributes{
-		Name: module.Name(),
+		Name: name,
 		Tags: tags,
 	}, attrs)
 }
@@ -170,106 +173,6 @@
 	return bazel.MakeLabelList(labels)
 }
 
-func apiLibraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) {
-	// cc_api_library_headers have a 1:1 mapping to arch/no-arch
-	// For API export, create a top-level arch-agnostic target and list the arch-specific targets as its deps
-
-	// arch-agnostic includes
-	apiIncludes := getModuleLibApiIncludes(ctx, module)
-	// arch and os specific includes
-	archApiIncludes, androidOsIncludes := archOsSpecificApiIncludes(ctx, module)
-	for _, arch := range allArches { // sorted iteration
-		archApiInclude := archApiIncludes[arch]
-		if !archApiInclude.isEmpty() {
-			createApiHeaderTarget(ctx, archApiInclude)
-			apiIncludes.addDep(archApiInclude.name)
-		}
-	}
-	// os==android includes
-	if !androidOsIncludes.isEmpty() {
-		createApiHeaderTarget(ctx, androidOsIncludes)
-		apiIncludes.addDep(androidOsIncludes.name)
-	}
-
-	if !apiIncludes.isEmpty() {
-		// override the name from <mod>.module-libapi.headers --> <mod>.contribution
-		apiIncludes.name = android.ApiContributionTargetName(module.Name())
-		createApiHeaderTarget(ctx, apiIncludes)
-	}
-}
-
-func createApiHeaderTarget(ctx android.TopDownMutatorContext, includes apiIncludes) {
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class:        "cc_api_library_headers",
-		Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
-	}
-	ctx.CreateBazelTargetModule(
-		props,
-		android.CommonAttributes{
-			Name:     includes.name,
-			SkipData: proptools.BoolPtr(true),
-		},
-		&includes.attrs,
-	)
-}
-
 var (
 	allArches = []string{"arm", "arm64", "x86", "x86_64"}
 )
-
-type archApiIncludes map[string]apiIncludes
-
-func archOsSpecificApiIncludes(ctx android.TopDownMutatorContext, module *Module) (archApiIncludes, apiIncludes) {
-	baseProps := bp2BuildParseBaseProps(ctx, module)
-	i := bp2BuildParseExportedIncludes(ctx, module, &baseProps.includes)
-	archRet := archApiIncludes{}
-	for _, arch := range allArches {
-		includes := i.Includes.SelectValue(
-			bazel.ArchConfigurationAxis,
-			arch)
-		systemIncludes := i.SystemIncludes.SelectValue(
-			bazel.ArchConfigurationAxis,
-			arch)
-		deps := baseProps.deps.SelectValue(
-			bazel.ArchConfigurationAxis,
-			arch)
-		attrs := bazelCcLibraryHeadersAttributes{
-			Export_includes:        bazel.MakeStringListAttribute(includes),
-			Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
-		}
-		apiDeps := apiBazelTargets(deps)
-		if !apiDeps.IsEmpty() {
-			attrs.Deps = bazel.MakeLabelListAttribute(apiDeps)
-		}
-		apiIncludes := apiIncludes{
-			name: android.ApiContributionTargetName(module.Name()) + "." + arch,
-			attrs: bazelCcApiLibraryHeadersAttributes{
-				bazelCcLibraryHeadersAttributes: attrs,
-				Arch:                            proptools.StringPtr(arch),
-			},
-		}
-		archRet[arch] = apiIncludes
-	}
-
-	// apiIncludes for os == Android
-	androidOsDeps := baseProps.deps.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid)
-	androidOsAttrs := bazelCcLibraryHeadersAttributes{
-		Export_includes: bazel.MakeStringListAttribute(
-			i.Includes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
-		),
-		Export_system_includes: bazel.MakeStringListAttribute(
-			i.SystemIncludes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
-		),
-	}
-	androidOsApiDeps := apiBazelTargets(androidOsDeps)
-	if !androidOsApiDeps.IsEmpty() {
-		androidOsAttrs.Deps = bazel.MakeLabelListAttribute(androidOsApiDeps)
-	}
-	osRet := apiIncludes{
-		name: android.ApiContributionTargetName(module.Name()) + ".androidos",
-		attrs: bazelCcApiLibraryHeadersAttributes{
-			bazelCcLibraryHeadersAttributes: androidOsAttrs,
-		},
-	}
-	return archRet, osRet
-}
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index d0ae4a5..da5db1c 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -21,6 +21,7 @@
 	"github.com/google/blueprint"
 
 	"android/soong/android"
+	"android/soong/bazel"
 )
 
 var (
@@ -79,9 +80,11 @@
 
 type headerModule struct {
 	android.ModuleBase
+	android.BazelModuleBase
 
 	properties headerProperties
 
+	srcPaths     android.Paths
 	installPaths android.Paths
 	licensePath  android.Path
 }
@@ -125,8 +128,8 @@
 
 	m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
 
-	srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
-	for _, header := range srcFiles {
+	m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
+	for _, header := range m.srcPaths {
 		installDir := getHeaderInstallDir(ctx, header, String(m.properties.From),
 			String(m.properties.To))
 		installedPath := ctx.InstallFile(installDir, header.Base(), header)
@@ -144,6 +147,29 @@
 	}
 }
 
+type bazelNdkHeadersAttributes struct {
+	Strip_import_prefix *string
+	Import_prefix       *string
+	Hdrs                bazel.LabelListAttribute
+}
+
+func (h *headerModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "ndk_headers",
+		Bzl_load_location: "//build/bazel/rules/cc:ndk_headers.bzl",
+	}
+	attrs := &bazelNdkHeadersAttributes{
+		Strip_import_prefix: h.properties.From,
+		Import_prefix:       h.properties.To,
+		Hdrs:                bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, h.properties.Srcs, h.properties.Exclude_srcs)),
+	}
+	ctx.CreateBazelTargetModule(
+		props,
+		android.CommonAttributes{Name: h.Name()},
+		attrs,
+	)
+}
+
 // ndk_headers installs the sets of ndk headers defined in the srcs property
 // to the sysroot base + "usr/include" + to directory + directory component.
 // ndk_headers requires the license file to be specified. Example:
@@ -154,10 +180,11 @@
 //	to = "bar"
 //	header = "include/foo/woodly/doodly.h"
 //	output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h"
-func ndkHeadersFactory() android.Module {
+func NdkHeadersFactory() android.Module {
 	module := &headerModule{}
 	module.AddProperties(&module.properties)
 	android.InitAndroidModule(module)
+	android.InitBazelModule(module)
 	return module
 }
 
@@ -193,6 +220,7 @@
 
 	properties versionedHeaderProperties
 
+	srcPaths     android.Paths
 	installPaths android.Paths
 	licensePath  android.Path
 }
@@ -211,9 +239,9 @@
 
 	fromSrcPath := android.PathForModuleSrc(ctx, String(m.properties.From))
 	toOutputPath := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To))
-	srcFiles := ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil)
+	m.srcPaths = ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil)
 	var installPaths []android.WritablePath
-	for _, header := range srcFiles {
+	for _, header := range m.srcPaths {
 		installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To))
 		installPath := installDir.Join(ctx, header.Base())
 		installPaths = append(installPaths, installPath)
@@ -224,11 +252,11 @@
 		ctx.ModuleErrorf("glob %q matched zero files", String(m.properties.From))
 	}
 
-	processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, srcFiles, installPaths)
+	processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, m.srcPaths, installPaths)
 }
 
 func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir android.Path,
-	srcFiles android.Paths, installPaths []android.WritablePath) android.Path {
+	srcPaths android.Paths, installPaths []android.WritablePath) android.Path {
 	// The versioner depends on a dependencies directory to simplify determining include paths
 	// when parsing headers. This directory contains architecture specific directories as well
 	// as a common directory, each of which contains symlinks to the actually directories to
@@ -253,7 +281,7 @@
 		Rule:            versionBionicHeaders,
 		Description:     "versioner preprocess " + srcDir.Rel(),
 		Output:          timestampFile,
-		Implicits:       append(srcFiles, depsGlob...),
+		Implicits:       append(srcPaths, depsGlob...),
 		ImplicitOutputs: installPaths,
 		Args: map[string]string{
 			"depsPath": depsPath.String(),
@@ -317,6 +345,7 @@
 
 	properties preprocessedHeadersProperties
 
+	srcPaths     android.Paths
 	installPaths android.Paths
 	licensePath  android.Path
 }
@@ -329,9 +358,9 @@
 	preprocessor := android.PathForModuleSrc(ctx, String(m.properties.Preprocessor))
 	m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
 
-	srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
+	m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
 	installDir := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To))
-	for _, src := range srcFiles {
+	for _, src := range m.srcPaths {
 		installPath := installDir.Join(ctx, src.Base())
 		m.installPaths = append(m.installPaths, installPath)
 
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 9281aeb..b3bb2da 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -43,11 +43,17 @@
 			CommandDeps: []string{"$ndkStubGenerator"},
 		}, "arch", "apiLevel", "apiMap", "flags")
 
+	// $headersList should include paths to public headers. All types
+	// that are defined outside of public headers will be excluded from
+	// ABI monitoring.
+	//
+	// STG tool doesn't access content of files listed in $headersList,
+	// so there is no need to add them to dependencies.
 	stg = pctx.AndroidStaticRule("stg",
 		blueprint.RuleParams{
-			Command:     "$stg -S :$symbolList --elf $in -o $out",
+			Command:     "$stg -S :$symbolList --file-filter :$headersList --elf $in -o $out",
 			CommandDeps: []string{"$stg"},
-		}, "symbolList")
+		}, "symbolList", "headersList")
 
 	stgdiff = pctx.AndroidStaticRule("stgdiff",
 		blueprint.RuleParams{
@@ -347,14 +353,19 @@
 	this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
 		this.apiLevel.String(), ctx.Arch().ArchType.String(),
 		this.libraryName(ctx), "abi.stg")
+	headersList := getNdkABIHeadersFile(ctx)
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        stg,
 		Description: fmt.Sprintf("stg %s", implementationLibrary),
 		Input:       implementationLibrary,
-		Implicit:    symbolList,
-		Output:      this.abiDumpPath,
+		Implicits: []android.Path{
+			symbolList,
+			headersList,
+		},
+		Output: this.abiDumpPath,
 		Args: map[string]string{
-			"symbolList": symbolList.String(),
+			"symbolList":  symbolList.String(),
+			"headersList": headersList.String(),
 		},
 	})
 }
@@ -404,7 +415,7 @@
 	// Also ensure that the ABI of the next API level (if there is one) matches
 	// this API level. *New* ABI is allowed, but any changes to APIs that exist
 	// in this API level are disallowed.
-	if !this.apiLevel.IsCurrent() {
+	if !this.apiLevel.IsCurrent() && prebuiltAbiDump.Valid() {
 		nextApiLevel := findNextApiLevel(ctx, this.apiLevel)
 		if nextApiLevel == nil {
 			panic(fmt.Errorf("could not determine which API level follows "+
@@ -424,10 +435,12 @@
 		} else {
 			ctx.Build(pctx, android.BuildParams{
 				Rule: stgdiff,
-				Description: fmt.Sprintf("abidiff %s %s", this.abiDumpPath,
-					nextAbiDump),
+				Description: fmt.Sprintf(
+					"Comparing ABI to the next API level %s %s",
+					prebuiltAbiDump, nextAbiDump),
 				Output: nextAbiDiffPath,
-				Inputs: android.Paths{this.abiDumpPath, nextAbiDump.Path()},
+				Inputs: android.Paths{
+					prebuiltAbiDump.Path(), nextAbiDump.Path()},
 				Args: map[string]string{
 					"args": "--format=small --ignore=interface_addition",
 				},
@@ -570,3 +583,40 @@
 	}
 	return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix)
 }
+
+func ndkLibraryBp2build(ctx android.Bp2buildMutatorContext, c *Module) {
+	ndk, _ := c.linker.(*stubDecorator)
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "cc_stub_suite",
+		Bzl_load_location: "//build/bazel/rules/cc:cc_stub_library.bzl",
+	}
+	sourceLibraryName := strings.TrimSuffix(c.Name(), ".ndk")
+	fromApiLevel, err := android.ApiLevelFromUser(ctx, proptools.String(ndk.properties.First_version))
+	if err != nil {
+		ctx.PropertyErrorf("first_version", "error converting first_version %v", proptools.String(ndk.properties.First_version))
+	}
+	symbolFileLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(ndk.properties.Symbol_file))
+	attrs := &bazelCcStubSuiteAttributes{
+		// TODO - b/300504837 Add ndk headers
+		Symbol_file: proptools.StringPtr(symbolFileLabel.Label),
+		Soname:      proptools.StringPtr(sourceLibraryName + ".so"),
+		Api_surface: proptools.StringPtr(android.PublicApi.String()),
+	}
+	if sourceLibrary, exists := ctx.ModuleFromName(sourceLibraryName); exists {
+		// the source library might not exist in minimal/unbuildable branches like kernel-build-tools.
+		// check for its existence
+		attrs.Source_library_label = proptools.StringPtr(c.GetBazelLabel(ctx, sourceLibrary))
+	}
+	if ctx.Config().RawPlatformSdkVersion() != nil {
+		// This is a hack to populate `versions` only on branches that set a platform_sdk_version
+		// This prevents errors on branches such as kernel-build-tools
+		// This hack is acceptable since we are not required to support NDK Bazel builds on those branches
+		attrs.Versions = bazel.MakeStringListAttribute(ndkLibraryVersions(ctx, fromApiLevel))
+	}
+
+	ctx.CreateBazelTargetModule(
+		props,
+		android.CommonAttributes{Name: c.Name() + "_stub_libs"},
+		attrs,
+	)
+}
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index d3a0a00..c3e6510 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -15,9 +15,11 @@
 package cc
 
 import (
+	"path/filepath"
 	"strings"
 
 	"android/soong/android"
+	"android/soong/bazel"
 )
 
 func init() {
@@ -64,6 +66,7 @@
 	module.Properties.Sdk_version = StringPtr("minimum")
 	module.Properties.AlwaysSdk = true
 	module.stl.Properties.Stl = StringPtr("none")
+	module.bazelable = true
 	return module.Init()
 }
 
@@ -84,12 +87,16 @@
 	module.Properties.AlwaysSdk = true
 	module.Properties.Sdk_version = StringPtr("current")
 	module.stl.Properties.Stl = StringPtr("none")
+	module.bazelable = true
 	return module.Init()
 }
 
+const (
+	libDir = "current/sources/cxx-stl/llvm-libc++/libs"
+)
+
 func getNdkStlLibDir(ctx android.ModuleContext) android.SourcePath {
-	libDir := "prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs"
-	return android.PathForSource(ctx, libDir).Join(ctx, ctx.Arch().Abi[0])
+	return android.PathForSource(ctx, ctx.ModuleDir(), libDir).Join(ctx, ctx.Arch().Abi[0])
 }
 
 func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags,
@@ -128,3 +135,81 @@
 
 	return lib
 }
+
+var (
+	archToAbiDirMap = map[string]string{
+		"android_arm":     "armeabi-v7a",
+		"android_arm64":   "arm64-v8a",
+		"android_riscv64": "riscv64",
+		"android_x86":     "x86",
+		"android_x86_64":  "x86_64",
+	}
+)
+
+// stlSrcBp2build returns a bazel label for the checked-in .so/.a file
+// It contains a select statement for each ABI
+func stlSrcBp2build(ctx android.Bp2buildMutatorContext, c *Module) bazel.LabelAttribute {
+	libName := strings.TrimPrefix(c.Name(), "ndk_")
+	libExt := ".so" // TODO - b/201079053: Support windows
+	if ctx.ModuleType() == "ndk_prebuilt_static_stl" {
+		libExt = ".a"
+	}
+	src := bazel.LabelAttribute{}
+	for arch, abiDir := range archToAbiDirMap {
+		srcPath := filepath.Join(libDir, abiDir, libName+libExt)
+		src.SetSelectValue(
+			bazel.OsArchConfigurationAxis,
+			arch,
+			android.BazelLabelForModuleSrcSingle(ctx, srcPath),
+		)
+	}
+	return src
+}
+
+// stlIncludesBp2build returns the includes exported by the STL
+func stlIncludesBp2build(c *Module) bazel.StringListAttribute {
+	linker, _ := c.linker.(*ndkPrebuiltStlLinker)
+	includeDirs := append(
+		[]string{},
+		linker.libraryDecorator.flagExporter.Properties.Export_include_dirs...,
+	)
+	includeDirs = append(
+		includeDirs,
+		linker.libraryDecorator.flagExporter.Properties.Export_system_include_dirs...,
+	)
+	return bazel.MakeStringListAttribute(android.FirstUniqueStrings(includeDirs))
+}
+
+func ndkPrebuiltStlBp2build(ctx android.Bp2buildMutatorContext, c *Module) {
+	if ctx.ModuleType() == "ndk_prebuilt_static_stl" {
+		ndkPrebuiltStaticStlBp2build(ctx, c)
+	} else {
+		ndkPrebuiltSharedStlBp2build(ctx, c)
+	}
+}
+
+func ndkPrebuiltStaticStlBp2build(ctx android.Bp2buildMutatorContext, c *Module) {
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "cc_prebuilt_library_static",
+		Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_static.bzl",
+	}
+	attrs := &bazelPrebuiltLibraryStaticAttributes{
+		Static_library:         stlSrcBp2build(ctx, c),
+		Export_system_includes: stlIncludesBp2build(c), // The exports are always as system
+	}
+	// TODO: min_sdk_version
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: c.Name()}, attrs)
+}
+
+func ndkPrebuiltSharedStlBp2build(ctx android.Bp2buildMutatorContext, c *Module) {
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "cc_prebuilt_library_shared",
+		Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_shared.bzl",
+	}
+	attrs := &bazelPrebuiltLibrarySharedAttributes{
+		Shared_library:         stlSrcBp2build(ctx, c),
+		Export_system_includes: stlIncludesBp2build(c), // The exports are always as system
+	}
+	// TODO: min_sdk_version
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: c.Name()}, attrs)
+}
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index feb3880..54a2ee2 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -54,6 +54,7 @@
 
 import (
 	"android/soong/android"
+	"strings"
 )
 
 func init() {
@@ -61,7 +62,7 @@
 }
 
 func RegisterNdkModuleTypes(ctx android.RegistrationContext) {
-	ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory)
+	ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory)
 	ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
 	ctx.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory)
 	ctx.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory)
@@ -96,15 +97,56 @@
 	return android.PathForOutput(ctx, "ndk.timestamp")
 }
 
+// The list of all NDK headers as they are located in the repo.
+// Used for ABI monitoring to track only structures defined in NDK headers.
+func getNdkABIHeadersFile(ctx android.PathContext) android.WritablePath {
+	return android.PathForOutput(ctx, "ndk_abi_headers.txt")
+}
+
 func NdkSingleton() android.Singleton {
 	return &ndkSingleton{}
 }
 
+// Collect all NDK exported headers paths into a file that is used to
+// detect public types that should be ABI monitored.
+//
+// Assume that we have the following code in exported header:
+//
+//	typedef struct Context Context;
+//	typedef struct Output {
+//	    ...
+//	} Output;
+//	void DoSomething(Context* ctx, Output* output);
+//
+// If none of public headers exported to end-users contain definition of
+// "struct Context", then "struct Context" layout and members shouldn't be
+// monitored. However we use DWARF information from a real library, which
+// may have access to the definition of "string Context" from
+// implementation headers, and it will leak to ABI.
+//
+// STG tool doesn't access source and header files, only DWARF information
+// from compiled library. And the DWARF contains file name where a type is
+// defined. So we need a rule to build a list of paths to public headers,
+// so STG can distinguish private types from public and do not monitor
+// private types that are not accessible to library users.
+func writeNdkAbiSrcFilter(ctx android.BuilderContext,
+	headerSrcPaths android.Paths, outputFile android.WritablePath) {
+	var filterBuilder strings.Builder
+	filterBuilder.WriteString("[decl_file_allowlist]\n")
+	for _, headerSrcPath := range headerSrcPaths {
+		filterBuilder.WriteString(headerSrcPath.String())
+		filterBuilder.WriteString("\n")
+	}
+
+	android.WriteFileRule(ctx, outputFile, filterBuilder.String())
+}
+
 type ndkSingleton struct{}
 
 func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
 	var staticLibInstallPaths android.Paths
-	var headerPaths android.Paths
+	var headerSrcPaths android.Paths
+	var headerInstallPaths android.Paths
 	var installPaths android.Paths
 	var licensePaths android.Paths
 	ctx.VisitAllModules(func(module android.Module) {
@@ -113,19 +155,22 @@
 		}
 
 		if m, ok := module.(*headerModule); ok {
-			headerPaths = append(headerPaths, m.installPaths...)
+			headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
+			headerInstallPaths = append(headerInstallPaths, m.installPaths...)
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
 
 		if m, ok := module.(*versionedHeaderModule); ok {
-			headerPaths = append(headerPaths, m.installPaths...)
+			headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
+			headerInstallPaths = append(headerInstallPaths, m.installPaths...)
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
 
 		if m, ok := module.(*preprocessedHeadersModule); ok {
-			headerPaths = append(headerPaths, m.installPaths...)
+			headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
+			headerInstallPaths = append(headerInstallPaths, m.installPaths...)
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
@@ -175,9 +220,11 @@
 	ctx.Build(pctx, android.BuildParams{
 		Rule:      android.Touch,
 		Output:    getNdkHeadersTimestampFile(ctx),
-		Implicits: headerPaths,
+		Implicits: headerInstallPaths,
 	})
 
+	writeNdkAbiSrcFilter(ctx, headerSrcPaths, getNdkABIHeadersFile(ctx))
+
 	fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
 
 	// There's a phony "ndk" rule defined in core/main.mk that depends on this.
diff --git a/cc/object.go b/cc/object.go
index ca14845..a3000e0 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -156,7 +156,7 @@
 
 // objectBp2Build is the bp2build converter from cc_object modules to the
 // Bazel equivalent target, plus any necessary include deps for the cc_object.
-func objectBp2Build(ctx android.TopDownMutatorContext, m *Module) {
+func objectBp2Build(ctx android.Bp2buildMutatorContext, m *Module) {
 	if m.compiler == nil {
 		// a cc_object must have access to the compiler decorator for its props.
 		ctx.ModuleErrorf("compiler must not be nil for a cc_object module")
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index a4ca590..b4819b0 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -363,12 +363,12 @@
 //     all variants
 //
 // In all cases, cc_prebuilt_library_static target names will be appended with "_bp2build_cc_library_static".
-func prebuiltLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+func prebuiltLibraryBp2Build(ctx android.Bp2buildMutatorContext, module *Module) {
 	prebuiltLibraryStaticBp2Build(ctx, module, true)
 	prebuiltLibrarySharedBp2Build(ctx, module)
 }
 
-func prebuiltLibraryStaticBp2Build(ctx android.TopDownMutatorContext, module *Module, fullBuild bool) {
+func prebuiltLibraryStaticBp2Build(ctx android.Bp2buildMutatorContext, module *Module, fullBuild bool) {
 	prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module, true)
 	exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, nil)
 
@@ -404,7 +404,7 @@
 	Export_system_includes bazel.StringListAttribute
 }
 
-func prebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+func prebuiltLibrarySharedBp2Build(ctx android.Bp2buildMutatorContext, module *Module) {
 	prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module, false)
 	exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, nil)
 
@@ -637,7 +637,7 @@
 	Src bazel.LabelAttribute
 }
 
-func prebuiltObjectBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+func prebuiltObjectBp2Build(ctx android.Bp2buildMutatorContext, module *Module) {
 	prebuiltAttrs := bp2BuildParsePrebuiltObjectProps(ctx, module)
 
 	attrs := &bazelPrebuiltObjectAttributes{
@@ -797,7 +797,7 @@
 	Strip stripAttributes
 }
 
-func prebuiltBinaryBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+func prebuiltBinaryBp2Build(ctx android.Bp2buildMutatorContext, module *Module) {
 	prebuiltAttrs := bp2BuildParsePrebuiltBinaryProps(ctx, module)
 
 	var la linkerAttributes
diff --git a/cc/proto.go b/cc/proto.go
index 0ed4381..4e08a4c 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -246,7 +246,7 @@
 	protoAttrs.Min_sdk_version = m.Properties.Min_sdk_version
 
 	name := m.Name() + suffix
-	tags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), m)
+	tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
 	ctx.CreateBazelTargetModule(
 		bazel.BazelTargetModuleProperties{
 			Rule_class:        rule_class,
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f37b5c7..9ceb1c8 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 {
@@ -677,12 +679,6 @@
 		s.Integer_overflow = nil
 	}
 
-	// TODO(b/254713216): CFI doesn't work for riscv64 yet because LTO doesn't work.
-	if ctx.Arch().ArchType == android.Riscv64 {
-		s.Cfi = nil
-		s.Diag.Cfi = nil
-	}
-
 	// Disable CFI for musl
 	if ctx.toolchain().Musl() {
 		s.Cfi = nil
diff --git a/cc/stl.go b/cc/stl.go
index 8f92dcb..a31a585 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -172,6 +172,7 @@
 		// The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
 		// its own includes. The includes are handled in CCBase.Flags().
 		deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...)
+		deps.HeaderLibs = append([]string{"ndk_system"}, deps.HeaderLibs...)
 	case "ndk_libc++_shared", "ndk_libc++_static":
 		if stl.Properties.SelectedStl == "ndk_libc++_shared" {
 			deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
@@ -219,8 +220,7 @@
 	case "libstdc++":
 		// Nothing
 	case "ndk_system":
-		ndkSrcRoot := android.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include")
-		flags.Local.CFlags = append(flags.Local.CFlags, "-isystem "+ndkSrcRoot.String())
+		// Nothing: The exports of ndk_system will be added automatically to the local cflags
 	case "ndk_libc++_shared", "ndk_libc++_static":
 		if ctx.Arch().ArchType == android.Arm {
 			// Make sure the _Unwind_XXX symbols are not re-exported.
diff --git a/cc/sysprop.go b/cc/sysprop.go
index 7ddd476..be03004 100644
--- a/cc/sysprop.go
+++ b/cc/sysprop.go
@@ -38,7 +38,7 @@
 }
 
 func Bp2buildSysprop(ctx android.Bp2buildMutatorContext, labels SyspropLibraryLabels, srcs bazel.LabelListAttribute, minSdkVersion *string) {
-	apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
+	apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module())
 	ctx.CreateBazelTargetModule(
 		bazel.BazelTargetModuleProperties{
 			Rule_class:        "sysprop_library",
diff --git a/cc/test.go b/cc/test.go
index ae62128..8c63dc6 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -25,6 +25,7 @@
 	"android/soong/bazel"
 	"android/soong/bazel/cquery"
 	"android/soong/tradefed"
+	"android/soong/ui/metrics/bp2build_metrics_proto"
 )
 
 // TestLinkerProperties properties to be registered via the linker
@@ -700,7 +701,7 @@
 // TODO(b/244432609): handle `isolated` property.
 // TODO(b/244432134): handle custom runpaths for tests that assume runfile layouts not
 // default to bazel. (see linkerInit function)
-func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+func testBinaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) {
 	var testBinaryAttrs testBinaryAttributes
 	testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m)
 
@@ -718,6 +719,13 @@
 				combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_libs))
 				data.SetSelectValue(axis, config, combinedData)
 				tags.SetSelectValue(axis, config, p.Test_options.Tags)
+
+				// TODO: b/300117121 - handle bp2build conversion of non-unit tests
+				// default to true to only handle non-nil falses
+				if !BoolDefault(p.Test_options.Unit_test, true) {
+					ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "Host unit_test = false")
+					return
+				}
 			}
 		}
 	}
diff --git a/cc/testing.go b/cc/testing.go
index d1632aa..7531f6d 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -41,7 +41,7 @@
 	ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
 	ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory)
 	ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
-	ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory)
+	ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory)
 }
 
 func GatherRequiredDepsForTest(oses ...android.OsType) string {
@@ -558,7 +558,7 @@
 	// This includes files that are needed by all, or at least most, instances of a cc module type.
 	android.MockFS{
 		// Needed for ndk_prebuilt_(shared|static)_stl.
-		"prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs": nil,
+		"defaults/cc/common/current/sources/cxx-stl/llvm-libc++/libs": nil,
 	}.AddToFixture(),
 )
 
@@ -671,7 +671,7 @@
 // PrepareForTestWithFdoProfile registers module types to test with fdo_profile
 var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory)
-	ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
+	ctx.RegisterModuleType("fdo_profile", FdoProfileFactory)
 })
 
 // TestConfig is the legacy way of creating a test Config for testing cc modules.
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 9ea337b..e8e930e 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -98,6 +98,11 @@
 			if !sanitizable.Shared() && sanitizable.IsSanitizerEnabled(scs) {
 				return false
 			}
+			// cfi and hwasan cannot be enabled at the same time.
+			// Skip variants that have both cfi and hwasan enabled.
+			if sanitizable.IsSanitizerEnabled(cfi) && sanitizable.IsSanitizerEnabled(Hwasan) {
+				return false
+			}
 			// cfi and hwasan also export both variants. But for static, we capture both.
 			// This is because cfi static libraries can't be linked from non-cfi modules,
 			// and vice versa.
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index 2e71fe1..a7308b4 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -76,8 +76,8 @@
 	if err != nil {
 		return nil, err
 	}
-	bytes := make([]byte, tocFile.FileHeader.UncompressedSize64)
-	if _, err := rc.Read(bytes); err != nil && err != io.EOF {
+	bytes, err := io.ReadAll(rc)
+	if err != nil {
 		return nil, err
 	}
 	rc.Close()
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 20e366e..d20847b 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -21,13 +21,11 @@
 	"fmt"
 	"os"
 	"path/filepath"
-	"regexp"
 	"strings"
 	"time"
 
 	"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 +74,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 +166,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 +434,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()
@@ -736,43 +616,6 @@
 	return excluded
 }
 
-// buildTargetsByPackage parses Bazel BUILD.bazel and BUILD files under
-// the workspace, and returns a map containing names of Bazel targets defined in
-// these BUILD files.
-// For example, maps "//foo/bar" to ["baz", "qux"] if `//foo/bar:{baz,qux}` exist.
-func buildTargetsByPackage(ctx *android.Context) map[string][]string {
-	existingBazelFiles, err := getExistingBazelRelatedFiles(topDir)
-	maybeQuit(err, "Error determining existing Bazel-related files")
-
-	result := map[string][]string{}
-
-	// Search for instances of `name = "$NAME"` (with arbitrary spacing).
-	targetNameRegex := regexp.MustCompile(`(?m)^\s*name\s*=\s*\"([^\"]+)\"`)
-
-	for _, path := range existingBazelFiles {
-		if !ctx.Config().Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(filepath.Dir(path)) {
-			continue
-		}
-		fullPath := shared.JoinPath(topDir, path)
-		sourceDir := filepath.Dir(path)
-		fileInfo, err := os.Stat(fullPath)
-		maybeQuit(err, "Error accessing Bazel file '%s'", fullPath)
-
-		if !fileInfo.IsDir() &&
-			(fileInfo.Name() == "BUILD" || fileInfo.Name() == "BUILD.bazel") {
-			// Process this BUILD file.
-			buildFileContent, err := os.ReadFile(fullPath)
-			maybeQuit(err, "Error reading Bazel file '%s'", fullPath)
-
-			matches := targetNameRegex.FindAllStringSubmatch(string(buildFileContent), -1)
-			for _, match := range matches {
-				result[sourceDir] = append(result[sourceDir], match[1])
-			}
-		}
-	}
-	return result
-}
-
 // Run Soong in the bp2build mode. This creates a standalone context that registers
 // an alternate pipeline of mutators and singletons specifically for generating
 // Bazel BUILD files instead of Ninja files.
@@ -781,7 +624,11 @@
 	ctx.EventHandler.Do("bp2build", func() {
 
 		ctx.EventHandler.Do("read_build", func() {
-			ctx.Config().SetBazelBuildFileTargets(buildTargetsByPackage(ctx))
+			existingBazelFiles, err := getExistingBazelRelatedFiles(topDir)
+			maybeQuit(err, "Error determining existing Bazel-related files")
+
+			err = ctx.RegisterExistingBazelTargets(topDir, existingBazelFiles)
+			maybeQuit(err, "Error parsing existing Bazel-related files")
 		})
 
 		// Propagate "allow misssing dependencies" bit. This is normally set in
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 4097e8a..3b8f4f5 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -289,10 +289,7 @@
 		}
 	}
 
-	// Fix up the source tree due to a repo bug where it doesn't remove
-	// linkfiles that have been removed
-	fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
-	fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
+	removeBadTargetRename(buildCtx, config)
 
 	// Create a source finder.
 	f := build.NewSourceFinder(buildCtx, config)
@@ -300,16 +297,26 @@
 	build.FindSources(buildCtx, config, f)
 }
 
-func fixBadDanglingLink(ctx build.Context, name string) {
-	_, err := os.Lstat(name)
+func removeBadTargetRename(ctx build.Context, config build.Config) {
+	log := ctx.ContextImpl.Logger
+	// find bad paths
+	m, err := filepath.Glob(filepath.Join(config.OutDir(), "bazel", "output", "execroot", "__main__", "bazel-out", "mixed_builds_product-*", "bin", "tools", "metalava", "metalava"))
 	if err != nil {
-		return
+		log.Fatalf("Glob for invalid file failed %s", err)
 	}
-	_, err = os.Stat(name)
-	if os.IsNotExist(err) {
-		err = os.Remove(name)
+	for _, f := range m {
+		info, err := os.Stat(f)
 		if err != nil {
-			ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
+			log.Fatalf("Stat of invalid file %q failed %s", f, err)
+		}
+		// if it's a directory, leave it, but remove the files
+		if !info.IsDir() {
+			err = os.Remove(f)
+			if err != nil {
+				log.Fatalf("Remove of invalid file %q failed %s", f, err)
+			} else {
+				log.Verbosef("Removed %q", f)
+			}
 		}
 	}
 }
diff --git a/compliance/OWNERS b/compliance/OWNERS
deleted file mode 100644
index f52e201..0000000
--- a/compliance/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-# OSEP Build
-bbadour@google.com
-kanouche@google.com
-napier@google.com
-
-# Open Source Compliance Tools
-rtp@google.com
-austinyuan@google.com
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..9423531 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.Bp2buildMutatorContext) (*bazelPrebuiltFileAttributes, bool) {
 	var src bazel.LabelAttribute
 	for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltEtcProperties{}) {
 		for config, p := range configToProps {
@@ -720,12 +721,20 @@
 				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)
 			}
 		}
-
-		for propName, productConfigProps := range android.ProductVariableProperties(ctx, ctx.Module()) {
+		productVarProperties, errs := android.ProductVariableProperties(ctx, ctx.Module())
+		for _, err := range errs {
+			ctx.ModuleErrorf("ProductVariableProperties error: %s", err)
+		}
+		for propName, productConfigProps := range productVarProperties {
 			for configProp, propVal := range productConfigProps {
 				if propName == "Src" {
 					props, ok := propVal.(*string)
@@ -779,21 +788,23 @@
 		attrs.Filename_from_src = bazel.BoolAttribute{Value: moduleProps.Filename_from_src}
 	}
 
-	return attrs
-
+	return attrs, true
 }
 
 // ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
 // prebuilt_* modules (except prebuilt_etc_xml) are PrebuiltEtc,
 // which we treat as *PrebuiltFile*
-func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	var dir = module.installDirBase
 	// prebuilt_file supports only `etc` or `usr/share`
 	if !(dir == "etc" || dir == "usr/share") {
 		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/filesystem/avb_add_hash_footer.go b/filesystem/avb_add_hash_footer.go
index f3fecd0..dabbc46 100644
--- a/filesystem/avb_add_hash_footer.go
+++ b/filesystem/avb_add_hash_footer.go
@@ -68,6 +68,9 @@
 	// List of properties to add to the footer
 	Props []avbProp
 
+	// The index used to prevent rollback of the image on device.
+	Rollback_index *int64
+
 	// Include descriptors from images
 	Include_descriptors_from_images []string `android:"path,arch_variant"`
 }
@@ -128,6 +131,14 @@
 		addAvbProp(ctx, cmd, prop)
 	}
 
+	if a.properties.Rollback_index != nil {
+		rollbackIndex := proptools.Int(a.properties.Rollback_index)
+		if rollbackIndex < 0 {
+			ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative")
+		}
+		cmd.Flag(fmt.Sprintf(" --rollback_index %x", rollbackIndex))
+	}
+
 	cmd.FlagWithOutput("--image ", a.output)
 
 	builder.Build("avbAddHashFooter", fmt.Sprintf("avbAddHashFooter %s", ctx.ModuleName()))
diff --git a/genrule/genrule.go b/genrule/genrule.go
index d1c2f13..01cac5b 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -920,7 +920,7 @@
 }
 
 // ConvertWithBp2build converts a Soong module -> Bazel target.
-func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (m *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	// Bazel only has the "tools" attribute.
 	tools_prop := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
 	tool_files_prop := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
@@ -993,7 +993,10 @@
 
 	var cmdProp bazel.StringAttribute
 	cmdProp.SetValue(replaceVariables(proptools.String(m.properties.Cmd)))
-	allProductVariableProps := android.ProductVariableProperties(ctx, m)
+	allProductVariableProps, errs := android.ProductVariableProperties(ctx, m)
+	for _, err := range errs {
+		ctx.ModuleErrorf("ProductVariableProperties error: %s", err)
+	}
 	if productVariableProps, ok := allProductVariableProps["Cmd"]; ok {
 		for productVariable, value := range productVariableProps {
 			var cmd string
diff --git a/jar/jar.go b/jar/jar.go
index f164ee1..54eded9 100644
--- a/jar/jar.go
+++ b/jar/jar.go
@@ -166,10 +166,23 @@
 	}
 	s.IsIdentRune = javaIdentRune
 
-	tok := s.Scan()
-	if sErr != nil {
-		return "", sErr
+	var tok rune
+	for {
+		tok = s.Scan()
+		if sErr != nil {
+			return "", sErr
+		}
+		// If the first token is an annotation, it could be annotating a package declaration, so consume them.
+		// Note that this does not support "complex" annotations with attributes, e.g. @Foo(x=y).
+		if tok != '@' {
+			break
+		}
+		tok = s.Scan()
+		if tok != scanner.Ident || sErr != nil {
+			return "", fmt.Errorf("expected annotation identifier, got @%v", tok)
+		}
 	}
+
 	if tok == scanner.Ident {
 		switch s.TokenText() {
 		case "package":
@@ -189,9 +202,6 @@
 		default:
 			return "", fmt.Errorf(`expected first token of java file to be "package", got %q`, s.TokenText())
 		}
-	} else if tok == '@' {
-		// File has no package statement, first token is an annotation
-		return "", nil
 	} else if tok == scanner.EOF {
 		// File no package statement, it has no non-whitespace non-comment tokens
 		return "", nil
diff --git a/jar/jar_test.go b/jar/jar_test.go
index c92011e..61da9bb 100644
--- a/jar/jar_test.go
+++ b/jar/jar_test.go
@@ -61,6 +61,16 @@
 			in:      "package 0foo.bar;",
 			wantErr: true,
 		},
+		{
+			name: "annotations",
+			in:   "@NonNullApi\n@X\npackage foo.bar;",
+			want: "foo.bar",
+		},
+		{
+			name:    "complex annotation",
+			in:      "@Foo(x=y)\n@package foo.bar;",
+			wantErr: true, // Complex annotation not supported yet.
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/java/aar.go b/java/aar.go
index 0216196..8f5deab 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -993,7 +993,7 @@
 			`jni_files=$$(find $outDir/jni -type f) && ` +
 			// print error message if there are no JNI libs for this arch
 			`[ -n "$$jni_files" ] || (echo "ERROR: no JNI libs found for arch ${archString}" && exit 1) && ` +
-			`${config.SoongZipCmd} -o $out -P 'lib/${archString}' ` +
+			`${config.SoongZipCmd} -o $out -L 0 -P 'lib/${archString}' ` +
 			`-C $outDir/jni/${archString} $$(echo $$jni_files | xargs -n1 printf " -f %s")`,
 		CommandDeps: []string{"${config.SoongZipCmd}"},
 	},
@@ -1239,7 +1239,7 @@
 	Sdk_version bazel.StringAttribute
 }
 
-func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) (*bazelAapt, bool) {
+func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.Bp2buildMutatorContext) (*bazelAapt, bool) {
 	manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
 
 	resourceFiles := bazel.LabelList{
@@ -1275,7 +1275,7 @@
 	}, true
 }
 
-func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (a *AARImport) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	aars := android.BazelLabelForModuleSrcExcludes(ctx, a.properties.Aars, []string{})
 	exportableStaticLibs := []string{}
 	// TODO(b/240716882): investigate and handle static_libs deps that are not imports. They are not supported for export by Bazel.
@@ -1328,7 +1328,7 @@
 	}
 }
 
-func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (a *AndroidLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	commonAttrs, bp2buildInfo, supported := a.convertLibraryAttrsBp2Build(ctx)
 	if !supported {
 		return
@@ -1340,7 +1340,10 @@
 	if !commonAttrs.Srcs.IsEmpty() {
 		deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
 	} else if !depLabels.Deps.IsEmpty() {
-		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
+		ctx.MarkBp2buildUnconvertible(
+			bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED,
+			"Module has direct dependencies but no sources. Bazel will not allow this.")
+		return
 	}
 	name := a.Name()
 	props := AndroidLibraryBazelTargetModuleProperties()
@@ -1349,6 +1352,9 @@
 	if !supported {
 		return
 	}
+	if hasJavaResources := aaptAttrs.ConvertJavaResources(ctx, commonAttrs); hasJavaResources {
+		return
+	}
 	ctx.CreateBazelTargetModule(
 		props,
 		android.CommonAttributes{Name: name},
diff --git a/java/app.go b/java/app.go
index d71cd77..ed1c107 100755
--- a/java/app.go
+++ b/java/app.go
@@ -31,6 +31,7 @@
 	"android/soong/dexpreopt"
 	"android/soong/genrule"
 	"android/soong/tradefed"
+	"android/soong/ui/metrics/bp2build_metrics_proto"
 )
 
 func init() {
@@ -316,6 +317,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() {
@@ -1104,6 +1116,8 @@
 	testConfig       android.Path
 	extraTestConfigs android.Paths
 	data             android.Paths
+
+	android.BazelModuleBase
 }
 
 func (a *AndroidTest) InstallInTestcases() bool {
@@ -1221,6 +1235,8 @@
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	android.InitOverridableModule(module, &module.overridableAppProperties.Overrides)
+
+	android.InitBazelModule(module)
 	return module
 }
 
@@ -1242,6 +1258,8 @@
 	AndroidApp
 
 	appTestHelperAppProperties appTestHelperAppProperties
+
+	android.BazelModuleBase
 }
 
 func (a *AndroidTestHelperApp) InstallInTestcases() bool {
@@ -1273,6 +1291,7 @@
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	android.InitApexModule(module)
+	android.InitBazelModule(module)
 	return module
 }
 
@@ -1579,11 +1598,11 @@
 	Certificate string
 }
 
-func (m *AndroidAppCertificate) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (m *AndroidAppCertificate) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	androidAppCertificateBp2Build(ctx, m)
 }
 
-func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *AndroidAppCertificate) {
+func androidAppCertificateBp2Build(ctx android.Bp2buildMutatorContext, module *AndroidAppCertificate) {
 	var certificate string
 	if module.properties.Certificate != nil {
 		certificate = *module.properties.Certificate
@@ -1603,7 +1622,6 @@
 
 type manifestValueAttribute struct {
 	MinSdkVersion    *string
-	MaxSdkVersion    *string
 	TargetSdkVersion *string
 }
 
@@ -1617,47 +1635,43 @@
 	Manifest_values  *manifestValueAttribute
 	Optimize         *bool
 	Proguard_specs   bazel.LabelListAttribute
+	Updatable        *bool
 }
 
-// ConvertWithBp2build is used to convert android_app to Bazel.
-func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
-	commonAttrs, bp2BuildInfo, supported := a.convertLibraryAttrsBp2Build(ctx)
-	if !supported {
-		return
+func (b bazelAapt) ConvertJavaResources(ctx android.Bp2buildMutatorContext, javaAttrs *javaCommonAttributes) bool {
+	// TODO (b/300470246) bp2build support for java_resources & java_resource_dirs in android rules
+	hasJavaResources := !javaAttrs.javaResourcesAttributes.Resources.IsEmpty()
+	if hasJavaResources {
+		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "(b/300470246) java resources in android_* module")
 	}
-	depLabels := bp2BuildInfo.DepLabels
+	return hasJavaResources
+}
 
-	deps := depLabels.Deps
-	deps.Append(depLabels.StaticDeps)
-
+func convertWithBp2build(ctx android.Bp2buildMutatorContext, a *AndroidApp) (bool, android.CommonAttributes, *bazelAndroidAppAttributes) {
 	aapt, supported := a.convertAaptAttrsWithBp2Build(ctx)
 	if !supported {
-		return
+		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
 	}
+	if a.appProperties.Jni_uses_platform_apis != nil {
+		ctx.MarkBp2buildUnconvertible(
+			bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED,
+			"TODO - b/299360988: Add bp2build support for jni_uses_platform_apis",
+		)
+		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
+	}
+	if a.appProperties.Jni_uses_sdk_apis != nil {
+		ctx.MarkBp2buildUnconvertible(
+			bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED,
+			"TODO - b/299360988: Add bp2build support for jni_uses_sdk_apis",
+		)
+		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
+	}
+
 	certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate)
 
-	manifestValues := &manifestValueAttribute{}
-	// TODO(b/274474008 ): Directly convert deviceProperties.Min_sdk_version in bp2build
-	// MinSdkVersion(ctx) calls SdkVersion(ctx) if no value for min_sdk_version is set
-	minSdkVersion := a.MinSdkVersion(ctx)
-	if !minSdkVersion.IsPreview() && !minSdkVersion.IsInvalid() {
-		if minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx); err == nil {
-			manifestValues.MinSdkVersion = &minSdkStr
-		}
-	}
-
-	maxSdkVersion := a.MaxSdkVersion(ctx)
-	if !maxSdkVersion.IsPreview() && !maxSdkVersion.IsInvalid() {
-		if maxSdkStr, err := maxSdkVersion.EffectiveVersionString(ctx); err == nil {
-			manifestValues.MaxSdkVersion = &maxSdkStr
-		}
-	}
-
-	targetSdkVersion := a.TargetSdkVersion(ctx)
-	if !targetSdkVersion.IsPreview() && !targetSdkVersion.IsInvalid() {
-		if targetSdkStr, err := targetSdkVersion.EffectiveVersionString(ctx); err == nil {
-			manifestValues.TargetSdkVersion = &targetSdkStr
-		}
+	manifestValues := &manifestValueAttribute{
+		MinSdkVersion:    a.deviceProperties.Min_sdk_version,
+		TargetSdkVersion: a.deviceProperties.Target_sdk_version,
 	}
 
 	appAttrs := &bazelAndroidAppAttributes{
@@ -1666,11 +1680,21 @@
 		Certificate:      certificate,
 		Certificate_name: certificateName,
 		Manifest_values:  manifestValues,
+		Updatable:        a.appProperties.Updatable,
 	}
 
-	if !BoolDefault(a.dexProperties.Optimize.Enabled, true) {
-		appAttrs.Optimize = proptools.BoolPtr(false)
-	} else {
+	// Optimization is..
+	// - enabled by default for android_app, android_test_helper_app
+	// - disabled by default for android_test
+	//
+	// TODO(b/192032291): Disable android_test_helper_app optimization by
+	// default after auditing downstream usage.
+	if a.dexProperties.Optimize.EnabledByDefault != a.dexer.effectiveOptimizeEnabled() {
+		// Property is explicitly defined by default from default, so emit the Bazel attribute.
+		appAttrs.Optimize = proptools.BoolPtr(a.dexer.effectiveOptimizeEnabled())
+	}
+
+	if a.dexer.effectiveOptimizeEnabled() {
 		handCraftedFlags := ""
 		if Bool(a.dexProperties.Optimize.Ignore_warnings) {
 			handCraftedFlags += "-ignorewarning "
@@ -1700,13 +1724,34 @@
 			})
 			appAttrs.Proguard_specs.Add(bazel.MakeLabelAttribute(":" + generatedFlagFileRuleName))
 		}
-
 	}
 
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class:        "android_binary",
-		Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl",
+	commonAttrs, bp2BuildInfo, supported := a.convertLibraryAttrsBp2Build(ctx)
+	if !supported {
+		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
 	}
+	if hasJavaResources := aapt.ConvertJavaResources(ctx, commonAttrs); hasJavaResources {
+		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
+	}
+
+	depLabels := bp2BuildInfo.DepLabels
+
+	deps := depLabels.Deps
+	deps.Append(depLabels.StaticDeps)
+
+	var jniDeps bazel.LabelListAttribute
+	archVariantProps := a.GetArchVariantProperties(ctx, &appProperties{})
+	for axis, configToProps := range archVariantProps {
+		for config, _props := range configToProps {
+			if archProps, ok := _props.(*appProperties); ok {
+				archJniLibs := android.BazelLabelForModuleDeps(
+					ctx,
+					android.LastUniqueStrings(android.CopyOf(archProps.Jni_libs)))
+				jniDeps.SetSelectValue(axis, config, archJniLibs)
+			}
+		}
+	}
+	deps.Append(jniDeps)
 
 	if !bp2BuildInfo.hasKotlin {
 		appAttrs.javaCommonAttributes = commonAttrs
@@ -1733,10 +1778,54 @@
 		}
 	}
 
-	ctx.CreateBazelTargetModule(
-		props,
-		android.CommonAttributes{Name: a.Name(), SkipData: proptools.BoolPtr(true)},
-		appAttrs,
-	)
+	return true, android.CommonAttributes{Name: a.Name(), SkipData: proptools.BoolPtr(true)}, appAttrs
+}
 
+// ConvertWithBp2build is used to convert android_app to Bazel.
+func (a *AndroidApp) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	if ok, commonAttrs, appAttrs := convertWithBp2build(ctx, a); ok {
+		props := bazel.BazelTargetModuleProperties{
+			Rule_class:        "android_binary",
+			Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl",
+		}
+
+		ctx.CreateBazelTargetModule(props, commonAttrs, appAttrs)
+	}
+
+}
+
+// ConvertWithBp2build is used to convert android_test to Bazel.
+func (at *AndroidTest) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	if ok, commonAttrs, appAttrs := convertWithBp2build(ctx, &at.AndroidApp); ok {
+		props := bazel.BazelTargetModuleProperties{
+			Rule_class:        "android_test",
+			Bzl_load_location: "//build/bazel/rules/android:android_test.bzl",
+		}
+
+		ctx.CreateBazelTargetModule(props, commonAttrs, appAttrs)
+	}
+
+}
+
+func (atha *AndroidTestHelperApp) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	if ok, commonAttrs, appAttrs := convertWithBp2build(ctx, &atha.AndroidApp); ok {
+		// an android_test_helper_app is an android_binary with testonly = True
+		commonAttrs.Testonly = proptools.BoolPtr(true)
+
+		// android_test_helper_app sets default values differently to android_app,
+		// https://cs.android.com/android/platform/superproject/main/+/main:build/soong/java/app.go;l=1273-1279;drc=e12c083198403ec694af6c625aed11327eb2bf7f
+		//
+		// installable: true (settable prop)
+		// use_embedded_native_libs: true (settable prop)
+		// lint.test: true (settable prop)
+		// AlwaysPackageNativeLibs: true (blueprint mutated prop)
+		// dexpreopt isTest: true (not prop)
+
+		props := bazel.BazelTargetModuleProperties{
+			Rule_class:        "android_binary",
+			Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl",
+		}
+
+		ctx.CreateBazelTargetModule(props, commonAttrs, appAttrs)
+	}
 }
diff --git a/java/app_import.go b/java/app_import.go
index ad1765e..c5d09fd 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -19,6 +19,7 @@
 import (
 	"fmt"
 	"reflect"
+	"strings"
 
 	"github.com/google/blueprint"
 
@@ -51,27 +52,11 @@
 		Description: "Uncompress dex files",
 	})
 
-	checkDexLibsAreUncompressedRule = pctx.AndroidStaticRule("check-dex-libs-are-uncompressed", blueprint.RuleParams{
-		// grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed
-		Command: "if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
-			"echo $in: Contains compressed JNI libraries and/or dex files >&2;" +
-			"exit 1; " +
-			"else " +
-			"touch $out; " +
-			"fi",
-		Description: "Check for compressed JNI libs or dex files",
-	})
-
-	checkJniLibsAreUncompressedRule = pctx.AndroidStaticRule("check-jni-libs-are-uncompressed", blueprint.RuleParams{
-		// grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed
-		Command: "if (zipinfo $in 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
-			"echo $in: Contains compressed JNI libraries >&2;" +
-			"exit 1; " +
-			"else " +
-			"touch $out; " +
-			"fi",
-		Description: "Check for compressed JNI libs or dex files",
-	})
+	checkPresignedApkRule = pctx.AndroidStaticRule("check-presigned-apk", blueprint.RuleParams{
+		Command:     "build/soong/scripts/check_prebuilt_presigned_apk.py --aapt2 ${config.Aapt2Cmd} --zipalign ${config.ZipAlign} $extraArgs $in $out",
+		CommandDeps: []string{"build/soong/scripts/check_prebuilt_presigned_apk.py", "${config.Aapt2Cmd}", "${config.ZipAlign}"},
+		Description: "Check presigned apk",
+	}, "extraArgs")
 )
 
 func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
@@ -277,6 +262,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 +281,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
 
@@ -346,25 +337,20 @@
 	// Sign or align the package if package has not been preprocessed
 
 	if proptools.Bool(a.properties.Preprocessed) {
-		var output android.WritablePath
-		if !proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
-			output = android.PathForModuleOut(ctx, "validated-prebuilt", apkFilename)
-			a.validatePreprocessedApk(ctx, srcApk, output)
-		} else {
-			// If using the input APK unmodified, still make a copy of it so that the output filename has the
-			// right basename.
-			output = android.PathForModuleOut(ctx, apkFilename)
-			ctx.Build(pctx, android.BuildParams{
-				Rule:   android.Cp,
-				Input:  srcApk,
-				Output: output,
-			})
-		}
+		validationStamp := a.validatePresignedApk(ctx, srcApk)
+		output := android.PathForModuleOut(ctx, apkFilename)
+		ctx.Build(pctx, android.BuildParams{
+			Rule:       android.Cp,
+			Input:      srcApk,
+			Output:     output,
+			Validation: validationStamp,
+		})
 		a.outputFile = output
 		a.certificate = PresignedCertificate
 	} 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 +363,9 @@
 		SignAppPackage(ctx, signed, jnisUncompressed, certificates, nil, lineageFile, rotationMinSdkVersion)
 		a.outputFile = signed
 	} else {
+		validationStamp := a.validatePresignedApk(ctx, srcApk)
 		alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
-		TransformZipAlign(ctx, alignedApk, jnisUncompressed)
+		TransformZipAlign(ctx, alignedApk, jnisUncompressed, []android.Path{validationStamp})
 		a.outputFile = alignedApk
 		a.certificate = PresignedCertificate
 	}
@@ -394,42 +381,28 @@
 	// TODO: androidmk converter jni libs
 }
 
-func (a *AndroidAppImport) validatePreprocessedApk(ctx android.ModuleContext, srcApk android.Path, dstApk android.WritablePath) {
-	var validations android.Paths
-
-	alignmentStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "alignment.stamp")
-	ctx.Build(pctx, android.BuildParams{
-		Rule:   checkZipAlignment,
-		Input:  srcApk,
-		Output: alignmentStamp,
-	})
-
-	validations = append(validations, alignmentStamp)
-	jniCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "jni_compression.stamp")
-	ctx.Build(pctx, android.BuildParams{
-		Rule:   checkJniLibsAreUncompressedRule,
-		Input:  srcApk,
-		Output: jniCompressionStamp,
-	})
-	validations = append(validations, jniCompressionStamp)
-
+func (a *AndroidAppImport) validatePresignedApk(ctx android.ModuleContext, srcApk android.Path) android.Path {
+	stamp := android.PathForModuleOut(ctx, "validated-prebuilt", "check.stamp")
+	var extraArgs []string
 	if a.Privileged() {
-		// It's ok for non-privileged apps to have compressed dex files, see go/gms-uncompressed-jni-slides
-		dexCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "dex_compression.stamp")
-		ctx.Build(pctx, android.BuildParams{
-			Rule:   checkDexLibsAreUncompressedRule,
-			Input:  srcApk,
-			Output: dexCompressionStamp,
-		})
-		validations = append(validations, dexCompressionStamp)
+		extraArgs = append(extraArgs, "--privileged")
+	}
+	if proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
+		extraArgs = append(extraArgs, "--skip-preprocessed-apk-checks")
+	}
+	if proptools.Bool(a.properties.Preprocessed) {
+		extraArgs = append(extraArgs, "--preprocessed")
 	}
 
 	ctx.Build(pctx, android.BuildParams{
-		Rule:        android.Cp,
-		Input:       srcApk,
-		Output:      dstApk,
-		Validations: validations,
+		Rule:   checkPresignedApkRule,
+		Input:  srcApk,
+		Output: stamp,
+		Args: map[string]string{
+			"extraArgs": strings.Join(extraArgs, " "),
+		},
 	})
+	return stamp
 }
 
 func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
diff --git a/java/app_import_test.go b/java/app_import_test.go
index bb8fab9..8f29bb3 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")
 	}
 }
 
@@ -669,14 +659,19 @@
 
 	apkName := "foo.apk"
 	variant := ctx.ModuleForTests("foo", "android_common")
-	outputBuildParams := variant.Output("validated-prebuilt/" + apkName).BuildParams
+	outputBuildParams := variant.Output(apkName).BuildParams
 	if outputBuildParams.Rule.String() != android.Cp.String() {
 		t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String())
 	}
 
 	// Make sure compression and aligning were validated.
-	if len(outputBuildParams.Validations) != 2 {
-		t.Errorf("Expected compression/alignment validation rules, found %d validations", len(outputBuildParams.Validations))
+	if outputBuildParams.Validation == nil {
+		t.Errorf("Expected validation rule, but was not found")
+	}
+
+	validationBuildParams := variant.Output("validated-prebuilt/check.stamp").BuildParams
+	if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
+		t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String())
 	}
 }
 
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 653323a..fb7b95a 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1077,8 +1077,8 @@
 
 }
 
-func (module *Module) addGeneratedSrcJars(path android.Path) {
-	module.properties.Generated_srcjars = append(module.properties.Generated_srcjars, path)
+func (j *Module) addGeneratedSrcJars(path android.Path) {
+	j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path)
 }
 
 func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) {
@@ -1615,7 +1615,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
@@ -2366,7 +2366,7 @@
 
 var _ ModuleWithStem = (*Module)(nil)
 
-func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (j *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	switch ctx.ModuleType() {
 	case "java_library", "java_library_host", "java_library_static", "tradefed_java_library_host":
 		if lib, ok := ctx.Module().(*Library); ok {
diff --git a/java/builder.go b/java/builder.go
index debf49a..ee7e225 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -259,19 +259,6 @@
 		},
 	)
 
-	checkZipAlignment = pctx.AndroidStaticRule("checkzipalign",
-		blueprint.RuleParams{
-			Command: "if ! ${config.ZipAlign} -c -p 4 $in > /dev/null; then " +
-				"echo $in: Improper package alignment >&2; " +
-				"exit 1; " +
-				"else " +
-				"touch $out; " +
-				"fi",
-			CommandDeps: []string{"${config.ZipAlign}"},
-			Description: "Check zip alignment",
-		},
-	)
-
 	convertImplementationJarToHeaderJarRule = pctx.AndroidStaticRule("convertImplementationJarToHeaderJar",
 		blueprint.RuleParams{
 			Command:     `${config.Zip2ZipCmd} -i ${in} -o ${out} -x 'META-INF/services/**/*'`,
@@ -689,12 +676,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/device_host_converter.go b/java/device_host_converter.go
index 5460dc9..c5ba245 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -198,7 +198,7 @@
 	Exports bazel.LabelListAttribute
 }
 
-func (d *DeviceHostConverter) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (d *DeviceHostConverter) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	ctx.CreateBazelTargetModule(
 		bazel.BazelTargetModuleProperties{
 			Rule_class:        "java_host_for_device",
diff --git a/java/dex.go b/java/dex.go
index 21937e1..c1d51c7 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -315,15 +315,14 @@
 
 	if BoolDefault(opt.Proguard_compatibility, true) {
 		r8Flags = append(r8Flags, "--force-proguard-compatibility")
-	} else {
+	}
+
+	if Bool(opt.Optimize) || Bool(opt.Obfuscate) {
 		// TODO(b/213833843): Allow configuration of the prefix via a build variable.
 		var sourceFilePrefix = "go/retraceme "
 		var sourceFileTemplate = "\"" + sourceFilePrefix + "%MAP_ID\""
-		// TODO(b/200967150): Also tag the source file in compat builds.
-		if Bool(opt.Optimize) || Bool(opt.Obfuscate) {
-			r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH")
-			r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate)
-		}
+		r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH")
+		r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate)
 	}
 
 	// TODO(ccross): Don't shrink app instrumentation tests by default.
@@ -450,7 +449,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/droiddoc.go b/java/droiddoc.go
index 3ba3065..d5547d0 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -22,6 +22,7 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/bazel"
 	"android/soong/java/config"
 )
 
@@ -844,6 +845,7 @@
 
 type ExportedDroiddocDir struct {
 	android.ModuleBase
+	android.BazelModuleBase
 
 	properties ExportedDroiddocDirProperties
 
@@ -856,6 +858,7 @@
 	module := &ExportedDroiddocDir{}
 	module.AddProperties(&module.properties)
 	android.InitAndroidModule(module)
+	android.InitBazelModule(module)
 	return module
 }
 
@@ -867,6 +870,28 @@
 	d.deps = android.PathsForModuleSrc(ctx, []string{filepath.Join(path, "**/*")})
 }
 
+// ConvertWithBp2build implements android.BazelModule.
+func (d *ExportedDroiddocDir) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	props := bazel.BazelTargetModuleProperties{
+		// Use the native py_library rule.
+		Rule_class:        "droiddoc_exported_dir",
+		Bzl_load_location: "//build/bazel/rules/droiddoc:droiddoc_exported_dir.bzl",
+	}
+
+	type BazelAttrs struct {
+		Dir  *string
+		Srcs bazel.LabelListAttribute
+	}
+
+	attrs := &BazelAttrs{
+		Dir:  proptools.StringPtr(*d.properties.Path),
+		Srcs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, []string{filepath.Join(*d.properties.Path, "**/*")})),
+	}
+
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: d.Name()}, attrs)
+
+}
+
 // Defaults
 type DocDefaults struct {
 	android.ModuleBase
diff --git a/java/droidstubs.go b/java/droidstubs.go
index f05ef1f..67a55bd 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -24,7 +24,6 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
-	"android/soong/bazel"
 	"android/soong/java/config"
 	"android/soong/remoteexec"
 )
@@ -539,7 +538,7 @@
 
 	// 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")
+	cmd.FlagWithArg("--format-defaults ", "overloaded-method-order=source")
 
 	return cmd
 }
@@ -855,34 +854,6 @@
 	}
 }
 
-var _ android.ApiProvider = (*Droidstubs)(nil)
-
-type bazelJavaApiContributionAttributes struct {
-	Api         bazel.LabelAttribute
-	Api_surface *string
-}
-
-func (d *Droidstubs) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class:        "java_api_contribution",
-		Bzl_load_location: "//build/bazel/rules/apis:java_api_contribution.bzl",
-	}
-	apiFile := d.properties.Check_api.Current.Api_file
-	// Do not generate a target if check_api is not set
-	if apiFile == nil {
-		return
-	}
-	attrs := &bazelJavaApiContributionAttributes{
-		Api: *bazel.MakeLabelAttribute(
-			android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label,
-		),
-		Api_surface: proptools.StringPtr(bazelApiSurfaceName(d.Name())),
-	}
-	ctx.CreateBazelTargetModule(props, android.CommonAttributes{
-		Name: android.ApiContributionTargetName(ctx.ModuleName()),
-	}, attrs)
-}
-
 func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
 	api_file := d.properties.Check_api.Current.Api_file
 	api_surface := d.properties.Api_surface
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 521aef3..bf692be 100644
--- a/java/java.go
+++ b/java/java.go
@@ -64,6 +64,7 @@
 	ctx.RegisterModuleType("dex_import", DexImportFactory)
 	ctx.RegisterModuleType("java_api_library", ApiLibraryFactory)
 	ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory)
+	ctx.RegisterModuleType("java_api_contribution_import", ApiContributionImportFactory)
 
 	// This mutator registers dependencies on dex2oat for modules that should be
 	// dexpreopted. This is done late when the final variants have been
@@ -1623,7 +1624,8 @@
 }
 
 type JavaApiImportInfo struct {
-	ApiFile android.Path
+	ApiFile    android.Path
+	ApiSurface string
 }
 
 var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{})
@@ -1635,7 +1637,8 @@
 	}
 
 	ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{
-		ApiFile: apiFile,
+		ApiFile:    apiFile,
+		ApiSurface: proptools.String(ap.properties.Api_surface),
 	})
 }
 
@@ -1664,11 +1667,6 @@
 	// This is a list of Soong modules
 	Api_contributions []string
 
-	// list of api.txt files relative to this directory that contribute to the
-	// API surface.
-	// This is a list of relative paths
-	Api_files []string `android:"path"`
-
 	// List of flags to be passed to the javac compiler to generate jar file
 	Javacflags []string
 
@@ -1798,6 +1796,7 @@
 		Flag("-jar").
 		Flag("-write_if_changed").
 		Flag("-ignore_missing_files").
+		Flag("-quiet").
 		FlagWithArg("-C ", unzippedSrcJarDir.String()).
 		FlagWithInput("-l ", classFilesList).
 		FlagWithOutput("-o ", al.stubsJarWithoutStaticLibs)
@@ -1815,26 +1814,22 @@
 	}
 }
 
-// API signature file names sorted from
-// the narrowest api scope to the widest api scope
-var scopeOrderedSourceFileNames = allApiScopes.Strings(
-	func(s *apiScope) string { return s.apiFilePrefix + "current.txt" })
+// Map where key is the api scope name and value is the int value
+// representing the order of the api scope, narrowest to the widest
+var scopeOrderMap = allApiScopes.MapToIndex(
+	func(s *apiScope) string { return s.name })
 
-func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFiles android.Paths) android.Paths {
-	sortedSrcFiles := android.Paths{}
-
-	for _, scopeSourceFileName := range scopeOrderedSourceFileNames {
-		for _, sourceFileName := range srcFiles {
-			if sourceFileName.Base() == scopeSourceFileName {
-				sortedSrcFiles = append(sortedSrcFiles, sourceFileName)
-			}
+func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo {
+	for _, srcFileInfo := range srcFilesInfo {
+		if srcFileInfo.ApiSurface == "" {
+			ctx.ModuleErrorf("Api surface not defined for the associated api file %s", srcFileInfo.ApiFile)
 		}
 	}
-	if len(srcFiles) != len(sortedSrcFiles) {
-		ctx.ModuleErrorf("Unrecognizable source file found within %s", srcFiles)
-	}
+	sort.Slice(srcFilesInfo, func(i, j int) bool {
+		return scopeOrderMap[srcFilesInfo[i].ApiSurface] < scopeOrderMap[srcFilesInfo[j].ApiSurface]
+	})
 
-	return sortedSrcFiles
+	return srcFilesInfo
 }
 
 func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1852,7 +1847,7 @@
 
 	homeDir := android.PathForModuleOut(ctx, "metalava", "home")
 
-	var srcFiles android.Paths
+	var srcFilesInfo []JavaApiImportInfo
 	var classPaths android.Paths
 	var staticLibs android.Paths
 	var depApiSrcsStubsJar android.Path
@@ -1861,11 +1856,10 @@
 		switch tag {
 		case javaApiContributionTag:
 			provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo)
-			providerApiFile := provider.ApiFile
-			if providerApiFile == nil && !ctx.Config().AllowMissingDependencies() {
+			if provider.ApiFile == nil && !ctx.Config().AllowMissingDependencies() {
 				ctx.ModuleErrorf("Error: %s has an empty api file.", dep.Name())
 			}
-			srcFiles = append(srcFiles, android.PathForSource(ctx, providerApiFile.String()))
+			srcFilesInfo = append(srcFilesInfo, provider)
 		case libTag:
 			provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
 			classPaths = append(classPaths, provider.HeaderJars...)
@@ -1878,17 +1872,16 @@
 		}
 	})
 
-	// Add the api_files inputs
-	for _, api := range al.properties.Api_files {
-		srcFiles = append(srcFiles, android.PathForModuleSrc(ctx, api))
+	srcFilesInfo = al.sortApiFilesByApiScope(ctx, srcFilesInfo)
+	var srcFiles android.Paths
+	for _, srcFileInfo := range srcFilesInfo {
+		srcFiles = append(srcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String()))
 	}
 
 	if srcFiles == nil && !ctx.Config().AllowMissingDependencies() {
 		ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
 	}
 
-	srcFiles = al.sortApiFilesByApiScope(ctx, srcFiles)
-
 	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
 
 	al.stubsFlags(ctx, cmd, stubsDir)
@@ -2758,7 +2751,7 @@
 	Additional_resources  bazel.LabelListAttribute
 }
 
-func (m *Library) getResourceFilegroupStripPrefix(ctx android.TopDownMutatorContext, resourceFilegroup string) (*string, bool) {
+func (m *Library) getResourceFilegroupStripPrefix(ctx android.Bp2buildMutatorContext, resourceFilegroup string) (*string, bool) {
 	if otherM, ok := ctx.ModuleFromName(resourceFilegroup); ok {
 		if fg, isFilegroup := otherM.(android.FileGroupPath); isFilegroup {
 			return proptools.StringPtr(filepath.Join(ctx.OtherModuleDir(otherM), fg.GetPath(ctx))), true
@@ -2767,7 +2760,7 @@
 	return proptools.StringPtr(""), false
 }
 
-func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorContext) *javaResourcesAttributes {
+func (m *Library) convertJavaResourcesAttributes(ctx android.Bp2buildMutatorContext) *javaResourcesAttributes {
 	var resources bazel.LabelList
 	var resourceStripPrefix *string
 
@@ -2826,7 +2819,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",
@@ -2898,14 +2891,19 @@
 // which has other non-attribute information needed for bp2build conversion
 // that needs different handling depending on the module types, and thus needs
 // to be returned to the calling function.
-func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo, bool) {
+func (m *Library) convertLibraryAttrsBp2Build(ctx android.Bp2buildMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo, bool) {
 	var srcs bazel.LabelListAttribute
 	var deps bazel.LabelListAttribute
 	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{})
@@ -3045,17 +3043,6 @@
 		}
 	}
 
-	protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])
-	// Soong does not differentiate between a java_library and the Bazel equivalent of
-	// a java_proto_library + proto_library pair. Instead, in Soong proto sources are
-	// listed directly in the srcs of a java_library, and the classes produced
-	// by protoc are included directly in the resulting JAR. Thus upstream dependencies
-	// that depend on a java_library with proto sources can link directly to the protobuf API,
-	// and so this should be a static dependency.
-	if protoDepLabel != nil {
-		staticDeps.Append(bazel.MakeSingleLabelListAttribute(*protoDepLabel))
-	}
-
 	depLabels := &javaDependencyLabels{}
 	depLabels.Deps = deps
 
@@ -3071,6 +3058,20 @@
 	}
 	depLabels.StaticDeps.Append(staticDeps)
 
+	var additionalProtoDeps bazel.LabelListAttribute
+	additionalProtoDeps.Append(depLabels.Deps)
+	additionalProtoDeps.Append(depLabels.StaticDeps)
+	protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition], additionalProtoDeps)
+	// Soong does not differentiate between a java_library and the Bazel equivalent of
+	// a java_proto_library + proto_library pair. Instead, in Soong proto sources are
+	// listed directly in the srcs of a java_library, and the classes produced
+	// by protoc are included directly in the resulting JAR. Thus upstream dependencies
+	// that depend on a java_library with proto sources can link directly to the protobuf API,
+	// and so this should be a static dependency.
+	if protoDepLabel != nil {
+		depLabels.StaticDeps.Append(bazel.MakeSingleLabelListAttribute(*protoDepLabel))
+	}
+
 	hasKotlin := !kotlinSrcs.IsEmpty()
 	commonAttrs.kotlinAttributes = &kotlinAttributes{
 		Kotlincflags: &m.properties.Kotlincflags,
@@ -3114,7 +3115,7 @@
 	}
 }
 
-func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
+func javaLibraryBp2Build(ctx android.Bp2buildMutatorContext, m *Library) {
 	commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx)
 	if !supported {
 		return
@@ -3122,16 +3123,22 @@
 	depLabels := bp2BuildInfo.DepLabels
 
 	deps := depLabels.Deps
+	exports := depLabels.StaticDeps
 	if !commonAttrs.Srcs.IsEmpty() {
-		deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
+		deps.Append(exports) // we should only append these if there are sources to use them
 	} else if !deps.IsEmpty() {
-		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
+		// java_library does not accept deps when there are no srcs because
+		// there is no compilation happening, but it accepts exports.
+		// The non-empty deps here are unnecessary as deps on the java_library
+		// since they aren't being propagated to any dependencies.
+		// So we can drop deps here.
+		deps = bazel.LabelListAttribute{}
 	}
 	var props bazel.BazelTargetModuleProperties
 	attrs := &javaLibraryAttributes{
 		javaCommonAttributes: commonAttrs,
 		Deps:                 deps,
-		Exports:              depLabels.StaticDeps,
+		Exports:              exports,
 	}
 	name := m.Name()
 
@@ -3164,7 +3171,7 @@
 }
 
 // JavaBinaryHostBp2Build is for java_binary_host bp2build.
-func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
+func javaBinaryHostBp2Build(ctx android.Bp2buildMutatorContext, m *Binary) {
 	commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx)
 	if !supported {
 		return
@@ -3251,7 +3258,7 @@
 }
 
 // javaTestHostBp2Build is for java_test_host bp2build.
-func javaTestHostBp2Build(ctx android.TopDownMutatorContext, m *TestHost) {
+func javaTestHostBp2Build(ctx android.Bp2buildMutatorContext, m *TestHost) {
 	commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx)
 	if !supported {
 		return
@@ -3304,7 +3311,7 @@
 
 // helper function that creates java_library target from java_binary_host or java_test_host,
 // and returns the library target name,
-func createLibraryTarget(ctx android.TopDownMutatorContext, libInfo libraryCreationInfo) string {
+func createLibraryTarget(ctx android.Bp2buildMutatorContext, libInfo libraryCreationInfo) string {
 	libName := libInfo.baseName + "_lib"
 	var libProps bazel.BazelTargetModuleProperties
 	if libInfo.hasKotlin {
@@ -3327,7 +3334,7 @@
 }
 
 // java_import bp2Build converter.
-func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (i *Import) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	var jars bazel.LabelListAttribute
 	archVariantProps := i.GetArchVariantProperties(ctx, &ImportProperties{})
 	for axis, configToProps := range archVariantProps {
@@ -3363,7 +3370,6 @@
 		javaLibraryBazelTargetModuleProperties(),
 		android.CommonAttributes{Name: name + "-neverlink"},
 		neverlinkAttrs)
-
 }
 
 var _ android.MixedBuildBuildable = (*Import)(nil)
@@ -3416,3 +3422,30 @@
 func (i *Import) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
 	return true
 }
+
+type JavaApiContributionImport struct {
+	JavaApiContribution
+
+	prebuilt android.Prebuilt
+}
+
+func ApiContributionImportFactory() android.Module {
+	module := &JavaApiContributionImport{}
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	android.InitPrebuiltModule(module, &[]string{""})
+	module.AddProperties(&module.properties)
+	return module
+}
+
+func (module *JavaApiContributionImport) Prebuilt() *android.Prebuilt {
+	return &module.prebuilt
+}
+
+func (module *JavaApiContributionImport) Name() string {
+	return module.prebuilt.Name(module.ModuleBase.Name())
+}
+
+func (ap *JavaApiContributionImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	ap.JavaApiContribution.GenerateAndroidBuildActions(ctx)
+}
diff --git a/java/java_test.go b/java/java_test.go
index 27933c3..b555a95 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1865,11 +1865,13 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	ctx, _ := testJavaWithFS(t, `
@@ -1883,7 +1885,6 @@
 			name: "bar2",
 			api_surface: "system",
 			api_contributions: ["foo1", "foo2"],
-			api_files: ["api1/current.txt", "api2/current.txt"]
 		}
 		`,
 		map[string][]byte{
@@ -1901,7 +1902,7 @@
 		},
 		{
 			moduleName:         "bar2",
-			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "api1/current.txt", "api2/current.txt"},
+			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
 		},
 	}
 	for _, c := range testcases {
@@ -1919,24 +1920,28 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_c := `
 	java_api_contribution {
 		name: "foo3",
-		api_file: "current.txt",
+		api_file: "system-current.txt",
+		api_surface: "system",
 	}
 	`
 	provider_bp_d := `
 	java_api_contribution {
 		name: "foo4",
-		api_file: "current.txt",
+		api_file: "system-current.txt",
+		api_surface: "system",
 	}
 	`
 	ctx, _ := testJavaWithFS(t, `
@@ -1969,7 +1974,6 @@
 			api_surface: "system",
 			defaults:["baz1", "baz2"],
 			api_contributions: ["foo4"],
-			api_files: ["api1/current.txt", "api2/current.txt"]
 		}
 		`,
 		map[string][]byte{
@@ -1992,8 +1996,9 @@
 			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
 		},
 		{
-			moduleName:         "bar3",
-			sourceTextFileDirs: []string{"c/current.txt", "a/current.txt", "b/current.txt", "d/current.txt", "api1/current.txt", "api2/current.txt"},
+			moduleName: "bar3",
+			// API text files need to be sorted from the narrower api scope to the wider api scope
+			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "c/system-current.txt", "d/system-current.txt"},
 		},
 	}
 	for _, c := range testcases {
@@ -2011,12 +2016,14 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	ctx, _ := testJavaWithFS(t, `
@@ -2064,12 +2071,14 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	lib_bp_a := `
@@ -2139,12 +2148,14 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	lib_bp_a := `
@@ -2213,12 +2224,14 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	lib_bp_a := `
@@ -2250,29 +2263,6 @@
 	android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar")
 }
 
-func TestJavaApiLibraryFilegroupInput(t *testing.T) {
-	ctx, _ := testJavaWithFS(t, `
-	    filegroup {
-			name: "default_current.txt",
-			srcs: ["current.txt"],
-		}
-
-		java_api_library {
-			name: "foo",
-			api_files: [":default_current.txt"],
-		}
-		`,
-		map[string][]byte{
-			"current.txt": nil,
-		})
-
-	m := ctx.ModuleForTests("foo", "android_common")
-	outputs := fmt.Sprint(m.AllOutputs())
-	if !strings.Contains(outputs, "foo/foo.jar") {
-		t.Errorf("Module output does not contain expected jar %s", "foo/foo.jar")
-	}
-}
-
 func TestTradefedOptions(t *testing.T) {
 	result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
 java_test_host {
@@ -2388,3 +2378,50 @@
 	javac := ctx.ModuleForTests("foo", "android_common").MaybeRule("javac")
 	android.AssertDeepEquals(t, "javac rule", nil, javac.Rule)
 }
+
+func TestJavaApiContributionImport(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_api_library {
+			name: "foo",
+			api_contributions: ["bar"],
+		}
+		java_api_contribution_import {
+			name: "bar",
+			api_file: "current.txt",
+			api_surface: "public",
+		}
+	`)
+	m := ctx.ModuleForTests("foo", "android_common")
+	manifest := m.Output("metalava.sbox.textproto")
+	sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+	manifestCommand := sboxProto.Commands[0].GetCommand()
+	sourceFilesFlag := "--source-files current.txt"
+	android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
+}
+
+func TestJavaApiLibraryApiFilesSorting(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_api_library {
+			name: "foo",
+			api_contributions: [
+				"system-server-api-stubs-docs-non-updatable.api.contribution",
+				"test-api-stubs-docs-non-updatable.api.contribution",
+				"system-api-stubs-docs-non-updatable.api.contribution",
+				"module-lib-api-stubs-docs-non-updatable.api.contribution",
+				"api-stubs-docs-non-updatable.api.contribution",
+			],
+		}
+	`)
+	m := ctx.ModuleForTests("foo", "android_common")
+	manifest := m.Output("metalava.sbox.textproto")
+	sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+	manifestCommand := sboxProto.Commands[0].GetCommand()
+
+	// Api files are sorted from the narrowest api scope to the widest api scope.
+	// test api and module lib api surface do not have subset/superset relationship,
+	// but they will never be passed as inputs at the same time.
+	sourceFilesFlag := "--source-files default/java/api/current.txt " +
+		"default/java/api/system-current.txt default/java/api/test-current.txt " +
+		"default/java/api/module-lib-current.txt default/java/api/system-server-current.txt"
+	android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag)
+}
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 1248275..662a2d7 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -130,7 +130,7 @@
 	Src bazel.LabelAttribute
 }
 
-func (p *platformCompatConfig) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (p *platformCompatConfig) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	props := bazel.BazelTargetModuleProperties{
 		Rule_class:        "platform_compat_config",
 		Bzl_load_location: "//build/bazel/rules/java:platform_compat_config.bzl",
diff --git a/java/plugin.go b/java/plugin.go
index 5127298..4d4c199 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -64,7 +64,7 @@
 }
 
 // ConvertWithBp2build is used to convert android_app to Bazel.
-func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (p *Plugin) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	pluginName := p.Name()
 	commonAttrs, bp2BuildInfo, supported := p.convertLibraryAttrsBp2Build(ctx)
 	if !supported {
diff --git a/java/proto.go b/java/proto.go
index 2ed7b27..48adadc 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -151,11 +151,17 @@
 	// a specific .proto file module explicitly.
 	Transitive_deps bazel.LabelListAttribute
 
+	// This is the libs and the static_libs of the original java_library module.
+	// On the bazel side, after proto sources are generated in java_*_proto_library, a java_library
+	// will compile them. The libs and static_libs from the original java_library module need
+	// to be linked because they are necessary in compile-time classpath.
+	Additional_proto_deps bazel.LabelListAttribute
+
 	Sdk_version  bazel.StringAttribute
 	Java_version bazel.StringAttribute
 }
 
-func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) *bazel.Label {
+func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute, AdditionalProtoDeps bazel.LabelListAttribute) *bazel.Label {
 	protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs)
 	if !ok {
 		return nil
@@ -184,10 +190,11 @@
 	}
 
 	protoAttrs := &protoAttributes{
-		Deps:            bazel.MakeLabelListAttribute(protoInfo.Proto_libs),
-		Transitive_deps: bazel.MakeLabelListAttribute(protoInfo.Transitive_proto_libs),
-		Java_version:    bazel.StringAttribute{Value: m.properties.Java_version},
-		Sdk_version:     bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
+		Deps:                  bazel.MakeLabelListAttribute(protoInfo.Proto_libs),
+		Transitive_deps:       bazel.MakeLabelListAttribute(protoInfo.Transitive_proto_libs),
+		Additional_proto_deps: AdditionalProtoDeps,
+		Java_version:          bazel.StringAttribute{Value: m.properties.Java_version},
+		Sdk_version:           bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
 	}
 
 	name := m.Name() + suffix
diff --git a/java/sdk_library.go b/java/sdk_library.go
index b1ddde0..e410a41 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -286,6 +286,17 @@
 	return list
 }
 
+// Method that maps the apiScopes properties to the index of each apiScopes elements.
+// apiScopes property to be used as the key can be specified with the input accessor.
+// Only a string property of apiScope can be used as the key of the map.
+func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]int {
+	ret := make(map[string]int)
+	for i, scope := range scopes {
+		ret[accessor(scope)] = i
+	}
+	return ret
+}
+
 var (
 	scopeByName    = make(map[string]*apiScope)
 	allScopeNames  []string
@@ -1633,7 +1644,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 +1840,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{}
 
@@ -2276,27 +2287,25 @@
 }
 
 type bazelSdkLibraryAttributes struct {
-	Public        bazel.StringAttribute
-	System        bazel.StringAttribute
-	Test          bazel.StringAttribute
-	Module_lib    bazel.StringAttribute
-	System_server bazel.StringAttribute
+	Public        *bazel.Label
+	System        *bazel.Label
+	Test          *bazel.Label
+	Module_lib    *bazel.Label
+	System_server *bazel.Label
 }
 
 // java_sdk_library bp2build converter
-func (module *SdkLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (module *SdkLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	if ctx.ModuleType() != "java_sdk_library" {
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
 		return
 	}
 
-	nameToAttr := make(map[string]bazel.StringAttribute)
+	nameToAttr := make(map[string]*bazel.Label)
 
 	for _, scope := range module.getGeneratedApiScopes(ctx) {
-		apiSurfaceFile := path.Join(module.getApiDir(), scope.apiFilePrefix+"current.txt")
-		var scopeStringAttribute bazel.StringAttribute
-		scopeStringAttribute.SetValue(apiSurfaceFile)
-		nameToAttr[scope.name] = scopeStringAttribute
+		apiSurfaceFile := android.BazelLabelForModuleSrcSingle(ctx, path.Join(module.getApiDir(), scope.apiFilePrefix+"current.txt"))
+		nameToAttr[scope.name] = &apiSurfaceFile
 	}
 
 	attrs := bazelSdkLibraryAttributes{
@@ -2355,6 +2364,7 @@
 type SdkLibraryImport struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.BazelModuleBase
 	prebuilt android.Prebuilt
 	android.ApexModuleBase
 
@@ -2438,6 +2448,7 @@
 
 	android.InitPrebuiltModule(module, &[]string{""})
 	android.InitApexModule(module)
+	android.InitBazelModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
 
 	module.SetDefaultableHook(func(mctx android.DefaultableHookContext) {
@@ -2448,6 +2459,33 @@
 	return module
 }
 
+// java_sdk_library bp2build converter
+func (i *SdkLibraryImport) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	nameToAttr := make(map[string]*bazel.Label)
+
+	for scope, props := range i.scopeProperties {
+		if api := proptools.String(props.Current_api); api != "" {
+			apiSurfaceFile := android.BazelLabelForModuleSrcSingle(ctx, api)
+			nameToAttr[scope.name] = &apiSurfaceFile
+		}
+	}
+
+	attrs := bazelSdkLibraryAttributes{
+		Public:        nameToAttr["public"],
+		System:        nameToAttr["system"],
+		Test:          nameToAttr["test"],
+		Module_lib:    nameToAttr["module-lib"],
+		System_server: nameToAttr["system-server"],
+	}
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "java_sdk_library",
+		Bzl_load_location: "//build/bazel/rules/java:sdk_library.bzl",
+	}
+
+	name := android.RemoveOptionalPrebuiltPrefix(i.Name())
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, &attrs)
+}
+
 var _ PermittedPackagesForUpdatableBootJars = (*SdkLibraryImport)(nil)
 
 func (module *SdkLibraryImport) PermittedPackagesForUpdatableBootJars() []string {
@@ -2479,6 +2517,10 @@
 		if len(scopeProperties.Stub_srcs) > 0 {
 			module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
 		}
+
+		if scopeProperties.Current_api != nil {
+			module.createPrebuiltApiContribution(mctx, apiScope, scopeProperties)
+		}
 	}
 
 	javaSdkLibraries := javaSdkLibraries(mctx.Config())
@@ -2534,6 +2576,25 @@
 	mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
 }
 
+func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+	api_file := scopeProperties.Current_api
+	api_surface := &apiScope.name
+
+	props := struct {
+		Name        *string
+		Api_surface *string
+		Api_file    *string
+		Visibility  []string
+	}{}
+
+	props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution")
+	props.Api_surface = api_surface
+	props.Api_file = api_file
+	props.Visibility = []string{"//visibility:override", "//visibility:public"}
+
+	mctx.CreateModule(ApiContributionImportFactory, &props)
+}
+
 // Add the dependencies on the child module in the component deps mutator so that it
 // creates references to the prebuilt and not the source modules.
 func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 118f8b6..0b46919 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -74,6 +74,8 @@
 		    name: "quuz",
 				public: {
 					jars: ["c.jar"],
+					current_api: "api/current.txt",
+					removed_api: "api/removed.txt",
 				},
 		}
 		java_sdk_library_import {
@@ -173,6 +175,9 @@
 		android.AssertDeepEquals(t, "qux exports (optional)", []string{}, optionalSdkLibs)
 	}
 
+	// test if quuz have created the api_contribution module
+	result.ModuleForTests(apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "")
+
 	fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8")
 	// tests if kotlinc generated files are NOT excluded from output of foo.
 	android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
@@ -1474,3 +1479,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/java/testing.go b/java/testing.go
index f2bcccf..98bea7f 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -424,30 +424,80 @@
 		`, extra)
 	}
 
-	extraApiLibraryModules := map[string]string{
-		"android_stubs_current.from-text":                  "api/current.txt",
-		"android_system_stubs_current.from-text":           "api/system-current.txt",
-		"android_test_stubs_current.from-text":             "api/test-current.txt",
-		"android_module_lib_stubs_current.from-text":       "api/module-lib-current.txt",
-		"android_module_lib_stubs_current_full.from-text":  "api/module-lib-current.txt",
-		"android_system_server_stubs_current.from-text":    "api/system-server-current.txt",
-		"core.current.stubs.from-text":                     "api/current.txt",
-		"legacy.core.platform.api.stubs.from-text":         "api/current.txt",
-		"stable.core.platform.api.stubs.from-text":         "api/current.txt",
-		"core-lambda-stubs.from-text":                      "api/current.txt",
-		"android-non-updatable.stubs.from-text":            "api/current.txt",
-		"android-non-updatable.stubs.system.from-text":     "api/system-current.txt",
-		"android-non-updatable.stubs.test.from-text":       "api/test-current.txt",
-		"android-non-updatable.stubs.module_lib.from-text": "api/module-lib-current.txt",
+	type apiContributionStruct struct {
+		name       string
+		apiSurface string
+		apiFile    string
 	}
 
-	for libName, apiFile := range extraApiLibraryModules {
+	var publicApiContribution = apiContributionStruct{
+		name:       "api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "public",
+		apiFile:    "api/current.txt",
+	}
+	var systemApiContribution = apiContributionStruct{
+		name:       "system-api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "system",
+		apiFile:    "api/system-current.txt",
+	}
+	var testApiContribution = apiContributionStruct{
+		name:       "test-api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "test",
+		apiFile:    "api/test-current.txt",
+	}
+	var moduleLibApiContribution = apiContributionStruct{
+		name:       "module-lib-api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "module-lib",
+		apiFile:    "api/module-lib-current.txt",
+	}
+	var systemServerApiContribution = apiContributionStruct{
+		// This module does not exist but is named this way for consistency
+		name:       "system-server-api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "system-server",
+		apiFile:    "api/system-server-current.txt",
+	}
+	var apiContributionStructs = []apiContributionStruct{
+		publicApiContribution,
+		systemApiContribution,
+		testApiContribution,
+		moduleLibApiContribution,
+		systemServerApiContribution,
+	}
+
+	extraApiLibraryModules := map[string]apiContributionStruct{
+		"android_stubs_current.from-text":                  publicApiContribution,
+		"android_system_stubs_current.from-text":           systemApiContribution,
+		"android_test_stubs_current.from-text":             testApiContribution,
+		"android_module_lib_stubs_current.from-text":       moduleLibApiContribution,
+		"android_module_lib_stubs_current_full.from-text":  moduleLibApiContribution,
+		"android_system_server_stubs_current.from-text":    systemServerApiContribution,
+		"core.current.stubs.from-text":                     publicApiContribution,
+		"legacy.core.platform.api.stubs.from-text":         publicApiContribution,
+		"stable.core.platform.api.stubs.from-text":         publicApiContribution,
+		"core-lambda-stubs.from-text":                      publicApiContribution,
+		"android-non-updatable.stubs.from-text":            publicApiContribution,
+		"android-non-updatable.stubs.system.from-text":     systemApiContribution,
+		"android-non-updatable.stubs.test.from-text":       testApiContribution,
+		"android-non-updatable.stubs.module_lib.from-text": moduleLibApiContribution,
+	}
+
+	for _, apiContribution := range apiContributionStructs {
+		bp += fmt.Sprintf(`
+			java_api_contribution {
+				name: "%s",
+				api_surface: "%s",
+				api_file: "%s",
+			}
+		`, apiContribution.name, apiContribution.apiSurface, apiContribution.apiFile)
+	}
+
+	for libName, apiContribution := range extraApiLibraryModules {
 		bp += fmt.Sprintf(`
             java_api_library {
                 name: "%s",
-                api_files: ["%s"],
+                api_contributions: ["%s"],
             }
-        `, libName, apiFile)
+        `, libName, apiContribution.name)
 	}
 
 	bp += `
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index 165697d..dad5892 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -107,7 +107,7 @@
 	Src bazel.LabelAttribute
 }
 
-func (l *linkerConfig) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (l *linkerConfig) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	if l.properties.Src == nil {
 		ctx.PropertyErrorf("src", "empty src is not supported")
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "")
diff --git a/python/bp2build.go b/python/bp2build.go
index 8bc3d0a..3b283e4 100644
--- a/python/bp2build.go
+++ b/python/bp2build.go
@@ -54,7 +54,7 @@
 	Imports bazel.StringListAttribute
 }
 
-func (m *PythonLibraryModule) makeArchVariantBaseAttributes(ctx android.TopDownMutatorContext) baseAttributes {
+func (m *PythonLibraryModule) makeArchVariantBaseAttributes(ctx android.Bp2buildMutatorContext) baseAttributes {
 	var attrs baseAttributes
 	archVariantBaseProps := m.GetArchVariantProperties(ctx, &BaseProperties{})
 	for axis, configToProps := range archVariantBaseProps {
@@ -123,7 +123,7 @@
 	return attrs
 }
 
-func (m *PythonLibraryModule) bp2buildPythonVersion(ctx android.TopDownMutatorContext) *string {
+func (m *PythonLibraryModule) bp2buildPythonVersion(ctx android.Bp2buildMutatorContext) *string {
 	py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, true)
 	py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
 	if py2Enabled && !py3Enabled {
@@ -146,7 +146,7 @@
 	Imports        bazel.StringListAttribute
 }
 
-func (p *PythonLibraryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (p *PythonLibraryModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	// TODO(b/182306917): this doesn't fully handle all nested props versioned
 	// by the python version, which would have been handled by the version split
 	// mutator. This is sufficient for very simple python_library modules under
@@ -176,7 +176,7 @@
 	}, attrs)
 }
 
-func (p *PythonBinaryModule) bp2buildBinaryProperties(ctx android.TopDownMutatorContext) (*bazelPythonBinaryAttributes, bazel.LabelListAttribute) {
+func (p *PythonBinaryModule) bp2buildBinaryProperties(ctx android.Bp2buildMutatorContext) (*bazelPythonBinaryAttributes, bazel.LabelListAttribute) {
 	// TODO(b/182306917): this doesn't fully handle all nested props versioned
 	// by the python version, which would have been handled by the version split
 	// mutator. This is sufficient for very simple python_binary_host modules
@@ -209,7 +209,7 @@
 	return attrs, baseAttrs.Data
 }
 
-func (p *PythonBinaryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (p *PythonBinaryModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	attrs, data := p.bp2buildBinaryProperties(ctx)
 
 	props := bazel.BazelTargetModuleProperties{
@@ -223,7 +223,7 @@
 	}, attrs)
 }
 
-func (p *PythonTestModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (p *PythonTestModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	// Python tests are currently exactly the same as binaries, but with a different module type
 	attrs, data := p.bp2buildBinaryProperties(ctx)
 
diff --git a/rust/binary.go b/rust/binary.go
index 1e24beb..1408ff1 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -15,9 +15,10 @@
 package rust
 
 import (
+	"fmt"
+
 	"android/soong/android"
 	"android/soong/bazel"
-	"fmt"
 )
 
 func init() {
@@ -199,7 +200,7 @@
 	Rustc_flags     bazel.StringListAttribute
 }
 
-func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+func binaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) {
 	binary := m.compiler.(*binaryDecorator)
 
 	var srcs bazel.LabelList
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/config/arm64_device.go b/rust/config/arm64_device.go
index 08ac2ef..564168b 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -21,7 +21,9 @@
 )
 
 var (
-	Arm64RustFlags            = []string{}
+	Arm64RustFlags = []string{
+		"-C force-frame-pointers=y",
+	}
 	Arm64ArchFeatureRustFlags = map[string][]string{}
 	Arm64LinkFlags            = []string{}
 
diff --git a/rust/config/global.go b/rust/config/global.go
index 4bd495d..c976617 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -25,7 +25,7 @@
 	pctx         = android.NewPackageContext("android/soong/rust/config")
 	exportedVars = android.NewExportedVariables(pctx)
 
-	RustDefaultVersion = "1.71.0"
+	RustDefaultVersion = "1.72.0"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2021"
 	Stdlibs            = []string{
diff --git a/rust/config/riscv64_device.go b/rust/config/riscv64_device.go
index d014dbf..0a9c61a 100644
--- a/rust/config/riscv64_device.go
+++ b/rust/config/riscv64_device.go
@@ -21,9 +21,15 @@
 )
 
 var (
-	Riscv64RustFlags            = []string{}
-	Riscv64ArchFeatureRustFlags = map[string][]string{"": {}}
-	Riscv64LinkFlags            = []string{}
+	Riscv64RustFlags = []string{
+		"-C force-frame-pointers=y",
+	}
+	Riscv64ArchFeatureRustFlags = map[string][]string{
+		"riscv64": {
+			"-C target-feature=+V,+Zba,+Zbb,+Zbs",
+		},
+	}
+	Riscv64LinkFlags = []string{}
 
 	Riscv64ArchVariantRustFlags = map[string][]string{"": {}}
 )
diff --git a/rust/config/x86_64_device.go b/rust/config/x86_64_device.go
index 3458ec9..45d1fd0 100644
--- a/rust/config/x86_64_device.go
+++ b/rust/config/x86_64_device.go
@@ -21,7 +21,9 @@
 )
 
 var (
-	x86_64RustFlags            = []string{}
+	x86_64RustFlags = []string{
+		"-C force-frame-pointers=y",
+	}
 	x86_64ArchFeatureRustFlags = map[string][]string{}
 	x86_64LinkFlags            = []string{}
 
diff --git a/rust/library.go b/rust/library.go
index 3f031c1..0357086 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -810,7 +810,7 @@
 	Proc_macro_deps bazel.LabelListAttribute
 }
 
-func libraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+func libraryBp2build(ctx android.Bp2buildMutatorContext, m *Module) {
 	lib := m.compiler.(*libraryDecorator)
 
 	srcs, compileData := srcsAndCompileDataAttrs(ctx, *lib.baseCompiler)
@@ -887,7 +887,7 @@
 	Version bazel.StringAttribute
 }
 
-func cargoBuildScriptBp2build(ctx android.TopDownMutatorContext, m *Module) *string {
+func cargoBuildScriptBp2build(ctx android.Bp2buildMutatorContext, m *Module) *string {
 	// Soong treats some crates like libprotobuf as special in that they have
 	// cargo build script ran to produce an out folder and check it into AOSP
 	// For example, https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/out/
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 26227d0..b93b24f 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -15,9 +15,10 @@
 package rust
 
 import (
+	"fmt"
+
 	"android/soong/android"
 	"android/soong/bazel"
-	"fmt"
 )
 
 func init() {
@@ -114,7 +115,7 @@
 	Rustc_flags    bazel.StringListAttribute
 }
 
-func procMacroBp2build(ctx android.TopDownMutatorContext, m *Module) {
+func procMacroBp2build(ctx android.Bp2buildMutatorContext, m *Module) {
 	procMacro := m.compiler.(*procMacroDecorator)
 	srcs, compileData := srcsAndCompileDataAttrs(ctx, *procMacro.baseCompiler)
 	deps := android.BazelLabelForModuleDeps(ctx, append(
diff --git a/rust/protobuf.go b/rust/protobuf.go
index ae82844..c3aa8dc 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -282,7 +282,7 @@
 	Srcs bazel.LabelListAttribute
 }
 
-func protoLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+func protoLibraryBp2build(ctx android.Bp2buildMutatorContext, m *Module) {
 	var protoFiles []string
 
 	for _, propsInterface := range m.sourceProvider.SourceProviderProps() {
@@ -305,7 +305,11 @@
 		},
 	}
 
-	ctx.CreateBazelTargetModule(
+	// TODO(b/295918553): Remove androidRestriction after rust toolchain for android is checked in.
+	var androidRestriction bazel.BoolAttribute
+	androidRestriction.SetSelectValue(bazel.OsConfigurationAxis, "android", proptools.BoolPtr(false))
+
+	ctx.CreateBazelTargetModuleWithRestrictions(
 		bazel.BazelTargetModuleProperties{
 			Rule_class: "proto_library",
 		},
@@ -317,9 +321,10 @@
 				android.BazelLabelForModuleSrc(ctx, protoFiles),
 			),
 		},
+		androidRestriction,
 	)
 
-	ctx.CreateBazelTargetModule(
+	ctx.CreateBazelTargetModuleWithRestrictions(
 		bazel.BazelTargetModuleProperties{
 			Rule_class:        "rust_proto_library",
 			Bzl_load_location: "@rules_rust//proto/protobuf:defs.bzl",
@@ -333,5 +338,6 @@
 			},
 			Deps: protoDeps,
 		},
+		androidRestriction,
 	)
 }
diff --git a/rust/rust.go b/rust/rust.go
index 1ee99cd..250e398 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -15,11 +15,12 @@
 package rust
 
 import (
+	"fmt"
+	"strings"
+
 	"android/soong/bazel"
 	"android/soong/bloaty"
 	"android/soong/ui/metrics/bp2build_metrics_proto"
-	"fmt"
-	"strings"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -1845,14 +1846,14 @@
 	return ""
 }
 
-func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (m *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	if ctx.ModuleType() == "rust_library_host" || ctx.ModuleType() == "rust_library" {
 		libraryBp2build(ctx, m)
 	} else if ctx.ModuleType() == "rust_proc_macro" {
 		procMacroBp2build(ctx, m)
 	} else if ctx.ModuleType() == "rust_binary_host" {
 		binaryBp2build(ctx, m)
-	} else if ctx.ModuleType() == "rust_protobuf_host" {
+	} else if ctx.ModuleType() == "rust_protobuf_host" || ctx.ModuleType() == "rust_protobuf" {
 		protoLibraryBp2build(ctx, m)
 	} else {
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
@@ -1864,7 +1865,7 @@
 // TODO(b/297344471): When crate_root prop is set which enforces inputs sandboxing,
 // always use `srcs` and `compile_data` props to generate `srcs` and `compile_data` attributes
 // instead of using globs.
-func srcsAndCompileDataAttrs(ctx android.TopDownMutatorContext, c baseCompiler) (bazel.LabelList, bazel.LabelList) {
+func srcsAndCompileDataAttrs(ctx android.Bp2buildMutatorContext, c baseCompiler) (bazel.LabelList, bazel.LabelList) {
 	var srcs bazel.LabelList
 	var compileData bazel.LabelList
 
diff --git a/scripts/check_prebuilt_presigned_apk.py b/scripts/check_prebuilt_presigned_apk.py
new file mode 100755
index 0000000..abedfb7
--- /dev/null
+++ b/scripts/check_prebuilt_presigned_apk.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+
+import subprocess
+import argparse
+import re
+import sys
+import zipfile
+
+def check_target_sdk_less_than_30(args):
+    if not args.aapt2:
+        sys.exit('--aapt2 is required')
+    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)")
+
+def has_preprocessed_issues(args, *, fail=False):
+    if not args.zipalign:
+        sys.exit('--zipalign is required')
+    ret = subprocess.run([args.zipalign, '-c', '-p', '4', args.apk], stdout=subprocess.DEVNULL).returncode
+    if ret != 0:
+        if fail:
+            sys.exit(args.apk + ': Improper zip alignment')
+        return True
+
+    with zipfile.ZipFile(args.apk) as zf:
+        for info in zf.infolist():
+            if info.filename.startswith('lib/') and info.filename.endswith('.so') and info.compress_type != zipfile.ZIP_STORED:
+                if fail:
+                    sys.exit(args.apk + ': Contains compressed JNI libraries')
+                return True
+            # It's ok for non-privileged apps to have compressed dex files, see go/gms-uncompressed-jni-slides
+            if args.privileged:
+                if info.filename.endswith('.dex') and info.compress_type != zipfile.ZIP_STORED:
+                    if fail:
+                        sys.exit(args.apk + ': Contains compressed dex files and is privileged')
+                    return True
+    return False
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--aapt2', help = "the path to the aapt2 executable")
+    parser.add_argument('--zipalign', help = "the path to the zipalign executable")
+    parser.add_argument('--skip-preprocessed-apk-checks', action = 'store_true', help = "the value of the soong property with the same name")
+    parser.add_argument('--preprocessed', action = 'store_true', help = "the value of the soong property with the same name")
+    parser.add_argument('--privileged', action = 'store_true', help = "the value of the soong property with the same name")
+    parser.add_argument('apk', help = "the apk to check")
+    parser.add_argument('stampfile', help = "a file to touch if successful")
+    args = parser.parse_args()
+
+    if not args.preprocessed:
+        check_target_sdk_less_than_30(args)
+    elif args.skip_preprocessed_apk_checks:
+        if not has_preprocessed_issues(args):
+            sys.exit('This module sets `skip_preprocessed_apk_checks: true`, but does not actually have any issues. Please remove `skip_preprocessed_apk_checks`.')
+    else:
+        has_preprocessed_issues(args, fail=True)
+
+    subprocess.check_call(["touch", args.stampfile])
+
+if __name__ == "__main__":
+    main()
diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py
index 3ac1b7e..c6aa3d0 100644
--- a/scripts/conv_linker_config.py
+++ b/scripts/conv_linker_config.py
@@ -120,6 +120,37 @@
         f.write(pb.SerializeToString())
 
 
+def Validate(args):
+    if os.path.isdir(args.input):
+        config_file = os.path.join(args.input, 'etc/linker.config.pb')
+        if os.path.exists(config_file):
+            args.input = config_file
+            Validate(args)
+        # OK if there's no linker config file.
+        return
+
+    if not os.path.isfile(args.input):
+        sys.exit(f"{args.input} is not a file")
+
+    pb = linker_config_pb2.LinkerConfig()
+    with open(args.input, 'rb') as f:
+        pb.ParseFromString(f.read())
+
+    if args.type == 'apex':
+        # Shouldn't use provideLibs/requireLibs in APEX linker.config.pb
+        if getattr(pb, 'provideLibs'):
+            sys.exit(f'{args.input}: provideLibs is set. Use provideSharedLibs in apex_manifest')
+        if getattr(pb, 'requireLibs'):
+            sys.exit(f'{args.input}: requireLibs is set. Use requireSharedLibs in apex_manifest')
+    elif args.type == 'system':
+        if getattr(pb, 'visible'):
+            sys.exit(f'{args.input}: do not use visible, which is for APEX')
+        if getattr(pb, 'permittedPaths'):
+            sys.exit(f'{args.input}: do not use permittedPaths, which is for APEX')
+    else:
+        sys.exit(f'Unknown type: {args.type}')
+
+
 def GetArgParser():
     parser = argparse.ArgumentParser()
     subparsers = parser.add_subparsers()
@@ -227,6 +258,18 @@
         help='Linker configuration files to merge.')
     append.set_defaults(func=Merge)
 
+    validate = subparsers.add_parser('validate', help='Validate configuration')
+    validate.add_argument(
+        '--type',
+        required=True,
+        choices=['apex', 'system'],
+        help='Type of linker configuration')
+    validate.add_argument(
+        'input',
+        help='Input can be a directory which has etc/linker.config.pb or a path'
+        ' to the linker config file')
+    validate.set_defaults(func=Validate)
+
     return parser
 
 
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/sh/sh_binary.go b/sh/sh_binary.go
index 00794cd..79a885f 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -190,6 +190,15 @@
 	return s.outputFilePath
 }
 
+func (s *ShBinary) OutputFiles(tag string) (android.Paths, error) {
+	switch tag {
+	case "":
+		return android.Paths{s.outputFilePath}, nil
+	default:
+		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+	}
+}
+
 func (s *ShBinary) SubDir() string {
 	return proptools.String(s.properties.Sub_dir)
 }
@@ -574,7 +583,7 @@
 	Auto_gen_config      *bool
 }
 
-func (m *ShBinary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (m *ShBinary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	srcs := bazel.MakeLabelListAttribute(
 		android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src}))
 
@@ -602,7 +611,7 @@
 	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
 }
 
-func (m *ShTest) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (m *ShTest) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	srcs := bazel.MakeLabelListAttribute(
 		android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src}))
 
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index a2c0fb7..d16bf32 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -591,7 +591,7 @@
 }
 
 // TODO(b/240463568): Additional properties will be added for API validation
-func (m *syspropLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (m *syspropLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	labels := cc.SyspropLibraryLabels{
 		SyspropLibraryLabel: m.BaseModuleName(),
 		SharedLibraryLabel:  m.CcImplementationModuleName(),
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 9de9b97..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,9 +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[system]="-I /system/bin/hwservicemanager"
-
   # 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.
@@ -158,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"
@@ -176,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/tradefed/autogen_bazel.go b/tradefed/autogen_bazel.go
index 8283984..cc16176 100644
--- a/tradefed/autogen_bazel.go
+++ b/tradefed/autogen_bazel.go
@@ -49,7 +49,7 @@
 }
 
 func GetTestConfigAttributes(
-	ctx android.TopDownMutatorContext,
+	ctx android.Bp2buildMutatorContext,
 	testConfig *string,
 	extraTestConfigs []string,
 	autoGenConfig *bool,
@@ -93,7 +93,7 @@
 }
 
 func GetTestConfig(
-	ctx android.TopDownMutatorContext,
+	ctx android.Bp2buildMutatorContext,
 	testConfig *string,
 ) *bazel.Label {
 
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/ninja.go b/ui/build/ninja.go
index 61aaad8..b69e938 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -194,6 +194,10 @@
 
 			// LLVM compiler wrapper options
 			"TOOLCHAIN_RUSAGE_OUTPUT",
+
+			// We don't want this build broken flag to cause reanalysis, so allow it through to the
+			// actions.
+			"BUILD_BROKEN_INCORRECT_PARTITION_IMAGES",
 		}, config.BuildBrokenNinjaUsesEnvVars()...)...)
 	}
 
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/xml/xml.go b/xml/xml.go
index 8c0c072..65fe12a 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -145,8 +145,12 @@
 	Schema            *string
 }
 
-func (p *prebuiltEtcXml) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
-	baseAttrs := p.PrebuiltEtc.Bp2buildHelper(ctx)
+func (p *prebuiltEtcXml) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+	baseAttrs, convertible := p.PrebuiltEtc.Bp2buildHelper(ctx)
+
+	if !convertible {
+		return
+	}
 
 	var schema *string
 	if p.properties.Schema != nil {
diff --git a/zip/cmd/main.go b/zip/cmd/main.go
index 5231fae..37537ab 100644
--- a/zip/cmd/main.go
+++ b/zip/cmd/main.go
@@ -174,6 +174,7 @@
 	traceFile := flags.String("trace", "", "write trace to file")
 	sha256Checksum := flags.Bool("sha256", false, "add a zip header to each file containing its SHA256 digest")
 	doNotWrite := flags.Bool("n", false, "Nothing is written to disk -- all other work happens")
+	quiet := flags.Bool("quiet", false, "do not print warnings to console")
 
 	flags.Var(&rootPrefix{}, "P", "path prefix within the zip at which to place files")
 	flags.Var(&listFiles{}, "l", "file containing list of files to zip")
@@ -238,6 +239,7 @@
 		IgnoreMissingFiles:       *ignoreMissingFiles,
 		Sha256Checksum:           *sha256Checksum,
 		DoNotWrite:               *doNotWrite,
+		Quiet:                    *quiet,
 	})
 	if err != nil {
 		fmt.Fprintln(os.Stderr, "error:", err.Error())
diff --git a/zip/zip.go b/zip/zip.go
index 30a2ee7..f91a5f2 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -283,6 +283,7 @@
 	IgnoreMissingFiles       bool
 	Sha256Checksum           bool
 	DoNotWrite               bool
+	Quiet                    bool
 
 	Stderr     io.Writer
 	Filesystem pathtools.FileSystem
@@ -340,7 +341,9 @@
 					Err:  os.ErrNotExist,
 				}
 				if args.IgnoreMissingFiles {
-					fmt.Fprintln(z.stderr, "warning:", err)
+					if !args.Quiet {
+						fmt.Fprintln(z.stderr, "warning:", err)
+					}
 				} else {
 					return err
 				}
@@ -357,7 +360,9 @@
 					Err:  os.ErrNotExist,
 				}
 				if args.IgnoreMissingFiles {
-					fmt.Fprintln(z.stderr, "warning:", err)
+					if !args.Quiet {
+						fmt.Fprintln(z.stderr, "warning:", err)
+					}
 				} else {
 					return err
 				}
@@ -368,7 +373,9 @@
 					Err:  syscall.ENOTDIR,
 				}
 				if args.IgnoreMissingFiles {
-					fmt.Fprintln(z.stderr, "warning:", err)
+					if !args.Quiet {
+						fmt.Fprintln(z.stderr, "warning:", err)
+					}
 				} else {
 					return err
 				}