Merge "Split Rust crate builds into compile and link phases."
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 1ece9fa..892e218 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -365,6 +365,8 @@
 		"system/testing/gtest_extras":                            Bp2BuildDefaultTrueRecursively,
 		"system/timezone/apex":                                   Bp2BuildDefaultTrueRecursively,
 		"system/timezone/output_data":                            Bp2BuildDefaultTrueRecursively,
+		"system/timezone/testdata":                               Bp2BuildDefaultTrueRecursively,
+		"system/timezone/testing":                                Bp2BuildDefaultTrueRecursively,
 		"system/tools/aidl/build/tests_bp2build":                 Bp2BuildDefaultTrue,
 		"system/tools/aidl/metadata":                             Bp2BuildDefaultTrue,
 		"system/tools/hidl/metadata":                             Bp2BuildDefaultTrue,
@@ -373,8 +375,9 @@
 		"system/tools/xsdc/utils":                                Bp2BuildDefaultTrueRecursively,
 		"system/unwinding/libunwindstack":                        Bp2BuildDefaultTrueRecursively,
 
-		"tools/apksig":   Bp2BuildDefaultTrue,
-		"tools/metalava": Bp2BuildDefaultTrue,
+		"tools/apksig":                               Bp2BuildDefaultTrue,
+		"tools/external_updater":                     Bp2BuildDefaultTrueRecursively,
+		"tools/metalava":                             Bp2BuildDefaultTrue,
 		"tools/platform-compat/java/android/compat":  Bp2BuildDefaultTrueRecursively,
 		"tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
 	}
@@ -406,8 +409,6 @@
 		// this BUILD file is globbed by //external/icu/icu4c/source:icu4c_test_data's "data/**/*".
 		"external/icu/icu4c/source/data/unidata/norm2":/* recursive = */ false,
 
-		"frameworks/ex/common":/* recursive = */ true,
-
 		// Building manually due to b/179889880: resource files cross package boundary
 		"packages/apps/Music":/* recursive = */ true,
 
@@ -473,6 +474,7 @@
 		"libgralloctypes",
 		"libnativewindow",
 		"libneuralnetworks",
+		"libneuralnetworks_static",
 		"libgraphicsenv",
 		"libhardware",
 		"libhardware_headers",
@@ -687,7 +689,6 @@
 		"libcodec2_soft_common",
 
 		// kotlin srcs in java libs
-		"CtsPkgInstallerConstants",
 		"kotlinx_atomicfu",
 
 		// kotlin srcs in java binary
@@ -700,6 +701,9 @@
 		//kotlin srcs in android_binary
 		"MusicKotlin",
 
+		// java_library with prebuilt sdk_version
+		"android-common",
+
 		// checked in current.txt for merged_txts
 		"non-updatable-current.txt",
 		"non-updatable-system-current.txt",
@@ -722,7 +726,6 @@
 
 		// min_sdk_version in android_app
 		"CtsShimUpgrade",
-		"fake-framework",
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
@@ -776,7 +779,8 @@
 		"tjbench", // TODO(b/240563612): Stem property
 
 		// java bugs
-		"libbase_ndk", // TODO(b/186826477): fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
+		"libbase_ndk",  // TODO(b/186826477): fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
+		"bouncycastle", // TODO(b/274474005): Need support for custom system_modules.
 
 		// python protos
 		"libprotobuf-python", // Has a handcrafted alternative
@@ -843,7 +847,6 @@
 		"libgmock_ndk",                                            // depends on unconverted modules: libgtest_ndk_c++
 		"libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libnativetesthelper_jni, libgmock_ndk
 		"libnativetesthelper_jni",   // depends on unconverted modules: libgtest_ndk_c++
-		"libprotobuf-java-nano",     // b/220869005, depends on non-public_current SDK
 		"libstatslog",               // depends on unconverted modules: libstatspull, statsd-aidl-ndk
 		"libstatslog_art",           // depends on unconverted modules: statslog_art.cpp, statslog_art.h
 		"linker_reloc_bench_main",   // depends on unconverted modules: liblinker_reloc_bench_*
@@ -1393,6 +1396,16 @@
 
 		// TODO(b/266459895): depends on libunwindstack
 		"libutils_test",
+
+		// TODO(b/274805756): Support core_platform and current java APIs
+		"fake-framework",
+
+		// TODO(b/277616982): These modules depend on private java APIs, but maybe they don't need to.
+		"StreamingProtoTest",
+		"textclassifierprotoslite",
+		"styleprotoslite",
+		"CtsPkgInstallerConstants",
+		"guava-android-testlib",
 	}
 
 	MixedBuildsDisabledList = []string{
@@ -1471,6 +1484,7 @@
 		// M5: tzdata launch
 		"com.android.tzdata",
 		"test1_com.android.tzdata",
+		"test3_com.android.tzdata",
 		// M7: adbd launch
 		"com.android.adbd",
 		"test_com.android.adbd",
@@ -1490,6 +1504,8 @@
 	// also be built - do not add them to this list.
 	StagingMixedBuildsEnabledList = []string{
 		"com.android.neuralnetworks",
+		"libneuralnetworks",
+		"libneuralnetworks_static",
 	}
 
 	// These should be the libs that are included by the apexes in the ProdMixedBuildsEnabledList
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 44dc055..5c429e2 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -960,9 +960,13 @@
 // request type.
 func (context *mixedBuildBazelContext) cqueryStarlarkFileContents() []byte {
 	requestTypeToCqueryIdEntries := map[cqueryRequest][]string{}
+	requestTypes := []cqueryRequest{}
 	for _, val := range context.requests {
 		cqueryId := getCqueryId(val)
 		mapEntryString := fmt.Sprintf("%q : True", cqueryId)
+		if _, seenKey := requestTypeToCqueryIdEntries[val.requestType]; !seenKey {
+			requestTypes = append(requestTypes, val.requestType)
+		}
 		requestTypeToCqueryIdEntries[val.requestType] =
 			append(requestTypeToCqueryIdEntries[val.requestType], mapEntryString)
 	}
@@ -984,7 +988,7 @@
     return id_string + ">>" + %s(target, id_string)
 `
 
-	for requestType := range requestTypeToCqueryIdEntries {
+	for _, requestType := range requestTypes {
 		labelMapName := requestType.Name() + "_Labels"
 		functionName := requestType.Name() + "_Fn"
 		labelRegistrationMapSection += fmt.Sprintf(mapDeclarationFormatString,
diff --git a/android/config.go b/android/config.go
index 6765f1f..2904581 100644
--- a/android/config.go
+++ b/android/config.go
@@ -420,6 +420,8 @@
 		fmt.Sprintf(`_arch_variant_product_var_constraints = %s`, archVariantProductVariablesJson),
 		"\n", `
 product_vars = _product_vars
+
+# TODO(b/269577299) Remove these when everything switches over to loading them from product_variable_constants.bzl
 product_var_constraints = _product_var_constraints
 arch_variant_product_var_constraints = _arch_variant_product_var_constraints
 `,
@@ -429,6 +431,13 @@
 	if err != nil {
 		return fmt.Errorf("Could not write .bzl config file %s", err)
 	}
+	err = pathtools.WriteFileIfChanged(filepath.Join(dir, "product_variable_constants.bzl"), []byte(fmt.Sprintf(`
+product_var_constraints = %s
+arch_variant_product_var_constraints = %s
+`, nonArchVariantProductVariablesJson, archVariantProductVariablesJson)), 0644)
+	if err != nil {
+		return fmt.Errorf("Could not write .bzl config file %s", err)
+	}
 	err = pathtools.WriteFileIfChanged(filepath.Join(dir, "BUILD"),
 		[]byte(bazel.GeneratedBazelFileWarning), 0644)
 	if err != nil {
@@ -824,6 +833,10 @@
 	return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version)
 }
 
+func (c *config) RawPlatformSdkVersion() *int {
+	return c.productVariables.Platform_sdk_version
+}
+
 func (c *config) PlatformSdkFinal() bool {
 	return Bool(c.productVariables.Platform_sdk_final)
 }
diff --git a/android/module.go b/android/module.go
index 76fe8dc..ba47453 100644
--- a/android/module.go
+++ b/android/module.go
@@ -550,6 +550,7 @@
 	ExportedToMake() bool
 	InitRc() Paths
 	VintfFragments() Paths
+	EffectiveLicenseKinds() []string
 	EffectiveLicenseFiles() Paths
 
 	AddProperties(props ...interface{})
@@ -2024,6 +2025,10 @@
 	return m.commonProperties.NamespaceExportedToMake
 }
 
+func (m *ModuleBase) EffectiveLicenseKinds() []string {
+	return m.commonProperties.Effective_license_kinds
+}
+
 func (m *ModuleBase) EffectiveLicenseFiles() Paths {
 	result := make(Paths, 0, len(m.commonProperties.Effective_license_text))
 	for _, p := range m.commonProperties.Effective_license_text {
diff --git a/android/namespace.go b/android/namespace.go
index c47a1c5..ebf85a1 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -325,8 +325,8 @@
 	namespace.id = strconv.Itoa(id)
 }
 
-func (r *NameResolver) MissingDependencyError(depender string, dependerNamespace blueprint.Namespace, depName string) (err error) {
-	text := fmt.Sprintf("%q depends on undefined module %q", depender, depName)
+func (r *NameResolver) MissingDependencyError(depender string, dependerNamespace blueprint.Namespace, depName string, guess []string) (err error) {
+	text := fmt.Sprintf("%q depends on undefined module %q.", depender, depName)
 
 	_, _, isAbs := r.parseFullyQualifiedName(depName)
 	if isAbs {
@@ -345,9 +345,10 @@
 		}
 		_, skipped := namespace.moduleContainer.SkippedModuleFromName(depName, nil)
 		if skipped {
-			skippedDepErrors = append(skippedDepErrors, namespace.moduleContainer.MissingDependencyError(depender, dependerNamespace, depName))
+			skippedDepErrors = append(skippedDepErrors, namespace.moduleContainer.MissingDependencyError(depender, dependerNamespace, depName, nil))
 		}
 	}
+
 	if len(foundInNamespaces) > 0 {
 		// determine which namespaces are visible to dependerNamespace
 		dependerNs := dependerNamespace.(*Namespace)
@@ -363,6 +364,10 @@
 		text += fmt.Sprintf("\n%s", err.Error())
 	}
 
+	if len(guess) > 0 {
+		text += fmt.Sprintf("\nOr did you mean %q?", guess)
+	}
+
 	return fmt.Errorf(text)
 }
 
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 7a387a0..ea51c6e 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -174,9 +174,10 @@
 			`,
 		}),
 	).
-		ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:4:5: "b" depends on undefined module "a"
+		ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:4:5: "b" depends on undefined module "a".
 Module "b" is defined in namespace "dir3" which can read these 2 namespaces: ["dir3" "."]
-Module "a" can be found in these namespaces: ["dir1" "dir2"]\E`)).
+Module "a" can be found in these namespaces: ["dir1" "dir2"]\E
+Or did you mean ["soong_namespace"]?`)).
 		RunTest(t)
 }
 
@@ -421,9 +422,10 @@
 			`,
 		}),
 	).
-		ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/subdir1/Android.bp:4:5: "b" depends on undefined module "a"
+		ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/subdir1/Android.bp:4:5: "b" depends on undefined module "a".
 Module "b" is defined in namespace "dir1/subdir1" which can read these 2 namespaces: ["dir1/subdir1" "."]
-Module "a" can be found in these namespaces: ["dir1"]\E`)).
+Module "a" can be found in these namespaces: ["dir1"]\E
+Or did you mean ["soong_namespace"]?`)).
 		RunTest(t)
 }
 
@@ -481,9 +483,10 @@
 			`,
 		}),
 	).
-		ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:5:5: "c" depends on undefined module "a"
+		ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:5:5: "c" depends on undefined module "a".
 Module "c" is defined in namespace "dir3" which can read these 3 namespaces: ["dir3" "dir2" "."]
-Module "a" can be found in these namespaces: ["dir1"]\E`)).
+Module "a" can be found in these namespaces: ["dir1"]\E
+Or did you mean ["b"]?`)).
 		RunTest(t)
 }
 
diff --git a/android/visibility.go b/android/visibility.go
index 5955133..3130135 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -47,7 +47,6 @@
 //   the dependency. If it cannot then an error is reported.
 //
 // TODO(b/130631145) - Make visibility work properly with prebuilts.
-// TODO(b/130796911) - Make visibility work properly with defaults.
 
 // Patterns for the values that can be specified in visibility property.
 const (
diff --git a/apex/builder.go b/apex/builder.go
index e3b6f8e..94aef49 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -71,6 +71,9 @@
 	pctx.HostBinToolVariable("make_erofs", "make_erofs")
 	pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool")
 	pctx.HostBinToolVariable("dexdeps", "dexdeps")
+	pctx.HostBinToolVariable("apex_sepolicy_tests", "apex_sepolicy_tests")
+	pctx.HostBinToolVariable("deapexer", "deapexer")
+	pctx.HostBinToolVariable("debugfs_static", "debugfs_static")
 	pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
 }
 
@@ -226,7 +229,12 @@
 		Description: "Generate symbol list used by Apex",
 	}, "image_dir", "readelf")
 
-	// Don't add more rules here. Consider using android.NewRuleBuilder instead.
+	apexSepolicyTestsRule = pctx.StaticRule("apexSepolicyTestsRule", blueprint.RuleParams{
+		Command: `${deapexer} --debugfs_path ${debugfs_static} list -Z ${in} > ${out}.fc` +
+			`&& ${apex_sepolicy_tests} -f ${out}.fc && touch ${out}`,
+		CommandDeps: []string{"${apex_sepolicy_tests}", "${deapexer}", "${debugfs_static}"},
+		Description: "run apex_sepolicy_tests",
+	})
 )
 
 // buildManifest creates buile rules to modify the input apex_manifest.json to add information
@@ -872,6 +880,10 @@
 		args["implicits"] = strings.Join(implicits.Strings(), ",")
 		args["outCommaList"] = signedOutputFile.String()
 	}
+	var validations android.Paths
+	if suffix == imageApexSuffix {
+		validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile.OutputPath))
+	}
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        rule,
 		Description: "signapk",
@@ -879,6 +891,7 @@
 		Input:       unsignedOutputFile,
 		Implicits:   implicits,
 		Args:        args,
+		Validations: validations,
 	})
 	if suffix == imageApexSuffix {
 		a.outputApexFile = signedOutputFile
@@ -1172,3 +1185,17 @@
 
 	return cannedFsConfig.OutputPath
 }
+
+// Runs apex_sepolicy_tests
+//
+// $ deapexer list -Z {apex_file} > {file_contexts}
+// $ apex_sepolicy_tests -f {file_contexts}
+func runApexSepolicyTests(ctx android.ModuleContext, apexFile android.OutputPath) android.Path {
+	timestamp := android.PathForModuleOut(ctx, "sepolicy_tests.timestamp")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   apexSepolicyTestsRule,
+		Input:  apexFile,
+		Output: timestamp,
+	})
+	return timestamp
+}
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
index 6020ee5..09d9dc1 100644
--- a/bp2build/aar_conversion_test.go
+++ b/bp2build/aar_conversion_test.go
@@ -66,9 +66,12 @@
 					"resource_files": `["res/res.png"]`,
 					"deps":           `[":static_lib_dep"]`,
 					"exports":        `[":static_lib_dep"]`,
-					"javacopts":      `["-source 1.7 -target 1.7"]`,
+					"java_version":   `"7"`,
 				}),
-			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
+			MakeNeverlinkDuplicateTargetWithAttrs(
+				"android_library",
+				"TestLib",
+				AttrNameToString{"java_version": `"7"`}),
 		}})
 }
 
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index ef3f124..928a1f2 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -53,6 +53,7 @@
 				"srcs":           `["app.java"]`,
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `["res/res.png"]`,
+				"sdk_version":    `"current"`,
 			}),
 		}})
 }
@@ -91,7 +92,8 @@
     ]`,
 				"custom_package":   `"com.google"`,
 				"deps":             `[":static_lib_dep"]`,
-				"javacopts":        `["-source 1.7 -target 1.7"]`,
+				"java_version":     `"7"`,
+				"sdk_version":      `"current"`,
 				"certificate_name": `"foocert"`,
 			}),
 		}})
@@ -131,6 +133,7 @@
     })`,
 				"manifest":       `"AndroidManifest.xml"`,
 				"resource_files": `["res/res.png"]`,
+				"sdk_version":    `"current"`,
 			}),
 		}})
 }
@@ -365,6 +368,7 @@
 				"manifest_values": `{
         "minSdkVersion": "24",
     }`,
+				"sdk_version": `"current"`,
 			}),
 		}})
 }
@@ -388,6 +392,7 @@
 				"manifest_values": `{
         "minSdkVersion": "30",
     }`,
+				"sdk_version": `"30"`,
 			}),
 		}})
 }
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 6a39e25..608fcd8 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -1,8 +1,11 @@
 package bp2build
 
 import (
+	"android/soong/starlark_fmt"
 	"encoding/json"
+	"fmt"
 	"reflect"
+	"strconv"
 	"strings"
 
 	"android/soong/android"
@@ -48,7 +51,9 @@
 	if err != nil {
 		panic(err)
 	}
+	files = append(files, newFile("metrics", GeneratedBuildFileName, "")) // Creates a //metrics package.
 	files = append(files, newFile("metrics", "converted_modules_path_map.json", string(convertedModulePathMap)))
+	files = append(files, newFile("metrics", "converted_modules_path_map.bzl", "modules = "+strings.ReplaceAll(string(convertedModulePathMap), "\\", "\\\\")))
 
 	files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
 
@@ -62,6 +67,7 @@
 	// TODO(b/269691302)  value of apiLevelsContent is product variable dependent and should be avoided for soong injection
 	files = append(files, newFile("api_levels", "api_levels.json", string(apiLevelsContent)))
 	files = append(files, newFile("api_levels", "api_levels.bzl", android.StarlarkApiLevelConfigs(cfg)))
+	files = append(files, newFile("api_levels", "platform_versions.bzl", platformVersionContents(cfg)))
 
 	files = append(files, newFile("allowlists", GeneratedBuildFileName, ""))
 	files = append(files, newFile("allowlists", "env.bzl", android.EnvironmentVarsFile(cfg)))
@@ -72,6 +78,31 @@
 	return files, nil
 }
 
+func platformVersionContents(cfg android.Config) string {
+	// Despite these coming from cfg.productVariables, they are actually hardcoded in global
+	// makefiles, not set in individual product config makesfiles, so they're safe to just export
+	// and load() directly.
+
+	platformVersionActiveCodenames := make([]string, 0, len(cfg.PlatformVersionActiveCodenames()))
+	for _, codename := range cfg.PlatformVersionActiveCodenames() {
+		platformVersionActiveCodenames = append(platformVersionActiveCodenames, fmt.Sprintf("%q", codename))
+	}
+
+	platformSdkVersion := "None"
+	if cfg.RawPlatformSdkVersion() != nil {
+		platformSdkVersion = strconv.Itoa(*cfg.RawPlatformSdkVersion())
+	}
+
+	return fmt.Sprintf(`
+platform_versions = struct(
+    platform_sdk_final = %s,
+    platform_sdk_version = %s,
+    platform_sdk_codename = %q,
+    platform_version_active_codenames = [%s],
+)
+`, starlark_fmt.PrintBool(cfg.PlatformSdkFinal()), platformSdkVersion, cfg.PlatformSdkCodename(), strings.Join(platformVersionActiveCodenames, ", "))
+}
+
 func CreateBazelFiles(
 	cfg android.Config,
 	ruleShims map[string]RuleShim,
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 8c1d2ae..2f5dc3c 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -131,9 +131,17 @@
 		},
 		{
 			dir:      "metrics",
+			basename: "BUILD.bazel",
+		},
+		{
+			dir:      "metrics",
 			basename: "converted_modules_path_map.json",
 		},
 		{
+			dir:      "metrics",
+			basename: "converted_modules_path_map.bzl",
+		},
+		{
 			dir:      "product_config",
 			basename: "soong_config_variables.bzl",
 		},
@@ -154,6 +162,10 @@
 			basename: "api_levels.bzl",
 		},
 		{
+			dir:      "api_levels",
+			basename: "platform_versions.bzl",
+		},
+		{
 			dir:      "allowlists",
 			basename: GeneratedBuildFileName,
 		},
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
index 1b9777c..c821f59 100644
--- a/bp2build/java_binary_host_conversion_test.go
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -57,24 +57,24 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-binary-host-1_lib", AttrNameToString{
-				"srcs": `["a.java"]`,
-				"deps": `["//other:jni-lib-1"]`,
-				"javacopts": `[
-        "-Xdoclint:all/protected",
-        "-source 1.8 -target 1.8",
-    ]`,
+				"srcs":         `["a.java"]`,
+				"deps":         `["//other:jni-lib-1"]`,
+				"java_version": `"8"`,
+				"javacopts":    `["-Xdoclint:all/protected"]`,
 				"target_compatible_with": `select({
         "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
         "//conditions:default": [],
-    })`}),
+    })`,
+			}),
 			MakeBazelTarget("java_binary", "java-binary-host-1", AttrNameToString{
-				"main_class":   `"com.android.test.MainClass"`,
-				"jvm_flags":    `["-Djava.library.path=$${RUNPATH}other"]`,
-				"runtime_deps": `[":java-binary-host-1_lib"]`,
+				"main_class": `"com.android.test.MainClass"`,
+				"jvm_flags":  `["-Djava.library.path=$${RUNPATH}other"]`,
 				"target_compatible_with": `select({
         "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
         "//conditions:default": [],
-    })`}),
+    })`,
+				"runtime_deps": `[":java-binary-host-1_lib"]`,
+			}),
 		},
 	})
 }
diff --git a/bp2build/java_host_for_device_conversion_test.go b/bp2build/java_host_for_device_conversion_test.go
index d908d00..448cba4 100644
--- a/bp2build/java_host_for_device_conversion_test.go
+++ b/bp2build/java_host_for_device_conversion_test.go
@@ -51,9 +51,11 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_host_for_device", "java-lib-1", AttrNameToString{
-				"deps": `[":java-lib-2"]`,
+				"exports": `[":java-lib-2"]`,
 			}),
-			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+			MakeNeverlinkDuplicateTargetWithAttrs("java_library", "java-lib-1", AttrNameToString{
+				"sdk_version": `"none"`,
+			}),
 			MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{
 				"srcs": `["b.java"]`,
 			}),
diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go
index a5c01cb..5661620 100644
--- a/bp2build/java_import_conversion_test.go
+++ b/bp2build/java_import_conversion_test.go
@@ -49,8 +49,9 @@
 				"jars": `["import.jar"]`,
 			}),
 			MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
-				"exports":   `[":example_import"]`,
-				"neverlink": `True`,
+				"exports":     `[":example_import"]`,
+				"neverlink":   `True`,
+				"sdk_version": `"none"`,
 			}),
 		}})
 }
@@ -86,8 +87,9 @@
     })`,
 			}),
 			MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
-				"exports":   `[":example_import"]`,
-				"neverlink": `True`,
+				"exports":     `[":example_import"]`,
+				"neverlink":   `True`,
+				"sdk_version": `"none"`,
 			}),
 		}})
 }
@@ -112,8 +114,9 @@
 				"jars": `["import.jar"]`,
 			}),
 			MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
-				"exports":   `[":example_import"]`,
-				"neverlink": `True`,
+				"exports":     `[":example_import"]`,
+				"neverlink":   `True`,
+				"sdk_version": `"none"`,
 			}),
 		}})
 }
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 683ee27..24b763b 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -172,10 +172,13 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
-				"srcs":      `["a.java"]`,
-				"javacopts": `["-source 11 -target 11"]`,
+				"srcs":         `["a.java"]`,
+				"java_version": `"11"`,
 			}),
-			MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+			MakeNeverlinkDuplicateTargetWithAttrs(
+				"java_library",
+				"java-lib-1",
+				AttrNameToString{"java_version": `"11"`}),
 		},
 	})
 }
diff --git a/bp2build/java_library_host_conversion_test.go b/bp2build/java_library_host_conversion_test.go
index 14854c0..9e47b09 100644
--- a/bp2build/java_library_host_conversion_test.go
+++ b/bp2build/java_library_host_conversion_test.go
@@ -63,8 +63,8 @@
     })`,
 			}),
 			MakeBazelTarget("java_library", "java-lib-host-2", AttrNameToString{
-				"javacopts": `["-source 1.9 -target 1.9"]`,
-				"srcs":      `["c.java"]`,
+				"java_version": `"9"`,
+				"srcs":         `["c.java"]`,
 				"target_compatible_with": `select({
         "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
         "//conditions:default": [],
@@ -77,6 +77,7 @@
         "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
         "//conditions:default": [],
     })`,
+				"java_version": `"9"`,
 			}),
 		},
 	})
diff --git a/bp2build/java_plugin_conversion_test.go b/bp2build/java_plugin_conversion_test.go
index 8c6337b..f2b6f20 100644
--- a/bp2build/java_plugin_conversion_test.go
+++ b/bp2build/java_plugin_conversion_test.go
@@ -67,7 +67,7 @@
         "a.java",
         "b.java",
     ]`,
-				"javacopts": `["-source 1.7 -target 1.7"]`,
+				"java_version": `"7"`,
 			}),
 		},
 	})
diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go
index d25b7c4..f546cf4 100644
--- a/bp2build/java_proto_conversion_test.go
+++ b/bp2build/java_proto_conversion_test.go
@@ -114,13 +114,17 @@
 				"java_lite_proto_library",
 				"java-protos_java_proto_lite",
 				AttrNameToString{
-					"deps": `[":java-protos_proto"]`,
+					"deps":         `[":java-protos_proto"]`,
+					"java_version": `"7"`,
 				}),
 			MakeBazelTarget("java_library", "java-protos", AttrNameToString{
-				"exports":   `[":java-protos_java_proto_lite"]`,
-				"javacopts": `["-source 1.7 -target 1.7"]`,
+				"exports":      `[":java-protos_java_proto_lite"]`,
+				"java_version": `"7"`,
 			}),
-			MakeNeverlinkDuplicateTarget("java_library", "java-protos"),
+			MakeNeverlinkDuplicateTargetWithAttrs(
+				"java_library",
+				"java-protos",
+				AttrNameToString{"java_version": `"7"`}),
 		},
 	})
 }
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 856b6ee..6e919db 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -642,10 +642,14 @@
 }
 
 func MakeNeverlinkDuplicateTarget(moduleType string, name string) string {
-	return MakeBazelTarget(moduleType, name+"-neverlink", AttrNameToString{
-		"neverlink": `True`,
-		"exports":   `[":` + name + `"]`,
-	})
+	return MakeNeverlinkDuplicateTargetWithAttrs(moduleType, name, AttrNameToString{})
+}
+
+func MakeNeverlinkDuplicateTargetWithAttrs(moduleType string, name string, extraAttrs AttrNameToString) string {
+	attrs := extraAttrs
+	attrs["neverlink"] = `True`
+	attrs["exports"] = `[":` + name + `"]`
+	return MakeBazelTarget(moduleType, name+"-neverlink", attrs)
 }
 
 func getTargetName(targetContent string) string {
diff --git a/cc/config/global.go b/cc/config/global.go
index 5b2191a..a2d5cf4 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -111,6 +111,9 @@
 
 		// Turn off FMA which got enabled by default in clang-r445002 (http://b/218805949)
 		"-ffp-contract=off",
+
+		// Turn off stack protector check for noreturn calls. (http://b/264965700)
+		"-mllvm -disable-check-noreturn-call",
 	}
 
 	commonGlobalConlyflags = []string{}
@@ -147,6 +150,9 @@
 	commonGlobalLldflags = []string{
 		"-fuse-ld=lld",
 		"-Wl,--icf=safe",
+
+		// Turn off stack protector check for noreturn calls. (http://b/264965700)
+		"-Wl,-mllvm,-disable-check-noreturn-call",
 	}
 
 	deviceGlobalCppflags = []string{
@@ -315,6 +321,9 @@
 	}
 
 	VersionScriptFlagPrefix = "-Wl,--version-script,"
+
+	VisibilityHiddenFlag  = "-fvisibility=hidden"
+	VisibilityDefaultFlag = "-fvisibility=default"
 )
 
 // BazelCcToolchainVars generates bzl file content containing variables for
@@ -405,6 +414,9 @@
 
 	exportedVars.ExportString("VersionScriptFlagPrefix", VersionScriptFlagPrefix)
 
+	exportedVars.ExportString("VisibilityHiddenFlag", VisibilityHiddenFlag)
+	exportedVars.ExportString("VisibilityDefaultFlag", VisibilityDefaultFlag)
+
 	// Everything in these lists is a crime against abstraction and dependency tracking.
 	// Do not add anything to this list.
 	commonGlobalIncludes := []string{
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 622558e..dffc6c6 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -142,6 +142,13 @@
 						staticLibInstallPaths, library.ndkSysrootPath)
 				}
 			}
+
+			if object, ok := m.linker.(*objectLinker); ok {
+				if object.ndkSysrootPath != nil {
+					staticLibInstallPaths = append(
+						staticLibInstallPaths, object.ndkSysrootPath)
+				}
+			}
 		}
 	})
 
diff --git a/cc/object.go b/cc/object.go
index ef44467..d65cdea 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -44,6 +44,10 @@
 type objectLinker struct {
 	*baseLinker
 	Properties ObjectLinkerProperties
+
+	// Location of the object in the sysroot. Empty if the object is not
+	// included in the NDK.
+	ndkSysrootPath android.Path
 }
 
 type objectBazelHandler struct {
@@ -99,6 +103,10 @@
 	// Indicates that this module is a CRT object. CRT objects will be split
 	// into a variant per-API level between min_sdk_version and current.
 	Crt *bool
+
+	// Indicates that this module should not be included in the NDK sysroot.
+	// Only applies to CRT objects. Defaults to false.
+	Exclude_from_ndk_sysroot *bool
 }
 
 func newObject(hod android.HostOrDeviceSupported) *Module {
@@ -268,17 +276,28 @@
 
 	objs = objs.Append(deps.Objs)
 
-	var outputFile android.Path
+	var output android.WritablePath
 	builderFlags := flagsToBuilderFlags(flags)
 	outputName := ctx.ModuleName()
 	if !strings.HasSuffix(outputName, objectExtension) {
 		outputName += objectExtension
 	}
 
-	if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
-		output := android.PathForModuleOut(ctx, outputName)
-		outputFile = output
+	// isForPlatform is terribly named and actually means isNotApex.
+	if Bool(object.Properties.Crt) &&
+		!Bool(object.Properties.Exclude_from_ndk_sysroot) && ctx.useSdk() &&
+		ctx.isSdkVariant() && ctx.isForPlatform() {
 
+		output = getVersionedLibraryInstallPath(ctx,
+			nativeApiLevelOrPanic(ctx, ctx.sdkVersion())).Join(ctx, outputName)
+		object.ndkSysrootPath = output
+	} else {
+		output = android.PathForModuleOut(ctx, outputName)
+	}
+
+	outputFile := output
+
+	if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
 		if String(object.Properties.Prefix_symbols) != "" {
 			transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), objs.objFiles[0],
 				builderFlags, output)
@@ -290,9 +309,6 @@
 			})
 		}
 	} else {
-		output := android.PathForModuleOut(ctx, outputName)
-		outputFile = output
-
 		if String(object.Properties.Prefix_symbols) != "" {
 			input := android.PathForModuleOut(ctx, "unprefixed", outputName)
 			transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
diff --git a/cc/object_test.go b/cc/object_test.go
index 5359a35..b1e2a0f 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -65,7 +65,7 @@
 	variant := "android_arm64_armv8-a_sdk"
 	crt := ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
 	android.AssertStringDoesContain(t, "crt dep of sdk variant", crt,
-		variant+"_29/crtbegin_dynamic.o")
+		"29/crtbegin_dynamic.o")
 
 	// platform variant uses the crt object built for platform
 	variant = "android_arm64_armv8-a"
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f19659c..4601ee6 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -64,12 +64,13 @@
 
 	cfiBlocklistPath     = "external/compiler-rt/lib/cfi"
 	cfiBlocklistFilename = "cfi_blocklist.txt"
-	cfiCflags            = []string{"-flto", "-fsanitize-cfi-cross-dso",
+	cfiCrossDsoFlag      = "-fsanitize-cfi-cross-dso"
+	cfiCflags            = []string{"-flto", cfiCrossDsoFlag,
 		"-fsanitize-ignorelist=" + cfiBlocklistPath + "/" + cfiBlocklistFilename}
 	// -flto and -fvisibility are required by clang when -fsanitize=cfi is
 	// used, but have no effect on assembly files
 	cfiAsflags = []string{"-flto", "-fvisibility=default"}
-	cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
+	cfiLdflags = []string{"-flto", cfiCrossDsoFlag, "-fsanitize=cfi",
 		"-Wl,-plugin-opt,O1"}
 	cfiExportsMapPath      = "build/soong/cc/config"
 	cfiExportsMapFilename  = "cfi_exports.map"
@@ -393,11 +394,13 @@
 	exportedVars.ExportStringList("DeviceOnlySanitizeFlags", deviceOnlySanitizeFlags)
 
 	// Leave out "-flto" from the slices exported to bazel, as we will use the
-	// dedicated LTO feature for this
-	exportedVars.ExportStringList("CfiCFlags", cfiCflags[1:])
+	// dedicated LTO feature for this. For C Flags and Linker Flags, also leave
+	// out the cross DSO flag which will be added separately by transitions.
+	exportedVars.ExportStringList("CfiCFlags", cfiCflags[2:])
+	exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[2:])
 	exportedVars.ExportStringList("CfiAsFlags", cfiAsflags[1:])
-	exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[1:])
 
+	exportedVars.ExportString("CfiCrossDsoFlag", cfiCrossDsoFlag)
 	exportedVars.ExportString("CfiBlocklistPath", cfiBlocklistPath)
 	exportedVars.ExportString("CfiBlocklistFilename", cfiBlocklistFilename)
 	exportedVars.ExportString("CfiExportsMapPath", cfiExportsMapPath)
@@ -613,6 +616,10 @@
 	if (ctx.Arch().ArchType != android.Arm64 && ctx.Arch().ArchType != android.Riscv64) || !ctx.toolchain().Bionic() {
 		s.Scs = nil
 	}
+	// ...but temporarily globally disabled on riscv64 (http://b/277909695).
+	if ctx.Arch().ArchType == android.Riscv64 {
+		s.Scs = nil
+	}
 
 	// Memtag_heap is only implemented on AArch64.
 	// Memtag ABI is Android specific for now, so disable for host.
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 718186d..29b17d4 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -1166,3 +1166,83 @@
 	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
 	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
 }
+
+func TestCfi(t *testing.T) {
+	t.Parallel()
+
+	bp := `
+	cc_library_shared {
+		name: "shared_with_cfi",
+		static_libs: [
+			"static_dep_with_cfi",
+			"static_dep_no_cfi",
+		],
+		sanitize: {
+			cfi: true,
+		},
+	}
+
+	cc_library_shared {
+		name: "shared_no_cfi",
+		static_libs: [
+			"static_dep_with_cfi",
+			"static_dep_no_cfi",
+		],
+	}
+
+	cc_library_static {
+		name: "static_dep_with_cfi",
+		sanitize: {
+			cfi: true,
+		},
+	}
+
+	cc_library_static {
+		name: "static_dep_no_cfi",
+	}
+
+	cc_library_shared {
+		name: "shared_rdep_no_cfi",
+		static_libs: ["static_dep_with_cfi_2"],
+	}
+
+	cc_library_static {
+		name: "static_dep_with_cfi_2",
+		sanitize: {
+			cfi: true,
+		},
+	}
+`
+	preparer := android.GroupFixturePreparers(
+		prepareForCcTest,
+	)
+	result := preparer.RunTestWithBp(t, bp)
+	ctx := result.TestContext
+
+	buildOs := "android_arm64_armv8-a"
+	shared_suffix := "_shared"
+	cfi_suffix := "_cfi"
+	static_suffix := "_static"
+
+	sharedWithCfiLib := result.ModuleForTests("shared_with_cfi", buildOs+shared_suffix+cfi_suffix)
+	sharedNoCfiLib := result.ModuleForTests("shared_no_cfi", buildOs+shared_suffix)
+	staticWithCfiLib := result.ModuleForTests("static_dep_with_cfi", buildOs+static_suffix)
+	staticWithCfiLibCfiVariant := result.ModuleForTests("static_dep_with_cfi", buildOs+static_suffix+cfi_suffix)
+	staticNoCfiLib := result.ModuleForTests("static_dep_no_cfi", buildOs+static_suffix)
+	staticNoCfiLibCfiVariant := result.ModuleForTests("static_dep_no_cfi", buildOs+static_suffix+cfi_suffix)
+	sharedRdepNoCfi := result.ModuleForTests("shared_rdep_no_cfi", buildOs+shared_suffix)
+	staticDepWithCfi2Lib := result.ModuleForTests("static_dep_with_cfi_2", buildOs+static_suffix)
+
+	// Confirm assumptions about propagation of CFI enablement
+	expectStaticLinkDep(t, ctx, sharedWithCfiLib, staticWithCfiLibCfiVariant)
+	expectStaticLinkDep(t, ctx, sharedNoCfiLib, staticWithCfiLib)
+	expectStaticLinkDep(t, ctx, sharedWithCfiLib, staticNoCfiLibCfiVariant)
+	expectStaticLinkDep(t, ctx, sharedNoCfiLib, staticNoCfiLib)
+	expectStaticLinkDep(t, ctx, sharedRdepNoCfi, staticDepWithCfi2Lib)
+
+	// Confirm that non-CFI variants do not add CFI flags
+	bazLibCflags := staticWithCfiLib.Rule("cc").Args["cFlags"]
+	if strings.Contains(bazLibCflags, "-fsanitize-cfi-cross-dso") {
+		t.Errorf("non-CFI variant of baz not expected to contain CFI flags ")
+	}
+}
diff --git a/cc/vndk.go b/cc/vndk.go
index 3b7c87d..be66cd7 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -674,8 +674,12 @@
 	snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
 
 	configsDir := filepath.Join(snapshotArchDir, "configs")
+	noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
 	includeDir := filepath.Join(snapshotArchDir, "include")
 
+	// set of notice files copied.
+	noticeBuilt := make(map[string]bool)
+
 	// paths of VNDK modules for GPL license checking
 	modulePaths := make(map[string]string)
 
@@ -700,28 +704,36 @@
 		snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base())
 		ret = append(ret, snapshot.CopyFileRule(pctx, ctx, libPath, snapshotLibOut))
 
+		// json struct to export snapshot information
+		prop := struct {
+			LicenseKinds        []string `json:",omitempty"`
+			LicenseTexts        []string `json:",omitempty"`
+			ExportedDirs        []string `json:",omitempty"`
+			ExportedSystemDirs  []string `json:",omitempty"`
+			ExportedFlags       []string `json:",omitempty"`
+			RelativeInstallPath string   `json:",omitempty"`
+		}{}
+
+		prop.LicenseKinds = m.EffectiveLicenseKinds()
+		prop.LicenseTexts = m.EffectiveLicenseFiles().Strings()
+
 		if ctx.Config().VndkSnapshotBuildArtifacts() {
-			prop := struct {
-				ExportedDirs        []string `json:",omitempty"`
-				ExportedSystemDirs  []string `json:",omitempty"`
-				ExportedFlags       []string `json:",omitempty"`
-				RelativeInstallPath string   `json:",omitempty"`
-			}{}
 			exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
 			prop.ExportedFlags = exportedInfo.Flags
 			prop.ExportedDirs = exportedInfo.IncludeDirs.Strings()
 			prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings()
 			prop.RelativeInstallPath = m.RelativeInstallPath()
-
-			propOut := snapshotLibOut + ".json"
-
-			j, err := json.Marshal(prop)
-			if err != nil {
-				ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
-				return nil, false
-			}
-			ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
 		}
+
+		propOut := snapshotLibOut + ".json"
+
+		j, err := json.Marshal(prop)
+		if err != nil {
+			ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
+			return nil, false
+		}
+		ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
+
 		return ret, true
 	}
 
@@ -761,6 +773,14 @@
 		moduleNames[stem] = ctx.ModuleName(m)
 		modulePaths[stem] = ctx.ModuleDir(m)
 
+		for _, notice := range m.EffectiveLicenseFiles() {
+			if _, ok := noticeBuilt[notice.String()]; !ok {
+				noticeBuilt[notice.String()] = true
+				snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
+					pctx, ctx, notice, filepath.Join(noticeDir, notice.String())))
+			}
+		}
+
 		if ctx.Config().VndkSnapshotBuildArtifacts() {
 			headers = append(headers, m.SnapshotHeaders()...)
 		}
diff --git a/java/aar.go b/java/aar.go
index 47e6efa..f1b137d 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -1015,9 +1015,10 @@
 }
 
 type bazelAndroidLibraryImport struct {
-	Aar     bazel.Label
-	Deps    bazel.LabelListAttribute
-	Exports bazel.LabelListAttribute
+	Aar         bazel.Label
+	Deps        bazel.LabelListAttribute
+	Exports     bazel.LabelListAttribute
+	Sdk_version bazel.StringAttribute
 }
 
 func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) *bazelAapt {
@@ -1059,9 +1060,10 @@
 		},
 		android.CommonAttributes{Name: name},
 		&bazelAndroidLibraryImport{
-			Aar:     aars.Includes[0],
-			Deps:    bazel.MakeLabelListAttribute(deps),
-			Exports: bazel.MakeLabelListAttribute(exports),
+			Aar:         aars.Includes[0],
+			Deps:        bazel.MakeLabelListAttribute(deps),
+			Exports:     bazel.MakeLabelListAttribute(exports),
+			Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
 		},
 	)
 
@@ -1073,6 +1075,9 @@
 			javaLibraryAttributes: &javaLibraryAttributes{
 				Neverlink: bazel.BoolAttribute{Value: &neverlink},
 				Exports:   bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+				javaCommonAttributes: &javaCommonAttributes{
+					Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
+				},
 			},
 		},
 	)
@@ -1119,6 +1124,10 @@
 			javaLibraryAttributes: &javaLibraryAttributes{
 				Neverlink: bazel.BoolAttribute{Value: &neverlink},
 				Exports:   bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+				javaCommonAttributes: &javaCommonAttributes{
+					Sdk_version:  bazel.StringAttribute{Value: a.deviceProperties.Sdk_version},
+					Java_version: bazel.StringAttribute{Value: a.properties.Java_version},
+				},
 			},
 		},
 	)
diff --git a/java/app.go b/java/app.go
index 52caf6d..03e2330 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1565,6 +1565,9 @@
 
 		appAttrs.bazelAapt = &bazelAapt{Manifest: aapt.Manifest}
 		appAttrs.Deps = bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + ktName})
+		appAttrs.javaCommonAttributes = &javaCommonAttributes{
+			Sdk_version: commonAttrs.Sdk_version,
+		}
 	}
 
 	ctx.CreateBazelTargetModule(
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 656c866..3581040 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -21,6 +21,8 @@
 	"android/soong/android"
 	"android/soong/bazel"
 	"android/soong/dexpreopt"
+
+	"github.com/google/blueprint/proptools"
 )
 
 type DeviceHostConverter struct {
@@ -191,7 +193,7 @@
 }
 
 type bazelDeviceHostConverterAttributes struct {
-	Deps bazel.LabelListAttribute
+	Exports bazel.LabelListAttribute
 }
 
 func (d *DeviceHostConverter) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
@@ -202,13 +204,15 @@
 		},
 		android.CommonAttributes{Name: d.Name()},
 		&bazelDeviceHostConverterAttributes{
-			Deps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, d.properties.Libs)),
+			Exports: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, d.properties.Libs)),
 		},
 	)
-	neverlinkProp := true
 	neverLinkAttrs := &javaLibraryAttributes{
 		Exports:   bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + d.Name()}),
-		Neverlink: bazel.BoolAttribute{Value: &neverlinkProp},
+		Neverlink: bazel.BoolAttribute{Value: proptools.BoolPtr(true)},
+		javaCommonAttributes: &javaCommonAttributes{
+			Sdk_version: bazel.StringAttribute{Value: proptools.StringPtr("none")},
+		},
 	}
 	ctx.CreateBazelTargetModule(
 		javaLibraryBazelTargetModuleProperties(),
diff --git a/java/java.go b/java/java.go
index d400b0c..2de4ea9 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2740,9 +2740,11 @@
 type javaCommonAttributes struct {
 	*javaResourcesAttributes
 	*kotlinAttributes
-	Srcs      bazel.LabelListAttribute
-	Plugins   bazel.LabelListAttribute
-	Javacopts bazel.StringListAttribute
+	Srcs         bazel.LabelListAttribute
+	Plugins      bazel.LabelListAttribute
+	Javacopts    bazel.StringListAttribute
+	Sdk_version  bazel.StringAttribute
+	Java_version bazel.StringAttribute
 }
 
 type javaDependencyLabels struct {
@@ -2873,10 +2875,6 @@
 	if m.properties.Javacflags != nil {
 		javacopts = append(javacopts, m.properties.Javacflags...)
 	}
-	if m.properties.Java_version != nil {
-		javaVersion := normalizeJavaVersion(ctx, *m.properties.Java_version).String()
-		javacopts = append(javacopts, fmt.Sprintf("-source %s -target %s", javaVersion, javaVersion))
-	}
 
 	epEnabled := m.properties.Errorprone.Enabled
 	//TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
@@ -2890,7 +2888,9 @@
 		Plugins: bazel.MakeLabelListAttribute(
 			android.BazelLabelForModuleDeps(ctx, m.properties.Plugins),
 		),
-		Javacopts: bazel.MakeStringListAttribute(javacopts),
+		Javacopts:    bazel.MakeStringListAttribute(javacopts),
+		Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
+		Sdk_version:  bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
 	}
 
 	for axis, configToProps := range archVariantProps {
@@ -2981,19 +2981,9 @@
 	deps := depLabels.Deps
 	if !commonAttrs.Srcs.IsEmpty() {
 		deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
-
-		sdkVersion := m.SdkVersion(ctx)
-		if sdkVersion.Kind == android.SdkPublic && sdkVersion.ApiLevel == android.FutureApiLevel {
-			// TODO(b/220869005) remove forced dependency on current public android.jar
-			deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import"))
-		} else if sdkVersion.Kind == android.SdkSystem && sdkVersion.ApiLevel == android.FutureApiLevel {
-			// TODO(b/215230098) remove forced dependency on current public android.jar
-			deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:system_current_android_sdk_java_import"))
-		}
 	} else if !deps.IsEmpty() {
 		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
 	}
-
 	var props bazel.BazelTargetModuleProperties
 	attrs := &javaLibraryAttributes{
 		javaCommonAttributes: commonAttrs,
@@ -3013,6 +3003,10 @@
 	neverLinkAttrs := &javaLibraryAttributes{
 		Exports:   bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
 		Neverlink: bazel.BoolAttribute{Value: &neverlinkProp},
+		javaCommonAttributes: &javaCommonAttributes{
+			Sdk_version:  bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
+			Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
+		},
 	}
 	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name + "-neverlink"}, neverLinkAttrs)
 
@@ -3152,6 +3146,9 @@
 	neverlinkAttrs := &javaLibraryAttributes{
 		Neverlink: bazel.BoolAttribute{Value: &neverlink},
 		Exports:   bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+		javaCommonAttributes: &javaCommonAttributes{
+			Sdk_version: bazel.StringAttribute{Value: proptools.StringPtr("none")},
+		},
 	}
 	ctx.CreateBazelTargetModule(
 		javaLibraryBazelTargetModuleProperties(),
diff --git a/java/proto.go b/java/proto.go
index 5280077..c732d98 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -143,7 +143,9 @@
 }
 
 type protoAttributes struct {
-	Deps bazel.LabelListAttribute
+	Deps         bazel.LabelListAttribute
+	Sdk_version  bazel.StringAttribute
+	Java_version bazel.StringAttribute
 }
 
 func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) *bazel.Label {
@@ -175,8 +177,11 @@
 	}
 
 	protoLabel := bazel.Label{Label: ":" + m.Name() + "_proto"}
-	var protoAttrs protoAttributes
-	protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}})
+	protoAttrs := &protoAttributes{
+		Deps:         bazel.MakeSingleLabelListAttribute(protoLabel),
+		Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
+		Sdk_version:  bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
+	}
 
 	name := m.Name() + suffix
 
@@ -186,7 +191,7 @@
 			Bzl_load_location: "//build/bazel/rules/java:proto.bzl",
 		},
 		android.CommonAttributes{Name: name},
-		&protoAttrs)
+		protoAttrs)
 
 	return &bazel.Label{Label: ":" + name}
 }
diff --git a/mk2rbc/soong_variables.go b/mk2rbc/soong_variables.go
index a52ec4f..7a6aa5f 100644
--- a/mk2rbc/soong_variables.go
+++ b/mk2rbc/soong_variables.go
@@ -67,7 +67,11 @@
 	var valueType starlarkType
 	switch typeString {
 	case "bool":
-		valueType = starlarkTypeBool
+		// TODO: We run into several issues later on if we type this as a bool:
+		//    - We still assign bool-typed variables to strings
+		//    - When emitting the final results as make code, some bool's false values have to
+		//      be an empty string, and some have to be false in order to match the make variables.
+		valueType = starlarkTypeString
 	case "csv":
 		// Only PLATFORM_VERSION_ALL_CODENAMES, and it's a list
 		valueType = starlarkTypeList
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 26fe432..9367ff0 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -189,6 +189,7 @@
     libs: [
         "linker_config_proto",
     ],
+    visibility: ["//system/linkerconfig"],
 }
 
 python_test_host {
diff --git a/starlark_fmt/format.go b/starlark_fmt/format.go
index 064fc21..a97f71b 100644
--- a/starlark_fmt/format.go
+++ b/starlark_fmt/format.go
@@ -35,7 +35,11 @@
 
 // PrintBool returns a Starlark compatible bool string.
 func PrintBool(item bool) string {
-	return strings.Title(fmt.Sprintf("%t", item))
+	if item {
+		return "True"
+	} else {
+		return "False"
+	}
 }
 
 // PrintsStringList returns a Starlark-compatible string of a list of Strings/Labels.