Merge "Fix false pos in bp2build-prog due to prebulits" into main
diff --git a/aconfig/java_aconfig_library.go b/aconfig/java_aconfig_library.go
index 53f8bd1..4db0ef7 100644
--- a/aconfig/java_aconfig_library.go
+++ b/aconfig/java_aconfig_library.go
@@ -52,6 +52,9 @@
 	} else {
 		ctx.AddDependency(ctx.Module(), declarationsTag, declarations)
 	}
+
+	// Add aconfig-annotations-lib as a dependency for the optimization / code stripping annotations
+	module.AddSharedLibrary("aconfig-annotations-lib")
 }
 
 func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(module *java.GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path {
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index d7fbb62..9916451 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -310,6 +310,7 @@
 		"packages/modules/StatsD/lib/libstatssocket":         Bp2BuildDefaultTrueRecursively,
 		"packages/modules/adb":                               Bp2BuildDefaultTrue,
 		"packages/modules/adb/apex":                          Bp2BuildDefaultTrue,
+		"packages/modules/adb/fastdeploy":                    Bp2BuildDefaultTrue,
 		"packages/modules/adb/crypto":                        Bp2BuildDefaultTrueRecursively,
 		"packages/modules/adb/libs":                          Bp2BuildDefaultTrueRecursively,
 		"packages/modules/adb/pairing_auth":                  Bp2BuildDefaultTrueRecursively,
@@ -488,6 +489,55 @@
 	}
 
 	Bp2buildModuleAlwaysConvertList = []string{
+		// aconfig
+		"libonce_cell",
+		"libanyhow",
+		"libunicode_segmentation",
+		"libmemchr",
+		"libbitflags-1.3.2",
+		"libryu",
+		"libitoa",
+		"libos_str_bytes",
+		"libheck",
+		"libclap_lex",
+		"libsyn",
+		"libquote",
+		"libunicode_ident",
+		"libproc_macro2",
+		"libthiserror_impl",
+		"libserde_derive",
+		"libclap_derive",
+		"libthiserror",
+		"libserde",
+		"libclap",
+		"libbytes",
+		"libprotobuf_support",
+		"libtinytemplate",
+		"libserde_json",
+		"libprotobuf",
+
+		"protoc-gen-rust",
+		"libprotobuf_codegen",
+		"libprotobuf_parse",
+		"libregex",
+		"libtempfile",
+		"libwhich",
+		"libregex_syntax",
+		"libfastrand",
+		"libeither",
+		"libaho_corasick",
+		"liblibc",
+		"libcfg_if",
+		"liblog_rust",
+		"libgetrandom",
+		"libremove_dir_all",
+		"libahash",
+		"libhashbrown",
+		"libindexmap",
+		"libaconfig_protos",
+		"libpaste",
+		"aconfig",
+
 		// ext
 		"tagsoup",
 
@@ -858,6 +908,9 @@
 		"hal_unit_tests",
 
 		"merge_annotation_zips_test",
+
+		// java_resources with multiple resource_dirs
+		"emma",
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
@@ -881,6 +934,20 @@
 	// the "prebuilt_" prefix to the name, so that it's differentiable from
 	// the source versions within Soong's module graph.
 	Bp2buildModuleDoNotConvertList = []string{
+		// rust modules that have cc deps
+		"liblogger",
+		"libbssl_ffi",
+		"libbssl_ffi_nostd",
+		"pull_rust",
+		"libstatslog_rust",
+		"libstatslog_rust_header",
+		"libflatbuffers",
+		"liblog_event_list",
+		"libminijail_rust",
+		"libminijail_sys",
+		"libfsverity_rs",
+		"libtombstoned_client_rust",
+
 		// TODO(b/263326760): Failed already.
 		"minijail_compiler_unittest",
 		"minijail_parser_unittest",
@@ -1546,6 +1613,7 @@
 		"permissive_mte_test",
 		"ICU4CTestRunner",
 		"DeviceLongPollingStubTest",
+		"FastDeployHostTests",
 
 		"libprotobuf-full-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
 		"libprotobuf-lite-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
diff --git a/android/api_levels.go b/android/api_levels.go
index 44c8640..3f538c0 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -19,6 +19,7 @@
 	"encoding/json"
 	"fmt"
 	"strconv"
+	"strings"
 )
 
 func init() {
@@ -237,6 +238,14 @@
 	}
 }
 
+func uncheckedFinalIncrementalApiLevel(num int, increment int) ApiLevel {
+	return ApiLevel{
+		value:     strconv.Itoa(num) + "." + strconv.Itoa(increment),
+		number:    num,
+		isPreview: false,
+	}
+}
+
 var NoneApiLevel = ApiLevel{
 	value: "(no version)",
 	// Not 0 because we don't want this to compare equal with the first preview.
@@ -371,6 +380,22 @@
 		return FutureApiLevel
 	}
 
+	if strings.Contains(raw, ".") {
+		// Check prebuilt incremental API format MM.m for major (API level) and minor (incremental) revisions
+		parts := strings.Split(raw, ".")
+		if len(parts) != 2 {
+			panic(fmt.Errorf("Found unexpected version '%s' for incremental API - expect MM.m format for incremental API with both major (MM) an minor (m) revision.", raw))
+		}
+		sdk, sdk_err := strconv.Atoi(parts[0])
+		qpr, qpr_err := strconv.Atoi(parts[1])
+		if sdk_err != nil || qpr_err != nil {
+			panic(fmt.Errorf("Unable to read version number for incremental api '%s'", raw))
+		}
+
+		apiLevel := uncheckedFinalIncrementalApiLevel(sdk, qpr)
+		return apiLevel
+	}
+
 	asInt, err := strconv.Atoi(raw)
 	if err != nil {
 		panic(fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", raw))
diff --git a/android/config.go b/android/config.go
index 3e7bb14..0b15c79 100644
--- a/android/config.go
+++ b/android/config.go
@@ -2081,3 +2081,7 @@
 func (c *config) GetApiLibraries() map[string]struct{} {
 	return c.apiLibraries
 }
+
+func (c *deviceConfig) CheckVendorSeappViolations() bool {
+	return Bool(c.config.productVariables.CheckVendorSeappViolations)
+}
diff --git a/android/mutator.go b/android/mutator.go
index 6bcac93..41477b8 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -231,6 +231,7 @@
 	BazelConversionPathContext
 
 	CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{})
+	CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute)
 }
 
 // PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
diff --git a/android/proto.go b/android/proto.go
index 6887900..3c4b4c7 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -17,6 +17,7 @@
 import (
 	"path/filepath"
 	"strings"
+	"sync"
 
 	"android/soong/bazel"
 
@@ -281,6 +282,13 @@
 				}
 			}
 
+			if p, ok := m.module.(PkgPathInterface); ok && p.PkgPath(ctx) != nil {
+				// python_library with pkg_path
+				// proto_library for this module should have the pkg_path as the import_prefix
+				attrs.Import_prefix = p.PkgPath(ctx)
+				attrs.Strip_import_prefix = proptools.StringPtr("")
+			}
+
 			tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module())
 
 			moduleDir := ctx.ModuleDir()
@@ -323,7 +331,8 @@
 				Label: l,
 			})
 		}
-		protoLibrariesInIncludeDir := createProtoLibraryTargetsForIncludeDirs(ctx, protoIncludeDirs)
+		// Partitioning by packages can create dupes of protoIncludeDirs, so dedupe it first.
+		protoLibrariesInIncludeDir := createProtoLibraryTargetsForIncludeDirs(ctx, SortedUniqueStrings(protoIncludeDirs))
 		transitiveProtoLibraries.Append(protoLibrariesInIncludeDir)
 	}
 
@@ -333,9 +342,15 @@
 	return info, true
 }
 
+// PkgPathInterface is used as a type assertion in bp2build to get pkg_path property of python_library_host
+type PkgPathInterface interface {
+	PkgPath(ctx BazelConversionContext) *string
+}
+
 var (
 	protoIncludeDirGeneratedSuffix = ".include_dir_bp2build_generated_proto"
 	protoIncludeDirsBp2buildKey    = NewOnceKey("protoIncludeDirsBp2build")
+	protoIncludeDirsBp2buildLock   sync.Mutex
 )
 
 func getProtoIncludeDirsBp2build(config Config) *map[protoIncludeDirKey]bool {
@@ -355,6 +370,9 @@
 // might create the targets in a subdirectory of `includeDir`
 // Returns the labels of the proto_library targets
 func createProtoLibraryTargetsForIncludeDirs(ctx Bp2buildMutatorContext, includeDirs []string) bazel.LabelList {
+	protoIncludeDirsBp2buildLock.Lock()
+	defer protoIncludeDirsBp2buildLock.Unlock()
+
 	var ret bazel.LabelList
 	for _, dir := range includeDirs {
 		if exists, _, _ := ctx.Config().fs.Exists(filepath.Join(dir, "Android.bp")); !exists {
@@ -389,7 +407,13 @@
 			if rel != "." {
 				attrs.Import_prefix = proptools.StringPtr(rel)
 			}
-			ctx.CreateBazelTargetModule(
+
+			// If a specific directory is listed in proto.include_dirs of two separate modules (one host-specific and another device-specific),
+			// we do not want to create the proto_library with target_compatible_with of the first visited of these two modules
+			// As a workarounds, delete `target_compatible_with`
+			alwaysEnabled := bazel.BoolAttribute{}
+			alwaysEnabled.Value = proptools.BoolPtr(true)
+			ctx.CreateBazelTargetModuleWithRestrictions(
 				bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
 				CommonAttributes{
 					Name: label,
@@ -399,6 +423,7 @@
 					Tags: bazel.MakeStringListAttribute([]string{"manual"}),
 				},
 				&attrs,
+				alwaysEnabled,
 			)
 		}
 	}
diff --git a/android/variable.go b/android/variable.go
index ca9a221..8805fe5 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -486,6 +486,8 @@
 	ReleaseAconfigFlagDefaultPermission string `json:",omitempty"`
 
 	KeepVndk *bool `json:",omitempty"`
+
+	CheckVendorSeappViolations *bool `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/bazel/configurability.go b/bazel/configurability.go
index aa58fdc..1fe8442 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -39,7 +39,7 @@
 
 	// Targets in arch.go
 	osArchAndroidArm        = "android_arm"
-	osArchAndroidArm64      = "android_arm64"
+	OsArchAndroidArm64      = "android_arm64"
 	osArchAndroidRiscv64    = "android_riscv64"
 	osArchAndroidX86        = "android_x86"
 	osArchAndroidX86_64     = "android_x86_64"
@@ -170,7 +170,7 @@
 
 	platformOsArchMap = map[string]string{
 		osArchAndroidArm:           "//build/bazel/platforms/os_arch:android_arm",
-		osArchAndroidArm64:         "//build/bazel/platforms/os_arch:android_arm64",
+		OsArchAndroidArm64:         "//build/bazel/platforms/os_arch:android_arm64",
 		osArchAndroidRiscv64:       "//build/bazel/platforms/os_arch:android_riscv64",
 		osArchAndroidX86:           "//build/bazel/platforms/os_arch:android_x86",
 		osArchAndroidX86_64:        "//build/bazel/platforms/os_arch:android_x86_64",
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
index 09d9dc1..a24378c 100644
--- a/bp2build/aar_conversion_test.go
+++ b/bp2build/aar_conversion_test.go
@@ -37,19 +37,19 @@
 		},
 		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
 android_library {
-        name: "TestLib",
-        srcs: ["lib.java"],
-        arch: {
-			arm: {
-				srcs: ["arm.java"],
-			},
-			x86: {
-				srcs: ["x86.java"],
-			}
+	name: "TestLib",
+	srcs: ["lib.java"],
+	arch: {
+		arm: {
+			srcs: ["arm.java"],
 		},
-        manifest: "manifest/AndroidManifest.xml",
-        static_libs: ["static_lib_dep"],
-        java_version: "7",
+		x86: {
+			srcs: ["x86.java"],
+		}
+	},
+	manifest: "manifest/AndroidManifest.xml",
+	static_libs: ["static_lib_dep"],
+	sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -66,12 +66,9 @@
 					"resource_files": `["res/res.png"]`,
 					"deps":           `[":static_lib_dep"]`,
 					"exports":        `[":static_lib_dep"]`,
-					"java_version":   `"7"`,
+					"sdk_version":    `"current"`, // use as default
 				}),
-			MakeNeverlinkDuplicateTargetWithAttrs(
-				"android_library",
-				"TestLib",
-				AttrNameToString{"java_version": `"7"`}),
+			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
 }
 
@@ -87,10 +84,11 @@
 		},
 		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "lib_dep") + `
 android_library {
-        name: "TestLib",
-        srcs: [],
-        manifest: "AndroidManifest.xml",
-        libs: ["lib_dep"],
+	name: "TestLib",
+	srcs: [],
+	manifest: "AndroidManifest.xml",
+	libs: ["lib_dep"],
+	sdk_version: "current",
 }
 `,
 		ExpectedErr:          fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."),
@@ -121,6 +119,7 @@
         name: "TestImport",
         aars: ["import.aar"],
         static_libs: ["static_lib_dep", "static_import_dep"],
+    sdk_version: "current",
 }
 `,
 			ExpectedBazelTargets: []string{
@@ -133,7 +132,8 @@
         ":static_lib_dep",
         ":static_import_dep",
     ]`,
-						"exports": `[":static_import_dep"]`,
+						"exports":     `[":static_import_dep"]`,
+						"sdk_version": `"current"`, // use as default
 					},
 				),
 				MakeNeverlinkDuplicateTarget("android_library", "TestImport"),
@@ -153,9 +153,10 @@
 		},
 		Blueprint: `
 android_library {
-        name: "TestLib",
-        srcs: ["a.java", "b.kt"],
-        common_srcs: ["c.kt"],
+	name: "TestLib",
+	srcs: ["a.java", "b.kt"],
+	common_srcs: ["c.kt"],
+	sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -170,6 +171,7 @@
 					"common_srcs":    `["c.kt"]`,
 					"manifest":       `"AndroidManifest.xml"`,
 					"resource_files": `[]`,
+					"sdk_version":    `"current"`, // use as default
 				}),
 			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
@@ -186,9 +188,10 @@
 		},
 		Blueprint: `
 android_library {
-        name: "TestLib",
-        srcs: ["a.java", "b.kt"],
-        kotlincflags: ["-flag1", "-flag2"],
+	name: "TestLib",
+	srcs: ["a.java", "b.kt"],
+	kotlincflags: ["-flag1", "-flag2"],
+	sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -206,6 +209,7 @@
     ]`,
 					"manifest":       `"AndroidManifest.xml"`,
 					"resource_files": `[]`,
+					"sdk_version":    `"current"`, // use as default
 				}),
 			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index 8ed94b4..25494a1 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -44,9 +44,9 @@
 		},
 		Blueprint: `
 android_app {
-        name: "TestApp",
-        srcs: ["app.java"],
-        sdk_version: "current",
+		name: "TestApp",
+		srcs: ["app.java"],
+		sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -75,17 +75,17 @@
 		},
 		Blueprint: simpleModuleDoNotConvertBp2build("android_app", "static_lib_dep") + `
 android_app {
-        name: "TestApp",
-        srcs: ["app.java"],
-        sdk_version: "current",
-        package_name: "com.google",
-        resource_dirs: ["resa", "resb"],
-        manifest: "manifest/AndroidManifest.xml",
-        static_libs: ["static_lib_dep"],
-        java_version: "7",
-        certificate: "foocert",
-        required: ["static_lib_dep"],
-        asset_dirs: ["assets_"],
+		name: "TestApp",
+		srcs: ["app.java"],
+		sdk_version: "current",
+		package_name: "com.google",
+		resource_dirs: ["resa", "resb"],
+		manifest: "manifest/AndroidManifest.xml",
+		static_libs: ["static_lib_dep"],
+		java_version: "7",
+		certificate: "foocert",
+		required: ["static_lib_dep"],
+		asset_dirs: ["assets_"],
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -120,16 +120,16 @@
 		},
 		Blueprint: `
 android_app {
-        name: "TestApp",
-        sdk_version: "current",
-        arch: {
-			arm: {
-				srcs: ["arm.java"],
-			},
-			x86: {
-				srcs: ["x86.java"],
-			}
+	name: "TestApp",
+	sdk_version: "current",
+	arch: {
+		arm: {
+			srcs: ["arm.java"],
+		},
+		x86: {
+			srcs: ["x86.java"],
 		}
+	}
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -154,8 +154,9 @@
 		Filesystem:                 map[string]string{},
 		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
 android_app {
-        name: "TestApp",
-        certificate: ":foocert",
+	name: "TestApp",
+	certificate: ":foocert",
+	sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -163,6 +164,7 @@
 				"certificate":    `":foocert"`,
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `[]`,
+				"sdk_version":    `"current"`, // use as default
 			}),
 		}})
 }
@@ -177,8 +179,9 @@
 		},
 		Blueprint: `
 android_app {
-        name: "TestApp",
-        certificate: "foocert",
+	name: "TestApp",
+	certificate: "foocert",
+	sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -186,6 +189,7 @@
 				"certificate":    `"foocert"`,
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `[]`,
+				"sdk_version":    `"current"`, // use as default
 			}),
 		}})
 }
@@ -200,8 +204,9 @@
 		},
 		Blueprint: `
 android_app {
-        name: "TestApp",
-        certificate: "foocert",
+	name: "TestApp",
+	certificate: "foocert",
+	sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -209,6 +214,7 @@
 				"certificate_name": `"foocert"`,
 				"manifest":         `"AndroidManifest.xml"`,
 				"resource_files":   `[]`,
+				"sdk_version":      `"current"`, // use as default
 			}),
 		}})
 }
@@ -219,22 +225,20 @@
 		ModuleTypeUnderTest:        "android_app",
 		ModuleTypeUnderTestFactory: java.AndroidAppFactory,
 		Filesystem:                 map[string]string{},
-		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") +
+			simpleModuleDoNotConvertBp2build("java_library", "barLib") + `
 android_app {
-        name: "foo",
-				libs: ["barLib"]
-}
-java_library{
-       name: "barLib",
+	name: "foo",
+	libs: ["barLib"],
+	sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
-			MakeBazelTarget("java_library", "barLib", AttrNameToString{}),
-			MakeNeverlinkDuplicateTarget("java_library", "barLib"),
 			MakeBazelTarget("android_binary", "foo", AttrNameToString{
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `[]`,
 				"deps":           `[":barLib-neverlink"]`,
+				"sdk_version":    `"current"`, // use as default
 			}),
 		}})
 }
@@ -247,21 +251,18 @@
 		Filesystem: map[string]string{
 			"res/res.png": "",
 		},
-		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") +
+			simpleModuleDoNotConvertBp2build("java_library", "barLib") + `
 android_app {
-        name: "foo",
-        srcs: ["a.java", "b.kt"],
-        certificate: ":foocert",
-        manifest: "fooManifest.xml",
-        libs: ["barLib"]
-}
-java_library{
-      name:   "barLib",
+	name: "foo",
+	srcs: ["a.java", "b.kt"],
+	certificate: ":foocert",
+	manifest: "fooManifest.xml",
+	libs: ["barLib"],
+	sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
-			MakeBazelTarget("java_library", "barLib", AttrNameToString{}),
-			MakeNeverlinkDuplicateTarget("java_library", "barLib"),
 			MakeBazelTarget("android_library", "foo_kt", AttrNameToString{
 				"srcs": `[
         "a.java",
@@ -270,11 +271,13 @@
 				"manifest":       `"fooManifest.xml"`,
 				"resource_files": `["res/res.png"]`,
 				"deps":           `[":barLib-neverlink"]`,
+				"sdk_version":    `"current"`, // use as default
 			}),
 			MakeBazelTarget("android_binary", "foo", AttrNameToString{
 				"deps":        `[":foo_kt"]`,
 				"certificate": `":foocert"`,
 				"manifest":    `"fooManifest.xml"`,
+				"sdk_version": `"current"`, // use as default
 			}),
 		}})
 }
@@ -289,31 +292,33 @@
 		},
 		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
 android_app {
-        name: "foo",
-        srcs: ["a.java"],
-        common_srcs: ["b.kt"],
-        certificate: "foocert",
-        manifest: "fooManifest.xml",
-        libs:        ["barLib"],
+	name: "foo",
+	srcs: ["a.java"],
+	common_srcs: ["b.kt"],
+	certificate: "foocert",
+	manifest: "fooManifest.xml",
+	libs:        ["barLib"],
+	sdk_version: "current",
 }
 java_library{
-      name:   "barLib",
+	name:   "barLib",
+	bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
-			MakeBazelTarget("java_library", "barLib", AttrNameToString{}),
-			MakeNeverlinkDuplicateTarget("java_library", "barLib"),
 			MakeBazelTarget("android_library", "foo_kt", AttrNameToString{
 				"srcs":           `["a.java"]`,
 				"common_srcs":    `["b.kt"]`,
 				"manifest":       `"fooManifest.xml"`,
 				"resource_files": `["res/res.png"]`,
 				"deps":           `[":barLib-neverlink"]`,
+				"sdk_version":    `"current"`, // use as default
 			}),
 			MakeBazelTarget("android_binary", "foo", AttrNameToString{
 				"deps":             `[":foo_kt"]`,
 				"certificate_name": `"foocert"`,
 				"manifest":         `"fooManifest.xml"`,
+				"sdk_version":      `"current"`, // use as default
 			}),
 		}})
 }
@@ -328,11 +333,12 @@
 		},
 		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
 android_app {
-        name: "foo",
-        srcs: ["a.java", "b.kt"],
-        certificate: ":foocert",
-        manifest: "fooManifest.xml",
-        kotlincflags: ["-flag1", "-flag2"],
+	name: "foo",
+	srcs: ["a.java", "b.kt"],
+	certificate: ":foocert",
+	manifest: "fooManifest.xml",
+	kotlincflags: ["-flag1", "-flag2"],
+	sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -347,11 +353,13 @@
         "-flag1",
         "-flag2",
     ]`,
+				"sdk_version": `"current"`, // use as default
 			}),
 			MakeBazelTarget("android_binary", "foo", AttrNameToString{
 				"deps":        `[":foo_kt"]`,
 				"certificate": `":foocert"`,
 				"manifest":    `"fooManifest.xml"`,
+				"sdk_version": `"current"`,
 			}),
 		}})
 }
@@ -364,11 +372,11 @@
 		Filesystem:                 map[string]string{},
 		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
 android_app {
-        name: "foo",
-        sdk_version: "current",
-        min_sdk_version: "24",
-        max_sdk_version: "30",
-        target_sdk_version: "29",
+	name: "foo",
+	sdk_version: "current",
+	min_sdk_version: "24",
+	max_sdk_version: "30",
+	target_sdk_version: "29",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -393,8 +401,8 @@
 		Filesystem:                 map[string]string{},
 		Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
 android_app {
-        name: "foo",
-        sdk_version: "30",
+	name: "foo",
+	sdk_version: "30",
 }
 `,
 		ExpectedBazelTargets: []string{
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 6501217..02ed57a 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -5120,7 +5120,7 @@
 	// bar dir
 	tc.Dir = "bar"
 	tc.ExpectedBazelTargets = []string{
-		MakeBazelTarget("proto_library", "bar.include_dir_bp2build_generated_proto", AttrNameToString{
+		MakeBazelTargetNoRestrictions("proto_library", "bar.include_dir_bp2build_generated_proto", AttrNameToString{
 			"srcs":                `["bar.proto"]`,
 			"strip_import_prefix": `""`,
 			"tags":                `["manual"]`,
@@ -5131,7 +5131,7 @@
 	// bar/baz dir
 	tc.Dir = "bar/baz"
 	tc.ExpectedBazelTargets = []string{
-		MakeBazelTarget("proto_library", "bar.include_dir_bp2build_generated_proto", AttrNameToString{
+		MakeBazelTargetNoRestrictions("proto_library", "bar.include_dir_bp2build_generated_proto", AttrNameToString{
 			"srcs":                `["//bar/baz:baz.proto"]`,
 			"strip_import_prefix": `""`,
 			"import_prefix":       `"baz"`,
@@ -5141,6 +5141,52 @@
 	runCcLibraryTestCase(t, tc)
 }
 
+func TestProtoIncludeDirsWithSrcsInMultiplePackages(t *testing.T) {
+	tc := Bp2buildTestCase{
+		Description:                "cc_library has srcs in multiple bazel packages and uses proto.include_dirs",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+cc_library_static {
+	name: "foo",
+	srcs: [
+	   "foo.proto",
+	   "bar/bar.proto",
+	],
+	proto: {
+		include_dirs: ["baz"],
+	}
+}
+` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+		Filesystem: map[string]string{
+			"bar/Android.bp": "", // package boundary
+			"baz/Android.bp": "",
+			"baz/baz.proto":  "",
+		},
+	}
+
+	tc.ExpectedBazelTargets = []string{
+		MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+			"local_includes":                    `["."]`,
+			"deps":                              `[":libprotobuf-cpp-lite"]`,
+			"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
+		}),
+		MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
+			"srcs": `["foo.proto"]`,
+			"tags": `["manual"]`,
+		}),
+		MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
+			"deps": `[
+        ":foo_proto",
+        "//bar:foo_proto",
+    ]`,
+			"transitive_deps": `["//baz:baz.include_dir_bp2build_generated_proto"]`,
+		}),
+	}
+	runCcLibraryTestCase(t, tc)
+
+}
+
 func TestProtoLocalIncludeDirs(t *testing.T) {
 	tc := Bp2buildTestCase{
 		Description:                "cc_library depends on .proto files using proto.local_include_dirs",
@@ -5187,7 +5233,7 @@
 	// foo/foo_subdir
 	tc.Dir = "foo/foo_subdir"
 	tc.ExpectedBazelTargets = []string{
-		MakeBazelTarget("proto_library", "foo.foo_subdir.include_dir_bp2build_generated_proto", AttrNameToString{
+		MakeBazelTargetNoRestrictions("proto_library", "foo.foo_subdir.include_dir_bp2build_generated_proto", AttrNameToString{
 			"srcs":                `["foo_subdir.proto"]`,
 			"strip_import_prefix": `""`,
 			"tags":                `["manual"]`,
diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go
index 76bbb57..9639ab9 100644
--- a/bp2build/cc_test_conversion_test.go
+++ b/bp2build/cc_test_conversion_test.go
@@ -139,6 +139,13 @@
         "host_without_device",
         "device",
     ]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 		},
@@ -166,6 +173,13 @@
         "host_without_device",
         "device",
     ]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 		},
@@ -197,6 +211,13 @@
         "host_without_device",
         "device",
     ]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 		},
@@ -228,6 +249,13 @@
         ":libgtest",
     ]`,
 				"runs_on": `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 		},
@@ -260,6 +288,13 @@
         ":libgtest",
     ]`,
 				"runs_on": `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 		},
@@ -297,6 +332,13 @@
 				"deps":                  `[":libgtest_isolated_main"]`,
 				"dynamic_deps":          `[":liblog"]`,
 				"runs_on":               `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 		},
@@ -324,6 +366,13 @@
         ":libgtest_main",
     ]`,
 				"runs_on": `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 		},
@@ -350,6 +399,13 @@
 				"deps":                   `[":libgtest_isolated_main"]`,
 				"dynamic_deps":           `[":liblog"]`,
 				"runs_on":                `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 		},
@@ -381,6 +437,13 @@
 				"gtest":                  "True",
 				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
 				"runs_on":                `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 			{"cc_test", "mytest_with_no_gtest", AttrNameToString{
@@ -388,6 +451,166 @@
 				"gtest":                  "False",
 				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
 				"runs_on":                `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
+			},
+			},
+		},
+	})
+}
+
+func TestCcTest_DisableMemtagHeap(t *testing.T) {
+	runCcTestTestCase(t, ccTestBp2buildTestCase{
+		description: "cc test that disable memtag_heap",
+		blueprint: `
+cc_test {
+	name: "mytest",
+	srcs: ["test.cpp"],
+	isolated: true,
+	sanitize: {
+		cfi: true,
+		memtag_heap: false,
+	},
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
+			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+		targets: []testBazelTarget{
+			{"cc_test", "mytest", AttrNameToString{
+				"local_includes":         `["."]`,
+				"srcs":                   `["test.cpp"]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+				"deps":                   `[":libgtest_isolated_main"]`,
+				"dynamic_deps":           `[":liblog"]`,
+				"runs_on":                `["device"]`,
+				"features": `["android_cfi"] + select({
+        "//build/bazel/platforms/os_arch:android_arm64": ["-memtag_heap"],
+        "//conditions:default": [],
+    })`,
+			},
+			},
+		},
+	})
+}
+
+func TestCcTest_RespectArm64MemtagHeap(t *testing.T) {
+	runCcTestTestCase(t, ccTestBp2buildTestCase{
+		description: "cc test that disable memtag_heap",
+		blueprint: `
+cc_test {
+	name: "mytest",
+	srcs: ["test.cpp"],
+	isolated: true,
+	target: {
+		android_arm64: {
+			sanitize: {
+				memtag_heap: false,
+			}
+		}
+	},
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
+			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+		targets: []testBazelTarget{
+			{"cc_test", "mytest", AttrNameToString{
+				"local_includes":         `["."]`,
+				"srcs":                   `["test.cpp"]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+				"deps":                   `[":libgtest_isolated_main"]`,
+				"dynamic_deps":           `[":liblog"]`,
+				"runs_on":                `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": ["-memtag_heap"],
+        "//conditions:default": [],
+    })`,
+			},
+			},
+		},
+	})
+}
+
+func TestCcTest_IgnoreNoneArm64MemtagHeap(t *testing.T) {
+	runCcTestTestCase(t, ccTestBp2buildTestCase{
+		description: "cc test that disable memtag_heap",
+		blueprint: `
+cc_test {
+	name: "mytest",
+	srcs: ["test.cpp"],
+	isolated: true,
+	arch: {
+		x86: {
+			sanitize: {
+				memtag_heap: false,
+			}
+		}
+	},
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
+			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+		targets: []testBazelTarget{
+			{"cc_test", "mytest", AttrNameToString{
+				"local_includes":         `["."]`,
+				"srcs":                   `["test.cpp"]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+				"deps":                   `[":libgtest_isolated_main"]`,
+				"dynamic_deps":           `[":liblog"]`,
+				"runs_on":                `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "memtag_heap",
+            "diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
+			},
+			},
+		},
+	})
+}
+
+func TestCcTest_Arm64MemtagHeapOverrideNoConfigOne(t *testing.T) {
+	runCcTestTestCase(t, ccTestBp2buildTestCase{
+		description: "cc test that disable memtag_heap",
+		blueprint: `
+cc_test {
+	name: "mytest",
+	srcs: ["test.cpp"],
+	isolated: true,
+	sanitize: {
+		memtag_heap: true,
+	},
+	target: {
+		android_arm64: {
+			sanitize: {
+				memtag_heap: false,
+				diag: {
+					memtag_heap: false,
+				},
+			}
+		}
+	},
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
+			simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+		targets: []testBazelTarget{
+			{"cc_test", "mytest", AttrNameToString{
+				"local_includes":         `["."]`,
+				"srcs":                   `["test.cpp"]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+				"deps":                   `[":libgtest_isolated_main"]`,
+				"dynamic_deps":           `[":liblog"]`,
+				"runs_on":                `["device"]`,
+				"features": `select({
+        "//build/bazel/platforms/os_arch:android_arm64": [
+            "-memtag_heap",
+            "-diag_memtag_heap",
+        ],
+        "//conditions:default": [],
+    })`,
 			},
 			},
 		},
diff --git a/bp2build/java_host_for_device_conversion_test.go b/bp2build/java_host_for_device_conversion_test.go
index 448cba4..1fa7126 100644
--- a/bp2build/java_host_for_device_conversion_test.go
+++ b/bp2build/java_host_for_device_conversion_test.go
@@ -48,6 +48,7 @@
     name: "java-lib-2",
     srcs: ["b.java"],
     bazel_module: { bp2build_available: true },
+    sdk_version: "current",
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_host_for_device", "java-lib-1", AttrNameToString{
@@ -57,7 +58,8 @@
 				"sdk_version": `"none"`,
 			}),
 			MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{
-				"srcs": `["b.java"]`,
+				"srcs":        `["b.java"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
 		},
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index c501a7b..7429ae6 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -42,22 +42,26 @@
     srcs: ["a.java", "b.java"],
     exclude_srcs: ["b.java"],
     libs: ["java-lib-2"],
+    sdk_version: "current",
     bazel_module: { bp2build_available: true },
 }
 
 java_library {
     name: "java-lib-2",
     srcs: ["b.java"],
+    sdk_version: "current",
     bazel_module: { bp2build_available: true },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
-				"srcs": `["a.java"]`,
-				"deps": `[":java-lib-2-neverlink"]`,
+				"srcs":        `["a.java"]`,
+				"deps":        `[":java-lib-2-neverlink"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 			MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{
-				"srcs": `["b.java"]`,
+				"srcs":        `["b.java"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
 		},
@@ -71,18 +75,21 @@
     srcs: ["a.java"],
     libs: ["java-lib-2"],
     static_libs: ["java-lib-3"],
+    sdk_version: "current",
     bazel_module: { bp2build_available: true },
 }
 
 java_library {
     name: "java-lib-2",
     srcs: ["b.java"],
+    sdk_version: "current",
     bazel_module: { bp2build_available: false },
 }
 
 java_library {
     name: "java-lib-3",
     srcs: ["c.java"],
+    sdk_version: "current",
     bazel_module: { bp2build_available: false },
 }`,
 		ExpectedBazelTargets: []string{
@@ -92,7 +99,8 @@
         ":java-lib-2-neverlink",
         ":java-lib-3",
     ]`,
-				"exports": `[":java-lib-3"]`,
+				"exports":     `[":java-lib-3"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
@@ -104,6 +112,7 @@
 		Blueprint: `java_library {
     name: "java-lib-1",
     static_libs: ["java-lib-2"],
+    sdk_version: "current",
     bazel_module: { bp2build_available: true },
 }
 
@@ -114,25 +123,40 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
-				"exports": `[":java-lib-2"]`,
+				"exports":     `[":java-lib-2"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
 	})
 }
 
+func TestJavaLibraryFailsToConvertNoSdkVersion(t *testing.T) {
+	runJavaLibraryTestCase(t, Bp2buildTestCase{
+		Blueprint: `
+java_library {
+    name: "lib",
+    bazel_module: { bp2build_available: true },
+}
+`,
+		ExpectedBazelTargets: []string{}, // no targets expected because sdk_version is not set
+	})
+}
+
 func TestJavaLibraryFailsToConvertLibsWithNoSrcs(t *testing.T) {
 	runJavaLibraryTestCase(t, Bp2buildTestCase{
 		ExpectedErr: fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."),
 		Blueprint: `java_library {
     name: "java-lib-1",
     libs: ["java-lib-2"],
+    sdk_version: "current",
     bazel_module: { bp2build_available: true },
 }
 
 java_library {
     name: "java-lib-2",
     srcs: ["a.java"],
+    sdk_version: "current",
     bazel_module: { bp2build_available: false },
 }`,
 		ExpectedBazelTargets: []string{},
@@ -144,6 +168,7 @@
 		Blueprint: `java_library {
     name: "java-lib-1",
     plugins: ["java-plugin-1"],
+    sdk_version: "current",
     bazel_module: { bp2build_available: true },
 }
 
@@ -154,7 +179,8 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
-				"plugins": `[":java-plugin-1"]`,
+				"plugins":     `[":java-plugin-1"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
@@ -169,16 +195,21 @@
     name: "java-lib-1",
     srcs: ["a.java"],
     java_version: "11",
+    sdk_version: "current",
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
 				"srcs":         `["a.java"]`,
 				"java_version": `"11"`,
+				"sdk_version":  `"current"`,
 			}),
 			MakeNeverlinkDuplicateTargetWithAttrs(
 				"java_library",
 				"java-lib-1",
-				AttrNameToString{"java_version": `"11"`}),
+				AttrNameToString{
+					"java_version": `"11"`,
+					"sdk_version":  `"current"`,
+				}),
 		},
 	})
 }
@@ -189,6 +220,7 @@
     name: "java-lib-1",
     srcs: ["a.java"],
     javacflags: ["-Xsuper-fast"],
+    sdk_version: "current",
     errorprone: {
         enabled: true,
         javacflags: ["-Xep:SpeedLimit:OFF"],
@@ -209,6 +241,7 @@
 				"plugins":                 `[":plugin2"]`,
 				"srcs":                    `["a.java"]`,
 				"errorprone_force_enable": `True`,
+				"sdk_version":             `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
@@ -222,6 +255,7 @@
 		Blueprint: `java_library {
     name: "java-lib-1",
     srcs: ["a.java"],
+    sdk_version: "current",
     javacflags: ["-Xsuper-fast"],
     errorprone: {
         javacflags: ["-Xep:SpeedLimit:OFF"],
@@ -229,8 +263,9 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
-				"javacopts": `["-Xsuper-fast"]`,
-				"srcs":      `["a.java"]`,
+				"javacopts":   `["-Xsuper-fast"]`,
+				"srcs":        `["a.java"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
@@ -243,6 +278,7 @@
     name: "java-lib-1",
     srcs: ["a.java"],
     javacflags: ["-Xsuper-fast"],
+    sdk_version: "current",
     errorprone: {
     enabled: false,
     },
@@ -253,7 +289,8 @@
         "-Xsuper-fast",
         "-XepDisableAllChecks",
     ]`,
-				"srcs": `["a.java"]`,
+				"srcs":        `["a.java"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
@@ -266,14 +303,15 @@
 		ModuleTypeUnderTest:        "java_library",
 		ModuleTypeUnderTestFactory: java.LibraryFactory,
 		Blueprint: `java_library {
-        name: "example_lib",
-        srcs: [
-			"a.java",
-			"b.java",
-			"a.logtag",
-			"b.logtag",
-		],
-        bazel_module: { bp2build_available: true },
+	name: "example_lib",
+	srcs: [
+		"a.java",
+		"b.java",
+		"a.logtag",
+		"b.logtag",
+	],
+	sdk_version: "current",
+	bazel_module: { bp2build_available: true },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("event_log_tags", "example_lib_logtags", AttrNameToString{
@@ -288,6 +326,7 @@
         "b.java",
         ":example_lib_logtags",
     ]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
 		}})
@@ -301,9 +340,10 @@
 			"adir/res/b.res":      "",
 			"adir/res/dir1/b.res": "",
 			"adir/Android.bp": `java_library {
-    name: "java-lib-1",
-    java_resources: ["res/a.res", "res/b.res"],
-    bazel_module: { bp2build_available: true },
+	name: "java-lib-1",
+	java_resources: ["res/a.res", "res/b.res"],
+	sdk_version: "current",
+	bazel_module: { bp2build_available: true },
 }`,
 		},
 		Blueprint: "",
@@ -314,6 +354,7 @@
         "res/b.res",
     ]`,
 				"resource_strip_prefix": `"adir"`,
+				"sdk_version":           `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
@@ -328,8 +369,9 @@
 			"res/dir1/b.res": "",
 		},
 		Blueprint: `java_library {
-    name: "java-lib-1",
+	name: "java-lib-1",
 	java_resource_dirs: ["res"],
+	sdk_version: "current",
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
@@ -339,6 +381,7 @@
         "res/b.res",
         "res/dir1/b.res",
     ]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
@@ -352,14 +395,16 @@
 			"res/exclude/b.res": "",
 		},
 		Blueprint: `java_library {
-    name: "java-lib-1",
+	name: "java-lib-1",
 	java_resource_dirs: ["res"],
+	sdk_version: "current",
 	exclude_java_resource_dirs: ["res/exclude"],
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
 				"resource_strip_prefix": `"res"`,
 				"resources":             `["res/a.res"]`,
+				"sdk_version":           `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
@@ -374,8 +419,9 @@
 			"res/dir1/exclude.res": "",
 		},
 		Blueprint: `java_library {
-    name: "java-lib-1",
+	name: "java-lib-1",
 	java_resource_dirs: ["res"],
+	sdk_version: "current",
 	exclude_java_resources: ["res/dir1/exclude.res"],
 }`,
 		ExpectedBazelTargets: []string{
@@ -385,24 +431,67 @@
         "res/a.res",
         "res/dir1/b.res",
     ]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
 	})
 }
 
-func TestJavaLibraryResourcesFailsWithMultipleDirs(t *testing.T) {
+func TestJavaLibraryResourcesWithMultipleDirs(t *testing.T) {
 	runJavaLibraryTestCase(t, Bp2buildTestCase{
 		Filesystem: map[string]string{
 			"res/a.res":  "",
-			"res1/a.res": "",
+			"res1/b.res": "",
 		},
 		Blueprint: `java_library {
-    name: "java-lib-1",
+	name: "java-lib-1",
 	java_resource_dirs: ["res", "res1"],
+	sdk_version: "current",
 }`,
-		ExpectedErr:          fmt.Errorf("bp2build does not support more than one directory in java_resource_dirs (b/226423379)"),
-		ExpectedBazelTargets: []string{},
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_resources", "java-lib-1_resource_dir_res1", AttrNameToString{
+				"resource_strip_prefix": `"res1"`,
+				"resources":             `["res1/b.res"]`,
+			}),
+			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
+				"additional_resources":  `["java-lib-1_resource_dir_res1"]`,
+				"resources":             `["res/a.res"]`,
+				"resource_strip_prefix": `"res"`,
+				"sdk_version":           `"current"`,
+			}),
+			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+		},
+	})
+}
+
+func TestJavaLibraryJavaResourcesAndResourceDirs(t *testing.T) {
+	runJavaLibraryTestCase(t, Bp2buildTestCase{
+		Filesystem: map[string]string{
+			"resdir/a.res": "",
+		},
+		Blueprint: `java_library {
+		name: "java-lib-1",
+		java_resources: ["res1", "res2"],
+		java_resource_dirs: ["resdir"],
+		sdk_version: "current",
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_resources", "java-lib-1_resource_dir_resdir", AttrNameToString{
+				"resource_strip_prefix": `"resdir"`,
+				"resources":             `["resdir/a.res"]`,
+			}),
+			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
+				"additional_resources":  `["java-lib-1_resource_dir_resdir"]`,
+				"resource_strip_prefix": `"."`,
+				"resources": `[
+        "res1",
+        "res2",
+    ]`,
+				"sdk_version": `"current"`,
+			}),
+			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+		},
 	})
 }
 
@@ -412,14 +501,15 @@
 		ModuleTypeUnderTest:        "java_library",
 		ModuleTypeUnderTestFactory: java.LibraryFactory,
 		Blueprint: `java_library {
-        name: "example_lib",
-        srcs: [
-			"a.java",
-			"b.java",
-			"a.aidl",
-			"b.aidl",
-		],
-        bazel_module: { bp2build_available: true },
+	name: "example_lib",
+	srcs: [
+		"a.java",
+		"b.java",
+		"a.aidl",
+		"b.aidl",
+	],
+	bazel_module: { bp2build_available: true },
+	sdk_version: "current",
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{
@@ -438,6 +528,7 @@
         "a.java",
         "b.java",
     ]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
 		}})
@@ -450,12 +541,13 @@
 		ModuleTypeUnderTestFactory: java.LibraryFactory,
 		Blueprint: `
 java_library {
-        name: "example_lib",
-        srcs: [
-			"a.java",
-			"b.aidl",
-		],
-        bazel_module: { bp2build_available: true },
+	name: "example_lib",
+	srcs: [
+		"a.java",
+		"b.aidl",
+	],
+	sdk_version: "current",
+	bazel_module: { bp2build_available: true },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{
@@ -465,9 +557,10 @@
 				"deps": `[":example_lib_aidl_library"]`,
 			}),
 			MakeBazelTarget("java_library", "example_lib", AttrNameToString{
-				"deps":    `[":example_lib_java_aidl_library"]`,
-				"exports": `[":example_lib_java_aidl_library"]`,
-				"srcs":    `["a.java"]`,
+				"deps":        `[":example_lib_java_aidl_library"]`,
+				"exports":     `[":example_lib_java_aidl_library"]`,
+				"srcs":        `["a.java"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
 		},
@@ -497,14 +590,15 @@
 	],
 }
 java_library {
-        name: "example_lib",
-        srcs: [
-			"a.java",
-			"b.java",
-			":aidl_files",
-			":random_other_files",
-		],
-        bazel_module: { bp2build_available: true },
+	name: "example_lib",
+	srcs: [
+		"a.java",
+		"b.java",
+		":aidl_files",
+		":random_other_files",
+	],
+	sdk_version: "current",
+	bazel_module: { bp2build_available: true },
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTargetNoRestrictions("aidl_library", "aidl_files", AttrNameToString{
@@ -525,6 +619,7 @@
         "b.java",
         ":random_other_files",
     ]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
 			MakeBazelTargetNoRestrictions("filegroup", "random_other_files", AttrNameToString{
@@ -547,24 +642,26 @@
 		Filesystem: map[string]string{
 			"path/to/A/Android.bp": `
 filegroup {
-	name: "A_aidl",
-	srcs: ["aidl/A.aidl"],
-	path: "aidl",
+  name: "A_aidl",
+  srcs: ["aidl/A.aidl"],
+  path: "aidl",
 }`,
 		},
 		Blueprint: `
 java_library {
-	name: "foo",
-	srcs: [
-		":A_aidl",
-	],
+  name: "foo",
+  srcs: [
+    ":A_aidl",
+  ],
+  sdk_version: "current",
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_aidl_library", "foo_java_aidl_library", AttrNameToString{
 				"deps": `["//path/to/A:A_aidl"]`,
 			}),
 			MakeBazelTarget("java_library", "foo", AttrNameToString{
-				"exports": `[":foo_java_aidl_library"]`,
+				"exports":     `[":foo_java_aidl_library"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "foo"),
 		},
@@ -581,16 +678,17 @@
 		ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
 		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
 android_library {
-	name: "TestLib",
-	manifest: "manifest/AndroidManifest.xml",
-	srcs: ["lib.java"],
-	arch: {
-		arm: {
-			neon: {
-				srcs: ["arm_neon.java"],
-			},
-		},
-	},
+  name: "TestLib",
+  manifest: "manifest/AndroidManifest.xml",
+  srcs: ["lib.java"],
+  sdk_version: "current",
+  arch: {
+    arm: {
+      neon: {
+        srcs: ["arm_neon.java"],
+      },
+    },
+  },
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -604,6 +702,7 @@
     })`,
 					"manifest":       `"manifest/AndroidManifest.xml"`,
 					"resource_files": `[]`,
+					"sdk_version":    `"current"`, // use as default
 				}),
 			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
@@ -617,19 +716,20 @@
 		ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
 		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
 android_library {
-	name: "TestLib",
-	manifest: "manifest/AndroidManifest.xml",
-	srcs: ["lib.java"],
-	arch: {
-		x86: {
-			ssse3: {
-				srcs: ["ssse3.java"],
-			},
-			sse4_1: {
-				srcs: ["sse4_1.java"],
-			},
-		},
-	},
+  name: "TestLib",
+  manifest: "manifest/AndroidManifest.xml",
+  srcs: ["lib.java"],
+  sdk_version: "current",
+  arch: {
+    x86: {
+      ssse3: {
+        srcs: ["ssse3.java"],
+      },
+      sse4_1: {
+        srcs: ["sse4_1.java"],
+      },
+    },
+  },
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -648,6 +748,7 @@
     })`,
 					"manifest":       `"manifest/AndroidManifest.xml"`,
 					"resource_files": `[]`,
+					"sdk_version":    `"current"`,
 				}),
 			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
@@ -661,17 +762,18 @@
 		ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
 		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
 android_library {
-	name: "TestLib",
-	manifest: "manifest/AndroidManifest.xml",
-	srcs: ["lib.java"],
-	arch: {
-		arm: {
-			srcs: ["arm_non_neon.java"],
-			neon: {
-				exclude_srcs: ["arm_non_neon.java"],
-			},
-		},
-	},
+  name: "TestLib",
+  manifest: "manifest/AndroidManifest.xml",
+  srcs: ["lib.java"],
+  arch: {
+    arm: {
+      srcs: ["arm_non_neon.java"],
+      neon: {
+        exclude_srcs: ["arm_non_neon.java"],
+      },
+    },
+  },
+  sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -686,6 +788,7 @@
     })`,
 					"manifest":       `"manifest/AndroidManifest.xml"`,
 					"resource_files": `[]`,
+					"sdk_version":    `"current"`, // use as default
 				}),
 			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
@@ -698,6 +801,7 @@
     name: "java-lib-1",
     srcs: ["a.java", "b.java", "c.kt"],
     bazel_module: { bp2build_available: true },
+    sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -707,6 +811,7 @@
         "b.java",
         "c.kt",
     ]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("kt_jvm_library", "java-lib-1"),
 		},
@@ -721,6 +826,7 @@
     srcs: [ "a.kt"],
     kotlincflags: ["-flag1", "-flag2"],
     bazel_module: { bp2build_available: true },
+    sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -730,6 +836,7 @@
         "-flag1",
         "-flag2",
     ]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("kt_jvm_library", "java-lib-1"),
 		},
@@ -744,6 +851,7 @@
     srcs: ["a.java", "b.java"],
     common_srcs: ["c.kt"],
     bazel_module: { bp2build_available: true },
+    sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -753,6 +861,7 @@
         "b.java",
     ]`,
 				"common_srcs": `["c.kt"]`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("kt_jvm_library", "java-lib-1"),
 		},
@@ -766,6 +875,7 @@
     name: "java-lib-1",
     srcs: ["a.java"],
     libs: ["java-lib-2"],
+    sdk_version: "current",
     target: {
         android: {
             libs: ["java-lib-3"],
@@ -775,16 +885,19 @@
     bazel_module: { bp2build_available: true },
 }
 
-	java_library{
-		name: "java-lib-2",
+  java_library{
+    name: "java-lib-2",
+    bazel_module: { bp2build_available: false },
 }
 
-	java_library{
-		name: "java-lib-3",
+  java_library{
+    name: "java-lib-3",
+    bazel_module: { bp2build_available: false },
 }
 
-	java_library{
-		name: "java-lib-4",
+  java_library{
+    name: "java-lib-4",
+    bazel_module: { bp2build_available: false },
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -801,14 +914,9 @@
         ],
         "//conditions:default": [],
     })`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
-			MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{}),
-			MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
-			MakeBazelTarget("java_library", "java-lib-3", AttrNameToString{}),
-			MakeNeverlinkDuplicateTarget("java_library", "java-lib-3"),
-			MakeBazelTarget("java_library", "java-lib-4", AttrNameToString{}),
-			MakeNeverlinkDuplicateTarget("java_library", "java-lib-4"),
 		},
 	})
 }
@@ -819,6 +927,7 @@
 		Blueprint: `java_library {
     name: "java-lib-1",
     srcs: ["a.java", "b.java"],
+    sdk_version: "current",
     target: {
         android: {
             exclude_srcs: ["a.java"],
@@ -833,6 +942,7 @@
         "//build/bazel/platforms/os:android": [],
         "//conditions:default": ["a.java"],
     })`,
+				"sdk_version": `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 		},
@@ -850,6 +960,7 @@
 		Blueprint: `java_library {
     name: "java-lib-1",
     srcs: ["a.java"],
+    sdk_version: "current",
     java_resources: [":filegroup1"],
     bazel_module: { bp2build_available: true },
 }
@@ -866,6 +977,7 @@
 				"srcs":                  `["a.java"]`,
 				"resources":             `[":filegroup1"]`,
 				"resource_strip_prefix": `"foo"`,
+				"sdk_version":           `"current"`,
 			}),
 			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
 			MakeBazelTargetNoRestrictions("filegroup", "filegroup1", AttrNameToString{
@@ -878,3 +990,59 @@
 		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	})
 }
+
+func TestJavaLibraryJavaResourcesMultipleFilegroup(t *testing.T) {
+	runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
+		Filesystem: map[string]string{
+			"a.res": "",
+		},
+		Description: "with java_resources that has multiple filegroups",
+		Blueprint: `java_library {
+    name: "java-lib-1",
+    srcs: ["a.java"],
+    java_resources: ["a.res", ":filegroup1", ":filegroup2"],
+    sdk_version: "current",
+    bazel_module: { bp2build_available: true },
+}
+
+filegroup {
+    name: "filegroup1",
+    path: "foo",
+    srcs: ["foo/a"],
+}
+
+filegroup {
+    name: "filegroup2",
+    path: "bar",
+    srcs: ["bar/a"],
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_resources", "java-lib-1_filegroup_resources_filegroup1", AttrNameToString{
+				"resource_strip_prefix": `"foo"`,
+				"resources":             `[":filegroup1"]`,
+			}),
+			MakeBazelTarget("java_resources", "java-lib-1_filegroup_resources_filegroup2", AttrNameToString{
+				"resource_strip_prefix": `"bar"`,
+				"resources":             `[":filegroup2"]`,
+			}),
+			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
+				"srcs":                  `["a.java"]`,
+				"resources":             `["a.res"]`,
+				"resource_strip_prefix": `"."`,
+				"additional_resources": `[
+        "java-lib-1_filegroup_resources_filegroup1",
+        "java-lib-1_filegroup_resources_filegroup2",
+    ]`,
+				"sdk_version": `"current"`,
+			}),
+			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+			MakeBazelTargetNoRestrictions("filegroup", "filegroup1", AttrNameToString{
+				"srcs": `["foo/a"]`}),
+			MakeBazelTargetNoRestrictions("filegroup", "filegroup2", AttrNameToString{
+				"srcs": `["bar/a"]`}),
+		},
+	}, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	})
+}
diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go
index f546cf4..5d6b088 100644
--- a/bp2build/java_proto_conversion_test.go
+++ b/bp2build/java_proto_conversion_test.go
@@ -68,6 +68,7 @@
         type: "%s",
     },
     srcs: ["a.proto"],
+    sdk_version: "current",
 }`
 
 	protoLibrary := MakeBazelTarget("proto_library", "java-protos_proto", AttrNameToString{
@@ -86,10 +87,12 @@
 					tc.javaLibraryType,
 					javaLibraryName,
 					AttrNameToString{
-						"deps": `[":java-protos_proto"]`,
+						"deps":        `[":java-protos_proto"]`,
+						"sdk_version": `"current"`,
 					}),
 				MakeBazelTarget("java_library", "java-protos", AttrNameToString{
-					"exports": fmt.Sprintf(`[":%s"]`, javaLibraryName),
+					"exports":     fmt.Sprintf(`[":%s"]`, javaLibraryName),
+					"sdk_version": `"current"`,
 				}),
 				MakeNeverlinkDuplicateTarget("java_library", "java-protos"),
 			},
@@ -104,6 +107,7 @@
     name: "java-protos",
     srcs: ["a.proto"],
     java_version: "7",
+    sdk_version: "current",
 }
 `,
 		ExpectedBazelTargets: []string{
@@ -116,15 +120,20 @@
 				AttrNameToString{
 					"deps":         `[":java-protos_proto"]`,
 					"java_version": `"7"`,
+					"sdk_version":  `"current"`,
 				}),
 			MakeBazelTarget("java_library", "java-protos", AttrNameToString{
 				"exports":      `[":java-protos_java_proto_lite"]`,
 				"java_version": `"7"`,
+				"sdk_version":  `"current"`,
 			}),
 			MakeNeverlinkDuplicateTargetWithAttrs(
 				"java_library",
 				"java-protos",
-				AttrNameToString{"java_version": `"7"`}),
+				AttrNameToString{
+					"java_version": `"7"`,
+					"sdk_version":  `"current"`,
+				}),
 		},
 	})
 }
diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go
index a53371d..595acd2 100644
--- a/bp2build/python_library_conversion_test.go
+++ b/bp2build/python_library_conversion_test.go
@@ -348,3 +348,43 @@
 		},
 	})
 }
+
+func TestPythonLibraryWithProtobufsAndPkgPath(t *testing.T) {
+	t.Parallel()
+	runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+		Description: "test python_library protobuf with pkg_path",
+		Filesystem: map[string]string{
+			"dir/foo.proto": "",
+			"dir/bar.proto": "", // bar contains "import dir/foo.proto"
+			"dir/Android.bp": `
+python_library {
+  name: "foo",
+  pkg_path: "dir",
+  srcs: [
+    "foo.proto",
+    "bar.proto",
+  ],
+  bazel_module: {bp2build_available: true},
+}`,
+		},
+		Dir: "dir",
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
+				"import_prefix":       `"dir"`,
+				"strip_import_prefix": `""`,
+				"srcs": `[
+        "foo.proto",
+        "bar.proto",
+    ]`,
+			}),
+			MakeBazelTarget("py_proto_library", "foo_py_proto", AttrNameToString{
+				"deps": `[":foo_proto"]`,
+			}),
+			MakeBazelTarget("py_library", "foo", AttrNameToString{
+				"srcs_version": `"PY3"`,
+				"imports":      `[".."]`,
+				"deps":         `[":foo_py_proto"]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/rust_binary_conversion_test.go b/bp2build/rust_binary_conversion_test.go
new file mode 100644
index 0000000..3364401
--- /dev/null
+++ b/bp2build/rust_binary_conversion_test.go
@@ -0,0 +1,74 @@
+package bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/rust"
+	"testing"
+)
+
+func runRustBinaryTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	RunBp2BuildTestCase(t, registerRustBinaryModuleTypes, tc)
+}
+
+func registerRustBinaryModuleTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("rust_binary_host", rust.RustBinaryHostFactory)
+	ctx.RegisterModuleType("rust_library_host", rust.RustLibraryHostFactory)
+	ctx.RegisterModuleType("rust_proc_macro", rust.ProcMacroFactory)
+
+}
+
+func TestRustBinaryHost(t *testing.T) {
+	runRustBinaryTestCase(t, Bp2buildTestCase{
+		Dir:       "external/rust/crates/foo",
+		Blueprint: "",
+		Filesystem: map[string]string{
+			"external/rust/crates/foo/src/lib.rs":    "",
+			"external/rust/crates/foo/src/helper.rs": "",
+			"external/rust/crates/foo/Android.bp": `
+rust_binary_host {
+	name: "libfoo",
+	crate_name: "foo",
+	srcs: ["src/main.rs"],
+	edition: "2021",
+	features: ["bah-enabled"],
+	cfgs: ["baz"],
+	rustlibs: ["libbar"],
+	proc_macros: ["libbah"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+			"external/rust/crates/bar/Android.bp": `
+rust_library_host {
+	name: "libbar",
+	crate_name: "bar",
+	srcs: ["src/lib.rs"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+			"external/rust/crates/bah/Android.bp": `
+rust_proc_macro {
+	name: "libbah",
+	crate_name: "bah",
+	srcs: ["src/lib.rs"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+		},
+		ExpectedBazelTargets: []string{
+			makeBazelTargetHostOrDevice("rust_binary", "libfoo", AttrNameToString{
+				"crate_name": `"foo"`,
+				"srcs": `[
+        "src/helper.rs",
+        "src/lib.rs",
+    ]`,
+				"deps":            `["//external/rust/crates/bar:libbar"]`,
+				"proc_macro_deps": `["//external/rust/crates/bah:libbah"]`,
+				"edition":         `"2021"`,
+				"crate_features":  `["bah-enabled"]`,
+				"rustc_flags":     `["--cfg=baz"]`,
+			}, android.HostSupported),
+		},
+	},
+	)
+}
diff --git a/bp2build/rust_library_conversion_test.go b/bp2build/rust_library_conversion_test.go
new file mode 100644
index 0000000..b860b76
--- /dev/null
+++ b/bp2build/rust_library_conversion_test.go
@@ -0,0 +1,96 @@
+package bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/rust"
+	"testing"
+)
+
+func runRustLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	RunBp2BuildTestCase(t, registerRustLibraryModuleTypes, tc)
+}
+
+func registerRustLibraryModuleTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("rust_library", rust.RustLibraryFactory)
+	ctx.RegisterModuleType("rust_library_host", rust.RustLibraryHostFactory)
+}
+
+func TestLibProtobuf(t *testing.T) {
+	runRustLibraryTestCase(t, Bp2buildTestCase{
+		Dir:       "external/rust/crates/foo",
+		Blueprint: "",
+		Filesystem: map[string]string{
+			"external/rust/crates/foo/src/lib.rs": "",
+			"external/rust/crates/foo/Android.bp": `
+rust_library_host {
+	name: "libprotobuf",
+	crate_name: "protobuf",
+	srcs: ["src/lib.rs"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+		},
+		ExpectedBazelTargets: []string{
+			// TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
+			makeBazelTargetHostOrDevice("rust_library", "libprotobuf", AttrNameToString{
+				"crate_name": `"protobuf"`,
+				"srcs":       `["src/lib.rs"]`,
+				"deps":       `[":libprotobuf_build_script"]`,
+			}, android.HostSupported),
+			makeBazelTargetHostOrDevice("cargo_build_script", "libprotobuf_build_script", AttrNameToString{
+				"srcs": `["build.rs"]`,
+			}, android.HostSupported),
+		},
+	},
+	)
+}
+
+func TestRustLibrary(t *testing.T) {
+	expectedAttrs := AttrNameToString{
+		"crate_name": `"foo"`,
+		"srcs": `[
+        "src/helper.rs",
+        "src/lib.rs",
+    ]`,
+		"crate_features": `["bah-enabled"]`,
+		"edition":        `"2021"`,
+		"rustc_flags":    `["--cfg=baz"]`,
+	}
+
+	runRustLibraryTestCase(t, Bp2buildTestCase{
+		Dir:       "external/rust/crates/foo",
+		Blueprint: "",
+		Filesystem: map[string]string{
+			"external/rust/crates/foo/src/lib.rs":    "",
+			"external/rust/crates/foo/src/helper.rs": "",
+			"external/rust/crates/foo/Android.bp": `
+rust_library {
+	name: "libfoo",
+	crate_name: "foo",
+    host_supported: true,
+	srcs: ["src/lib.rs"],
+	edition: "2021",
+	features: ["bah-enabled"],
+	cfgs: ["baz"],
+    bazel_module: { bp2build_available: true },
+}
+rust_library_host {
+    name: "libfoo_host",
+    crate_name: "foo",
+    srcs: ["src/lib.rs"],
+    edition: "2021",
+    features: ["bah-enabled"],
+    cfgs: ["baz"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+		},
+		ExpectedBazelTargets: []string{
+			// TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
+			makeBazelTargetHostOrDevice("rust_library", "libfoo", expectedAttrs, android.HostSupported),
+			makeBazelTargetHostOrDevice("rust_library", "libfoo_host", expectedAttrs, android.HostSupported),
+		},
+	},
+	)
+}
diff --git a/bp2build/rust_proc_macro_conversion_test.go b/bp2build/rust_proc_macro_conversion_test.go
new file mode 100644
index 0000000..82e080d
--- /dev/null
+++ b/bp2build/rust_proc_macro_conversion_test.go
@@ -0,0 +1,62 @@
+package bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/rust"
+	"testing"
+)
+
+func rustRustProcMacroTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	RunBp2BuildTestCase(t, registerRustProcMacroModuleTypes, tc)
+}
+
+func registerRustProcMacroModuleTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("rust_library_host", rust.RustLibraryHostFactory)
+	ctx.RegisterModuleType("rust_proc_macro", rust.ProcMacroFactory)
+}
+
+func TestRustProcMacroLibrary(t *testing.T) {
+	runRustLibraryTestCase(t, Bp2buildTestCase{
+		Dir:       "external/rust/crates/foo",
+		Blueprint: "",
+		Filesystem: map[string]string{
+			"external/rust/crates/foo/src/lib.rs":    "",
+			"external/rust/crates/foo/src/helper.rs": "",
+			"external/rust/crates/foo/Android.bp": `
+rust_proc_macro {
+	name: "libfoo",
+	crate_name: "foo",
+	srcs: ["src/lib.rs"],
+	edition: "2021",
+	features: ["bah-enabled"],
+	cfgs: ["baz"],
+	rustlibs: ["libbar"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+			"external/rust/crates/bar/src/lib.rs": "",
+			"external/rust/crates/bar/Android.bp": `
+rust_library_host {
+    name: "libbar",
+    crate_name: "bar",
+    srcs: ["src/lib.rs"],
+    bazel_module: { bp2build_available: true },
+}`,
+		},
+		ExpectedBazelTargets: []string{
+			makeBazelTargetHostOrDevice("rust_proc_macro", "libfoo", AttrNameToString{
+				"crate_name": `"foo"`,
+				"srcs": `[
+        "src/helper.rs",
+        "src/lib.rs",
+    ]`,
+				"crate_features": `["bah-enabled"]`,
+				"edition":        `"2021"`,
+				"rustc_flags":    `["--cfg=baz"]`,
+				"deps":           `["//external/rust/crates/bar:libbar"]`,
+			}, android.HostSupported),
+		},
+	},
+	)
+}
diff --git a/bp2build/rust_protobuf_conversion_test.go b/bp2build/rust_protobuf_conversion_test.go
new file mode 100644
index 0000000..a779c36
--- /dev/null
+++ b/bp2build/rust_protobuf_conversion_test.go
@@ -0,0 +1,46 @@
+package bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/rust"
+	"testing"
+)
+
+func runRustProtobufTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	RunBp2BuildTestCase(t, registerRustProtobufModuleTypes, tc)
+}
+
+func registerRustProtobufModuleTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("rust_protobuf_host", rust.RustProtobufHostFactory)
+
+}
+
+func TestRustProtobufHostTestCase(t *testing.T) {
+	runRustProtobufTestCase(t, Bp2buildTestCase{
+		Dir:       "external/rust/crates/foo",
+		Blueprint: "",
+		Filesystem: map[string]string{
+			"external/rust/crates/foo/src/lib.rs":    "",
+			"external/rust/crates/foo/src/helper.rs": "",
+			"external/rust/crates/foo/Android.bp": `
+rust_protobuf_host {
+	name: "libfoo",
+	crate_name: "foo",
+	protos: ["src/foo.proto"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+		},
+		ExpectedBazelTargets: []string{
+			makeBazelTargetHostOrDevice("proto_library", "libfoo_proto", AttrNameToString{
+				"srcs": `["src/foo.proto"]`,
+			}, android.HostSupported),
+			makeBazelTargetHostOrDevice("rust_proto_library", "libfoo", AttrNameToString{
+				"crate_name": `"foo"`,
+				"deps":       `[":libfoo_proto"]`,
+			}, android.HostSupported),
+		},
+	},
+	)
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 18ae82d..42d955e 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -688,7 +688,9 @@
 }
 
 func MakeNeverlinkDuplicateTarget(moduleType string, name string) string {
-	return MakeNeverlinkDuplicateTargetWithAttrs(moduleType, name, AttrNameToString{})
+	return MakeNeverlinkDuplicateTargetWithAttrs(moduleType, name, AttrNameToString{
+		"sdk_version": `"current"`, // use as default
+	})
 }
 
 func MakeNeverlinkDuplicateTargetWithAttrs(moduleType string, name string, extraAttrs AttrNameToString) string {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index ce35b5c..e0e543f 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -530,9 +530,9 @@
 
 	entries.SubName = ""
 
-	if c.isSanitizerEnabled(cfi) {
+	if c.IsSanitizerEnabled(cfi) {
 		entries.SubName += ".cfi"
-	} else if c.isSanitizerEnabled(Hwasan) {
+	} else if c.IsSanitizerEnabled(Hwasan) {
 		entries.SubName += ".hwasan"
 	}
 
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 7f78e28..83553c8 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -851,7 +851,7 @@
 	return ret
 }
 
-// bp2BuildParseBaseProps returns all compiler, linker, library attributes of a cc module..
+// bp2BuildParseBaseProps returns all compiler, linker, library attributes of a cc module.
 func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes {
 	archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
 	archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{})
@@ -1936,6 +1936,8 @@
 	sanitizerFeatures := bazel.StringListAttribute{}
 	sanitizerCopts := bazel.StringListAttribute{}
 	sanitizerCompilerInputs := bazel.LabelListAttribute{}
+	memtagFeatures := bazel.StringListAttribute{}
+	memtagFeature := ""
 	bp2BuildPropParseHelper(ctx, m, &SanitizeProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
 		var features []string
 		if sanitizerProps, ok := props.(*SanitizeProperties); ok {
@@ -1960,9 +1962,18 @@
 					features = append(features, "android_cfi_assembly_support")
 				}
 			}
+
+			if sanitizerProps.Sanitize.Memtag_heap != nil {
+				if (axis == bazel.NoConfigAxis && memtagFeature == "") ||
+					(axis == bazel.OsArchConfigurationAxis && config == bazel.OsArchAndroidArm64) {
+					memtagFeature = setMemtagValue(sanitizerProps, &memtagFeatures)
+				}
+			}
 			sanitizerFeatures.SetSelectValue(axis, config, features)
 		}
 	})
+	sanitizerFeatures.Append(memtagFeatures)
+
 	return sanitizerValues{
 		features:                 sanitizerFeatures,
 		copts:                    sanitizerCopts,
@@ -1970,6 +1981,26 @@
 	}
 }
 
+func setMemtagValue(sanitizerProps *SanitizeProperties, memtagFeatures *bazel.StringListAttribute) string {
+	var features []string
+	if proptools.Bool(sanitizerProps.Sanitize.Memtag_heap) {
+		features = append(features, "memtag_heap")
+	} else {
+		features = append(features, "-memtag_heap")
+	}
+	// Logic comes from: https://cs.android.com/android/platform/superproject/main/+/32ea1afbd1148b0b78553f24fa61116c999eb968:build/soong/cc/sanitize.go;l=910
+	if sanitizerProps.Sanitize.Diag.Memtag_heap != nil {
+		if proptools.Bool(sanitizerProps.Sanitize.Diag.Memtag_heap) {
+			features = append(features, "diag_memtag_heap")
+		} else {
+			features = append(features, "-diag_memtag_heap")
+		}
+	}
+	memtagFeatures.SetSelectValue(bazel.OsArchConfigurationAxis, bazel.OsArchAndroidArm64, features)
+
+	return features[0]
+}
+
 func bp2buildLtoFeatures(ctx android.BazelConversionPathContext, m *Module) bazel.StringListAttribute {
 	lto_feature_name := "android_thin_lto"
 	ltoBoolFeatures := bazel.BoolAttribute{}
diff --git a/cc/linkable.go b/cc/linkable.go
index 2099399..5b5b856 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -95,6 +95,18 @@
 
 	// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
 	IsSnapshotPrebuilt() bool
+
+	// IsSnapshotSanitizer returns true if this snapshot module implements SnapshotSanitizer.
+	IsSnapshotSanitizer() bool
+
+	// IsSnapshotSanitizerAvailable returns true if this snapshot module has a sanitizer source available (cfi, hwasan).
+	IsSnapshotSanitizerAvailable(t SanitizerType) bool
+
+	// SetSnapshotSanitizerVariation sets the sanitizer variation type for this snapshot module.
+	SetSnapshotSanitizerVariation(t SanitizerType, enabled bool)
+
+	// IsSnapshotUnsanitizedVariant returns true if this is the unsanitized snapshot module variant.
+	IsSnapshotUnsanitizedVariant() bool
 }
 
 // LinkableInterface is an interface for a type of module that is linkable in a C++ library.
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 8eea7db..f37b5c7 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -1189,7 +1189,7 @@
 	if sanitizeable, ok := ctx.Module().(Sanitizeable); ok {
 		enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name())
 		ctx.VisitDirectDeps(func(dep android.Module) {
-			if c, ok := dep.(*Module); ok && c.sanitize.isSanitizerEnabled(s.sanitizer) {
+			if c, ok := dep.(PlatformSanitizeable); ok && c.IsSanitizerEnabled(s.sanitizer) {
 				enabled = true
 			}
 		})
@@ -1243,12 +1243,10 @@
 		}
 	}
 
-	if c, ok := ctx.Module().(*Module); ok {
-		//TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable
-
+	if c, ok := ctx.Module().(LinkableInterface); ok {
 		// Check if it's a snapshot module supporting sanitizer
-		if ss, ok := c.linker.(snapshotSanitizer); ok {
-			if ss.isSanitizerAvailable(s.sanitizer) {
+		if c.IsSnapshotSanitizer() {
+			if c.IsSnapshotSanitizerAvailable(s.sanitizer) {
 				return []string{"", s.sanitizer.variationName()}
 			} else {
 				return []string{""}
@@ -1280,8 +1278,8 @@
 
 func (s *sanitizerSplitMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
 	if d, ok := ctx.Module().(PlatformSanitizeable); ok {
-		if dm, ok := ctx.Module().(*Module); ok {
-			if ss, ok := dm.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) {
+		if dm, ok := ctx.Module().(LinkableInterface); ok {
+			if dm.IsSnapshotSanitizerAvailable(s.sanitizer) {
 				return incomingVariation
 			}
 		}
@@ -1396,19 +1394,19 @@
 		if sanitizerVariation {
 			sanitizeable.AddSanitizerDependencies(mctx, s.sanitizer.name())
 		}
-	} else if c, ok := mctx.Module().(*Module); ok {
-		if ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) {
-			if !ss.isUnsanitizedVariant() {
+	} else if c, ok := mctx.Module().(LinkableInterface); ok {
+		if c.IsSnapshotSanitizerAvailable(s.sanitizer) {
+			if !c.IsSnapshotUnsanitizedVariant() {
 				// Snapshot sanitizer may have only one variantion.
 				// Skip exporting the module if it already has a sanitizer variation.
 				c.SetPreventInstall()
 				c.SetHideFromMake()
 				return
 			}
-			c.linker.(snapshotSanitizer).setSanitizerVariation(s.sanitizer, sanitizerVariation)
+			c.SetSnapshotSanitizerVariation(s.sanitizer, sanitizerVariation)
 
 			// Export the static lib name to make
-			if c.static() && c.ExportedToMake() {
+			if c.Static() && c.ExportedToMake() {
 				// use BaseModuleName which is the name for Make.
 				if s.sanitizer == cfi {
 					cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
@@ -1420,6 +1418,35 @@
 	}
 }
 
+func (c *Module) IsSnapshotSanitizer() bool {
+	if _, ok := c.linker.(SnapshotSanitizer); ok {
+		return true
+	}
+	return false
+}
+
+func (c *Module) IsSnapshotSanitizerAvailable(t SanitizerType) bool {
+	if ss, ok := c.linker.(SnapshotSanitizer); ok {
+		return ss.IsSanitizerAvailable(t)
+	}
+	return false
+}
+
+func (c *Module) SetSnapshotSanitizerVariation(t SanitizerType, enabled bool) {
+	if ss, ok := c.linker.(SnapshotSanitizer); ok {
+		ss.SetSanitizerVariation(t, enabled)
+	} else {
+		panic(fmt.Errorf("Calling SetSnapshotSanitizerVariation on a non-snapshotLibraryDecorator: %s", c.Name()))
+	}
+}
+
+func (c *Module) IsSnapshotUnsanitizedVariant() bool {
+	if ss, ok := c.linker.(SnapshotSanitizer); ok {
+		return ss.IsUnsanitizedVariant()
+	}
+	return false
+}
+
 func (c *Module) SanitizeNever() bool {
 	return Bool(c.sanitize.Properties.SanitizeMutated.Never)
 }
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index bb13310..e29c446 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -403,11 +403,11 @@
 	Sanitize_minimal_dep *bool `android:"arch_variant"`
 }
 
-type snapshotSanitizer interface {
-	isSanitizerAvailable(t SanitizerType) bool
-	setSanitizerVariation(t SanitizerType, enabled bool)
-	isSanitizerEnabled(t SanitizerType) bool
-	isUnsanitizedVariant() bool
+type SnapshotSanitizer interface {
+	IsSanitizerAvailable(t SanitizerType) bool
+	SetSanitizerVariation(t SanitizerType, enabled bool)
+	IsSanitizerEnabled(t SanitizerType) bool
+	IsUnsanitizedVariant() bool
 }
 
 type snapshotLibraryDecorator struct {
@@ -460,9 +460,9 @@
 		return p.libraryDecorator.link(ctx, flags, deps, objs)
 	}
 
-	if p.isSanitizerEnabled(cfi) {
+	if p.IsSanitizerEnabled(cfi) {
 		p.properties = p.sanitizerProperties.Cfi
-	} else if p.isSanitizerEnabled(Hwasan) {
+	} else if p.IsSanitizerEnabled(Hwasan) {
 		p.properties = p.sanitizerProperties.Hwasan
 	}
 
@@ -526,9 +526,9 @@
 	return false
 }
 
-var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil)
+var _ SnapshotSanitizer = (*snapshotLibraryDecorator)(nil)
 
-func (p *snapshotLibraryDecorator) isSanitizerAvailable(t SanitizerType) bool {
+func (p *snapshotLibraryDecorator) IsSanitizerAvailable(t SanitizerType) bool {
 	switch t {
 	case cfi:
 		return p.sanitizerProperties.Cfi.Src != nil
@@ -539,23 +539,23 @@
 	}
 }
 
-func (p *snapshotLibraryDecorator) setSanitizerVariation(t SanitizerType, enabled bool) {
-	if !enabled || p.isSanitizerEnabled(t) {
+func (p *snapshotLibraryDecorator) SetSanitizerVariation(t SanitizerType, enabled bool) {
+	if !enabled || p.IsSanitizerEnabled(t) {
 		return
 	}
-	if !p.isUnsanitizedVariant() {
+	if !p.IsUnsanitizedVariant() {
 		panic(fmt.Errorf("snapshot Sanitizer must be one of Cfi or Hwasan but not both"))
 	}
 	p.sanitizerProperties.SanitizerVariation = t
 }
 
-func (p *snapshotLibraryDecorator) isSanitizerEnabled(t SanitizerType) bool {
+func (p *snapshotLibraryDecorator) IsSanitizerEnabled(t SanitizerType) bool {
 	return p.sanitizerProperties.SanitizerVariation == t
 }
 
-func (p *snapshotLibraryDecorator) isUnsanitizedVariant() bool {
-	return !p.isSanitizerEnabled(Asan) &&
-		!p.isSanitizerEnabled(Hwasan)
+func (p *snapshotLibraryDecorator) IsUnsanitizedVariant() bool {
+	return !p.IsSanitizerEnabled(Asan) &&
+		!p.IsSanitizerEnabled(Hwasan)
 }
 
 func snapshotLibraryFactory(image SnapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {
diff --git a/cc/test.go b/cc/test.go
index adc80c2..c643862 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -720,6 +720,21 @@
 		}
 	}
 
+	// The logic comes from https://cs.android.com/android/platform/superproject/main/+/0df8153267f96da877febc5332240fa06ceb8533:build/soong/cc/sanitize.go;l=488
+	var features bazel.StringListAttribute
+	curFeatures := testBinaryAttrs.binaryAttributes.Features.SelectValue(bazel.OsArchConfigurationAxis, bazel.OsArchAndroidArm64)
+	var newFeatures []string
+	if !android.InList("memtag_heap", curFeatures) && !android.InList("-memtag_heap", curFeatures) {
+		newFeatures = append(newFeatures, "memtag_heap")
+		if !android.InList("diag_memtag_heap", curFeatures) && !android.InList("-diag_memtag_heap", curFeatures) {
+			newFeatures = append(newFeatures, "diag_memtag_heap")
+		}
+	}
+
+	features.SetSelectValue(bazel.OsArchConfigurationAxis, bazel.OsArchAndroidArm64, newFeatures)
+	testBinaryAttrs.binaryAttributes.Features.Append(features)
+	testBinaryAttrs.binaryAttributes.Features.DeduplicateAxesFromBase()
+
 	m.convertTidyAttributes(ctx, &testBinaryAttrs.tidyAttributes)
 
 	testBinary := m.linker.(*testBinary)
diff --git a/java/app.go b/java/app.go
index 7cf86c0..dadae48 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1059,6 +1059,7 @@
 
 	module.Module.dexProperties.Optimize.EnabledByDefault = true
 	module.Module.dexProperties.Optimize.Shrink = proptools.BoolPtr(true)
+	module.Module.dexProperties.Optimize.Proguard_compatibility = proptools.BoolPtr(false)
 
 	module.Module.properties.Instrument = true
 	module.Module.properties.Supports_static_instrumentation = true
diff --git a/java/dex.go b/java/dex.go
index df501bf..21937e1 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -45,8 +45,8 @@
 		// Whether to continue building even if warnings are emitted.  Defaults to true.
 		Ignore_warnings *bool
 
-		// If true, runs R8 in Proguard compatibility mode (default).
-		// Otherwise, runs R8 in full mode.
+		// If true, runs R8 in Proguard compatibility mode, otherwise runs R8 in full mode.
+		// Defaults to false for apps, true for libraries and tests.
 		Proguard_compatibility *bool
 
 		// If true, optimize for size by removing unused code.  Defaults to true for apps,
@@ -217,8 +217,9 @@
 	// Note: Targets with a min SDK kind of core_platform (e.g., framework.jar) or unspecified (e.g.,
 	// services.jar), are not classified as stable, which is WAI.
 	// TODO(b/232073181): Expand to additional min SDK cases after validation.
+	var addAndroidPlatformBuildFlag = false
 	if !dexParams.sdkVersion.Stable() {
-		flags = append(flags, "--android-platform-build")
+		addAndroidPlatformBuildFlag = true
 	}
 
 	effectiveVersion, err := dexParams.minSdkVersion.EffectiveVersion(ctx)
@@ -226,7 +227,18 @@
 		ctx.PropertyErrorf("min_sdk_version", "%s", err)
 	}
 
-	flags = append(flags, "--min-api "+strconv.Itoa(effectiveVersion.FinalOrFutureInt()))
+	// If the specified SDK level is 10000, then configure the compiler to use the
+	// current platform SDK level and to compile the build as a platform build.
+	var minApiFlagValue = effectiveVersion.FinalOrFutureInt()
+	if minApiFlagValue == 10000 {
+		minApiFlagValue = ctx.Config().PlatformSdkVersion().FinalInt()
+		addAndroidPlatformBuildFlag = true
+	}
+	flags = append(flags, "--min-api "+strconv.Itoa(minApiFlagValue))
+
+	if addAndroidPlatformBuildFlag {
+		flags = append(flags, "--android-platform-build")
+	}
 	return flags, deps
 }
 
diff --git a/java/generated_java_library.go b/java/generated_java_library.go
index 1cab6ac..578237e 100644
--- a/java/generated_java_library.go
+++ b/java/generated_java_library.go
@@ -22,6 +22,10 @@
 	Library
 	callbacks  GeneratedJavaLibraryCallbacks
 	moduleName string
+
+	// true if we've already called DepsMutator. Can't call AddLibrary or AddSharedLibrary
+	// after DepsMutator.
+	depsMutatorDone bool
 }
 
 type GeneratedJavaLibraryCallbacks interface {
@@ -59,8 +63,25 @@
 	return module
 }
 
+// Add a java shared library as a dependency, as if they had said `libs: [ "name" ]`
+func (module *GeneratedJavaLibraryModule) AddSharedLibrary(name string) {
+	if module.depsMutatorDone {
+		panic("GeneratedJavaLibraryModule.AddLibrary called after DepsMutator")
+	}
+	module.Library.properties.Libs = append(module.Library.properties.Libs, name)
+}
+
+// Add a java shared library as a dependency, as if they had said `libs: [ "name" ]`
+func (module *GeneratedJavaLibraryModule) AddStaticLibrary(name string) {
+	if module.depsMutatorDone {
+		panic("GeneratedJavaLibraryModule.AddStaticLibrary called after DepsMutator")
+	}
+	module.Library.properties.Static_libs = append(module.Library.properties.Static_libs, name)
+}
+
 func (module *GeneratedJavaLibraryModule) DepsMutator(ctx android.BottomUpMutatorContext) {
 	module.callbacks.DepsMutator(module, ctx)
+	module.depsMutatorDone = true
 	module.Library.DepsMutator(ctx)
 }
 
diff --git a/java/java.go b/java/java.go
index fe7f88f..6c448a2 100644
--- a/java/java.go
+++ b/java/java.go
@@ -21,6 +21,7 @@
 import (
 	"fmt"
 	"path/filepath"
+	"sort"
 	"strings"
 
 	"android/soong/bazel"
@@ -2756,32 +2757,41 @@
 type javaResourcesAttributes struct {
 	Resources             bazel.LabelListAttribute
 	Resource_strip_prefix *string
+	Additional_resources  bazel.LabelListAttribute
 }
 
-func (m *Library) javaResourcesGetSingleFilegroupStripPrefix(ctx android.TopDownMutatorContext) (string, bool) {
-	if otherM, ok := ctx.ModuleFromName(m.properties.Java_resources[0]); ok && len(m.properties.Java_resources) == 1 {
+func (m *Library) getResourceFilegroupStripPrefix(ctx android.TopDownMutatorContext, resourceFilegroup string) (*string, bool) {
+	if otherM, ok := ctx.ModuleFromName(resourceFilegroup); ok {
 		if fg, isFilegroup := otherM.(android.FileGroupPath); isFilegroup {
-			return filepath.Join(ctx.OtherModuleDir(otherM), fg.GetPath(ctx)), true
+			return proptools.StringPtr(filepath.Join(ctx.OtherModuleDir(otherM), fg.GetPath(ctx))), true
 		}
 	}
-	return "", false
+	return proptools.StringPtr(""), false
 }
 
 func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorContext) *javaResourcesAttributes {
 	var resources bazel.LabelList
 	var resourceStripPrefix *string
 
-	if m.properties.Java_resources != nil && len(m.properties.Java_resource_dirs) > 0 {
-		ctx.ModuleErrorf("bp2build doesn't support both java_resources and java_resource_dirs being set on the same module.")
-	}
+	additionalJavaResourcesMap := make(map[string]*javaResourcesAttributes)
 
 	if m.properties.Java_resources != nil {
-		if prefix, ok := m.javaResourcesGetSingleFilegroupStripPrefix(ctx); ok {
-			resourceStripPrefix = proptools.StringPtr(prefix)
-		} else {
+		for _, res := range m.properties.Java_resources {
+			if prefix, isFilegroup := m.getResourceFilegroupStripPrefix(ctx, res); isFilegroup {
+				otherM, _ := ctx.ModuleFromName(res)
+				resourcesTargetName := ctx.ModuleName() + "_filegroup_resources_" + otherM.Name()
+				additionalJavaResourcesMap[resourcesTargetName] = &javaResourcesAttributes{
+					Resources:             bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, []string{res})),
+					Resource_strip_prefix: prefix,
+				}
+			} else {
+				resources.Append(android.BazelLabelForModuleSrc(ctx, []string{res}))
+			}
+		}
+
+		if !resources.IsEmpty() {
 			resourceStripPrefix = proptools.StringPtr(ctx.ModuleDir())
 		}
-		resources.Append(android.BazelLabelForModuleSrc(ctx, m.properties.Java_resources))
 	}
 
 	//TODO(b/179889880) handle case where glob includes files outside package
@@ -2792,23 +2802,51 @@
 		m.properties.Exclude_java_resources,
 	)
 
-	for i, resDep := range resDeps {
+	for _, resDep := range resDeps {
 		dir, files := resDep.dir, resDep.files
 
-		resources.Append(bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, files)))
-
 		// Bazel includes the relative path from the WORKSPACE root when placing the resource
 		// inside the JAR file, so we need to remove that prefix
-		resourceStripPrefix = proptools.StringPtr(dir.String())
-		if i > 0 {
-			// TODO(b/226423379) allow multiple resource prefixes
-			ctx.ModuleErrorf("bp2build does not support more than one directory in java_resource_dirs (b/226423379)")
+		prefix := proptools.StringPtr(dir.String())
+		resourcesTargetName := ctx.ModuleName() + "_resource_dir_" + dir.String()
+		additionalJavaResourcesMap[resourcesTargetName] = &javaResourcesAttributes{
+			Resources:             bazel.MakeLabelListAttribute(bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, files))),
+			Resource_strip_prefix: prefix,
 		}
 	}
 
+	var additionalResourceLabels bazel.LabelList
+	if len(additionalJavaResourcesMap) > 0 {
+		var additionalResources []string
+		for resName, _ := range additionalJavaResourcesMap {
+			additionalResources = append(additionalResources, resName)
+		}
+		sort.Strings(additionalResources)
+
+		for i, resName := range additionalResources {
+			resAttr := additionalJavaResourcesMap[resName]
+			if resourceStripPrefix == nil && i == 0 {
+				resourceStripPrefix = resAttr.Resource_strip_prefix
+				resources = resAttr.Resources.Value
+			} else {
+				ctx.CreateBazelTargetModule(
+					bazel.BazelTargetModuleProperties{
+						Rule_class:        "java_resources",
+						Bzl_load_location: "//build/bazel/rules/java:java_resources.bzl",
+					},
+					android.CommonAttributes{Name: resName},
+					resAttr,
+				)
+				additionalResourceLabels.Append(android.BazelLabelForModuleSrc(ctx, []string{resName}))
+			}
+		}
+
+	}
+
 	return &javaResourcesAttributes{
 		Resources:             bazel.MakeLabelListAttribute(resources),
 		Resource_strip_prefix: resourceStripPrefix,
+		Additional_resources:  bazel.MakeLabelListAttribute(additionalResourceLabels),
 	}
 }
 
@@ -2867,6 +2905,11 @@
 	var deps bazel.LabelListAttribute
 	var staticDeps bazel.LabelListAttribute
 
+	if proptools.String(m.deviceProperties.Sdk_version) == "" && m.DeviceSupported() {
+		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "sdk_version unset")
+		return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false
+	}
+
 	archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
 	for axis, configToProps := range archVariantProps {
 		for config, _props := range configToProps {
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 044802e..99cb99b 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -55,6 +55,11 @@
 
 	// If set to true, compile dex for java_import modules. Defaults to false.
 	Imports_compile_dex *bool
+
+	// If set to true, allow incremental platform API of the form MM.m where MM is the major release
+	// version corresponding to the API level/SDK_INT and m is an incremental release version
+	// (e.g. API changes associated with QPR). Defaults to false.
+	Allow_incremental_platform_api *bool
 }
 
 type prebuiltApis struct {
@@ -69,6 +74,8 @@
 // parsePrebuiltPath parses the relevant variables out of a variety of paths, e.g.
 // <version>/<scope>/<module>.jar
 // <version>/<scope>/api/<module>.txt
+// *Note when using incremental platform API, <version> may be of the form MM.m where MM is the
+// API level and m is an incremental release, otherwise <version> is a single integer corresponding to the API level only.
 // extensions/<version>/<scope>/<module>.jar
 // extensions/<version>/<scope>/api/<module>.txt
 func parsePrebuiltPath(ctx android.LoadHookContext, p string) (module string, version string, scope string) {
@@ -90,8 +97,25 @@
 }
 
 // parseFinalizedPrebuiltPath is like parsePrebuiltPath, but verifies the version is numeric (a finalized version).
-func parseFinalizedPrebuiltPath(ctx android.LoadHookContext, p string) (module string, version int, scope string) {
+func parseFinalizedPrebuiltPath(ctx android.LoadHookContext, p string, allowIncremental bool) (module string, version int, release int, scope string) {
 	module, v, scope := parsePrebuiltPath(ctx, p)
+	if allowIncremental {
+		parts := strings.Split(v, ".")
+		if len(parts) != 2 {
+			ctx.ModuleErrorf("Found unexpected version '%v' for incremental prebuilts - expect MM.m format for incremental API with both major (MM) an minor (m) revision.", v)
+			return
+		}
+		sdk, sdk_err := strconv.Atoi(parts[0])
+		qpr, qpr_err := strconv.Atoi(parts[1])
+		if sdk_err != nil || qpr_err != nil {
+			ctx.ModuleErrorf("Unable to read version number for incremental prebuilt api '%v'", v)
+			return
+		}
+		version = sdk
+		release = qpr
+		return
+	}
+	release = 0
 	version, err := strconv.Atoi(v)
 	if err != nil {
 		ctx.ModuleErrorf("Found finalized API files in non-numeric dir '%v'", v)
@@ -268,29 +292,35 @@
 	}
 
 	// Create modules for all (<module>, <scope, <version>) triplets,
+	allowIncremental := proptools.BoolDefault(p.properties.Allow_incremental_platform_api, false)
 	for _, f := range apiLevelFiles {
-		module, version, scope := parseFinalizedPrebuiltPath(mctx, f)
-		createApiModule(mctx, PrebuiltApiModuleName(module, scope, strconv.Itoa(version)), f)
+		module, version, release, scope := parseFinalizedPrebuiltPath(mctx, f, allowIncremental)
+		if allowIncremental {
+			incrementalVersion := strconv.Itoa(version) + "." + strconv.Itoa(release)
+			createApiModule(mctx, PrebuiltApiModuleName(module, scope, incrementalVersion), f)
+		} else {
+			createApiModule(mctx, PrebuiltApiModuleName(module, scope, strconv.Itoa(version)), f)
+		}
 	}
 
 	// Figure out the latest version of each module/scope
 	type latestApiInfo struct {
 		module, scope, path string
-		version             int
+		version, release    int
 		isExtensionApiFile  bool
 	}
 
 	getLatest := func(files []string, isExtensionApiFile bool) map[string]latestApiInfo {
 		m := make(map[string]latestApiInfo)
 		for _, f := range files {
-			module, version, scope := parseFinalizedPrebuiltPath(mctx, f)
+			module, version, release, scope := parseFinalizedPrebuiltPath(mctx, f, allowIncremental)
 			if strings.HasSuffix(module, "incompatibilities") {
 				continue
 			}
 			key := module + "." + scope
 			info, exists := m[key]
-			if !exists || version > info.version {
-				m[key] = latestApiInfo{module, scope, f, version, isExtensionApiFile}
+			if !exists || version > info.version || (version == info.version && release > info.release) {
+				m[key] = latestApiInfo{module, scope, f, version, release, isExtensionApiFile}
 			}
 		}
 		return m
diff --git a/java/prebuilt_apis_test.go b/java/prebuilt_apis_test.go
index 2b84353..b6fb2c6 100644
--- a/java/prebuilt_apis_test.go
+++ b/java/prebuilt_apis_test.go
@@ -99,3 +99,26 @@
 	android.AssertStringEquals(t, "Expected latest bar = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
 	android.AssertStringEquals(t, "Expected latest baz = api level 32", "prebuilts/sdk/32/public/api/baz.txt", baz_input)
 }
+
+func TestPrebuiltApis_WithIncrementalApi(t *testing.T) {
+	runTestWithIncrementalApi := func() (foo_input, bar_input, baz_input string) {
+		result := android.GroupFixturePreparers(
+			prepareForJavaTest,
+			FixtureWithPrebuiltIncrementalApis(map[string][]string{
+				"33.0":    {"foo"},
+				"33.1":    {"foo", "bar", "baz"},
+				"33.2":    {"foo", "bar"},
+				"current": {"foo", "bar"},
+			}),
+		).RunTest(t)
+		foo_input = result.ModuleForTests("foo.api.public.latest", "").Rule("generator").Implicits[0].String()
+		bar_input = result.ModuleForTests("bar.api.public.latest", "").Rule("generator").Implicits[0].String()
+		baz_input = result.ModuleForTests("baz.api.public.latest", "").Rule("generator").Implicits[0].String()
+		return
+	}
+	// 33.1 is the latest for baz, 33.2 is the latest for both foo & bar
+	foo_input, bar_input, baz_input := runTestWithIncrementalApi()
+	android.AssertStringEquals(t, "Expected latest foo = api level 33.2", "prebuilts/sdk/33.2/public/api/foo.txt", foo_input)
+	android.AssertStringEquals(t, "Expected latest bar = api level 33.2", "prebuilts/sdk/33.2/public/api/bar.txt", bar_input)
+	android.AssertStringEquals(t, "Expected latest baz = api level 33.1", "prebuilts/sdk/33.1/public/api/baz.txt", baz_input)
+}
diff --git a/java/proto.go b/java/proto.go
index c732d98..2ed7b27 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -143,7 +143,14 @@
 }
 
 type protoAttributes struct {
-	Deps         bazel.LabelListAttribute
+	Deps bazel.LabelListAttribute
+
+	// A list of proto_library targets that the proto_library in `deps` depends on
+	// This list is overestimation.
+	// Overestimation is necessary since Soong includes other protos via proto.include_dirs and not
+	// a specific .proto file module explicitly.
+	Transitive_deps bazel.LabelListAttribute
+
 	Sdk_version  bazel.StringAttribute
 	Java_version bazel.StringAttribute
 }
@@ -176,11 +183,11 @@
 		ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ)
 	}
 
-	protoLabel := bazel.Label{Label: ":" + m.Name() + "_proto"}
 	protoAttrs := &protoAttributes{
-		Deps:         bazel.MakeSingleLabelListAttribute(protoLabel),
-		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),
+		Java_version:    bazel.StringAttribute{Value: m.properties.Java_version},
+		Sdk_version:     bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
 	}
 
 	name := m.Name() + suffix
diff --git a/java/testing.go b/java/testing.go
index 3a238d7..f2bcccf 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -225,6 +225,29 @@
 	)
 }
 
+func FixtureWithPrebuiltIncrementalApis(apiLevel2Modules map[string][]string) android.FixturePreparer {
+	mockFS := android.MockFS{}
+	path := "prebuilts/sdk/Android.bp"
+
+	bp := fmt.Sprintf(`
+			prebuilt_apis {
+				name: "sdk",
+				api_dirs: ["%s"],
+				allow_incremental_platform_api: true,
+				imports_sdk_version: "none",
+				imports_compile_dex: true,
+			}
+		`, strings.Join(android.SortedKeys(apiLevel2Modules), `", "`))
+
+	for release, modules := range apiLevel2Modules {
+		mockFS.Merge(prebuiltApisFilesForModules([]string{release}, modules))
+	}
+	return android.GroupFixturePreparers(
+		android.FixtureAddTextFile(path, bp),
+		android.FixtureMergeMockFs(mockFS),
+	)
+}
+
 func prebuiltApisFilesForModules(apiLevels []string, modules []string) map[string][]byte {
 	libs := append([]string{"android"}, modules...)
 
@@ -385,6 +408,8 @@
 		"kotlin-stdlib-jdk8",
 		"kotlin-annotations",
 		"stub-annotations",
+
+		"aconfig-annotations-lib",
 	}
 
 	for _, extra := range extraModules {
diff --git a/provenance/provenance_singleton.go b/provenance/provenance_singleton.go
index 5d27c0c..97345af 100644
--- a/provenance/provenance_singleton.go
+++ b/provenance/provenance_singleton.go
@@ -38,7 +38,9 @@
 			Command: `rm -rf $out && ` +
 				`echo "# proto-file: build/soong/provenance/proto/provenance_metadata.proto" > $out && ` +
 				`echo "# proto-message: ProvenanceMetaDataList" >> $out && ` +
-				`for file in $in; do echo '' >> $out; echo 'metadata {' | cat - $$file | grep -Ev "^#.*|^$$" >> $out; echo '}' >> $out; done`,
+				`cat $out.rsp | tr ' ' '\n' | while read -r file || [ -n "$$file" ]; do echo '' >> $out; echo 'metadata {' | cat - $$file | grep -Ev "^#.*|^$$" >> $out; echo '}' >> $out; done`,
+			Rspfile:        `$out.rsp`,
+			RspfileContent: `$in`,
 		})
 )
 
diff --git a/python/python.go b/python/python.go
index e6bdeee..8b31c6c 100644
--- a/python/python.go
+++ b/python/python.go
@@ -197,6 +197,14 @@
 	return String(p.properties.Pkg_path)
 }
 
+// PkgPath is the "public" version of `getPkgPath` that is only available during bp2build
+func (p *PythonLibraryModule) PkgPath(ctx android.BazelConversionContext) *string {
+	if ctx.Config().BuildMode != android.Bp2build {
+		ctx.ModuleErrorf("PkgPath is only supported in bp2build mode")
+	}
+	return p.properties.Pkg_path
+}
+
 func (p *PythonLibraryModule) getBaseProperties() *BaseProperties {
 	return &p.properties
 }
diff --git a/rust/binary.go b/rust/binary.go
index e6f1539..1e24beb 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -16,6 +16,8 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
+	"fmt"
 )
 
 func init() {
@@ -60,6 +62,8 @@
 func NewRustBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
 	module := newModule(hod, android.MultilibFirst)
 
+	android.InitBazelModule(module)
+
 	binary := &binaryDecorator{
 		baseCompiler: NewBaseCompiler("bin", "", InstallInSystem),
 	}
@@ -183,3 +187,88 @@
 func (binary *binaryDecorator) testBinary() bool {
 	return false
 }
+
+type rustBinaryLibraryAttributes struct {
+	Srcs            bazel.LabelListAttribute
+	Compile_data    bazel.LabelListAttribute
+	Crate_name      bazel.StringAttribute
+	Edition         bazel.StringAttribute
+	Crate_features  bazel.StringListAttribute
+	Deps            bazel.LabelListAttribute
+	Proc_macro_deps bazel.LabelListAttribute
+	Rustc_flags     bazel.StringListAttribute
+}
+
+func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+	binary := m.compiler.(*binaryDecorator)
+
+	var srcs bazel.LabelList
+	var compileData bazel.LabelList
+
+	if binary.baseCompiler.Properties.Srcs[0] == "src/main.rs" {
+		srcs = android.BazelLabelForModuleSrc(ctx, []string{"src/**/*.rs"})
+		compileData = android.BazelLabelForModuleSrc(
+			ctx,
+			[]string{
+				"src/**/*.proto",
+				"examples/**/*.rs",
+				"**/*.md",
+				"templates/**/*.template",
+			},
+		)
+	} else {
+		srcs = android.BazelLabelForModuleSrc(ctx, binary.baseCompiler.Properties.Srcs)
+	}
+
+	deps := android.BazelLabelForModuleDeps(ctx, append(
+		binary.baseCompiler.Properties.Rustlibs,
+	))
+
+	procMacroDeps := android.BazelLabelForModuleDeps(ctx, binary.baseCompiler.Properties.Proc_macros)
+
+	var rustcFLags []string
+	for _, cfg := range binary.baseCompiler.Properties.Cfgs {
+		rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
+	}
+
+	attrs := &rustBinaryLibraryAttributes{
+		Srcs: bazel.MakeLabelListAttribute(
+			srcs,
+		),
+		Compile_data: bazel.MakeLabelListAttribute(
+			compileData,
+		),
+		Crate_name: bazel.StringAttribute{
+			Value: &binary.baseCompiler.Properties.Crate_name,
+		},
+		Edition: bazel.StringAttribute{
+			Value: binary.baseCompiler.Properties.Edition,
+		},
+		Crate_features: bazel.StringListAttribute{
+			Value: binary.baseCompiler.Properties.Features,
+		},
+		Deps: bazel.MakeLabelListAttribute(
+			deps,
+		),
+		Proc_macro_deps: bazel.MakeLabelListAttribute(
+			procMacroDeps,
+		),
+		Rustc_flags: bazel.StringListAttribute{
+			Value: append(
+				rustcFLags,
+				binary.baseCompiler.Properties.Flags...,
+			),
+		},
+	}
+
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "rust_binary",
+			Bzl_load_location: "@rules_rust//rust:defs.bzl",
+		},
+		android.CommonAttributes{
+			Name: m.Name(),
+		},
+		attrs,
+	)
+}
diff --git a/rust/config/global.go b/rust/config/global.go
index ca2c9af..4bd495d 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -54,11 +54,11 @@
 		"-C symbol-mangling-version=v0",
 		"--color always",
 		"-Zdylib-lto",
+		"-Z link-native-libraries=no",
 	}
 
 	deviceGlobalRustFlags = []string{
 		"-C panic=abort",
-		"-Z link-native-libraries=no",
 		// Generate additional debug info for AutoFDO
 		"-Z debug-info-for-profiling",
 	}
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 235f517..4c04ce8 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -60,6 +60,25 @@
 	fuzz.binaryDecorator.baseCompiler.dir64 = "fuzz"
 	fuzz.binaryDecorator.baseCompiler.location = InstallInData
 	module.sanitize.SetSanitizer(cc.Fuzzer, true)
+
+	// The fuzzer runtime is not present for darwin or bionic host modules, so disable rust_fuzz modules for these.
+	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+
+		extraProps := struct {
+			Target struct {
+				Darwin struct {
+					Enabled *bool
+				}
+				Linux_bionic struct {
+					Enabled *bool
+				}
+			}
+		}{}
+		extraProps.Target.Darwin.Enabled = cc.BoolPtr(false)
+		extraProps.Target.Linux_bionic.Enabled = cc.BoolPtr(false)
+		ctx.AppendProperties(&extraProps)
+	})
+
 	module.compiler = fuzz
 	return module, fuzz
 }
diff --git a/rust/library.go b/rust/library.go
index 419fcfc..3f031c1 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -20,7 +20,10 @@
 	"strings"
 
 	"android/soong/android"
+	"android/soong/bazel"
 	"android/soong/cc"
+
+	"github.com/google/blueprint/proptools"
 )
 
 var (
@@ -398,6 +401,8 @@
 func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
 	module := newModule(hod, android.MultilibBoth)
 
+	android.InitBazelModule(module)
+
 	library := &libraryDecorator{
 		MutatedProperties: LibraryMutatedProperties{
 			BuildDylib:  false,
@@ -793,3 +798,155 @@
 	// TODO(185577950): If support for generated headers is added, they need to be collected here as well.
 	l.collectedSnapshotHeaders = ret
 }
+
+type rustLibraryAttributes struct {
+	Srcs            bazel.LabelListAttribute
+	Compile_data    bazel.LabelListAttribute
+	Crate_name      bazel.StringAttribute
+	Edition         bazel.StringAttribute
+	Crate_features  bazel.StringListAttribute
+	Deps            bazel.LabelListAttribute
+	Rustc_flags     bazel.StringListAttribute
+	Proc_macro_deps bazel.LabelListAttribute
+}
+
+func libraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+	lib := m.compiler.(*libraryDecorator)
+
+	srcs, compileData := srcsAndCompileDataAttrs(ctx, *lib.baseCompiler)
+
+	deps := android.BazelLabelForModuleDeps(ctx, append(
+		lib.baseCompiler.Properties.Rustlibs,
+		lib.baseCompiler.Properties.Rlibs...,
+	))
+
+	cargoBuildScript := cargoBuildScriptBp2build(ctx, m)
+	if cargoBuildScript != nil {
+		deps.Add(&bazel.Label{
+			Label: ":" + *cargoBuildScript,
+		})
+	}
+
+	procMacroDeps := android.BazelLabelForModuleDeps(ctx, lib.baseCompiler.Properties.Proc_macros)
+
+	var rustcFLags []string
+	for _, cfg := range lib.baseCompiler.Properties.Cfgs {
+		rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
+	}
+
+	attrs := &rustLibraryAttributes{
+		Srcs: bazel.MakeLabelListAttribute(
+			srcs,
+		),
+		Compile_data: bazel.MakeLabelListAttribute(
+			compileData,
+		),
+		Crate_name: bazel.StringAttribute{
+			Value: &lib.baseCompiler.Properties.Crate_name,
+		},
+		Edition: bazel.StringAttribute{
+			Value: lib.baseCompiler.Properties.Edition,
+		},
+		Crate_features: bazel.StringListAttribute{
+			Value: lib.baseCompiler.Properties.Features,
+		},
+		Deps: bazel.MakeLabelListAttribute(
+			deps,
+		),
+		Proc_macro_deps: bazel.MakeLabelListAttribute(
+			procMacroDeps,
+		),
+		Rustc_flags: bazel.StringListAttribute{
+			Value: append(
+				rustcFLags,
+				lib.baseCompiler.Properties.Flags...,
+			),
+		},
+	}
+
+	// TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
+	var restriction bazel.BoolAttribute
+	restriction.SetSelectValue(bazel.OsConfigurationAxis, "android", proptools.BoolPtr(false))
+
+	ctx.CreateBazelTargetModuleWithRestrictions(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "rust_library",
+			Bzl_load_location: "@rules_rust//rust:defs.bzl",
+		},
+		android.CommonAttributes{
+			Name: m.Name(),
+		},
+		attrs,
+		restriction,
+	)
+}
+
+type cargoBuildScriptAttributes struct {
+	Srcs    bazel.LabelListAttribute
+	Edition bazel.StringAttribute
+	Version bazel.StringAttribute
+}
+
+func cargoBuildScriptBp2build(ctx android.TopDownMutatorContext, m *Module) *string {
+	// Soong treats some crates like libprotobuf as special in that they have
+	// cargo build script ran to produce an out folder and check it into AOSP
+	// For example, https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/out/
+	// is produced by cargo build script https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/build.rs
+	// The out folder is then fed into `rust_library` by a genrule
+	// https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/Android.bp;l=22
+	// This allows Soong to decouple from cargo completely.
+
+	// Soong decouples from cargo so that it has control over cc compilation.
+	// https://cs.android.com/android/platform/superproject/main/+/main:development/scripts/cargo2android.py;l=1033-1041;drc=8449944a50a0445a5ecaf9b7aed12608c81bf3f1
+	// generates a `cc_library_static` module to have custom cc flags.
+	// Since bp2build will convert the cc modules to cc targets which include the cflags,
+	// Bazel does not need to have this optimization.
+
+	// Performance-wise: rust_library -> cargo_build_script vs rust_library -> genrule (like Soong)
+	// don't have any major difference in build time in Bazel. So using cargo_build_script does not slow
+	// down the build.
+
+	// The benefit of using `cargo_build_script` here is that it would take care of setting correct
+	// `OUT_DIR` for us - similar to what Soong does here
+	// https://cs.android.com/android/platform/superproject/main/+/main:build/soong/rust/builder.go;l=202-218;drc=f29ca58e88c5846bbe8955e5192135e5ab4f14a1
+
+	// TODO(b/297364081): cargo2android.py has logic for when generate/not cc_library_static and out directory
+	// bp2build might be able use the same logic for when to use `cargo_build_script`.
+	// For now, we're building libprotobuf_build_script as a one-off until we have a more principled solution
+	if m.Name() != "libprotobuf" {
+		return nil
+	}
+
+	lib := m.compiler.(*libraryDecorator)
+
+	name := m.Name() + "_build_script"
+	attrs := &cargoBuildScriptAttributes{
+		Srcs: bazel.MakeLabelListAttribute(
+			android.BazelLabelForModuleSrc(ctx, []string{"build.rs"}),
+		),
+		Edition: bazel.StringAttribute{
+			Value: lib.baseCompiler.Properties.Edition,
+		},
+		Version: bazel.StringAttribute{
+			Value: lib.baseCompiler.Properties.Cargo_pkg_version,
+		},
+	}
+
+	// TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
+	var restriction bazel.BoolAttribute
+	restriction.SetSelectValue(bazel.OsConfigurationAxis, "android", proptools.BoolPtr(false))
+
+	ctx.CreateBazelTargetModuleWithRestrictions(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "cargo_build_script",
+			Bzl_load_location: "@rules_rust//cargo:cargo_build_script.bzl",
+		},
+		android.CommonAttributes{
+			Name: name,
+		},
+		attrs,
+		restriction,
+	)
+
+	return &name
+}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 832b62c..26227d0 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -16,6 +16,8 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
+	"fmt"
 )
 
 func init() {
@@ -47,6 +49,8 @@
 func NewProcMacro(hod android.HostOrDeviceSupported) (*Module, *procMacroDecorator) {
 	module := newModule(hod, android.MultilibFirst)
 
+	android.InitBazelModule(module)
+
 	procMacro := &procMacroDecorator{
 		baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem),
 		flagExporter: NewFlagExporter(),
@@ -99,3 +103,65 @@
 	// Proc_macros are never installed
 	return false
 }
+
+type procMacroAttributes struct {
+	Srcs           bazel.LabelListAttribute
+	Compile_data   bazel.LabelListAttribute
+	Crate_name     bazel.StringAttribute
+	Edition        bazel.StringAttribute
+	Crate_features bazel.StringListAttribute
+	Deps           bazel.LabelListAttribute
+	Rustc_flags    bazel.StringListAttribute
+}
+
+func procMacroBp2build(ctx android.TopDownMutatorContext, m *Module) {
+	procMacro := m.compiler.(*procMacroDecorator)
+	srcs, compileData := srcsAndCompileDataAttrs(ctx, *procMacro.baseCompiler)
+	deps := android.BazelLabelForModuleDeps(ctx, append(
+		procMacro.baseCompiler.Properties.Rustlibs,
+		procMacro.baseCompiler.Properties.Rlibs...,
+	))
+
+	var rustcFLags []string
+	for _, cfg := range procMacro.baseCompiler.Properties.Cfgs {
+		rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
+	}
+
+	attrs := &procMacroAttributes{
+		Srcs: bazel.MakeLabelListAttribute(
+			srcs,
+		),
+		Compile_data: bazel.MakeLabelListAttribute(
+			compileData,
+		),
+		Crate_name: bazel.StringAttribute{
+			Value: &procMacro.baseCompiler.Properties.Crate_name,
+		},
+		Edition: bazel.StringAttribute{
+			Value: procMacro.baseCompiler.Properties.Edition,
+		},
+		Crate_features: bazel.StringListAttribute{
+			Value: procMacro.baseCompiler.Properties.Features,
+		},
+		Deps: bazel.MakeLabelListAttribute(
+			deps,
+		),
+		Rustc_flags: bazel.StringListAttribute{
+			Value: append(
+				rustcFLags,
+				procMacro.baseCompiler.Properties.Flags...,
+			),
+		},
+	}
+	// m.IsConvertedByBp2build()
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "rust_proc_macro",
+			Bzl_load_location: "@rules_rust//rust:defs.bzl",
+		},
+		android.CommonAttributes{
+			Name: m.Name(),
+		},
+		attrs,
+	)
+}
diff --git a/rust/protobuf.go b/rust/protobuf.go
index a14ebea..ae82844 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -19,6 +19,9 @@
 	"strings"
 
 	"android/soong/android"
+	"android/soong/bazel"
+
+	"github.com/google/blueprint/proptools"
 )
 
 var (
@@ -264,5 +267,71 @@
 
 	module := NewSourceProviderModule(hod, protobuf, false, false)
 
+	android.InitBazelModule(module)
+
 	return module, protobuf
 }
+
+type rustProtoAttributes struct {
+	Srcs       bazel.LabelListAttribute
+	Crate_name bazel.StringAttribute
+	Deps       bazel.LabelListAttribute
+}
+
+type protoLibraryAttributes struct {
+	Srcs bazel.LabelListAttribute
+}
+
+func protoLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+	var protoFiles []string
+
+	for _, propsInterface := range m.sourceProvider.SourceProviderProps() {
+		if possibleProps, ok := propsInterface.(*ProtobufProperties); ok {
+			protoFiles = possibleProps.Protos
+			break
+		}
+	}
+
+	protoLibraryName := m.Name() + "_proto"
+
+	protoDeps := bazel.LabelListAttribute{
+		Value: bazel.LabelList{
+			Includes: []bazel.Label{
+				{
+					Label:              ":" + protoLibraryName,
+					OriginalModuleName: m.Name(),
+				},
+			},
+		},
+	}
+
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class: "proto_library",
+		},
+		android.CommonAttributes{
+			Name: protoLibraryName,
+		},
+		&protoLibraryAttributes{
+			Srcs: bazel.MakeLabelListAttribute(
+				android.BazelLabelForModuleSrc(ctx, protoFiles),
+			),
+		},
+	)
+
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "rust_proto_library",
+			Bzl_load_location: "@rules_rust//proto/protobuf:defs.bzl",
+		},
+		android.CommonAttributes{
+			Name: m.Name(),
+		},
+		&rustProtoAttributes{
+			Crate_name: bazel.StringAttribute{
+				Value: proptools.StringPtr(m.CrateName()),
+			},
+			Deps: protoDeps,
+		},
+	)
+}
diff --git a/rust/rust.go b/rust/rust.go
index 689ff38..1ee99cd 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -15,7 +15,9 @@
 package rust
 
 import (
+	"android/soong/bazel"
 	"android/soong/bloaty"
+	"android/soong/ui/metrics/bp2build_metrics_proto"
 	"fmt"
 	"strings"
 
@@ -169,6 +171,8 @@
 	apexSdkVersion android.ApiLevel
 
 	transitiveAndroidMkSharedLibs *android.DepSet[string]
+
+	android.BazelModuleBase
 }
 
 func (mod *Module) Header() bool {
@@ -1841,6 +1845,46 @@
 	return ""
 }
 
+func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	if ctx.ModuleType() == "rust_library_host" || ctx.ModuleType() == "rust_library" {
+		libraryBp2build(ctx, m)
+	} else if ctx.ModuleType() == "rust_proc_macro" {
+		procMacroBp2build(ctx, m)
+	} else if ctx.ModuleType() == "rust_binary_host" {
+		binaryBp2build(ctx, m)
+	} else if ctx.ModuleType() == "rust_protobuf_host" {
+		protoLibraryBp2build(ctx, m)
+	} else {
+		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
+	}
+}
+
+// This is a workaround by assuming the conventions that rust crate repos are structured
+// while waiting for the sandboxing work to complete.
+// TODO(b/297344471): When crate_root prop is set which enforces inputs sandboxing,
+// always use `srcs` and `compile_data` props to generate `srcs` and `compile_data` attributes
+// instead of using globs.
+func srcsAndCompileDataAttrs(ctx android.TopDownMutatorContext, c baseCompiler) (bazel.LabelList, bazel.LabelList) {
+	var srcs bazel.LabelList
+	var compileData bazel.LabelList
+
+	if c.Properties.Srcs[0] == "src/lib.rs" {
+		srcs = android.BazelLabelForModuleSrc(ctx, []string{"src/**/*.rs"})
+		compileData = android.BazelLabelForModuleSrc(
+			ctx,
+			[]string{
+				"src/**/*.proto",
+				"examples/**/*.rs",
+				"**/*.md",
+			},
+		)
+	} else {
+		srcs = android.BazelLabelForModuleSrc(ctx, c.Properties.Srcs)
+	}
+
+	return srcs, compileData
+}
+
 var Bool = proptools.Bool
 var BoolDefault = proptools.BoolDefault
 var String = proptools.String
diff --git a/rust/snapshot_prebuilt.go b/rust/snapshot_prebuilt.go
index 32d3916..42e3cef 100644
--- a/rust/snapshot_prebuilt.go
+++ b/rust/snapshot_prebuilt.go
@@ -15,6 +15,8 @@
 package rust
 
 import (
+	"fmt"
+
 	"android/soong/android"
 	"android/soong/cc"
 
@@ -26,17 +28,80 @@
 	*libraryDecorator
 	properties          cc.SnapshotLibraryProperties
 	sanitizerProperties struct {
-		CfiEnabled bool `blueprint:"mutated"`
+		SanitizerVariation cc.SanitizerType `blueprint:"mutated"`
 
-		// Library flags for cfi variant.
-		Cfi cc.SnapshotLibraryProperties `android:"arch_variant"`
+		//TODO: Library flags for cfi variant when CFI is supported.
+		//Cfi cc.SnapshotLibraryProperties `android:"arch_variant"`
+
+		// Library flags for hwasan variant.
+		Hwasan cc.SnapshotLibraryProperties `android:"arch_variant"`
 	}
 }
 
+var _ cc.SnapshotSanitizer = (*snapshotLibraryDecorator)(nil)
+
+func (library *snapshotLibraryDecorator) IsSanitizerAvailable(t cc.SanitizerType) bool {
+	switch t {
+	//TODO: When CFI is supported, add a check here as well
+	case cc.Hwasan:
+		return library.sanitizerProperties.Hwasan.Src != nil
+	default:
+		return false
+	}
+}
+
+func (library *snapshotLibraryDecorator) SetSanitizerVariation(t cc.SanitizerType, enabled bool) {
+	if !enabled || library.IsSanitizerEnabled(t) {
+		return
+	}
+	if !library.IsUnsanitizedVariant() {
+		panic(fmt.Errorf("snapshot Sanitizer must be one of Cfi or Hwasan but not both"))
+	}
+	library.sanitizerProperties.SanitizerVariation = t
+}
+
+func (library *snapshotLibraryDecorator) IsSanitizerEnabled(t cc.SanitizerType) bool {
+	return library.sanitizerProperties.SanitizerVariation == t
+}
+
+func (library *snapshotLibraryDecorator) IsUnsanitizedVariant() bool {
+	//TODO: When CFI is supported, add a check here as well
+	return !library.IsSanitizerEnabled(cc.Hwasan)
+}
+
 func init() {
 	registerRustSnapshotModules(android.InitRegistrationContext)
 }
 
+func (mod *Module) IsSnapshotSanitizerAvailable(t cc.SanitizerType) bool {
+	if ss, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
+		return ss.IsSanitizerAvailable(t)
+	}
+	return false
+}
+
+func (mod *Module) SetSnapshotSanitizerVariation(t cc.SanitizerType, enabled bool) {
+	if ss, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
+		ss.SetSanitizerVariation(t, enabled)
+	} else {
+		panic(fmt.Errorf("Calling SetSnapshotSanitizerVariation on a non-snapshotLibraryDecorator: %s", mod.Name()))
+	}
+}
+
+func (mod *Module) IsSnapshotUnsanitizedVariant() bool {
+	if ss, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
+		return ss.IsUnsanitizedVariant()
+	}
+	return false
+}
+
+func (mod *Module) IsSnapshotSanitizer() bool {
+	if _, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
+		return true
+	}
+	return false
+}
+
 func registerRustSnapshotModules(ctx android.RegistrationContext) {
 	cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
 		"vendor_snapshot_rlib", VendorSnapshotRlibFactory)
@@ -81,6 +146,9 @@
 
 	library.SetSnapshotAndroidMkSuffix(ctx, variant)
 
+	if library.IsSanitizerEnabled(cc.Hwasan) {
+		library.properties = library.sanitizerProperties.Hwasan
+	}
 	if !library.MatchesWithDevice(ctx.DeviceConfig()) {
 		return buildOutput{}
 	}