Merge changes I55a5a295,I9c09451d,I05177388

* changes:
  Use the profiles in the APEX to dexpreopt system server jars.
  Add tests for the ignored "profile_guided: true" property.
  Output dex_preopt to SDK snapshot.
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 4fc6ae3..7ce0d9b 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -143,7 +143,10 @@
 		"external/javassist":                     Bp2BuildDefaultTrueRecursively,
 		"external/jemalloc_new":                  Bp2BuildDefaultTrueRecursively,
 		"external/jsoncpp":                       Bp2BuildDefaultTrueRecursively,
+		"external/jsr305":                        Bp2BuildDefaultTrueRecursively,
+		"external/jsr330":                        Bp2BuildDefaultTrueRecursively,
 		"external/junit":                         Bp2BuildDefaultTrueRecursively,
+		"external/kotlinc":                       Bp2BuildDefaultTrueRecursively,
 		"external/libaom":                        Bp2BuildDefaultTrueRecursively,
 		"external/libavc":                        Bp2BuildDefaultTrueRecursively,
 		"external/libcap":                        Bp2BuildDefaultTrueRecursively,
@@ -276,6 +279,7 @@
 		"platform_testing/tests/example": Bp2BuildDefaultTrueRecursively,
 
 		"prebuilts/clang/host/linux-x86":           Bp2BuildDefaultTrueRecursively,
+		"prebuilts/gradle-plugin":                  Bp2BuildDefaultTrueRecursively,
 		"prebuilts/runtime/mainline/platform/sdk":  Bp2BuildDefaultTrueRecursively,
 		"prebuilts/sdk/current/extras/app-toolkit": Bp2BuildDefaultTrue,
 		"prebuilts/sdk/current/support":            Bp2BuildDefaultTrue,
@@ -345,7 +349,8 @@
 		"system/tools/sysprop":                                   Bp2BuildDefaultTrue,
 		"system/unwinding/libunwindstack":                        Bp2BuildDefaultTrueRecursively,
 
-		"tools/apksig": Bp2BuildDefaultTrue,
+		"tools/apksig":   Bp2BuildDefaultTrue,
+		"tools/metalava": Bp2BuildDefaultTrue,
 		"tools/platform-compat/java/android/compat":  Bp2BuildDefaultTrueRecursively,
 		"tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
 	}
@@ -369,7 +374,6 @@
 		"external/bazelbuild-kotlin-rules":/* recursive = */ true,
 		"external/bazel-skylib":/* recursive = */ true,
 		"external/guava":/* recursive = */ true,
-		"external/jsr305":/* recursive = */ true,
 		"external/protobuf":/* recursive = */ false,
 		"external/python/absl-py":/* recursive = */ true,
 
@@ -379,8 +383,8 @@
 		"frameworks/base/tools/codegen":/* recursive = */ true,
 		"frameworks/ex/common":/* recursive = */ true,
 
+		// Building manually due to b/179889880: resource files cross package boundary
 		"packages/apps/Music":/* recursive = */ true,
-		"packages/apps/QuickSearchBox":/* recursive = */ true,
 
 		"prebuilts/abi-dumps/platform":/* recursive = */ true,
 		"prebuilts/abi-dumps/ndk":/* recursive = */ true,
@@ -679,16 +683,20 @@
 
 		// kotlin srcs in android_library
 		"renderscript_toolkit",
+
+		//kotlin srcs in android_binary
+		"MusicKotlin",
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
 		"aidl_interface_headers",
+		"bpf",
 		"license",
 		"linker_config",
 		"java_import",
 		"java_import_host",
+		"java_sdk_library",
 		"sysprop_library",
-		"bpf",
 	}
 
 	// Add the names of modules that bp2build should never convert, if it is
@@ -1404,6 +1412,13 @@
 	ProdMixedBuildsEnabledList = []string{
 		"com.android.tzdata",
 		"test1_com.android.tzdata",
+		"com.android.adbd",
+		"test_com.android.adbd",
+		"adbd_test",
+		"adb_crypto_test",
+		"adb_pairing_auth_test",
+		"adb_pairing_connection_test",
+		"adb_tls_connection_test",
 	}
 
 	// Staging-mode allowlist. Modules in this list are only built
@@ -1411,12 +1426,5 @@
 	// which will soon be added to the prod allowlist.
 	// It is implicit that all modules in ProdMixedBuildsEnabledList will
 	// also be built - do not add them to this list.
-	StagingMixedBuildsEnabledList = []string{
-		"com.android.adbd",
-		"adbd_test",
-		"adb_crypto_test",
-		"adb_pairing_auth_test",
-		"adb_pairing_connection_test",
-		"adb_tls_connection_test",
-	}
+	StagingMixedBuildsEnabledList = []string{}
 )
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 9ff6b52..8c34c92 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -32,6 +32,7 @@
 	"android/soong/starlark_fmt"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/metrics"
 
 	"android/soong/bazel"
 )
@@ -45,11 +46,14 @@
 		CommandDeps: []string{"${bazelBuildRunfilesTool}"},
 	}, "outDir")
 	allowedBazelEnvironmentVars = []string{
+		// clang-tidy
 		"ALLOW_LOCAL_TIDY_TRUE",
 		"DEFAULT_TIDY_HEADER_DIRS",
 		"TIDY_TIMEOUT",
 		"WITH_TIDY",
 		"WITH_TIDY_FLAGS",
+		"TIDY_EXTERNAL_VENDOR",
+
 		"SKIP_ABI_CHECKS",
 		"UNSAFE_DISABLE_APEX_ALLOWED_DEPS_CHECK",
 		"AUTO_ZERO_INITIALIZE",
@@ -132,6 +136,10 @@
 	return fmt.Sprintf("cquery(%s,%s,%s)", c.label, c.requestType.Name(), c.configKey)
 }
 
+type invokeBazelContext interface {
+	GetEventHandler() *metrics.EventHandler
+}
+
 // BazelContext is a context object useful for interacting with Bazel during
 // the course of a build. Use of Bazel to evaluate part of the build graph
 // is referred to as a "mixed build". (Some modules are managed by Soong,
@@ -168,7 +176,7 @@
 	// Issues commands to Bazel to receive results for all cquery requests
 	// queued in the BazelContext. The ctx argument is optional and is only
 	// used for performance data collection
-	InvokeBazel(config Config, ctx *Context) error
+	InvokeBazel(config Config, ctx invokeBazelContext) error
 
 	// Returns true if Bazel handling is enabled for the module with the given name.
 	// Note that this only implies "bazel mixed build" allowlisting. The caller
@@ -188,7 +196,7 @@
 
 type bazelRunner interface {
 	createBazelCommand(config Config, paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) *exec.Cmd
-	issueBazelCommand(bazelCmd *exec.Cmd) (output string, errorMessage string, error error)
+	issueBazelCommand(bazelCmd *exec.Cmd, eventHandler *metrics.EventHandler) (output string, errorMessage string, error error)
 }
 
 type bazelPaths struct {
@@ -296,7 +304,7 @@
 	return result, nil
 }
 
-func (m MockBazelContext) InvokeBazel(_ Config, _ *Context) error {
+func (m MockBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
 	panic("unimplemented")
 }
 
@@ -414,7 +422,7 @@
 	panic("implement me")
 }
 
-func (n noopBazelContext) InvokeBazel(_ Config, _ *Context) error {
+func (n noopBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
 	panic("unimplemented")
 }
 
@@ -592,7 +600,7 @@
 	return cmd
 }
 
-func (r *mockBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd) (string, string, error) {
+func (r *mockBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd, _ *metrics.EventHandler) (string, string, error) {
 	if command, ok := r.tokens[bazelCmd]; ok {
 		return r.bazelCommandResults[command], "", nil
 	}
@@ -605,7 +613,9 @@
 // Returns (stdout, stderr, error). The first and second return values are strings
 // containing the stdout and stderr of the run command, and an error is returned if
 // the invocation returned an error code.
-func (r *builtinBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd) (string, string, error) {
+func (r *builtinBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd, eventHandler *metrics.EventHandler) (string, string, error) {
+	eventHandler.Begin("bazel command")
+	defer eventHandler.End("bazel command")
 	stderr := &bytes.Buffer{}
 	bazelCmd.Stderr = stderr
 	if output, err := bazelCmd.Output(); err != nil {
@@ -982,11 +992,10 @@
 
 // Issues commands to Bazel to receive results for all cquery requests
 // queued in the BazelContext.
-func (context *mixedBuildBazelContext) InvokeBazel(config Config, ctx *Context) error {
-	if ctx != nil {
-		ctx.EventHandler.Begin("bazel")
-		defer ctx.EventHandler.End("bazel")
-	}
+func (context *mixedBuildBazelContext) InvokeBazel(config Config, ctx invokeBazelContext) error {
+	eventHandler := ctx.GetEventHandler()
+	eventHandler.Begin("bazel")
+	defer eventHandler.End("bazel")
 
 	if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" {
 		if err := os.MkdirAll(metricsDir, 0777); err != nil {
@@ -1009,11 +1018,10 @@
 	return nil
 }
 
-func (context *mixedBuildBazelContext) runCquery(config Config, ctx *Context) error {
-	if ctx != nil {
-		ctx.EventHandler.Begin("cquery")
-		defer ctx.EventHandler.End("cquery")
-	}
+func (context *mixedBuildBazelContext) runCquery(config Config, ctx invokeBazelContext) error {
+	eventHandler := ctx.GetEventHandler()
+	eventHandler.Begin("cquery")
+	defer eventHandler.End("cquery")
 	soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
 	mixedBuildsPath := filepath.Join(soongInjectionPath, "mixed_builds")
 	if _, err := os.Stat(mixedBuildsPath); os.IsNotExist(err) {
@@ -1038,7 +1046,7 @@
 
 	cqueryCommandWithFlag := context.createBazelCommand(config, context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
 		"--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath))
-	cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag)
+	cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag, eventHandler)
 	if cqueryErr != nil {
 		return cqueryErr
 	}
@@ -1072,11 +1080,10 @@
 	return nil
 }
 
-func (context *mixedBuildBazelContext) runAquery(config Config, ctx *Context) error {
-	if ctx != nil {
-		ctx.EventHandler.Begin("aquery")
-		defer ctx.EventHandler.End("aquery")
-	}
+func (context *mixedBuildBazelContext) runAquery(config Config, ctx invokeBazelContext) error {
+	eventHandler := ctx.GetEventHandler()
+	eventHandler.Begin("aquery")
+	defer eventHandler.End("aquery")
 	// Issue an aquery command to retrieve action information about the bazel build tree.
 	//
 	// Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
@@ -1102,23 +1109,22 @@
 		}
 	}
 	aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
-		extraFlags...))
+		extraFlags...), eventHandler)
 	if err != nil {
 		return err
 	}
-	context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
+	context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput), eventHandler)
 	return err
 }
 
-func (context *mixedBuildBazelContext) generateBazelSymlinks(config Config, ctx *Context) error {
-	if ctx != nil {
-		ctx.EventHandler.Begin("symlinks")
-		defer ctx.EventHandler.End("symlinks")
-	}
+func (context *mixedBuildBazelContext) generateBazelSymlinks(config Config, ctx invokeBazelContext) error {
+	eventHandler := ctx.GetEventHandler()
+	eventHandler.Begin("symlinks")
+	defer eventHandler.End("symlinks")
 	// Issue a build command of the phony root to generate symlink forests for dependencies of the
 	// Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
 	// but some of symlinks may be required to resolve source dependencies of the build.
-	_, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd))
+	_, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd), eventHandler)
 	return err
 }
 
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index d971802..4a4ecb5 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -11,11 +11,18 @@
 	"android/soong/bazel/cquery"
 	analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
 
+	"github.com/google/blueprint/metrics"
 	"google.golang.org/protobuf/proto"
 )
 
 var testConfig = TestConfig("out", nil, "", nil)
 
+type testInvokeBazelContext struct{}
+
+func (t *testInvokeBazelContext) GetEventHandler() *metrics.EventHandler {
+	return &metrics.EventHandler{}
+}
+
 func TestRequestResultsAfterInvokeBazel(t *testing.T) {
 	label := "@//foo:bar"
 	cfg := configKey{"arm64_armv8-a", Android}
@@ -23,7 +30,7 @@
 		bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
 	})
 	bazelContext.QueueBazelRequest(label, cquery.GetOutputFiles, cfg)
-	err := bazelContext.InvokeBazel(testConfig, nil)
+	err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
 	if err != nil {
 		t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
 	}
@@ -37,7 +44,7 @@
 
 func TestInvokeBazelWritesBazelFiles(t *testing.T) {
 	bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
-	err := bazelContext.InvokeBazel(testConfig, nil)
+	err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
 	if err != nil {
 		t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
 	}
@@ -118,7 +125,7 @@
 		bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
 			bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
 
-		err = bazelContext.InvokeBazel(testConfig, nil)
+		err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
 		if err != nil {
 			t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
 		}
@@ -197,7 +204,7 @@
 func verifyExtraFlags(t *testing.T, config Config, expected string) string {
 	bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
 
-	err := bazelContext.InvokeBazel(config, nil)
+	err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
 	if err != nil {
 		t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
 	}
diff --git a/android/config.go b/android/config.go
index bb3cc97..c0f84c8 100644
--- a/android/config.go
+++ b/android/config.go
@@ -727,6 +727,10 @@
 	return value == "0" || value == "n" || value == "no" || value == "off" || value == "false"
 }
 
+func (c *config) TargetsJava17() bool {
+	return c.IsEnvTrue("EXPERIMENTAL_TARGET_JAVA_VERSION_17")
+}
+
 // EnvDeps returns the environment variables this build depends on. The first
 // call to this function blocks future reads from the environment.
 func (c *config) EnvDeps() map[string]string {
diff --git a/android/mutator.go b/android/mutator.go
index 4e55609..4dacb8d 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -709,24 +709,29 @@
 // module and returns it as a list of keyed tags.
 func ApexAvailableTags(mod Module) bazel.StringListAttribute {
 	attr := bazel.StringListAttribute{}
-	tags := []string{}
 	// Transform specific attributes into tags.
 	if am, ok := mod.(ApexModule); ok {
 		// TODO(b/218841706): hidl_interface has the apex_available prop, but it's
 		// defined directly as a prop and not via ApexModule, so this doesn't
 		// pick those props up.
-		// TODO(b/260694842): This does not pick up aidl_interface.backend.ndk.apex_available.
-		for _, a := range am.apexModuleBase().ApexAvailable() {
-			tags = append(tags, "apex_available="+a)
-		}
-	}
-	if len(tags) > 0 {
-		// This avoids creating a tags attr with an empty list if there are no tags.
-		attr.Value = tags
+		attr.Value = ConvertApexAvailableToTags(am.apexModuleBase().ApexAvailable())
 	}
 	return attr
 }
 
+func ConvertApexAvailableToTags(apexAvailable []string) []string {
+	if len(apexAvailable) == 0 {
+		// We need nil specifically to make bp2build not add the tags property at all,
+		// instead of adding it with an empty list
+		return nil
+	}
+	result := make([]string, 0, len(apexAvailable))
+	for _, a := range apexAvailable {
+		result = append(result, "apex_available="+a)
+	}
+	return result
+}
+
 func (t *topDownMutatorContext) createBazelTargetModule(
 	bazelProps bazel.BazelTargetModuleProperties,
 	commonAttrs CommonAttributes,
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 21eebd2..dbdfa33 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"reflect"
 	"strings"
 	"testing"
 
@@ -267,3 +268,22 @@
 		FixtureWithRootAndroidBp(`test {name: "foo"}`),
 	).RunTest(t)
 }
+
+func TestConvertApexAvailableToTags(t *testing.T) {
+	input := []string{
+		"com.android.adbd",
+		"//apex_available:platform",
+	}
+	actual := ConvertApexAvailableToTags(input)
+	expected := []string{
+		"apex_available=com.android.adbd",
+		"apex_available=//apex_available:platform",
+	}
+	if !reflect.DeepEqual(actual, expected) {
+		t.Errorf("Expected: %v, actual: %v", expected, actual)
+	}
+
+	if ConvertApexAvailableToTags(nil) != nil {
+		t.Errorf("Expected providing nil to return nil")
+	}
+}
diff --git a/android/paths.go b/android/paths.go
index 6c3009f..eaa6a8d 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1709,10 +1709,10 @@
 func pathForInstall(ctx PathContext, os OsType, arch ArchType, partition string, debug bool,
 	pathComponents ...string) InstallPath {
 
-	var partionPaths []string
+	var partitionPaths []string
 
 	if os.Class == Device {
-		partionPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
+		partitionPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
 	} else {
 		osName := os.String()
 		if os == Linux {
@@ -1734,21 +1734,21 @@
 		if os.Class == Host && (arch == X86_64 || arch == Common) {
 			archName = "x86"
 		}
-		partionPaths = []string{"host", osName + "-" + archName, partition}
+		partitionPaths = []string{"host", osName + "-" + archName, partition}
 	}
 	if debug {
-		partionPaths = append([]string{"debug"}, partionPaths...)
+		partitionPaths = append([]string{"debug"}, partitionPaths...)
 	}
 
-	partionPath, err := validatePath(partionPaths...)
+	partitionPath, err := validatePath(partitionPaths...)
 	if err != nil {
 		reportPathError(ctx, err)
 	}
 
 	base := InstallPath{
-		basePath:     basePath{partionPath, ""},
+		basePath:     basePath{partitionPath, ""},
 		soongOutDir:  ctx.Config().soongOutDir,
-		partitionDir: partionPath,
+		partitionDir: partitionPath,
 		partition:    partition,
 	}
 
diff --git a/android/variable.go b/android/variable.go
index e714fc4..f7ac7d6 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -64,6 +64,12 @@
 			Enabled *bool `android:"arch_variant"`
 		} `android:"arch_variant"`
 
+		// similar to `Unbundled_build`, but `Always_use_prebuilt_sdks` means that it uses prebuilt
+		// sdk specifically.
+		Always_use_prebuilt_sdks struct {
+			Enabled *bool `android:"arch_variant"`
+		} `android:"arch_variant"`
+
 		Malloc_not_svelte struct {
 			Cflags              []string `android:"arch_variant"`
 			Shared_libs         []string `android:"arch_variant"`
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index f646742..61058df 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -166,10 +166,9 @@
 		}
 	} else {
 		llvmStrip := config.ClangPath(ctx, "bin/llvm-strip")
-		llvmLib64 := config.ClangPath(ctx, "lib64/libc++.so.1")
-		llvmLib := config.ClangPath(ctx, "lib/libc++.so.1")
+		llvmLib := config.ClangPath(ctx, "lib/x86_64-unknown-linux-gnu/libc++.so.1")
 		for _, strip := range s.properties.Strip_files {
-			cmd := builder.Command().Tool(llvmStrip).ImplicitTool(llvmLib64).ImplicitTool(llvmLib)
+			cmd := builder.Command().Tool(llvmStrip).ImplicitTool(llvmLib)
 			if !ctx.Windows() {
 				cmd.Flag("-x")
 			}
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 6faed70..1581949 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -55,17 +55,17 @@
 			   touch ${out};
 			else
 				echo -e "\n******************************";
-				echo "ERROR: go/apex-allowed-deps-error";
+				echo "ERROR: go/apex-allowed-deps-error contains more information";
 				echo "******************************";
 				echo "Detected changes to allowed dependencies in updatable modules.";
 				echo "To fix and update packages/modules/common/build/allowed_deps.txt, please run:";
 				echo -e "$$ (croot && packages/modules/common/build/update-apex-allowed-deps.sh)\n";
 				echo "When submitting the generated CL, you must include the following information";
 				echo "in the commit message if you are adding a new dependency:";
-				echo "Apex-Size-Increase:";
-				echo "Previous-Platform-Support:";
-				echo "Aosp-First:";
-				echo "Test-Info:";
+				echo "Apex-Size-Increase: Expected binary size increase for affected APEXes (or the size of the .jar / .so file of the new library)";
+				echo "Previous-Platform-Support: Are the maintainers of the new dependency committed to supporting previous platform releases?";
+				echo "Aosp-First: Is the new dependency being developed AOSP-first or internal?";
+				echo "Test-Info: What’s the testing strategy for the new dependency? Does it have its own tests, and are you adding integration tests? How/when are the tests run?";
 				echo "You do not need OWNERS approval to submit the change, but mainline-modularization@";
 				echo "will periodically review additions and may require changes.";
 				echo -e "******************************\n";
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 80cf70a..6af472a 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -23,9 +23,11 @@
 	"sort"
 	"strings"
 
+	analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+
+	"github.com/google/blueprint/metrics"
 	"github.com/google/blueprint/proptools"
 	"google.golang.org/protobuf/proto"
-	analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
 )
 
 type artifactId int
@@ -313,7 +315,7 @@
 // action graph, as described by the given action graph json proto.
 // BuildStatements are one-to-one with actions in the given action graph, and AqueryDepsets
 // are one-to-one with Bazel's depSetOfFiles objects.
-func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, []AqueryDepset, error) {
+func AqueryBuildStatements(aqueryJsonProto []byte, eventHandler *metrics.EventHandler) ([]BuildStatement, []AqueryDepset, error) {
 	aqueryProto := &analysis_v2_proto.ActionGraphContainer{}
 	err := proto.Unmarshal(aqueryJsonProto, aqueryProto)
 	if err != nil {
@@ -387,74 +389,92 @@
 				ParentId: pathFragmentId(protoPathFragments.ParentId)})
 
 	}
-	aqueryHandler, err := newAqueryHandler(aqueryResult)
-	if err != nil {
-		return nil, nil, err
-	}
 
-	var buildStatements []BuildStatement
-	for _, actionEntry := range aqueryResult.Actions {
-		if shouldSkipAction(actionEntry) {
-			continue
-		}
-
-		var buildStatement BuildStatement
-		if actionEntry.isSymlinkAction() {
-			buildStatement, err = aqueryHandler.symlinkActionBuildStatement(actionEntry)
-		} else if actionEntry.isTemplateExpandAction() && len(actionEntry.Arguments) < 1 {
-			buildStatement, err = aqueryHandler.templateExpandActionBuildStatement(actionEntry)
-		} else if actionEntry.isFileWriteAction() {
-			buildStatement, err = aqueryHandler.fileWriteActionBuildStatement(actionEntry)
-		} else if actionEntry.isSymlinkTreeAction() {
-			buildStatement, err = aqueryHandler.symlinkTreeActionBuildStatement(actionEntry)
-		} else if len(actionEntry.Arguments) < 1 {
-			return nil, nil, fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic)
-		} else {
-			buildStatement, err = aqueryHandler.normalActionBuildStatement(actionEntry)
-		}
-
+	var aqueryHandler *aqueryArtifactHandler
+	{
+		eventHandler.Begin("init_handler")
+		defer eventHandler.End("init_handler")
+		aqueryHandler, err = newAqueryHandler(aqueryResult)
 		if err != nil {
 			return nil, nil, err
 		}
-		buildStatements = append(buildStatements, buildStatement)
+	}
+
+	var buildStatements []BuildStatement
+	{
+		eventHandler.Begin("build_statements")
+		defer eventHandler.End("build_statements")
+		for _, actionEntry := range aqueryResult.Actions {
+			if shouldSkipAction(actionEntry) {
+				continue
+			}
+
+			var buildStatement BuildStatement
+			if actionEntry.isSymlinkAction() {
+				buildStatement, err = aqueryHandler.symlinkActionBuildStatement(actionEntry)
+			} else if actionEntry.isTemplateExpandAction() && len(actionEntry.Arguments) < 1 {
+				buildStatement, err = aqueryHandler.templateExpandActionBuildStatement(actionEntry)
+			} else if actionEntry.isFileWriteAction() {
+				buildStatement, err = aqueryHandler.fileWriteActionBuildStatement(actionEntry)
+			} else if actionEntry.isSymlinkTreeAction() {
+				buildStatement, err = aqueryHandler.symlinkTreeActionBuildStatement(actionEntry)
+			} else if len(actionEntry.Arguments) < 1 {
+				err = fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic)
+			} else {
+				buildStatement, err = aqueryHandler.normalActionBuildStatement(actionEntry)
+			}
+
+			if err != nil {
+				return nil, nil, err
+			}
+			buildStatements = append(buildStatements, buildStatement)
+		}
 	}
 
 	depsetsByHash := map[string]AqueryDepset{}
 	var depsets []AqueryDepset
-	for _, aqueryDepset := range aqueryHandler.depsetIdToAqueryDepset {
-		if prevEntry, hasKey := depsetsByHash[aqueryDepset.ContentHash]; hasKey {
-			// Two depsets collide on hash. Ensure that their contents are identical.
-			if !reflect.DeepEqual(aqueryDepset, prevEntry) {
-				return nil, nil, fmt.Errorf("two different depsets have the same hash: %v, %v", prevEntry, aqueryDepset)
+	{
+		eventHandler.Begin("depsets")
+		defer eventHandler.End("depsets")
+		for _, aqueryDepset := range aqueryHandler.depsetIdToAqueryDepset {
+			if prevEntry, hasKey := depsetsByHash[aqueryDepset.ContentHash]; hasKey {
+				// Two depsets collide on hash. Ensure that their contents are identical.
+				if !reflect.DeepEqual(aqueryDepset, prevEntry) {
+					return nil, nil, fmt.Errorf("two different depsets have the same hash: %v, %v", prevEntry, aqueryDepset)
+				}
+			} else {
+				depsetsByHash[aqueryDepset.ContentHash] = aqueryDepset
+				depsets = append(depsets, aqueryDepset)
 			}
-		} else {
-			depsetsByHash[aqueryDepset.ContentHash] = aqueryDepset
-			depsets = append(depsets, aqueryDepset)
 		}
 	}
 
-	// Build Statements and depsets must be sorted by their content hash to
-	// preserve determinism between builds (this will result in consistent ninja file
-	// output). Note they are not sorted by their original IDs nor their Bazel ordering,
-	// as Bazel gives nondeterministic ordering / identifiers in aquery responses.
-	sort.Slice(buildStatements, func(i, j int) bool {
-		// For build statements, compare output lists. In Bazel, each output file
-		// may only have one action which generates it, so this will provide
-		// a deterministic ordering.
-		outputs_i := buildStatements[i].OutputPaths
-		outputs_j := buildStatements[j].OutputPaths
-		if len(outputs_i) != len(outputs_j) {
-			return len(outputs_i) < len(outputs_j)
-		}
-		if len(outputs_i) == 0 {
-			// No outputs for these actions, so compare commands.
-			return buildStatements[i].Command < buildStatements[j].Command
-		}
-		// There may be multiple outputs, but the output ordering is deterministic.
-		return outputs_i[0] < outputs_j[0]
+	eventHandler.Do("build_statement_sort", func() {
+		// Build Statements and depsets must be sorted by their content hash to
+		// preserve determinism between builds (this will result in consistent ninja file
+		// output). Note they are not sorted by their original IDs nor their Bazel ordering,
+		// as Bazel gives nondeterministic ordering / identifiers in aquery responses.
+		sort.Slice(buildStatements, func(i, j int) bool {
+			// For build statements, compare output lists. In Bazel, each output file
+			// may only have one action which generates it, so this will provide
+			// a deterministic ordering.
+			outputs_i := buildStatements[i].OutputPaths
+			outputs_j := buildStatements[j].OutputPaths
+			if len(outputs_i) != len(outputs_j) {
+				return len(outputs_i) < len(outputs_j)
+			}
+			if len(outputs_i) == 0 {
+				// No outputs for these actions, so compare commands.
+				return buildStatements[i].Command < buildStatements[j].Command
+			}
+			// There may be multiple outputs, but the output ordering is deterministic.
+			return outputs_i[0] < outputs_j[0]
+		})
 	})
-	sort.Slice(depsets, func(i, j int) bool {
-		return depsets[i].ContentHash < depsets[j].ContentHash
+	eventHandler.Do("depset_sort", func() {
+		sort.Slice(depsets, func(i, j int) bool {
+			return depsets[i].ContentHash < depsets[j].ContentHash
+		})
 	})
 	return buildStatements, depsets, nil
 }
@@ -651,17 +671,18 @@
 	return replacer.Replace(actionEntry.TemplateContent)
 }
 
+// \->\\, $->\$, `->\`, "->\", \n->\\n, '->'"'"'
+var commandLineArgumentReplacer = strings.NewReplacer(
+	`\`, `\\`,
+	`$`, `\$`,
+	"`", "\\`",
+	`"`, `\"`,
+	"\n", "\\n",
+	`'`, `'"'"'`,
+)
+
 func escapeCommandlineArgument(str string) string {
-	// \->\\, $->\$, `->\`, "->\", \n->\\n, '->'"'"'
-	replacer := strings.NewReplacer(
-		`\`, `\\`,
-		`$`, `\$`,
-		"`", "\\`",
-		`"`, `\"`,
-		"\n", "\\n",
-		`'`, `'"'"'`,
-	)
-	return replacer.Replace(str)
+	return commandLineArgumentReplacer.Replace(str)
 }
 
 func (a action) isSymlinkAction() bool {
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 4d1503e..c6b139e 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -21,8 +21,10 @@
 	"sort"
 	"testing"
 
-	"google.golang.org/protobuf/proto"
 	analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+
+	"github.com/google/blueprint/metrics"
+	"google.golang.org/protobuf/proto"
 )
 
 func TestAqueryMultiArchGenrule(t *testing.T) {
@@ -136,7 +138,7 @@
 		t.Error(err)
 		return
 	}
-	actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
+	actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
 	var expectedBuildStatements []BuildStatement
 	for _, arch := range []string{"arm", "arm64", "x86", "x86_64"} {
 		expectedBuildStatements = append(expectedBuildStatements,
@@ -195,7 +197,7 @@
 		t.Error(err)
 		return
 	}
-	_, _, err = AqueryBuildStatements(data)
+	_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
 	assertError(t, err, "undefined outputId 3")
 }
 
@@ -226,7 +228,7 @@
 		t.Error(err)
 		return
 	}
-	_, _, err = AqueryBuildStatements(data)
+	_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
 	assertError(t, err, "undefined (not even empty) input depsetId 2")
 }
 
@@ -257,7 +259,7 @@
 		t.Error(err)
 		return
 	}
-	_, _, err = AqueryBuildStatements(data)
+	_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
 	assertError(t, err, "undefined input depsetId 42 (referenced by depsetId 1)")
 }
 
@@ -288,7 +290,7 @@
 		t.Error(err)
 		return
 	}
-	_, _, err = AqueryBuildStatements(data)
+	_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
 	assertError(t, err, "undefined input artifactId 3")
 }
 
@@ -319,7 +321,7 @@
 		t.Error(err)
 		return
 	}
-	_, _, err = AqueryBuildStatements(data)
+	_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
 	assertError(t, err, "undefined path fragment id 3")
 }
 
@@ -352,7 +354,7 @@
 		t.Error(err)
 		return
 	}
-	actual, _, err := AqueryBuildStatements(data)
+	actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
 	if err != nil {
 		t.Errorf("Unexpected error %q", err)
 	}
@@ -402,7 +404,7 @@
 		t.Error(err)
 		return
 	}
-	_, _, err = AqueryBuildStatements(data)
+	_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
 	assertError(t, err, `found multiple potential depfiles "two.d", "other.d"`)
 }
 
@@ -483,7 +485,7 @@
 		t.Error(err)
 		return
 	}
-	actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
+	actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
 
 	expectedBuildStatements := []BuildStatement{
 		{
@@ -538,7 +540,7 @@
 		t.Error(err)
 		return
 	}
-	actual, _, err := AqueryBuildStatements(data)
+	actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
 	if err != nil {
 		t.Errorf("Unexpected error %q", err)
 	}
@@ -594,7 +596,7 @@
 		t.Error(err)
 		return
 	}
-	actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
+	actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
 	if len(actualDepsets) != 1 {
 		t.Errorf("expected 1 depset but found %#v", actualDepsets)
 		return
@@ -681,7 +683,7 @@
 		t.Error(err)
 		return
 	}
-	actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
+	actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
 	if len(actualDepsets) != 0 {
 		t.Errorf("expected 0 depsets but found %#v", actualDepsets)
 		return
@@ -748,7 +750,7 @@
 		t.Error(err)
 		return
 	}
-	actualBuildStatements, actualDepsets, err := AqueryBuildStatements(data)
+	actualBuildStatements, actualDepsets, err := AqueryBuildStatements(data, &metrics.EventHandler{})
 	if err != nil {
 		t.Errorf("Unexpected error %q", err)
 	}
@@ -845,7 +847,7 @@
 		t.Error(err)
 		return
 	}
-	actual, _, err := AqueryBuildStatements(data)
+	actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
 
 	if err != nil {
 		t.Errorf("Unexpected error %q", err)
@@ -894,7 +896,7 @@
 		t.Error(err)
 		return
 	}
-	actual, _, err := AqueryBuildStatements(data)
+	actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
 	if err != nil {
 		t.Errorf("Unexpected error %q", err)
 	}
@@ -940,7 +942,7 @@
 		t.Error(err)
 		return
 	}
-	_, _, err = AqueryBuildStatements(data)
+	_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
 	assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file" "other_file"], output ["symlink"]`)
 }
 
@@ -971,7 +973,7 @@
 		t.Error(err)
 		return
 	}
-	_, _, err = AqueryBuildStatements(data)
+	_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
 	assertError(t, err, "undefined outputId 2")
 }
 
@@ -1004,7 +1006,7 @@
 		t.Error(err)
 		return
 	}
-	actual, _, err := AqueryBuildStatements(data)
+	actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
 	if err != nil {
 		t.Errorf("Unexpected error %q", err)
 	}
@@ -1046,7 +1048,7 @@
 		t.Error(err)
 		return
 	}
-	_, _, err = AqueryBuildStatements(data)
+	_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
 	assertError(t, err, `Expect 1 output to template expand action, got: output []`)
 }
 
@@ -1074,7 +1076,7 @@
 		t.Error(err)
 		return
 	}
-	actual, _, err := AqueryBuildStatements(data)
+	actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
 	if err != nil {
 		t.Errorf("Unexpected error %q", err)
 	}
@@ -1111,7 +1113,7 @@
 		t.Error(err)
 		return
 	}
-	actual, _, err := AqueryBuildStatements(data)
+	actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
 	if err != nil {
 		t.Errorf("Unexpected error %q", err)
 	}
diff --git a/bp2build/java_sdk_library_conversion_test.go b/bp2build/java_sdk_library_conversion_test.go
new file mode 100644
index 0000000..9ce7446
--- /dev/null
+++ b/bp2build/java_sdk_library_conversion_test.go
@@ -0,0 +1,148 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+	"testing"
+
+	"android/soong/android"
+	"android/soong/java"
+)
+
+func runJavaSdkLibraryTestCaseWithRegistrationCtxFunc(t *testing.T, tc Bp2buildTestCase, registrationCtxFunc func(ctx android.RegistrationContext)) {
+	t.Helper()
+	(&tc).ModuleTypeUnderTest = "java_sdk_library"
+	(&tc).ModuleTypeUnderTestFactory = java.SdkLibraryFactory
+	RunBp2BuildTestCase(t, registrationCtxFunc, tc)
+}
+
+func runJavaSdkLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	runJavaSdkLibraryTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {})
+}
+
+func TestJavaSdkLibraryApiSurfaceGeneral(t *testing.T) {
+	runJavaSdkLibraryTestCase(t, Bp2buildTestCase{
+		Description: "limited java_sdk_library for api surfaces, general conversion",
+		Filesystem: map[string]string{
+			"build/soong/scripts/gen-java-current-api-files.sh": "",
+			"api/current.txt":               "",
+			"api/system-current.txt":        "",
+			"api/test-current.txt":          "",
+			"api/module-lib-current.txt":    "",
+			"api/system-server-current.txt": "",
+			"api/removed.txt":               "",
+			"api/system-removed.txt":        "",
+			"api/test-removed.txt":          "",
+			"api/module-lib-removed.txt":    "",
+			"api/system-server-removed.txt": "",
+		},
+		Blueprint: `java_sdk_library {
+    name: "java-sdk-lib",
+    srcs: ["a.java"],
+    public: {enabled: true},
+    system: {enabled: true},
+    test: {enabled: true},
+    module_lib: {enabled: true},
+    system_server: {enabled: true},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_sdk_library", "java-sdk-lib", AttrNameToString{
+				"public":        `"api/current.txt"`,
+				"system":        `"api/system-current.txt"`,
+				"test":          `"api/test-current.txt"`,
+				"module_lib":    `"api/module-lib-current.txt"`,
+				"system_server": `"api/system-server-current.txt"`,
+			}),
+		},
+	})
+}
+
+func TestJavaSdkLibraryApiSurfacePublicDefault(t *testing.T) {
+	runJavaSdkLibraryTestCase(t, Bp2buildTestCase{
+		Description: "limited java_sdk_library for api surfaces, public prop uses default value",
+		Filesystem: map[string]string{
+			"build/soong/scripts/gen-java-current-api-files.sh": "",
+			"api/current.txt":               "",
+			"api/system-current.txt":        "",
+			"api/test-current.txt":          "",
+			"api/module-lib-current.txt":    "",
+			"api/system-server-current.txt": "",
+			"api/removed.txt":               "",
+			"api/system-removed.txt":        "",
+			"api/test-removed.txt":          "",
+			"api/module-lib-removed.txt":    "",
+			"api/system-server-removed.txt": "",
+		},
+		Blueprint: `java_sdk_library {
+    name: "java-sdk-lib",
+    srcs: ["a.java"],
+    system: {enabled: false},
+    test: {enabled: false},
+    module_lib: {enabled: false},
+    system_server: {enabled: false},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_sdk_library", "java-sdk-lib", AttrNameToString{
+				"public": `"api/current.txt"`,
+			}),
+		},
+	})
+}
+
+func TestJavaSdkLibraryApiSurfacePublicNotEnabled(t *testing.T) {
+	runJavaSdkLibraryTestCase(t, Bp2buildTestCase{
+		Description: "limited java_sdk_library for api surfaces, public enable is false",
+		Filesystem: map[string]string{
+			"build/soong/scripts/gen-java-current-api-files.sh": "",
+			"api/current.txt": "",
+			"api/removed.txt": "",
+		},
+		Blueprint: `java_sdk_library {
+   name: "java-sdk-lib",
+   srcs: ["a.java"],
+   public: {enabled: false},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_sdk_library", "java-sdk-lib", AttrNameToString{}),
+		},
+	})
+}
+
+func TestJavaSdkLibraryApiSurfaceNoScopeIsSet(t *testing.T) {
+	runJavaSdkLibraryTestCase(t, Bp2buildTestCase{
+		Description: "limited java_sdk_library for api surfaces, none of the api scopes is set",
+		Filesystem: map[string]string{
+			"build/soong/scripts/gen-java-current-api-files.sh": "",
+			"api/current.txt":        "",
+			"api/system-current.txt": "",
+			"api/test-current.txt":   "",
+			"api/removed.txt":        "",
+			"api/system-removed.txt": "",
+			"api/test-removed.txt":   "",
+		},
+		Blueprint: `java_sdk_library {
+   name: "java-sdk-lib",
+   srcs: ["a.java"],
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_sdk_library", "java-sdk-lib", AttrNameToString{
+				"public": `"api/current.txt"`,
+				"system": `"api/system-current.txt"`,
+				"test":   `"api/test-current.txt"`,
+			}),
+		},
+	})
+}
diff --git a/cc/config/global.go b/cc/config/global.go
index 454a4db..05dc773 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -247,16 +247,11 @@
 	noOverride64GlobalCflags = []string{}
 
 	noOverrideExternalGlobalCflags = []string{
-		// http://b/148815709
 		"-Wno-sizeof-array-div",
-		// http://b/197240255
 		"-Wno-unused-but-set-variable",
 		"-Wno-unused-but-set-parameter",
-		// http://b/215753485
 		"-Wno-bitwise-instead-of-logical",
-		// http://b/232926688
 		"-Wno-misleading-indentation",
-		// http://b/241941550
 		"-Wno-array-parameter",
 	}
 
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 67208b2..b3619c8 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -35,7 +35,9 @@
 	}
 
 	riscv64Lldflags = append(riscv64Ldflags,
-		"-Wl,-z,max-page-size=4096")
+		"-Wl,-z,max-page-size=4096",
+		"-Wl,-plugin-opt,-emulated-tls=0",
+	)
 
 	riscv64Cppflags = []string{}
 
diff --git a/cc/lto_test.go b/cc/lto_test.go
index cee5aa3..4220f32 100644
--- a/cc/lto_test.go
+++ b/cc/lto_test.go
@@ -209,3 +209,33 @@
 	android.AssertStringDoesNotContain(t, "got flag for LTO in variant that doesn't expect it",
 		libFooWithoutLto.Args["ldFlags"], "-flto=thin")
 }
+
+func TestLtoDoesNotPropagateToRuntimeLibs(t *testing.T) {
+	t.Parallel()
+	bp := `
+	cc_library {
+		name: "runtime_libbar",
+		srcs: ["bar.c"],
+	}
+
+	cc_library {
+		name: "libfoo",
+		srcs: ["foo.c"],
+		runtime_libs: ["runtime_libbar"],
+		lto: {
+			thin: true,
+		},
+	}`
+
+	result := android.GroupFixturePreparers(
+		prepareForCcTest,
+	).RunTestWithBp(t, bp)
+
+	libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+	libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
+
+	android.AssertStringDoesContain(t, "missing flag for LTO in LTO enabled library",
+		libFoo.Args["ldFlags"], "-flto=thin")
+	android.AssertStringDoesNotContain(t, "got flag for LTO in runtime_lib",
+		libBar.Args["ldFlags"], "-flto=thin")
+}
diff --git a/java/config/config.go b/java/config/config.go
index 7c22076..293eb92 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -195,6 +195,7 @@
 	pctx.HostBinToolVariable("ManifestMergerCmd", "manifest-merger")
 
 	pctx.HostBinToolVariable("Class2NonSdkList", "class2nonsdklist")
+	pctx.HostBinToolVariable("MergeCsvCommand", "merge_csv")
 	pctx.HostBinToolVariable("HiddenAPI", "hiddenapi")
 
 	hostBinToolVariableWithSdkToolsPrebuilt("Aapt2Cmd", "aapt2")
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index cf9c7ad..c4fc65f 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -20,10 +20,17 @@
 	"android/soong/android"
 )
 
-var hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", blueprint.RuleParams{
-	Command:     "${config.Class2NonSdkList} --stub-api-flags ${stubAPIFlags} $in $outFlag $out",
-	CommandDeps: []string{"${config.Class2NonSdkList}"},
-}, "outFlag", "stubAPIFlags")
+var (
+	hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", blueprint.RuleParams{
+		Command:     "${config.Class2NonSdkList} --stub-api-flags ${stubAPIFlags} $in $outFlag $out",
+		CommandDeps: []string{"${config.Class2NonSdkList}"},
+	}, "outFlag", "stubAPIFlags")
+
+	hiddenAPIGenerateIndexRule = pctx.AndroidStaticRule("hiddenAPIGenerateIndex", blueprint.RuleParams{
+		Command:     "${config.MergeCsvCommand} --zip_input --key_field signature --output=$out $in",
+		CommandDeps: []string{"${config.MergeCsvCommand}"},
+	})
+)
 
 type hiddenAPI struct {
 	// True if the module containing this structure contributes to the hiddenapi information or has
@@ -216,14 +223,12 @@
 // created by the unsupported app usage annotation processor during compilation of the class
 // implementation jar.
 func buildRuleToGenerateIndex(ctx android.ModuleContext, desc string, classesJars android.Paths, indexCSV android.WritablePath) {
-	rule := android.NewRuleBuilder(pctx, ctx)
-	rule.Command().
-		BuiltTool("merge_csv").
-		Flag("--zip_input").
-		Flag("--key_field signature").
-		FlagWithOutput("--output=", indexCSV).
-		Inputs(classesJars)
-	rule.Build(desc, desc)
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        hiddenAPIGenerateIndexRule,
+		Description: desc,
+		Inputs:      classesJars,
+		Output:      indexCSV,
+	})
 }
 
 var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", blueprint.RuleParams{
diff --git a/java/java.go b/java/java.go
index f1600d9..c2fcccf 100644
--- a/java/java.go
+++ b/java/java.go
@@ -517,8 +517,14 @@
 		return normalizeJavaVersion(ctx, javaVersion)
 	} else if ctx.Device() {
 		return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion(ctx))
-	} else {
+	} else if ctx.Config().TargetsJava17() {
+		// Temporary experimental flag to be able to try and build with
+		// java version 17 options.  The flag, if used, just sets Java
+		// 17 as the default version, leaving any components that
+		// target an older version intact.
 		return JAVA_VERSION_17
+	} else {
+		return JAVA_VERSION_11
 	}
 }
 
@@ -1638,6 +1644,10 @@
 	// List of shared java libs that this module has dependencies to and
 	// should be passed as classpath in javac invocation
 	Libs []string
+
+	// List of java libs that this module has static dependencies to and will be
+	// passed in metalava invocation
+	Static_libs []string
 }
 
 func ApiLibraryFactory() android.Module {
@@ -1710,6 +1720,7 @@
 		ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
 	}
 	ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...)
+	ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...)
 }
 
 func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1729,6 +1740,7 @@
 
 	var srcFiles android.Paths
 	var classPaths android.Paths
+	var staticLibs android.Paths
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		tag := ctx.OtherModuleDependencyTag(dep)
 		switch tag {
@@ -1742,6 +1754,9 @@
 		case libTag:
 			provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
 			classPaths = append(classPaths, provider.HeaderJars...)
+		case staticLibTag:
+			provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+			staticLibs = append(staticLibs, provider.HeaderJars...)
 		}
 	})
 
@@ -1766,7 +1781,7 @@
 		FlagWithArg("-D ", stubsDir.String())
 
 	rule.Build("metalava", "metalava merged")
-
+	compiledStubs := android.PathForModuleOut(ctx, ctx.ModuleName(), "stubs.jar")
 	al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), "android.jar")
 
 	var flags javaBuilderFlags
@@ -1774,9 +1789,17 @@
 	flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
 	flags.classpath = classpath(classPaths)
 
-	TransformJavaToClasses(ctx, al.stubsJar, 0, android.Paths{},
+	TransformJavaToClasses(ctx, compiledStubs, 0, android.Paths{},
 		android.Paths{al.stubsSrcJar}, flags, android.Paths{})
 
+	builder := android.NewRuleBuilder(pctx, ctx)
+	builder.Command().
+		BuiltTool("merge_zips").
+		Output(al.stubsJar).
+		Inputs(android.Paths{compiledStubs}).
+		Inputs(staticLibs)
+	builder.Build("merge_zips", "merge jar files")
+
 	ctx.Phony(ctx.ModuleName(), al.stubsJar)
 
 	ctx.SetProvider(JavaInfoProvider, JavaInfo{
diff --git a/java/java_test.go b/java/java_test.go
index 21993ec..dc42e9e 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2128,6 +2128,80 @@
 	}
 }
 
+func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
+	provider_bp_a := `
+	java_api_contribution {
+		name: "foo1",
+		api_file: "foo1.txt",
+	}
+	`
+	provider_bp_b := `
+	java_api_contribution {
+		name: "foo2",
+		api_file: "foo2.txt",
+	}
+	`
+	lib_bp_a := `
+	java_library {
+		name: "lib1",
+		srcs: ["Lib.java"],
+	}
+	`
+	lib_bp_b := `
+	java_library {
+		name: "lib2",
+		srcs: ["Lib.java"],
+	}
+	`
+
+	ctx, _ := testJavaWithFS(t, `
+		java_api_library {
+			name: "bar1",
+			api_surface: "public",
+			api_contributions: ["foo1"],
+			static_libs: ["lib1"],
+		}
+
+		java_api_library {
+			name: "bar2",
+			api_surface: "system",
+			api_contributions: ["foo1", "foo2"],
+			static_libs: ["lib1", "lib2", "bar1"],
+		}
+		`,
+		map[string][]byte{
+			"a/Android.bp": []byte(provider_bp_a),
+			"b/Android.bp": []byte(provider_bp_b),
+			"c/Android.bp": []byte(lib_bp_a),
+			"c/Lib.java":   {},
+			"d/Android.bp": []byte(lib_bp_b),
+			"d/Lib.java":   {},
+		})
+
+	testcases := []struct {
+		moduleName        string
+		staticLibJarNames []string
+	}{
+		{
+			moduleName:        "bar1",
+			staticLibJarNames: []string{"lib1.jar"},
+		},
+		{
+			moduleName:        "bar2",
+			staticLibJarNames: []string{"lib1.jar", "lib2.jar", "bar1/android.jar"},
+		},
+	}
+	for _, c := range testcases {
+		m := ctx.ModuleForTests(c.moduleName, "android_common")
+		mergeZipsCommand := m.Rule("merge_zips").RuleParams.Command
+		for _, jarName := range c.staticLibJarNames {
+			if !strings.Contains(mergeZipsCommand, jarName) {
+				t.Errorf("merge_zips command does not contain expected jar %s", jarName)
+			}
+		}
+	}
+}
+
 func TestTradefedOptions(t *testing.T) {
 	result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
 java_test_host {
diff --git a/java/robolectric.go b/java/robolectric.go
index 68f27b8..008b8b1 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -302,6 +302,9 @@
 		func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 			entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
 			entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", "robolectric-tests")
+			if r.testConfig != nil {
+				entries.SetPath("LOCAL_FULL_TEST_CONFIG", r.testConfig)
+			}
 		})
 
 	entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
diff --git a/java/sdk.go b/java/sdk.go
index 10ae3f6..b0da5af 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -57,10 +57,14 @@
 		return JAVA_VERSION_8
 	} else if sdk.FinalOrFutureInt() <= 31 {
 		return JAVA_VERSION_9
-	} else if sdk.FinalOrFutureInt() <= 32 {
-		return JAVA_VERSION_11
-	} else {
+	} else if ctx.Config().TargetsJava17() {
+		// Temporary experimental flag to be able to try and build with
+		// java version 17 options.  The flag, if used, just sets Java
+		// 17 as the default version, leaving any components that
+		// target an older version intact.
 		return JAVA_VERSION_17
+	} else {
+		return JAVA_VERSION_11
 	}
 }
 
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 591ec05..c168c53 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -28,6 +28,7 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/bazel"
 	"android/soong/dexpreopt"
 )
 
@@ -546,14 +547,14 @@
 
 	// The properties specific to the module-lib api scope
 	//
-	// Unless explicitly specified by using test.enabled the module-lib api scope is
-	// disabled by default.
+	// Unless explicitly specified by using module_lib.enabled the module_lib api
+	// scope is disabled by default.
 	Module_lib ApiScopeProperties
 
 	// The properties specific to the system-server api scope
 	//
-	// Unless explicitly specified by using test.enabled the module-lib api scope is
-	// disabled by default.
+	// Unless explicitly specified by using system_server.enabled the
+	// system_server api scope is disabled by default.
 	System_server ApiScopeProperties
 
 	// Determines if the stubs are preferred over the implementation library
@@ -1163,6 +1164,8 @@
 type SdkLibrary struct {
 	Library
 
+	android.BazelModuleBase
+
 	sdkLibraryProperties sdkLibraryProperties
 
 	// Map from api scope to the scope specific property structure.
@@ -2081,9 +2084,48 @@
 			module.CreateInternalModules(ctx)
 		}
 	})
+	android.InitBazelModule(module)
 	return module
 }
 
+type bazelSdkLibraryAttributes struct {
+	Public        bazel.StringAttribute
+	System        bazel.StringAttribute
+	Test          bazel.StringAttribute
+	Module_lib    bazel.StringAttribute
+	System_server bazel.StringAttribute
+}
+
+// java_sdk_library bp2build converter
+func (module *SdkLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	if ctx.ModuleType() != "java_sdk_library" {
+		return
+	}
+
+	nameToAttr := make(map[string]bazel.StringAttribute)
+
+	for _, scope := range module.getGeneratedApiScopes(ctx) {
+		apiSurfaceFile := path.Join(module.getApiDir(), scope.apiFilePrefix+"current.txt")
+		var scopeStringAttribute bazel.StringAttribute
+		scopeStringAttribute.SetValue(apiSurfaceFile)
+		nameToAttr[scope.name] = scopeStringAttribute
+	}
+
+	attrs := bazelSdkLibraryAttributes{
+		Public:        nameToAttr["public"],
+		System:        nameToAttr["system"],
+		Test:          nameToAttr["test"],
+		Module_lib:    nameToAttr["module-lib"],
+		System_server: nameToAttr["system-server"],
+	}
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "java_sdk_library",
+		Bzl_load_location: "//build/bazel/rules/java:sdk_library.bzl",
+	}
+
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, &attrs)
+}
+
 //
 // SDK library prebuilts
 //
diff --git a/rust/builder.go b/rust/builder.go
index 7dd9dd2..5b5c993 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -399,7 +399,7 @@
 	// Silence warnings about renamed lints for third-party crates
 	modulePath := android.PathForModuleSrc(ctx).String()
 	if android.IsThirdPartyPath(modulePath) {
-		rustdocFlags = append(rustdocFlags, " -A renamed_and_removed_lints")
+		rustdocFlags = append(rustdocFlags, " -A warnings")
 	}
 
 	// Yes, the same out directory is used simultaneously by all rustdoc builds.
diff --git a/rust/compiler.go b/rust/compiler.go
index 8ec42f0..31acd49 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -208,6 +208,10 @@
 	panic("baseCompiler does not implement SetDisabled()")
 }
 
+func (compiler *baseCompiler) noStdlibs() bool {
+	return Bool(compiler.Properties.No_stdlibs)
+}
+
 func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath {
 	panic("baseCompiler does not implement coverageOutputZipPath()")
 }
diff --git a/rust/config/global.go b/rust/config/global.go
index 50ac1f7..ef428b8 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
 var pctx = android.NewPackageContext("android/soong/rust/config")
 
 var (
-	RustDefaultVersion = "1.65.0.p1"
+	RustDefaultVersion = "1.66.1"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2021"
 	Stdlibs            = []string{
diff --git a/rust/coverage.go b/rust/coverage.go
index 5ea481f..bc6504d 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -21,6 +21,7 @@
 )
 
 var CovLibraryName = "libprofile-clang-extras"
+var ProfilerBuiltins = "libprofiler_builtins.rust_sysroot"
 
 // Add '%c' to default specifier after we resolve http://b/210012154
 const profileInstrFlag = "-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw"
@@ -41,6 +42,11 @@
 		ctx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
 		}, cc.CoverageDepTag, CovLibraryName)
+
+		// no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
+		if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() {
+			ctx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}, rlibDepTag, ProfilerBuiltins)
+		}
 	}
 
 	return deps
@@ -60,6 +66,13 @@
 		flags.LinkFlags = append(flags.LinkFlags,
 			profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
 		deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
+
+		// no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
+		if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() {
+			profiler_builtins := ctx.GetDirectDepWithTag(ProfilerBuiltins, rlibDepTag).(*Module)
+			deps.RLibs = append(deps.RLibs, RustLibrary{Path: profiler_builtins.OutputFile().Path(), CrateName: profiler_builtins.CrateName()})
+		}
+
 		if cc.EnableContinuousCoverage(ctx) {
 			flags.RustFlags = append(flags.RustFlags, "-C llvm-args=--runtime-counter-relocation")
 			flags.LinkFlags = append(flags.LinkFlags, "-Wl,-mllvm,-runtime-counter-relocation")
diff --git a/rust/rust.go b/rust/rust.go
index 67e0d7c..e4cf671 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -490,6 +490,7 @@
 	SetDisabled()
 
 	stdLinkage(ctx *depsContext) RustLinkage
+	noStdlibs() bool
 
 	unstrippedOutputFilePath() android.Path
 	strippedOutputFilePath() android.OptionalPath
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index f3bad73..fda5ca0 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -803,7 +803,6 @@
   setup
 
   mkdir -p "a/${GENERATED_BUILD_FILE_NAME}"
-  touch a/a.txt
   cat > a/Android.bp <<EOF
 filegroup {
   name: "a",
@@ -813,7 +812,6 @@
 EOF
 
   mkdir -p "b/${GENERATED_BUILD_FILE_NAME}"
-  touch b/b.txt
   cat > b/Android.bp <<EOF
 filegroup {
   name: "b",
@@ -826,8 +824,8 @@
     fail "Build should have failed"
   fi
 
-  grep -q "a/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for a/${GENERATED_BUILD_FILE_NAME} not found"
-  grep -q -v "b/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for b/${GENERATED_BUILD_FILE_NAME} found but not expected"
+  # we should expect at least one error
+  grep -q -E "(a|b)/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for ${GENERATED_BUILD_FILE_NAME} not found"
 }
 
 function test_bp2build_back_and_forth_null_build {