Merge changes from topics "revert-2629131-sandbox-rust-inputs-JRFPQTIPEY", "revert-2758566-WBNIADIEXA" into main

* changes:
  Revert^3 "add rust_toolchain_rustc_prebuilt module type"
  Revert^3 "add crate_root property to rust modules"
  Revert^3 "allow Ninja variables in RuleBuilder API"
  Revert "conditionally escape rule builder command"
  Revert "support sandboxed rust rules"
  Revert "fix failing rust_aconfig_library test"
  Revert "rustSetToolchainSource to use linux-x86 srcs"
  Revert "remove rust deps on clang prebuilts"
diff --git a/aconfig/cc_aconfig_library.go b/aconfig/cc_aconfig_library.go
index ec86af7..0583bef 100644
--- a/aconfig/cc_aconfig_library.go
+++ b/aconfig/cc_aconfig_library.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
 	"android/soong/cc"
 
 	"github.com/google/blueprint"
@@ -31,6 +32,8 @@
 
 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
@@ -72,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
@@ -138,3 +141,33 @@
 		},
 	})
 }
+
+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/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 5b77ba9..4d1b3b0 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -196,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,
@@ -244,7 +245,6 @@
 		"frameworks/hardware/interfaces/stats/aidl":          Bp2BuildDefaultTrue,
 		"frameworks/libs/modules-utils/build":                Bp2BuildDefaultTrueRecursively,
 		"frameworks/libs/modules-utils/java":                 Bp2BuildDefaultTrue,
-		"frameworks/libs/net/common/native":                  Bp2BuildDefaultTrueRecursively, // TODO(b/296014682): Remove this path
 		"frameworks/native":                                  Bp2BuildDefaultTrue,
 		"frameworks/native/libs/adbd_auth":                   Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/arect":                       Bp2BuildDefaultTrueRecursively,
@@ -340,6 +340,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,
@@ -432,6 +433,7 @@
 
 		"tools/apifinder":                             Bp2BuildDefaultTrue,
 		"tools/apksig":                                Bp2BuildDefaultTrue,
+		"tools/dexter/slicer":                         Bp2BuildDefaultTrueRecursively,
 		"tools/external_updater":                      Bp2BuildDefaultTrueRecursively,
 		"tools/metalava":                              Bp2BuildDefaultTrueRecursively,
 		"tools/platform-compat/java/android/compat":   Bp2BuildDefaultTrueRecursively,
@@ -753,6 +755,7 @@
 		//system/core/fs_mgr
 		"libfs_mgr",
 
+		"libcodec2_aidl",
 		"libcodec2_hidl@1.0",
 		"libcodec2_hidl@1.1",
 		"libcodec2_hidl@1.2",
@@ -852,6 +855,10 @@
 
 		"libstagefright_headers",
 
+		// Apps with JNI libs
+		"SimpleJNI",
+		"libsimplejni",
+
 		// aidl
 		"aidl",
 		"libaidl-common",
@@ -914,14 +921,44 @@
 		"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",
@@ -934,8 +971,11 @@
 		"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
@@ -1011,7 +1051,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-util-full",       // TODO(b/210751803), we don't handle path property for filegroups
 
 		// go deps:
 		"analyze_bcpf",              // depends on bpmodify a blueprint_go_binary.
@@ -1675,6 +1714,9 @@
 		"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
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 8634dab..4516396 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -600,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, "")
@@ -634,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..56ec17d 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -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)
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index ac862d4..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)
 }
 
diff --git a/android/config.go b/android/config.go
index 445c6cd..f9d616d 100644
--- a/android/config.go
+++ b/android/config.go
@@ -200,7 +200,7 @@
 // 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 vendor/google both have the release
+	// 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)
@@ -2022,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
 		}
 	}
@@ -2073,6 +2072,11 @@
 	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)
 }
diff --git a/android/filegroup.go b/android/filegroup.go
index a4bbcae..5a8c4b9 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -86,12 +86,6 @@
 	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 Bp2buildMutatorContext) {
 	srcs := bazel.MakeLabelListAttribute(
diff --git a/android/module.go b/android/module.go
index f4b51ea..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()
@@ -1430,7 +1430,7 @@
 // If compile_mulitilib is set to
 // 1. 32: Add an incompatibility constraint for non-32 arches
 // 1. 64: Add an incompatibility constraint for non-64 arches
-func addCompatibilityConstraintForCompileMultilib(ctx *topDownMutatorContext, enabled *bazel.LabelListAttribute) {
+func addCompatibilityConstraintForCompileMultilib(ctx *bottomUpMutatorContext, enabled *bazel.LabelListAttribute) {
 	mod := ctx.Module().base()
 	multilib, _ := decodeMultilib(mod, mod.commonProperties.CompileOS, ctx.Config().IgnorePrefer32OnDevice())
 
@@ -1456,7 +1456,7 @@
 
 // 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, errs := ProductVariableProperties(ctx, ctx.Module())
 	for _, err := range errs {
@@ -1639,35 +1639,16 @@
 }
 
 func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) {
-	reason := m.commonProperties.BazelConversionStatus.UnconvertedReason
-	if reason != nil {
-		panic(fmt.Errorf("bp2build: internal error trying to convert module '%s' marked unconvertible. Reason type %d: %s",
-			m.Name(),
-			reason.ReasonType,
-			reason.Detail))
-	}
 	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 {
-		fmt.Println(m.commonProperties.BazelConversionStatus.Bp2buildInfo)
-		panic(fmt.Errorf("bp2build: internal error trying to mark converted module '%s' as unconvertible. Reason type %d: %s",
-			m.Name(),
-			reasonType,
-			detail))
-	}
 	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
 }
@@ -3100,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 0284794..57ff1e0 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -38,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,
@@ -56,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...)
 
@@ -283,7 +277,6 @@
 
 type TopDownMutatorContext interface {
 	BaseMutatorContext
-	Bp2buildMutatorContext
 
 	// 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.
@@ -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/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/apex/builder.go b/apex/builder.go
index 1204dbb..729917f 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -17,6 +17,7 @@
 import (
 	"encoding/json"
 	"fmt"
+	"path"
 	"path/filepath"
 	"runtime"
 	"sort"
@@ -231,11 +232,11 @@
 		Description: "run apex_linkerconfig_validation",
 	}, "image_dir")
 
-	apexVintfFragmentsValidationRule = pctx.StaticRule("apexVintfFragmentsValidationRule", blueprint.RuleParams{
-		Command:     `/bin/bash -c '(shopt -s nullglob; for f in ${image_dir}/etc/vintf/*.xml; do VINTF_IGNORE_TARGET_FCM_VERSION=true ${assemble_vintf} -i "$$f" > /dev/null; done)' && touch ${out}`,
+	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 apex_vintf_validation",
-	}, "image_dir")
+		Description: "run assemble_vintf",
+	})
 )
 
 // buildManifest creates buile rules to modify the input apex_manifest.json to add information
@@ -458,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
@@ -495,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 {
@@ -513,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.
@@ -858,9 +882,6 @@
 	}
 	var validations android.Paths
 	validations = append(validations, runApexLinkerconfigValidation(ctx, unsignedOutputFile.OutputPath, imageDir.OutputPath))
-	if !a.testApex && a.SocSpecific() {
-		validations = append(validations, runApexVintfFragmentsValidation(ctx, unsignedOutputFile.OutputPath, imageDir.OutputPath))
-	}
 	// TODO(b/279688635) deapexer supports [ext4]
 	if suffix == imageApexSuffix && ext4 == a.payloadFsType {
 		validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile.OutputPath))
@@ -1128,19 +1149,6 @@
 	return timestamp
 }
 
-func runApexVintfFragmentsValidation(ctx android.ModuleContext, apexFile android.OutputPath, imageDir android.OutputPath) android.Path {
-	timestamp := android.PathForModuleOut(ctx, "apex_vintf_fragments_validation.timestamp")
-	ctx.Build(pctx, android.BuildParams{
-		Rule:   apexVintfFragmentsValidationRule,
-		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/bp2build/Android.bp b/bp2build/Android.bp
index 755b7a3..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",
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
index 59aacbb..40356a1 100644
--- a/bp2build/aar_conversion_test.go
+++ b/bp2build/aar_conversion_test.go
@@ -110,7 +110,7 @@
 				"import.aar": "",
 				"dep.aar":    "",
 			},
-			StubbedBuildDefinitions: []string{"static_lib_dep", "prebuilt_static_import_dep"},
+			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
@@ -125,6 +125,7 @@
 // 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{
diff --git a/bp2build/aconfig_conversion_test.go b/bp2build/aconfig_conversion_test.go
index ddb62f7..cbf42ac 100644
--- a/bp2build/aconfig_conversion_test.go
+++ b/bp2build/aconfig_conversion_test.go
@@ -19,10 +19,12 @@
 
 	"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) {
@@ -90,3 +92,46 @@
 		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 0daa4fe..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,8 +80,9 @@
 			"manifest/AndroidManifest.xml": "",
 			"assets_/asset.png":            "",
 		},
-		StubbedBuildDefinitions: []string{"static_lib_dep"},
-		Blueprint: simpleModule("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"],
@@ -100,6 +103,7 @@
 		obfuscate: false,
 		ignore_warnings: true,
 	},
+	jni_libs: ["jni_lib"],
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -110,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"`,
@@ -427,7 +434,6 @@
 	name: "foo",
 	sdk_version: "current",
 	min_sdk_version: "24",
-	max_sdk_version: "30",
 	target_sdk_version: "29",
 	optimize: {
 		enabled: false,
@@ -439,7 +445,6 @@
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `[]`,
 				"manifest_values": `{
-        "maxSdkVersion": "30",
         "minSdkVersion": "24",
         "targetSdkVersion": "29",
     }`,
@@ -468,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..52413fa
--- /dev/null
+++ b/bp2build/android_test_conversion_test.go
@@ -0,0 +1,103 @@
+// 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",
+		optimize: {
+			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"`,
+			}),
+		}})
+}
+
+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`,
+			}),
+		}})
+}
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 2a58d01..5871d59 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -112,7 +112,7 @@
 }
 
 cc_binary { name: "cc_binary_1"}
-sh_binary { name: "sh_binary_2"}
+sh_binary { name: "sh_binary_2", src: "foo.sh"}
 
 apex {
 	name: "com.android.apogee",
@@ -609,7 +609,7 @@
 }
 
 cc_binary { name: "cc_binary_1" }
-sh_binary { name: "sh_binary_2" }
+sh_binary { name: "sh_binary_2", src: "foo.sh"}
 
 apex {
 	name: "com.android.apogee",
@@ -736,7 +736,7 @@
 }
 
 cc_binary { name: "cc_binary_1"}
-sh_binary { name: "sh_binary_2"}
+sh_binary { name: "sh_binary_2", src: "foo.sh"}
 
 apex_test {
 	name: "com.android.apogee",
@@ -818,7 +818,7 @@
 		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{"//system/sepolicy/apex:com.android.apogee-file_contexts"},
+		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 {
@@ -828,7 +828,6 @@
 			"a/b/Android.bp": `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -852,7 +851,7 @@
 		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{"//system/sepolicy/apex:com.android.apogee-file_contexts"},
+		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 {
@@ -863,7 +862,6 @@
 apex {
 	name: "com.android.apogee",
   manifest: "apogee_manifest.json",
-	bazel_module: { bp2build_available: false },
 }
 `,
 		},
@@ -887,7 +885,7 @@
 		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{"//system/sepolicy/apex:com.android.apogee-file_contexts"},
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
@@ -898,7 +896,6 @@
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -920,7 +917,7 @@
 		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{"//system/sepolicy/apex:com.android.apogee-file_contexts"},
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
@@ -932,7 +929,6 @@
 apex {
 	name: "com.android.apogee",
   manifest: "apogee_manifest.json",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -954,7 +950,7 @@
 		Description:                "override_apex - override package name",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
-		StubbedBuildDefinitions:    []string{"//system/sepolicy/apex:com.android.apogee-file_contexts"},
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
@@ -965,7 +961,6 @@
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 }
 
 override_apex {
@@ -1109,7 +1104,7 @@
 		Description:                "override_apex - logging_parent - no override",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
-		StubbedBuildDefinitions:    []string{"//system/sepolicy/apex:com.android.apogee-file_contexts"},
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
@@ -1120,7 +1115,6 @@
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 	logging_parent: "foo.bar.baz",
 }
 
@@ -1144,7 +1138,7 @@
 		Description:                "override_apex - logging_parent - override",
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
-		StubbedBuildDefinitions:    []string{"//system/sepolicy/apex:com.android.apogee-file_contexts"},
+		StubbedBuildDefinitions:    []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"},
 		Filesystem: map[string]string{
 			"system/sepolicy/apex/Android.bp": `
 filegroup {
@@ -1155,7 +1149,6 @@
 		Blueprint: `
 apex {
 	name: "com.android.apogee",
-	bazel_module: { bp2build_available: false },
 	logging_parent: "foo.bar.baz",
 }
 
@@ -1398,7 +1391,7 @@
 		ModuleTypeUnderTest:        "override_apex",
 		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
 		Filesystem:                 map[string]string{},
-		StubbedBuildDefinitions:    []string{"com.android.apogee.certificate", "com.android.apogee", "com.android.apogee-file_contexts"},
+		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",
@@ -1417,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 {
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index 3d9cae0..7c26262 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -53,9 +53,9 @@
 		return res, err
 	}
 
-	currentProductFolder := fmt.Sprintf("build/bazel/products/%s-%s", targetProduct, targetBuildVariant)
+	currentProductFolder := fmt.Sprintf("build/bazel/products/%s", targetProduct)
 	if len(productVariables.PartitionVars.ProductDirectory) > 0 {
-		currentProductFolder = fmt.Sprintf("%s%s-%s", productVariables.PartitionVars.ProductDirectory, targetProduct, targetBuildVariant)
+		currentProductFolder = fmt.Sprintf("%s%s", productVariables.PartitionVars.ProductDirectory, targetProduct)
 	}
 
 	productReplacer := strings.NewReplacer(
@@ -73,7 +73,7 @@
 	}
 
 	productLabelsToVariables := make(map[string]*android.ProductVariables)
-	productLabelsToVariables[productReplacer.Replace("@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}")] = &productVariables
+	productLabelsToVariables[productReplacer.Replace("@//{PRODUCT_FOLDER}:{PRODUCT}")] = &productVariables
 	for product, productVariablesStarlark := range productsForTestingMap {
 		productVariables, err := starlarkMapToProductVariables(productVariablesStarlark)
 		if err != nil {
@@ -84,10 +84,10 @@
 
 	res.bp2buildTargets = make(map[string]BazelTargets)
 	res.bp2buildTargets[currentProductFolder] = append(res.bp2buildTargets[currentProductFolder], BazelTarget{
-		name:        productReplacer.Replace("{PRODUCT}-{VARIANT}"),
+		name:        productReplacer.Replace("{PRODUCT}"),
 		packageName: currentProductFolder,
 		content: productReplacer.Replace(`android_product(
-    name = "{PRODUCT}-{VARIANT}",
+    name = "{PRODUCT}",
     soong_variables = _soong_variables,
 )`),
 		ruleClass: "android_product",
@@ -134,7 +134,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"],
 )
@@ -148,34 +148,35 @@
 # 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}",
-  "@//{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 @//{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=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
-build:linux_x86 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86
-build:linux_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
-build:linux_bionic_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_bionic_x86_64
-build:linux_musl_x86 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86
-build:linux_musl_x86_64 --platforms=@//{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 @//{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 @//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64
+build --host_platform @//{PRODUCT_FOLDER}:{PRODUCT}_darwin_x86_64
 `)),
 	}
 	res.bp2buildFiles = []BazelFile{
@@ -237,12 +238,6 @@
 	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 {
@@ -270,7 +265,6 @@
 		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, ",")))
@@ -281,7 +275,6 @@
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:device_platform=%s\n", label))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:enable_cfi=%t\n", proptools.BoolDefault(productVariables.EnableCFI, true)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:enforce_vintf_manifest=%t\n", proptools.Bool(productVariables.Enforce_vintf_manifest)))
-		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:eng=%t\n", proptools.Bool(productVariables.Eng)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:malloc_not_svelte=%t\n", proptools.Bool(productVariables.Malloc_not_svelte)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:malloc_pattern_fill_contents=%t\n", proptools.Bool(productVariables.Malloc_pattern_fill_contents)))
 		result.WriteString(fmt.Sprintf("    --//build/bazel/product_config:malloc_zero_contents=%t\n", proptools.Bool(productVariables.Malloc_zero_contents)))
@@ -290,6 +283,7 @@
 		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))
@@ -301,7 +295,6 @@
 		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)))
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 15b7766..e6941df 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -713,27 +713,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)
@@ -761,24 +766,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...)
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 329c907..afbfffa 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -1994,6 +1994,41 @@
 	})
 }
 
+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".
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index ec603c2..560123e 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -1857,7 +1857,6 @@
 		Blueprint: soongCcLibraryPreamble + `
 cc_library {
 	name: "libc_musl",
-	bazel_module: { bp2build_available: false },
 }
 
 cc_library {
@@ -1912,10 +1911,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 {
@@ -5184,3 +5183,30 @@
 	}
 	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 bf3351a..fde4c97 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -58,6 +58,7 @@
 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) {
@@ -417,3 +418,67 @@
 		},
 	})
 }
+
+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 6f600da..6fa14e3 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -1595,6 +1595,7 @@
 		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",
@@ -1607,23 +1608,20 @@
 }
 cc_library_shared {
 	name: "libNoStubs",
-	bazel_module: { bp2build_available: false },
 }
 cc_library_shared {
 	name: "libHasApexStubs",
 	stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 	apex_available: ["apex_a"],
 }
 cc_library_shared {
 	name: "libHasApexAndNdkStubs",
 	stubs: { symbol_file: "b.map.txt", versions: ["28", "29", "current"] },
-	bazel_module: { bp2build_available: false },
 	apex_available: ["apex_b"],
 }
 ndk_library {
 	name: "libHasApexAndNdkStubs",
-	bazel_module: { bp2build_available: false },
+	first_version: "28",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -1635,7 +1633,7 @@
         ],
         "//build/bazel/rules/apex:unbundled_app": [
             ":libHasApexStubs",
-            "//.:libHasApexAndNdkStubs.ndk_stub_libs",
+            "//.:libHasApexAndNdkStubs.ndk_stub_libs-current",
         ],
         "//conditions:default": [
             ":libHasApexStubs",
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 0587aae..7b97b39 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1398,11 +1398,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 {
@@ -1425,11 +1425,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 {
diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go
index 679a364..392a962 100644
--- a/bp2build/cc_test_conversion_test.go
+++ b/bp2build/cc_test_conversion_test.go
@@ -631,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/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
index 7d8ab63..4271f76 100644
--- a/bp2build/java_binary_host_conversion_test.go
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -114,7 +114,7 @@
 	runJavaBinaryHostTestCase(t, Bp2buildTestCase{
 		Description:             "java_binary_host with srcs, libs.",
 		Filesystem:              testFs,
-		StubbedBuildDefinitions: []string{"prebuilt_java-lib-dep-1"},
+		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"],
diff --git a/bp2build/java_plugin_conversion_test.go b/bp2build/java_plugin_conversion_test.go
index b284112..dcc17b5 100644
--- a/bp2build/java_plugin_conversion_test.go
+++ b/bp2build/java_plugin_conversion_test.go
@@ -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 b254710..4e96efe 100644
--- a/bp2build/java_proto_conversion_test.go
+++ b/bp2build/java_proto_conversion_test.go
@@ -140,18 +140,23 @@
 
 func TestJavaLibsAndOnlyProtoSrcs(t *testing.T) {
 	runJavaProtoTestCase(t, Bp2buildTestCase{
-		Description: "java_library that has only proto srcs",
+		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"],
+    libs: ["java-lib-1"],
+    static_libs: ["java-lib-2"],
     java_version: "7",
     sdk_version: "current",
 }
 
 java_library_static {
-    name: "java-lib",
-    bazel_module: { bp2build_available: false },
+    name: "java-lib-1",
+}
+
+java_library_static {
+    name: "java-lib-2",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -162,12 +167,19 @@
 				"java_lite_proto_library",
 				"java-protos_java_proto_lite",
 				AttrNameToString{
-					"deps":         `[":java-protos_proto"]`,
+					"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-protos_java_proto_lite"]`,
+				"exports": `[
+        ":java-lib-2",
+        ":java-protos_java_proto_lite",
+    ]`,
 				"java_version": `"7"`,
 				"sdk_version":  `"current"`,
 			}),
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/testing.go b/bp2build/testing.go
index a810709..dfd4d57 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -571,23 +571,6 @@
 	)
 }
 
-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.Bp2buildMutatorContext, m *customModule) {
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 38777ff..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",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 6a49915..5dc119e 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))
 
@@ -1143,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 {
@@ -1283,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
@@ -1490,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
@@ -1587,13 +1587,13 @@
 	return exists && ctx.OtherModuleType(mod) == "ndk_library"
 }
 
-func SetStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis,
+func SetStubsForDynamicDeps(ctx android.Bp2buildMutatorContext, axis bazel.ConfigurationAxis,
 	config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *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{}
@@ -1657,9 +1657,11 @@
 			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",
+					Label: "//" + ctx.OtherModuleDir(ndkLibModule) + ":" + ndkLibModule.Name() + "_stub_libs-" + ver,
 				}
 			}
 			// add the ndk lib label to this axis
diff --git a/cc/cc.go b/cc/cc.go
index 9aa0cac..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
@@ -4215,6 +4216,16 @@
 
 // ConvertWithBp2build converts Module to Bazel for bp2build.
 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:
@@ -4262,24 +4273,6 @@
 	}
 }
 
-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/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 b9dc71b..e66ce08 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -517,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 {
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 5eba6ab..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"
@@ -175,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 1a8e90f..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,6 +80,7 @@
 
 type headerModule struct {
 	android.ModuleBase
+	android.BazelModuleBase
 
 	properties headerProperties
 
@@ -145,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:
@@ -155,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
 }
 
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 9ec2ae4..54a2ee2 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -62,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)
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/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 7a6cf1b..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
@@ -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 07bee01..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 {
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/java/aar.go b/java/aar.go
index f28d971..8f5deab 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -1352,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 2edd3f7..6030500 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() {
@@ -1257,6 +1258,8 @@
 	AndroidApp
 
 	appTestHelperAppProperties appTestHelperAppProperties
+
+	android.BazelModuleBase
 }
 
 func (a *AndroidTestHelperApp) InstallInTestcases() bool {
@@ -1288,6 +1291,7 @@
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	android.InitApexModule(module)
+	android.InitBazelModule(module)
 	return module
 }
 
@@ -1618,7 +1622,6 @@
 
 type manifestValueAttribute struct {
 	MinSdkVersion    *string
-	MaxSdkVersion    *string
 	TargetSdkVersion *string
 }
 
@@ -1632,6 +1635,16 @@
 	Manifest_values  *manifestValueAttribute
 	Optimize         *bool
 	Proguard_specs   bazel.LabelListAttribute
+	Updatable        *bool
+}
+
+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")
+	}
+	return hasJavaResources
 }
 
 func convertWithBp2build(ctx android.Bp2buildMutatorContext, a *AndroidApp) (bool, android.CommonAttributes, *bazelAndroidAppAttributes) {
@@ -1639,30 +1652,26 @@
 	if !supported {
 		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{
@@ -1671,6 +1680,7 @@
 		Certificate:      certificate,
 		Certificate_name: certificateName,
 		Manifest_values:  manifestValues,
+		Updatable:        a.appProperties.Updatable,
 	}
 
 	if !BoolDefault(a.dexProperties.Optimize.Enabled, true) {
@@ -1711,11 +1721,29 @@
 	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
 		appAttrs.bazelAapt = aapt
@@ -1769,3 +1797,27 @@
 	}
 
 }
+
+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)
+
+		// additionally, it 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)
+		// optimize EnabledByDefault: true (blueprint mutated 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/base.go b/java/base.go
index a007717..a110aff 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) {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 1d5dd76..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"
 )
@@ -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/java.go b/java/java.go
index d5aeb7c..fbad4f3 100644
--- a/java/java.go
+++ b/java/java.go
@@ -3067,17 +3067,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
 
@@ -3093,6 +3082,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,
diff --git a/java/kotlin.go b/java/kotlin.go
index 3637e2e..aa2db0e 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -145,7 +145,7 @@
 			`$kaptProcessorPath ` +
 			`$kaptProcessor ` +
 			`-Xbuild-file=$kotlinBuildFile && ` +
-			`${config.SoongZipCmd} -jar -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
+			`${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
 			`rm -rf "$srcJarDir"`,
 		CommandDeps: []string{
 			"${config.KotlincCmd}",
@@ -157,6 +157,7 @@
 		},
 		Rspfile:        "$out.rsp",
 		RspfileContent: `$in`,
+		Restat:         true,
 	},
 	"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor",
 	"classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget",
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