Merge "Remove SettingsOverlay* from legacyCorePlatformApiModules"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 16f144e..2e4068d 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -166,6 +166,7 @@
 		"external/minijail":                      Bp2BuildDefaultTrueRecursively,
 		"external/objenesis":                     Bp2BuildDefaultTrueRecursively,
 		"external/openscreen":                    Bp2BuildDefaultTrueRecursively,
+		"external/ow2-asm":                       Bp2BuildDefaultTrueRecursively,
 		"external/pcre":                          Bp2BuildDefaultTrueRecursively,
 		"external/protobuf":                      Bp2BuildDefaultTrueRecursively,
 		"external/python/six":                    Bp2BuildDefaultTrueRecursively,
@@ -347,6 +348,7 @@
 		".":/*recursive = */ false,
 
 		"build/bazel":/* recursive = */ true,
+		"build/make/core":/* recursive = */ false,
 		"build/bazel_common_rules":/* recursive = */ true,
 		// build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
 		"build/make/tools":/* recursive = */ false,
@@ -382,6 +384,8 @@
 		"prebuilts/sdk":/* recursive = */ false,
 		"prebuilts/sdk/tools":/* recursive = */ false,
 		"prebuilts/r8":/* recursive = */ false,
+
+		"tools/asuite/atest/":/* recursive = */ true,
 	}
 
 	Bp2buildModuleAlwaysConvertList = []string{
@@ -647,6 +651,10 @@
 		"libcodec2_soft_avcenc",
 		"libcodec2_soft_aacdec",
 		"libcodec2_soft_common",
+
+		// kotlin srcs in java libs
+		"CtsPkgInstallerConstants",
+		"kotlinx_atomicfu",
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
diff --git a/android/arch.go b/android/arch.go
index 086e945..6acf9cf 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -16,6 +16,7 @@
 
 import (
 	"encoding"
+	"encoding/json"
 	"fmt"
 	"reflect"
 	"runtime"
@@ -1681,10 +1682,10 @@
 
 // archConfig describes a built-in configuration.
 type archConfig struct {
-	arch        string
-	archVariant string
-	cpuVariant  string
-	abi         []string
+	Arch        string   `json:"arch"`
+	ArchVariant string   `json:"arch_variant"`
+	CpuVariant  string   `json:"cpu_variant"`
+	Abi         []string `json:"abis"`
 }
 
 // getNdkAbisConfig returns the list of archConfigs that are used for building
@@ -1713,8 +1714,8 @@
 	var ret []Target
 
 	for _, config := range archConfigs {
-		arch, err := decodeArch(Android, config.arch, &config.archVariant,
-			&config.cpuVariant, config.abi)
+		arch, err := decodeArch(Android, config.Arch, &config.ArchVariant,
+			&config.CpuVariant, config.Abi)
 		if err != nil {
 			return nil, err
 		}
@@ -2284,6 +2285,14 @@
 	return starlark_fmt.PrintDict(valDict, 0)
 }
 
+func printArchConfigList(arches []archConfig) string {
+	jsonOut, err := json.MarshalIndent(arches, "", starlark_fmt.Indention(1))
+	if err != nil {
+		panic(fmt.Errorf("Error converting arch configs %#v to json: %q", arches, err))
+	}
+	return fmt.Sprintf("json.decode('''%s''')", string(jsonOut))
+}
+
 func StarlarkArchConfigurations() string {
 	return fmt.Sprintf(`
 _arch_to_variants = %s
@@ -2294,13 +2303,21 @@
 
 _android_arch_feature_for_arch_variant = %s
 
+_aml_arches = %s
+
+_ndk_arches = %s
+
 arch_to_variants = _arch_to_variants
 arch_to_cpu_variants = _arch_to_cpu_variants
 arch_to_features = _arch_to_features
 android_arch_feature_for_arch_variants = _android_arch_feature_for_arch_variant
+aml_arches = _aml_arches
+ndk_arches = _ndk_arches
 `, printArchTypeStarlarkDict(archVariants),
 		printArchTypeStarlarkDict(cpuVariants),
 		printArchTypeStarlarkDict(archFeatures),
 		printArchTypeNestedStarlarkDict(androidArchFeatureMap),
+		printArchConfigList(getAmlAbisConfig()),
+		printArchConfigList(getNdkAbisConfig()),
 	)
 }
diff --git a/android/bazel.go b/android/bazel.go
index d30cb80..60989f6 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -341,16 +341,19 @@
 		// Exact dir match
 		return true
 	}
+	var i int
 	// Check if subtree match
-	for prefix, recursive := range a.keepExistingBuildFile {
-		if recursive {
-			if strings.HasPrefix(dir, prefix+"/") {
-				return true
-			}
+	for {
+		j := strings.Index(dir[i:], "/")
+		if j == -1 {
+			return false //default
+		}
+		prefix := dir[0 : i+j]
+		i = i + j + 1 // skip the "/"
+		if recursive, ok := a.keepExistingBuildFile[prefix]; ok && recursive {
+			return true
 		}
 	}
-	// Default
-	return false
 }
 
 var bp2BuildAllowListKey = NewOnceKey("Bp2BuildAllowlist")
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index eec78d2..e2751d6 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -150,8 +150,9 @@
 	// ** end Cquery Results Retrieval Functions
 
 	// Issues commands to Bazel to receive results for all cquery requests
-	// queued in the BazelContext.
-	InvokeBazel(config Config) error
+	// queued in the BazelContext. The ctx argument is optional and is only
+	// used for performance data collection
+	InvokeBazel(config Config, ctx *Context) 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
@@ -259,7 +260,7 @@
 	return result, nil
 }
 
-func (m MockBazelContext) InvokeBazel(_ Config) error {
+func (m MockBazelContext) InvokeBazel(_ Config, ctx *Context) error {
 	panic("unimplemented")
 }
 
@@ -355,7 +356,7 @@
 	panic("implement me")
 }
 
-func (n noopBazelContext) InvokeBazel(_ Config) error {
+func (n noopBazelContext) InvokeBazel(_ Config, ctx *Context) error {
 	panic("unimplemented")
 }
 
@@ -865,51 +866,78 @@
 	return filepath.Dir(p.soongOutDir)
 }
 
+const buildrootLabel = "@soong_injection//mixed_builds:buildroot"
+
+var (
+	cqueryCmd = bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)}
+	aqueryCmd = bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
+	buildCmd  = bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
+)
+
 // Issues commands to Bazel to receive results for all cquery requests
 // queued in the BazelContext.
-func (context *bazelContext) InvokeBazel(config Config) error {
+func (context *bazelContext) InvokeBazel(config Config, ctx *Context) error {
+	if ctx != nil {
+		ctx.EventHandler.Begin("bazel")
+		defer ctx.EventHandler.End("bazel")
+	}
+
+	if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" {
+		if err := os.MkdirAll(metricsDir, 0777); err != nil {
+			return err
+		}
+	}
 	context.results = make(map[cqueryKey]string)
+	if err := context.runCquery(ctx); err != nil {
+		return err
+	}
+	if err := context.runAquery(config, ctx); err != nil {
+		return err
+	}
+	if err := context.generateBazelSymlinks(ctx); err != nil {
+		return err
+	}
 
-	var err error
+	// Clear requests.
+	context.requests = map[cqueryKey]bool{}
+	return nil
+}
 
+func (context *bazelContext) runCquery(ctx *Context) error {
+	if ctx != nil {
+		ctx.EventHandler.Begin("cquery")
+		defer ctx.EventHandler.End("cquery")
+	}
 	soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
 	mixedBuildsPath := filepath.Join(soongInjectionPath, "mixed_builds")
 	if _, err := os.Stat(mixedBuildsPath); os.IsNotExist(err) {
 		err = os.MkdirAll(mixedBuildsPath, 0777)
-	}
-	if err != nil {
-		return err
-	}
-	if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" {
-		err = os.MkdirAll(metricsDir, 0777)
 		if err != nil {
 			return err
 		}
 	}
-	if err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
+	if err := ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
 		return err
 	}
-	if err = ioutil.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
+	if err := ioutil.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
 		return err
 	}
-	if err = ioutil.WriteFile(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
+	if err := ioutil.WriteFile(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
 		return err
 	}
 	cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
-	if err = ioutil.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
+	if err := ioutil.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
 		return err
 	}
 
-	const buildrootLabel = "@soong_injection//mixed_builds:buildroot"
-	cqueryCmd := bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)}
 	cqueryCommandWithFlag := context.createBazelCommand(context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
 		"--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath))
-	cqueryOutput, cqueryErr, err := context.issueBazelCommand(cqueryCommandWithFlag)
-	if err != nil {
-		return err
+	cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag)
+	if cqueryErr != nil {
+		return cqueryErr
 	}
 	cqueryCommandPrint := fmt.Sprintf("cquery command line:\n  %s \n\n\n", printableCqueryCommand(cqueryCommandWithFlag))
-	if err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryCommandPrint+cqueryOutput), 0666); err != nil {
+	if err := ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryCommandPrint+cqueryOutput), 0666); err != nil {
 		return err
 	}
 	cqueryResults := map[string]string{}
@@ -924,10 +952,17 @@
 			context.results[val] = cqueryResult
 		} else {
 			return fmt.Errorf("missing result for bazel target %s. query output: [%s], cquery err: [%s]",
-				getCqueryId(val), cqueryOutput, cqueryErr)
+				getCqueryId(val), cqueryOutput, cqueryErrorMessage)
 		}
 	}
+	return nil
+}
 
+func (context *bazelContext) runAquery(config Config, ctx *Context) error {
+	if ctx != nil {
+		ctx.EventHandler.Begin("aquery")
+		defer ctx.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
@@ -937,6 +972,12 @@
 		extraFlags = append(extraFlags, "--collect_code_coverage")
 		paths := make([]string, 0, 2)
 		if p := config.productVariables.NativeCoveragePaths; len(p) > 0 {
+			for i, _ := range p {
+				// TODO(b/259404593) convert path wildcard to regex values
+				if p[i] == "*" {
+					p[i] = ".*"
+				}
+			}
 			paths = append(paths, JoinWithPrefixAndSeparator(p, "+", ","))
 		}
 		if p := config.productVariables.NativeCoverageExcludePaths; len(p) > 0 {
@@ -946,26 +987,25 @@
 			extraFlags = append(extraFlags, "--instrumentation_filter="+strings.Join(paths, ","))
 		}
 	}
-	aqueryCmd := bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
-	if aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
-		extraFlags...)); err == nil {
-		context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
-	}
+	aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
+		extraFlags...))
 	if err != nil {
 		return err
 	}
+	context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
+	return err
+}
 
+func (context *bazelContext) generateBazelSymlinks(ctx *Context) error {
+	if ctx != nil {
+		ctx.EventHandler.Begin("symlinks")
+		defer ctx.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.
-	buildCmd := bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
-	if _, _, err = context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd)); err != nil {
-		return err
-	}
-
-	// Clear requests.
-	context.requests = map[cqueryKey]bool{}
-	return nil
+	_, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd))
+	return err
 }
 
 func (context *bazelContext) BuildStatementsToRegister() []bazel.BuildStatement {
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index 6e3acd5..bc16cb5 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -23,7 +23,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)
+	err := bazelContext.InvokeBazel(testConfig, nil)
 	if err != nil {
 		t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
 	}
@@ -37,7 +37,7 @@
 
 func TestInvokeBazelWritesBazelFiles(t *testing.T) {
 	bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
-	err := bazelContext.InvokeBazel(testConfig)
+	err := bazelContext.InvokeBazel(testConfig, nil)
 	if err != nil {
 		t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
 	}
@@ -118,7 +118,7 @@
 		bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
 			bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
 
-		err = bazelContext.InvokeBazel(testConfig)
+		err = bazelContext.InvokeBazel(testConfig, nil)
 		if err != nil {
 			t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
 		}
@@ -155,6 +155,10 @@
 	testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
 	verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=-bar1`)
 
+	testConfig.productVariables.NativeCoveragePaths = []string{"*"}
+	testConfig.productVariables.NativeCoverageExcludePaths = nil
+	verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+.*`)
+
 	testConfig.productVariables.ClangCoverage = boolPtr(false)
 	actual := verifyExtraFlags(t, testConfig, ``)
 	if strings.Contains(actual, "--collect_code_coverage") ||
@@ -166,7 +170,7 @@
 func verifyExtraFlags(t *testing.T, config Config, expected string) string {
 	bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
 
-	err := bazelContext.InvokeBazel(config)
+	err := bazelContext.InvokeBazel(config, nil)
 	if err != nil {
 		t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
 	}
@@ -193,7 +197,7 @@
 	}
 	aqueryCommand := bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}
 	if _, exists := bazelCommandResults[aqueryCommand]; !exists {
-		bazelCommandResults[aqueryCommand] = "{}\n"
+		bazelCommandResults[aqueryCommand] = ""
 	}
 	runner := &mockBazelRunner{bazelCommandResults: bazelCommandResults}
 	return &bazelContext{
diff --git a/android/config.go b/android/config.go
index 0c3e2d1..1deb7d4 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1272,10 +1272,6 @@
 	return coverage
 }
 
-func (c *deviceConfig) AfdoAdditionalProfileDirs() []string {
-	return c.config.productVariables.AfdoAdditionalProfileDirs
-}
-
 func (c *deviceConfig) PgoAdditionalProfileDirs() []string {
 	return c.config.productVariables.PgoAdditionalProfileDirs
 }
diff --git a/android/defs.go b/android/defs.go
index 2a28e98..9ae360e 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -25,7 +25,8 @@
 )
 
 var (
-	pctx = NewPackageContext("android/soong/android")
+	pctx         = NewPackageContext("android/soong/android")
+	exportedVars = NewExportedVariables(pctx)
 
 	cpPreserveSymlinks = pctx.VariableConfigMethod("cpPreserveSymlinks",
 		Config.CpPreserveSymlinksFlags)
@@ -128,6 +129,13 @@
 	pctx.VariableFunc("RBEWrapper", func(ctx PackageVarContext) string {
 		return ctx.Config().RBEWrapper()
 	})
+
+	exportedVars.ExportStringList("NeverAllowNotInIncludeDir", neverallowNotInIncludeDir)
+	exportedVars.ExportStringList("NeverAllowNoUseIncludeDir", neverallowNoUseIncludeDir)
+}
+
+func BazelCcToolchainVars(config Config) string {
+	return BazelToolchainVars(config, exportedVars)
 }
 
 var (
diff --git a/android/filegroup.go b/android/filegroup.go
index af4d89a..d21d146 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -122,16 +122,18 @@
 		if fg.ShouldConvertToProtoLibrary(ctx) {
 			// TODO(b/246997908): we can remove this tag if we could figure out a
 			// solution for this bug.
-			tags := []string{"manual"}
 			attrs := &ProtoAttrs{
 				Srcs:                srcs,
 				Strip_import_prefix: fg.properties.Path,
-				Tags:                tags,
 			}
 
+			tags := []string{"manual"}
 			ctx.CreateBazelTargetModule(
 				bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
-				CommonAttributes{Name: fg.Name() + convertedProtoLibrarySuffix},
+				CommonAttributes{
+					Name: fg.Name() + convertedProtoLibrarySuffix,
+					Tags: bazel.MakeStringListAttribute(tags),
+				},
 				attrs)
 		}
 
diff --git a/android/fixture.go b/android/fixture.go
index f33e718..3f01f5a 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -658,7 +658,7 @@
 
 func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture {
 	config := TestConfig(buildDir, nil, "", nil)
-	ctx := NewTestContext(config)
+	ctx := newTestContextForFixture(config)
 	fixture := &fixture{
 		preparers: preparers,
 		t:         t,
@@ -790,6 +790,16 @@
 		}
 	}
 
+	// Create and set the Context's NameInterface. It needs to be created here as it depends on the
+	// configuration that has been prepared for this fixture.
+	resolver := NewNameResolver(ctx.config)
+
+	// Set the NameInterface in the main Context.
+	ctx.SetNameInterface(resolver)
+
+	// Set the NameResolver in the TestContext.
+	ctx.NameResolver = resolver
+
 	ctx.Register()
 	var ninjaDeps []string
 	extraNinjaDeps, errs := ctx.ParseBlueprintsFiles("ignored")
diff --git a/android/gen_notice.go b/android/gen_notice.go
index 008aac5..28fddbc 100644
--- a/android/gen_notice.go
+++ b/android/gen_notice.go
@@ -61,6 +61,9 @@
 				if mod == nil {
 					continue
 				}
+				if !mod.Enabled() { // don't depend on variants without build rules
+					continue
+				}
 				modules = append(modules, mod)
 			}
 		}
diff --git a/android/namespace.go b/android/namespace.go
index a3ff761..b43ffdf 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -91,7 +91,27 @@
 	namespaceExportFilter func(*Namespace) bool
 }
 
-func NewNameResolver(namespaceExportFilter func(*Namespace) bool) *NameResolver {
+// NameResolverConfig provides the subset of the Config interface needed by the
+// NewNameResolver function.
+type NameResolverConfig interface {
+	// ExportedNamespaces is the list of namespaces that Soong must export to
+	// make.
+	ExportedNamespaces() []string
+}
+
+func NewNameResolver(config NameResolverConfig) *NameResolver {
+	namespacePathsToExport := make(map[string]bool)
+
+	for _, namespaceName := range config.ExportedNamespaces() {
+		namespacePathsToExport[namespaceName] = true
+	}
+
+	namespacePathsToExport["."] = true // always export the root namespace
+
+	namespaceExportFilter := func(namespace *Namespace) bool {
+		return namespacePathsToExport[namespace.Path]
+	}
+
 	r := &NameResolver{
 		namespacesByDir:       sync.Map{},
 		namespaceExportFilter: namespaceExportFilter,
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 87d1320..7a387a0 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -602,6 +602,36 @@
 	// RunTest will report any errors
 }
 
+func TestNamespace_Exports(t *testing.T) {
+	result := GroupFixturePreparers(
+		prepareForTestWithNamespace,
+		FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+			variables.NamespacesToExport = []string{"dir1"}
+		}),
+		dirBpToPreparer(map[string]string{
+			"dir1": `
+				soong_namespace {
+				}
+				test_module {
+					name: "a",
+				}
+			`,
+			"dir2": `
+				soong_namespace {
+				}
+				test_module {
+					name: "b",
+				}
+			`,
+		}),
+	).RunTest(t)
+
+	aModule := result.Module("a", "")
+	AssertBoolEquals(t, "a exported", true, aModule.ExportedToMake())
+	bModule := result.Module("b", "")
+	AssertBoolEquals(t, "b not exported", false, bModule.ExportedToMake())
+}
+
 // some utils to support the tests
 
 var prepareForTestWithNamespace = GroupFixturePreparers(
diff --git a/android/neverallow.go b/android/neverallow.go
index d288439..293bac8 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -74,8 +74,8 @@
 			"supported for custom conversion, use allowlists.go instead.")
 }
 
-func createIncludeDirsRules() []Rule {
-	notInIncludeDir := []string{
+var (
+	neverallowNotInIncludeDir = []string{
 		"art",
 		"art/libnativebridge",
 		"art/libnativeloader",
@@ -91,7 +91,7 @@
 		"external/vixl",
 		"external/wycheproof",
 	}
-	noUseIncludeDir := []string{
+	neverallowNoUseIncludeDir = []string{
 		"frameworks/av/apex",
 		"frameworks/av/tools",
 		"frameworks/native/cmds",
@@ -103,10 +103,12 @@
 		"system/libfmq",
 		"system/libvintf",
 	}
+)
 
-	rules := make([]Rule, 0, len(notInIncludeDir)+len(noUseIncludeDir))
+func createIncludeDirsRules() []Rule {
+	rules := make([]Rule, 0, len(neverallowNotInIncludeDir)+len(neverallowNoUseIncludeDir))
 
-	for _, path := range notInIncludeDir {
+	for _, path := range neverallowNotInIncludeDir {
 		rule :=
 			NeverAllow().
 				WithMatcher("include_dirs", StartsWith(path+"/")).
@@ -116,7 +118,7 @@
 		rules = append(rules, rule)
 	}
 
-	for _, path := range noUseIncludeDir {
+	for _, path := range neverallowNoUseIncludeDir {
 		rule := NeverAllow().In(path+"/").WithMatcher("include_dirs", isSetMatcherInstance).
 			Because("include_dirs is deprecated, all usages of them in '" + path + "' have been migrated" +
 				" to use alternate mechanisms and so can no longer be used.")
diff --git a/android/proto.go b/android/proto.go
index 3cac9a1..8204f77 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -164,7 +164,6 @@
 	Srcs                bazel.LabelListAttribute
 	Strip_import_prefix *string
 	Deps                bazel.LabelListAttribute
-	Tags                []string
 }
 
 // For each package in the include_dirs property a proto_library target should
diff --git a/android/testing.go b/android/testing.go
index 2256c96..8fcf440 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -30,19 +30,11 @@
 	"github.com/google/blueprint/proptools"
 )
 
-func NewTestContext(config Config) *TestContext {
-	namespaceExportFilter := func(namespace *Namespace) bool {
-		return true
-	}
-
-	nameResolver := NewNameResolver(namespaceExportFilter)
+func newTestContextForFixture(config Config) *TestContext {
 	ctx := &TestContext{
-		Context:      &Context{blueprint.NewContext(), config},
-		NameResolver: nameResolver,
+		Context: &Context{blueprint.NewContext(), config},
 	}
 
-	ctx.SetNameInterface(nameResolver)
-
 	ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator)
 
 	ctx.SetFs(ctx.config.fs)
@@ -53,6 +45,16 @@
 	return ctx
 }
 
+func NewTestContext(config Config) *TestContext {
+	ctx := newTestContextForFixture(config)
+
+	nameResolver := NewNameResolver(config)
+	ctx.NameResolver = nameResolver
+	ctx.SetNameInterface(nameResolver)
+
+	return ctx
+}
+
 var PrepareForTestWithArchMutator = GroupFixturePreparers(
 	// Configure architecture targets in the fixture config.
 	FixtureModifyConfig(modifyTestConfigToSupportArchMutator),
diff --git a/android/variable.go b/android/variable.go
index 37ecab5..28f22c9 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -336,8 +336,7 @@
 
 	NamespacesToExport []string `json:",omitempty"`
 
-	AfdoAdditionalProfileDirs []string `json:",omitempty"`
-	PgoAdditionalProfileDirs  []string `json:",omitempty"`
+	PgoAdditionalProfileDirs []string `json:",omitempty"`
 
 	VndkUseCoreVariant         *bool `json:",omitempty"`
 	VndkSnapshotBuildArtifacts *bool `json:",omitempty"`
diff --git a/apex/apex.go b/apex/apex.go
index 72403f9..04808c1 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -455,9 +455,6 @@
 	// Processed file_contexts files
 	fileContexts android.WritablePath
 
-	// Path to notice file in html.gz format.
-	htmlGzNotice android.WritablePath
-
 	// The built APEX file. This is the main product.
 	// Could be .apex or .capex
 	outputFile android.WritablePath
@@ -1903,14 +1900,12 @@
 	apexType := a.properties.ApexType
 	switch apexType {
 	case imageApex:
-
-		// TODO(b/190817312): Generate the notice file from the apex rule.
-		a.htmlGzNotice = android.PathForBazelOut(ctx, "NOTICE.html.gz")
 		a.bundleModuleFile = android.PathForBazelOut(ctx, outputs.BundleFile)
 		a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.SymbolsUsedByApex))
 		a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.BackingLibs))
 		// TODO(b/239084755): Generate the java api using.xml file from Bazel.
 		a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.JavaSymbolsUsedByApex))
+		a.installedFilesFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.InstalledFiles))
 		installSuffix := imageApexSuffix
 		if a.isCompressed {
 			installSuffix = imageCapexSuffix
@@ -2507,7 +2502,8 @@
 		filesToAdd = append(filesToAdd, *af)
 	}
 
-	if pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex(); pathInApex != "" {
+	pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex()
+	if pathInApex != "" && !java.SkipDexpreoptBootJars(ctx) {
 		pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost()
 		tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex)
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 985ad59..ea3e734 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -9775,6 +9775,7 @@
 						SymbolsUsedByApex:     "foo_using.txt",
 						JavaSymbolsUsedByApex: "foo_using.xml",
 						BundleFile:            "apex_bundle.zip",
+						InstalledFiles:        "installed-files.txt",
 
 						// unused
 						PackageName:  "pkg_name",
@@ -9820,6 +9821,10 @@
 		t.Errorf("Expected output file %q, got %q", w, g)
 	}
 
+	if w, g := "out/bazel/execroot/__main__/installed-files.txt", ab.installedFilesFile.String(); w != g {
+		t.Errorf("Expected installed-files.txt %q, got %q", w, g)
+	}
+
 	mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
 	var builder strings.Builder
 	mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData)
@@ -9828,4 +9833,7 @@
 	if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/apex_bundle.zip"; !strings.Contains(data, w) {
 		t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
 	}
+	if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/installed-files.txt:foo-installed-files.txt)"; !strings.Contains(data, w) {
+		t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
+	}
 }
diff --git a/apex/builder.go b/apex/builder.go
index e4c1673..9e368b6 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -650,9 +650,9 @@
 		}
 
 		// Create a NOTICE file, and embed it as an asset file in the APEX.
-		a.htmlGzNotice = android.PathForModuleOut(ctx, "NOTICE.html.gz")
+		htmlGzNotice := android.PathForModuleOut(ctx, "NOTICE.html.gz")
 		android.BuildNoticeHtmlOutputFromLicenseMetadata(
-			ctx, a.htmlGzNotice, "", "",
+			ctx, htmlGzNotice, "", "",
 			[]string{
 				android.PathForModuleInstall(ctx).String() + "/",
 				android.PathForModuleInPartitionInstall(ctx, "apex").String() + "/",
@@ -660,7 +660,7 @@
 		noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
 		builder := android.NewRuleBuilder(pctx, ctx)
 		builder.Command().Text("cp").
-			Input(a.htmlGzNotice).
+			Input(htmlGzNotice).
 			Output(noticeAssetPath)
 		builder.Build("notice_dir", "Building notice dir")
 		implicitInputs = append(implicitInputs, noticeAssetPath)
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index eb44dd1..b675f17 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -232,6 +232,7 @@
     "java_symbols_used_by_apex": info.java_symbols_used_by_apex.path,
     "backing_libs": info.backing_libs.path,
     "bundle_file": info.base_with_config_zip.path,
+    "installed_files": info.installed_files.path,
 })`
 }
 
@@ -247,6 +248,7 @@
 	JavaSymbolsUsedByApex string   `json:"java_symbols_used_by_apex"`
 	BackingLibs           string   `json:"backing_libs"`
 	BundleFile            string   `json:"bundle_file"`
+	InstalledFiles        string   `json:"installed_files"`
 }
 
 // ParseResult returns a value obtained by parsing the result of the request's Starlark function.
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index a0a993f..1d30535 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -176,6 +176,7 @@
 	"symbols_used_by_apex": "path/to/my.apex_using.txt",
 	"backing_libs":"path/to/backing.txt",
 	"bundle_file": "dir/bundlefile.zip",
+	"installed_files":"path/to/installed-files.txt",
 	"provides_native_libs":[]
 }`,
 			expectedOutput: ApexInfo{
@@ -189,6 +190,7 @@
 				SymbolsUsedByApex: "path/to/my.apex_using.txt",
 				BackingLibs:       "path/to/backing.txt",
 				BundleFile:        "dir/bundlefile.zip",
+				InstalledFiles:    "path/to/installed-files.txt",
 			},
 		},
 	}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 8ca13b8..6eb93bc 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -23,6 +23,9 @@
 func CreateSoongInjectionFiles(cfg android.Config, metrics CodegenMetrics) []BazelFile {
 	var files []BazelFile
 
+	files = append(files, newFile("android", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
+	files = append(files, newFile("android", "constants.bzl", android.BazelCcToolchainVars(cfg)))
+
 	files = append(files, newFile("cc_toolchain", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
 	files = append(files, newFile("cc_toolchain", "constants.bzl", cc_config.BazelCcToolchainVars(cfg)))
 
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index cfd6128..8de2f83 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -88,6 +88,14 @@
 
 	expectedFilePaths := []bazelFilepath{
 		{
+			dir:      "android",
+			basename: GeneratedBuildFileName,
+		},
+		{
+			dir:      "android",
+			basename: "constants.bzl",
+		},
+		{
 			dir:      "cc_toolchain",
 			basename: GeneratedBuildFileName,
 		},
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 74e2dbd..00056f8 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -649,3 +649,46 @@
 				}),
 		}})
 }
+
+func TestJavaLibraryKotlinSrcs(t *testing.T) {
+	runJavaLibraryTestCase(t, Bp2buildTestCase{
+		Description: "java_library with kotlin  srcs",
+		Blueprint: `java_library {
+    name: "java-lib-1",
+    srcs: ["a.java", "b.java", "c.kt"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("kt_jvm_library", "java-lib-1", AttrNameToString{
+				"srcs": `[
+        "a.java",
+        "b.java",
+        "c.kt",
+    ]`,
+			}),
+		},
+	})
+}
+
+func TestJavaLibraryKotlinCommonSrcs(t *testing.T) {
+	runJavaLibraryTestCase(t, Bp2buildTestCase{
+		Description: "java_library with kotlin  common_srcs",
+		Blueprint: `java_library {
+    name: "java-lib-1",
+    srcs: ["a.java", "b.java"],
+    common_srcs: ["c.kt"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("kt_jvm_library", "java-lib-1", AttrNameToString{
+				"srcs": `[
+        "a.java",
+        "b.java",
+    ]`,
+				"common_srcs": `["c.kt"]`,
+			}),
+		},
+	})
+}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 7376750..a840fa3 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -24,6 +24,7 @@
 	"android/soong/android"
 	"android/soong/bazel"
 	"android/soong/bazel/cquery"
+	"android/soong/cc"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -32,9 +33,7 @@
 func init() {
 	registerBpfBuildComponents(android.InitRegistrationContext)
 	pctx.Import("android/soong/cc/config")
-	if runtime.GOOS != "darwin" {
-		pctx.StaticVariable("relPwd", "PWD=/proc/self/cwd")
-	}
+	pctx.StaticVariable("relPwd", cc.PwdPrefix())
 }
 
 var (
diff --git a/cc/afdo.go b/cc/afdo.go
index fb66bbe..d36f4af 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -36,7 +36,7 @@
 
 func getAfdoProfileProjects(config android.DeviceConfig) []string {
 	return config.OnceStringSlice(afdoProfileProjectsConfigKey, func() []string {
-		return append(globalAfdoProfileProjects, config.AfdoAdditionalProfileDirs()...)
+		return globalAfdoProfileProjects
 	})
 }
 
diff --git a/cc/builder.go b/cc/builder.go
index 75e4736..46cea0b 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -924,9 +924,9 @@
 }
 
 // sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump).
-func sourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
-	baseName, exportedHeaderFlags string, diffFlags []string, prevVersion int,
-	checkAllApis, isLlndk, isNdk, isVndkExt, previousVersionDiff bool) android.OptionalPath {
+func sourceAbiDiff(ctx android.ModuleContext, inputDump, referenceDump android.Path,
+	baseName string, diffFlags []string, prevVersion int,
+	checkAllApis, isLlndkOrNdk, isVndkExt, previousVersionDiff bool) android.OptionalPath {
 
 	var outputFile android.ModuleOutPath
 	if previousVersionDiff {
@@ -955,7 +955,7 @@
 		extraFlags = append(extraFlags, "-target-version", "current")
 	}
 
-	if isLlndk || isNdk {
+	if isLlndkOrNdk {
 		extraFlags = append(extraFlags, "-consider-opaque-types-different")
 	}
 	if isVndkExt || previousVersionDiff {
diff --git a/cc/config/global.go b/cc/config/global.go
index 9f18784..e5c0a8e 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -292,6 +292,8 @@
 	llvmNextExtraCommonGlobalCflags = []string{
 		// New warnings to be fixed after clang-r475365
 		"-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
+		// Skip deprecated flags.
+		"-Wno-unused-command-line-argument",
 	}
 
 	IllegalFlags = []string{
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 825be7f..67208b2 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -32,7 +32,6 @@
 
 	riscv64Ldflags = []string{
 		"-Wl,--hash-style=gnu",
-		"-Wl,-z,separate-code",
 	}
 
 	riscv64Lldflags = append(riscv64Ldflags,
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index f32ebf2..1180da4 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -55,6 +55,21 @@
 		// http://b/241819232
 		"-misc-const-correctness",
 	}
+
+	extraArgFlags = []string{
+		// We might be using the static analyzer through clang tidy.
+		// https://bugs.llvm.org/show_bug.cgi?id=32914
+		"-D__clang_analyzer__",
+
+		// A recent change in clang-tidy (r328258) enabled destructor inlining, which
+		// appears to cause a number of false positives. Until that's resolved, this turns
+		// off the effects of r328258.
+		// https://bugs.llvm.org/show_bug.cgi?id=37459
+		"-Xclang",
+		"-analyzer-config",
+		"-Xclang",
+		"c++-temp-dtor-inlining=false",
+	}
 )
 
 func init() {
@@ -145,6 +160,8 @@
 		return strings.Join(globalNoErrorCheckList, ",")
 	})
 
+	exportedVars.ExportStringListStaticVariable("TidyExtraArgFlags", extraArgFlags)
+
 	// To reduce duplicate warnings from the same header files,
 	// header-filter will contain only the module directory and
 	// those specified by DEFAULT_TIDY_HEADER_DIRS.
@@ -235,6 +252,10 @@
 	return ""
 }
 
+func TidyExtraArgFlags() []string {
+	return extraArgFlags
+}
+
 func TidyFlagsForSrcFile(srcFile android.Path, flags string) string {
 	// Disable clang-analyzer-* checks globally for generated source files
 	// because some of them are too huge. Local .bp files can add wanted
diff --git a/cc/library.go b/cc/library.go
index 03a5575..b639930 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1875,25 +1875,21 @@
 	}
 }
 
+func currRefAbiDumpVersion(ctx ModuleContext, isVndk bool) string {
+	if isVndk {
+		// Each version of VNDK is independent, so follow the VNDK version which is the codename or PLATFORM_SDK_VERSION.
+		return ctx.Module().(*Module).VndkVersion()
+	} else if ctx.Config().PlatformSdkFinal() {
+		// After sdk finalization, the ABI of the latest API level must be consistent with the source code,
+		// so choose PLATFORM_SDK_VERSION as the current version.
+		return ctx.Config().PlatformSdkVersion().String()
+	} else {
+		return "current"
+	}
+}
+
 func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
 	if library.sabi.shouldCreateSourceAbiDump() {
-		var version string
-		var prevVersion int
-
-		if ctx.useVndk() {
-			// For modules linking against vndk, follow its vndk version
-			version = ctx.Module().(*Module).VndkVersion()
-		} else {
-			// After sdk finalizatoin, the ABI of the latest API level must be consistent with the source code
-			// so the chosen reference dump is the PLATFORM_SDK_VERSION.
-			if ctx.Config().PlatformSdkFinal() {
-				version = ctx.Config().PlatformSdkVersion().String()
-			} else {
-				version = "current"
-			}
-			prevVersion = prevDumpRefVersion(ctx)
-		}
-
 		exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
 		var SourceAbiFlags []string
 		for _, dir := range exportIncludeDirs.Strings() {
@@ -1910,26 +1906,31 @@
 
 		addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
 
+		isVndk := ctx.useVndk() && ctx.isVndk()
+		isNdk := ctx.isNdk(ctx.Config())
+		isLlndk := ctx.isImplementationForLLNDKPublic()
 		// If NDK or PLATFORM library, check against previous version ABI.
-		if !ctx.useVndk() {
+		if !isVndk {
+			prevVersion := prevDumpRefVersion(ctx)
 			prevRefAbiDumpFile := getRefAbiDumpFile(ctx, strconv.Itoa(prevVersion), fileName)
 			if prevRefAbiDumpFile != nil {
 				library.prevSAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
-					prevRefAbiDumpFile, fileName, exportedHeaderFlags,
+					prevRefAbiDumpFile, fileName,
 					library.Properties.Header_abi_checker.Diff_flags, prevVersion,
 					Bool(library.Properties.Header_abi_checker.Check_all_apis),
-					ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt(), true)
+					isLlndk || isNdk, ctx.IsVndkExt(), true)
 			}
 		}
 
-		refAbiDumpFile := getRefAbiDumpFile(ctx, version, fileName)
+		currVersion := currRefAbiDumpVersion(ctx, isVndk)
+		refAbiDumpFile := getRefAbiDumpFile(ctx, currVersion, fileName)
 		if refAbiDumpFile != nil {
 			library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
-				refAbiDumpFile, fileName, exportedHeaderFlags,
+				refAbiDumpFile, fileName,
 				library.Properties.Header_abi_checker.Diff_flags,
 				/* unused if not previousVersionDiff */ 0,
 				Bool(library.Properties.Header_abi_checker.Check_all_apis),
-				ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt(), false)
+				isLlndk || isNdk, ctx.IsVndkExt(), false)
 		}
 	}
 }
diff --git a/cc/library_stub.go b/cc/library_stub.go
index 2fb21a3..043c03c 100644
--- a/cc/library_stub.go
+++ b/cc/library_stub.go
@@ -288,8 +288,8 @@
 }
 
 type variantExporterProperties struct {
-	// Header directory or library to export
-	Export_headers []string
+	// Header directory to export
+	Export_headers []string `android:"arch_variant"`
 
 	// Export all headers as system include
 	Export_headers_as_system *bool
diff --git a/cc/strip.go b/cc/strip.go
index 5c32d8b..c60e135 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -56,9 +56,7 @@
 	forceEnable := Bool(stripper.StripProperties.Strip.All) ||
 		Bool(stripper.StripProperties.Strip.Keep_symbols) ||
 		Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame)
-	// create_minidebuginfo doesn't work for riscv64 yet, disable stripping for now
-	riscv64 := actx.Arch().ArchType == android.Riscv64
-	return !forceDisable && (forceEnable || defaultEnable) && !riscv64
+	return !forceDisable && (forceEnable || defaultEnable)
 }
 
 // Keep this consistent with //build/bazel/rules/stripped_shared_library.bzl.
diff --git a/cc/tidy.go b/cc/tidy.go
index a3d548b..bbcaece 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -136,19 +136,7 @@
 		flags.TidyFlags = append(flags.TidyFlags, "-extra-arg-before=-fno-caret-diagnostics")
 	}
 
-	extraArgFlags := []string{
-		// We might be using the static analyzer through clang tidy.
-		// https://bugs.llvm.org/show_bug.cgi?id=32914
-		"-D__clang_analyzer__",
-
-		// A recent change in clang-tidy (r328258) enabled destructor inlining, which
-		// appears to cause a number of false positives. Until that's resolved, this turns
-		// off the effects of r328258.
-		// https://bugs.llvm.org/show_bug.cgi?id=37459
-		"-Xclang", "-analyzer-config", "-Xclang", "c++-temp-dtor-inlining=false",
-	}
-
-	for _, f := range extraArgFlags {
+	for _, f := range config.TidyExtraArgFlags() {
 		flags.TidyFlags = append(flags.TidyFlags, "-extra-arg-before="+f)
 	}
 
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 3fed1a1..bc2d5cb 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -106,24 +106,11 @@
 }
 
 func newNameResolver(config android.Config) *android.NameResolver {
-	namespacePathsToExport := make(map[string]bool)
-
-	for _, namespaceName := range config.ExportedNamespaces() {
-		namespacePathsToExport[namespaceName] = true
-	}
-
-	namespacePathsToExport["."] = true // always export the root namespace
-
-	exportFilter := func(namespace *android.Namespace) bool {
-		return namespacePathsToExport[namespace.Path]
-	}
-
-	return android.NewNameResolver(exportFilter)
+	return android.NewNameResolver(config)
 }
 
 func newContext(configuration android.Config) *android.Context {
 	ctx := android.NewContext(configuration)
-	ctx.Register()
 	ctx.SetNameInterface(newNameResolver(configuration))
 	ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
 	return ctx
@@ -165,14 +152,12 @@
 // Bazel-enabled mode. Attaches a mutator to queue Bazel requests, adds a
 // BeforePrepareBuildActionsHook to invoke Bazel, and then uses Bazel metadata
 // for modules that should be handled by Bazel.
-func runMixedModeBuild(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) {
+func runMixedModeBuild(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) string {
 	ctx.EventHandler.Begin("mixed_build")
 	defer ctx.EventHandler.End("mixed_build")
 
 	bazelHook := func() error {
-		ctx.EventHandler.Begin("bazel")
-		defer ctx.EventHandler.End("bazel")
-		return configuration.BazelContext.InvokeBazel(configuration)
+		return configuration.BazelContext.InvokeBazel(configuration, ctx)
 	}
 	ctx.SetBeforePrepareBuildActionsHook(bazelHook)
 	ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, bootstrap.DoEverything, ctx.Context, configuration)
@@ -188,6 +173,7 @@
 	ninjaDeps = append(ninjaDeps, globListFiles...)
 
 	writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
+	return cmdlineArgs.OutFile
 }
 
 // Run the code-generation phase to convert BazelTargetModules to BUILD files.
@@ -206,12 +192,11 @@
 
 // Run the code-generation phase to convert API contributions to BUILD files.
 // Return marker file for the new synthetic workspace
-func runApiBp2build(configuration android.Config, extraNinjaDeps []string) string {
-	// Create a new context and register mutators that are only meaningful to API export
-	ctx := android.NewContext(configuration)
+func runApiBp2build(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) string {
 	ctx.EventHandler.Begin("api_bp2build")
 	defer ctx.EventHandler.End("api_bp2build")
-	ctx.SetNameInterface(newNameResolver(configuration))
+	// Do not allow missing dependencies.
+	ctx.SetAllowMissingDependencies(false)
 	ctx.RegisterForApiBazelConversion()
 
 	// Register the Android.bp files in the tree
@@ -256,6 +241,11 @@
 	// Exclude all src BUILD files
 	excludes = append(excludes, apiBuildFileExcludes()...)
 
+	// Android.bp files for api surfaces are mounted to out/, but out/ should not be a
+	// dep for api_bp2build.
+	// Otherwise api_bp2build will be run every single time
+	excludes = append(excludes, configuration.OutDir())
+
 	// Create the symlink forest
 	symlinkDeps := bp2build.PlantSymlinkForest(
 		configuration.IsEnvTrue("BP2BUILD_VERBOSE"),
@@ -349,61 +339,77 @@
 // output file of the specific activity.
 func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string, metricsDir string) string {
 	if configuration.BuildMode == android.SymlinkForest {
-		runSymlinkForestCreation(configuration, extraNinjaDeps, metricsDir)
-		return symlinkForestMarker
+		return runSymlinkForestCreation(configuration, ctx, extraNinjaDeps, metricsDir)
 	} else if configuration.BuildMode == android.Bp2build {
 		// Run the alternate pipeline of bp2build mutators and singleton to convert
 		// Blueprint to BUILD files before everything else.
-		runBp2Build(configuration, extraNinjaDeps, metricsDir)
-		return bp2buildMarker
-	} else if configuration.IsMixedBuildsEnabled() {
-		runMixedModeBuild(configuration, ctx, extraNinjaDeps)
+		return runBp2Build(configuration, ctx, extraNinjaDeps, metricsDir)
 	} else if configuration.BuildMode == android.ApiBp2build {
-		return runApiBp2build(configuration, extraNinjaDeps)
+		outputFile := runApiBp2build(configuration, ctx, extraNinjaDeps)
+		writeMetrics(configuration, ctx.EventHandler, metricsDir)
+		return outputFile
 	} else {
-		var stopBefore bootstrap.StopBefore
-		if configuration.BuildMode == android.GenerateModuleGraph {
-			stopBefore = bootstrap.StopBeforeWriteNinja
-		} else if configuration.BuildMode == android.GenerateQueryView || configuration.BuildMode == android.GenerateDocFile {
-			stopBefore = bootstrap.StopBeforePrepareBuildActions
+		ctx.Register()
+
+		var outputFile string
+		if configuration.IsMixedBuildsEnabled() {
+			outputFile = runMixedModeBuild(configuration, ctx, extraNinjaDeps)
 		} else {
-			stopBefore = bootstrap.DoEverything
+			outputFile = runSoongOnlyBuild(configuration, ctx, extraNinjaDeps)
 		}
 
-		ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, stopBefore, ctx.Context, configuration)
-		ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+		writeMetrics(configuration, ctx.EventHandler, metricsDir)
 
-		globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
-		ninjaDeps = append(ninjaDeps, globListFiles...)
+		return outputFile
+	}
+}
 
-		// Convert the Soong module graph into Bazel BUILD files.
-		if configuration.BuildMode == android.GenerateQueryView {
-			queryviewMarkerFile := bazelQueryViewDir + ".marker"
-			runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx)
-			writeDepFile(queryviewMarkerFile, ctx.EventHandler, ninjaDeps)
-			return queryviewMarkerFile
-		} else if configuration.BuildMode == android.GenerateModuleGraph {
-			writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile)
-			writeDepFile(moduleGraphFile, ctx.EventHandler, ninjaDeps)
-			return moduleGraphFile
-		} else if configuration.BuildMode == android.GenerateDocFile {
-			// TODO: we could make writeDocs() return the list of documentation files
-			// written and add them to the .d file. Then soong_docs would be re-run
-			// whenever one is deleted.
-			if err := writeDocs(ctx, shared.JoinPath(topDir, docFile)); err != nil {
-				fmt.Fprintf(os.Stderr, "error building Soong documentation: %s\n", err)
-				os.Exit(1)
-			}
-			writeDepFile(docFile, ctx.EventHandler, ninjaDeps)
-			return docFile
-		} else {
-			// The actual output (build.ninja) was written in the RunBlueprint() call
-			// above
-			writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
-		}
+// runSoongOnlyBuild runs the standard Soong build in a number of different modes.
+func runSoongOnlyBuild(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) string {
+	ctx.EventHandler.Begin("soong_build")
+	defer ctx.EventHandler.End("soong_build")
+
+	var stopBefore bootstrap.StopBefore
+	if configuration.BuildMode == android.GenerateModuleGraph {
+		stopBefore = bootstrap.StopBeforeWriteNinja
+	} else if configuration.BuildMode == android.GenerateQueryView || configuration.BuildMode == android.GenerateDocFile {
+		stopBefore = bootstrap.StopBeforePrepareBuildActions
+	} else {
+		stopBefore = bootstrap.DoEverything
 	}
 
-	return cmdlineArgs.OutFile
+	ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, stopBefore, ctx.Context, configuration)
+	ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+
+	globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
+	ninjaDeps = append(ninjaDeps, globListFiles...)
+
+	// Convert the Soong module graph into Bazel BUILD files.
+	if configuration.BuildMode == android.GenerateQueryView {
+		queryviewMarkerFile := bazelQueryViewDir + ".marker"
+		runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx)
+		writeDepFile(queryviewMarkerFile, ctx.EventHandler, ninjaDeps)
+		return queryviewMarkerFile
+	} else if configuration.BuildMode == android.GenerateModuleGraph {
+		writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile)
+		writeDepFile(moduleGraphFile, ctx.EventHandler, ninjaDeps)
+		return moduleGraphFile
+	} else if configuration.BuildMode == android.GenerateDocFile {
+		// TODO: we could make writeDocs() return the list of documentation files
+		// written and add them to the .d file. Then soong_docs would be re-run
+		// whenever one is deleted.
+		if err := writeDocs(ctx, shared.JoinPath(topDir, docFile)); err != nil {
+			fmt.Fprintf(os.Stderr, "error building Soong documentation: %s\n", err)
+			os.Exit(1)
+		}
+		writeDepFile(docFile, ctx.EventHandler, ninjaDeps)
+		return docFile
+	} else {
+		// The actual output (build.ninja) was written in the RunBlueprint() call
+		// above
+		writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
+		return cmdlineArgs.OutFile
+	}
 }
 
 // soong_ui dumps the available environment variables to
@@ -463,13 +469,9 @@
 	logDir := availableEnv["LOG_DIR"]
 
 	ctx := newContext(configuration)
-	ctx.EventHandler.Begin("soong_build")
 
 	finalOutputFile := doChosenActivity(ctx, configuration, extraNinjaDeps, logDir)
 
-	ctx.EventHandler.End("soong_build")
-	writeMetrics(configuration, ctx.EventHandler, logDir)
-
 	writeUsedEnvironmentFile(configuration, finalOutputFile)
 }
 
@@ -614,9 +616,7 @@
 // Ideally, bp2build would write a file that contains instructions to the
 // symlink tree creation binary. Then the latter would not need to depend on
 // the very heavy-weight machinery of soong_build .
-func runSymlinkForestCreation(configuration android.Config, extraNinjaDeps []string, metricsDir string) {
-	eventHandler := &metrics.EventHandler{}
-
+func runSymlinkForestCreation(configuration android.Config, ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
 	var ninjaDeps []string
 	ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
 
@@ -643,13 +643,13 @@
 	// Such a directory SHOULD be added to `ninjaDeps` so that a child directory
 	// or file created/deleted under it would trigger an update of the symlink
 	// forest.
-	eventHandler.Do("symlink_forest", func() {
+	ctx.EventHandler.Do("symlink_forest", func() {
 		symlinkForestDeps := bp2build.PlantSymlinkForest(
 			configuration.IsEnvTrue("BP2BUILD_VERBOSE"), topDir, workspaceRoot, generatedRoot, excludes)
 		ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
 	})
 
-	writeDepFile(symlinkForestMarker, eventHandler, ninjaDeps)
+	writeDepFile(symlinkForestMarker, ctx.EventHandler, ninjaDeps)
 	touch(shared.JoinPath(topDir, symlinkForestMarker))
 	codegenMetrics := bp2build.ReadCodegenMetrics(metricsDir)
 	if codegenMetrics == nil {
@@ -659,27 +659,24 @@
 		//TODO (usta) we cannot determine if we loaded a stale file, i.e. from an unrelated prior
 		//invocation of codegen. We should simply use a separate .pb file
 	}
-	writeBp2BuildMetrics(codegenMetrics, eventHandler, metricsDir)
+	writeBp2BuildMetrics(codegenMetrics, ctx.EventHandler, metricsDir)
+
+	return symlinkForestMarker
 }
 
 // Run Soong in the bp2build mode. This creates a standalone context that registers
 // an alternate pipeline of mutators and singletons specifically for generating
 // Bazel BUILD files instead of Ninja files.
-func runBp2Build(configuration android.Config, extraNinjaDeps []string, metricsDir string) {
+func runBp2Build(configuration android.Config, ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
 	var codegenMetrics *bp2build.CodegenMetrics
-	eventHandler := &metrics.EventHandler{}
-	eventHandler.Do("bp2build", func() {
-
-		// Register an alternate set of singletons and mutators for bazel
-		// conversion for Bazel conversion.
-		bp2buildCtx := android.NewContext(configuration)
+	ctx.EventHandler.Do("bp2build", func() {
 
 		// Propagate "allow misssing dependencies" bit. This is normally set in
-		// newContext(), but we create bp2buildCtx without calling that method.
-		bp2buildCtx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
-		bp2buildCtx.SetNameInterface(newNameResolver(configuration))
-		bp2buildCtx.RegisterForBazelConversion()
-		bp2buildCtx.SetModuleListFile(cmdlineArgs.ModuleListFile)
+		// newContext(), but we create ctx without calling that method.
+		ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
+		ctx.SetNameInterface(newNameResolver(configuration))
+		ctx.RegisterForBazelConversion()
+		ctx.SetModuleListFile(cmdlineArgs.ModuleListFile)
 
 		var ninjaDeps []string
 		ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
@@ -687,25 +684,25 @@
 		// Run the loading and analysis pipeline to prepare the graph of regular
 		// Modules parsed from Android.bp files, and the BazelTargetModules mapped
 		// from the regular Modules.
-		eventHandler.Do("bootstrap", func() {
+		ctx.EventHandler.Do("bootstrap", func() {
 			blueprintArgs := cmdlineArgs
-			bootstrapDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.StopBeforePrepareBuildActions, bp2buildCtx.Context, configuration)
+			bootstrapDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.StopBeforePrepareBuildActions, ctx.Context, configuration)
 			ninjaDeps = append(ninjaDeps, bootstrapDeps...)
 		})
 
-		globListFiles := writeBuildGlobsNinjaFile(bp2buildCtx, configuration.SoongOutDir(), configuration)
+		globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
 		ninjaDeps = append(ninjaDeps, globListFiles...)
 
 		// Run the code-generation phase to convert BazelTargetModules to BUILD files
 		// and print conversion codegenMetrics to the user.
-		codegenContext := bp2build.NewCodegenContext(configuration, bp2buildCtx, bp2build.Bp2Build)
-		eventHandler.Do("codegen", func() {
+		codegenContext := bp2build.NewCodegenContext(configuration, ctx, bp2build.Bp2Build)
+		ctx.EventHandler.Do("codegen", func() {
 			codegenMetrics = bp2build.Codegen(codegenContext)
 		})
 
 		ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
 
-		writeDepFile(bp2buildMarker, eventHandler, ninjaDeps)
+		writeDepFile(bp2buildMarker, ctx.EventHandler, ninjaDeps)
 		touch(shared.JoinPath(topDir, bp2buildMarker))
 	})
 
@@ -715,7 +712,8 @@
 	if configuration.IsEnvTrue("BP2BUILD_VERBOSE") {
 		codegenMetrics.Print()
 	}
-	writeBp2BuildMetrics(codegenMetrics, eventHandler, metricsDir)
+	writeBp2BuildMetrics(codegenMetrics, ctx.EventHandler, metricsDir)
+	return bp2buildMarker
 }
 
 // Write Bp2Build metrics into $LOG_DIR
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index eefda19..609a29c 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -96,6 +96,8 @@
 	// quickly silence build errors. This flag should be used with caution and only as a temporary
 	// measure, as it masks real errors and affects performance.
 	RelaxUsesLibraryCheck bool
+
+	EnableUffdGc bool // preopt with the assumption that userfaultfd GC will be used on device.
 }
 
 var allPlatformSystemServerJarsKey = android.NewOnceKey("allPlatformSystemServerJars")
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index fdfd22e..e3404a5 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -495,6 +495,10 @@
 		cmd.FlagWithInput("--profile-file=", profile)
 	}
 
+	if global.EnableUffdGc {
+		cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+	}
+
 	rule.Install(odexPath, odexInstallPath)
 	rule.Install(vdexPath, vdexInstallPath)
 }
diff --git a/filesystem/avb_add_hash_footer.go b/filesystem/avb_add_hash_footer.go
index af3bdbe..1ee0edc 100644
--- a/filesystem/avb_add_hash_footer.go
+++ b/filesystem/avb_add_hash_footer.go
@@ -23,10 +23,6 @@
 	"android/soong/android"
 )
 
-func init() {
-	android.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory)
-}
-
 type avbAddHashFooter struct {
 	android.ModuleBase
 
@@ -36,6 +32,17 @@
 	installDir android.InstallPath
 }
 
+type avbProp struct {
+	// Name of a property
+	Name *string
+
+	// Value of a property. Can't be used together with `file`.
+	Value *string
+
+	// File from which the value of the prop is read from. Can't be used together with `value`.
+	File *string `android:"path,arch_variant"`
+}
+
 type avbAddHashFooterProperties struct {
 	// Source file of this image. Can reference a genrule type module with the ":module" syntax.
 	Src *string `android:"path,arch_variant"`
@@ -57,6 +64,9 @@
 
 	// The salt in hex. Required for reproducible builds.
 	Salt *string
+
+	// List of properties to add to the footer
+	Props []avbProp
 }
 
 // The AVB footer adds verification information to the image.
@@ -106,6 +116,10 @@
 	}
 	cmd.FlagWithArg("--salt ", proptools.String(a.properties.Salt))
 
+	for _, prop := range a.properties.Props {
+		addAvbProp(ctx, cmd, prop)
+	}
+
 	cmd.FlagWithOutput("--image ", a.output)
 
 	builder.Build("avbAddHashFooter", fmt.Sprintf("avbAddHashFooter %s", ctx.ModuleName()))
@@ -114,6 +128,32 @@
 	ctx.InstallFile(a.installDir, a.installFileName(), a.output)
 }
 
+func addAvbProp(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, prop avbProp) {
+	name := proptools.String(prop.Name)
+	value := proptools.String(prop.Value)
+	file := proptools.String(prop.File)
+	if name == "" {
+		ctx.PropertyErrorf("name", "can't be empty")
+		return
+	}
+	if value == "" && file == "" {
+		ctx.PropertyErrorf("value", "either value or file should be set")
+		return
+	}
+	if value != "" && file != "" {
+		ctx.PropertyErrorf("value", "value and file can't be set at the same time")
+		return
+	}
+
+	if value != "" {
+		cmd.FlagWithArg("--prop ", proptools.ShellEscape(fmt.Sprintf("%s:%s", name, value)))
+	} else {
+		p := android.PathForModuleSrc(ctx, file)
+		cmd.Input(p)
+		cmd.FlagWithArg("--prop_from_file ", proptools.ShellEscape(fmt.Sprintf("%s:%s", name, cmd.PathForInput(p))))
+	}
+}
+
 var _ android.AndroidMkEntriesProvider = (*avbAddHashFooter)(nil)
 
 // Implements android.AndroidMkEntriesProvider
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 6e1e78a..1365d4a 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -34,6 +34,7 @@
 func registerBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("android_filesystem", filesystemFactory)
 	ctx.RegisterModuleType("android_system_image", systemImageFactory)
+	ctx.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory)
 }
 
 type filesystem struct {
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index cda06d9..9bfcc3d 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -125,3 +125,37 @@
 	module := result.ModuleForTests("myfilesystem", "android_common").Module().(*systemImage)
 	android.AssertDeepEquals(t, "entries should have foo only", []string{"components/foo"}, module.entries)
 }
+
+func TestAvbAddHashFooter(t *testing.T) {
+	result := fixture.RunTestWithBp(t, `
+		avb_add_hash_footer {
+			name: "myfooter",
+			src: "input.img",
+			filename: "output.img",
+			partition_name: "mypartition",
+			private_key: "mykey",
+			salt: "1111",
+			props: [
+				{
+					name: "prop1",
+					value: "value1",
+				},
+				{
+					name: "prop2",
+					file: "value_file",
+				},
+			],
+		}
+	`)
+	cmd := result.ModuleForTests("myfooter", "android_arm64_armv8-a").Rule("avbAddHashFooter").RuleParams.Command
+	android.AssertStringDoesContain(t, "Can't find correct --partition_name argument",
+		cmd, "--partition_name mypartition")
+	android.AssertStringDoesContain(t, "Can't find correct --key argument",
+		cmd, "--key mykey")
+	android.AssertStringDoesContain(t, "Can't find --salt argument",
+		cmd, "--salt 1111")
+	android.AssertStringDoesContain(t, "Can't find --prop argument",
+		cmd, "--prop 'prop1:value1'")
+	android.AssertStringDoesContain(t, "Can't find --prop_from_file argument",
+		cmd, "--prop_from_file 'prop2:value_file'")
+}
diff --git a/go.mod b/go.mod
index 5f0b91a..7239f6d 100644
--- a/go.mod
+++ b/go.mod
@@ -1,24 +1,21 @@
 module android/soong
 
-require google.golang.org/protobuf v0.0.0
+require (
+  google.golang.org/protobuf v0.0.0
+  github.com/google/blueprint v0.0.0
+  prebuilts/bazel/common/proto/analysis_v2 v0.0.0
+  prebuilts/bazel/common/proto/build v0.0.0 // indirect
+)
 
-require github.com/google/blueprint v0.0.0
-
-replace google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf
-
-replace github.com/google/blueprint v0.0.0 => ../blueprint
+replace (
+  google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf
+  github.com/google/blueprint v0.0.0 => ../blueprint
+  github.com/google/go-cmp v0.5.5 => ../../external/go-cmp
+  prebuilts/bazel/common/proto/analysis_v2 => ../../prebuilts/bazel/common/proto/analysis_v2
+  prebuilts/bazel/common/proto/build => ../../prebuilts/bazel/common/proto/build
+)
 
 // Indirect deps from golang-protobuf
 exclude github.com/golang/protobuf v1.5.0
 
-replace github.com/google/go-cmp v0.5.5 => ../../external/go-cmp
-
-require prebuilts/bazel/common/proto/analysis_v2 v0.0.0
-
-replace prebuilts/bazel/common/proto/analysis_v2 => ../../prebuilts/bazel/common/proto/analysis_v2
-
-require prebuilts/bazel/common/proto/build v0.0.0 // indirect
-
-replace prebuilts/bazel/common/proto/build => ../../prebuilts/bazel/common/proto/build
-
-go 1.18
+go 2.0
diff --git a/java/Android.bp b/java/Android.bp
index 0bf7a0b..9d63319 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -91,6 +91,7 @@
         "dexpreopt_config_test.go",
         "droiddoc_test.go",
         "droidstubs_test.go",
+        "fuzz_test.go",
         "genrule_test.go",
         "hiddenapi_singleton_test.go",
         "jacoco_test.go",
diff --git a/java/aar.go b/java/aar.go
index 6261f29..0fdde03 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -1046,7 +1046,8 @@
 }
 
 func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
-	commonAttrs, depLabels := a.convertLibraryAttrsBp2Build(ctx)
+	commonAttrs, bp2buildInfo := a.convertLibraryAttrsBp2Build(ctx)
+	depLabels := bp2buildInfo.DepLabels
 
 	deps := depLabels.Deps
 	if !commonAttrs.Srcs.IsEmpty() {
diff --git a/java/app.go b/java/app.go
index 2a51e10..a822cbf 100755
--- a/java/app.go
+++ b/java/app.go
@@ -591,7 +591,7 @@
 		// Set a certificate to avoid panics later when accessing it.
 		mainCertificate = Certificate{
 			Key: android.PathForModuleOut(ctx, "missing.pk8"),
-			Pem: android.PathForModuleOut(ctx, "missing.pem"),
+			Pem: android.PathForModuleOut(ctx, "missing.x509.pem"),
 		}
 	}
 
@@ -1492,7 +1492,8 @@
 
 // ConvertWithBp2build is used to convert android_app to Bazel.
 func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
-	commonAttrs, depLabels := a.convertLibraryAttrsBp2Build(ctx)
+	commonAttrs, bp2BuildInfo := a.convertLibraryAttrsBp2Build(ctx)
+	depLabels := bp2BuildInfo.DepLabels
 
 	deps := depLabels.Deps
 	deps.Append(depLabels.StaticDeps)
diff --git a/java/base.go b/java/base.go
index 602e8d8..5d24981 100644
--- a/java/base.go
+++ b/java/base.go
@@ -868,7 +868,7 @@
 	flags = append(flags, genAidlIncludeFlags(ctx, aidlSrcs, includeDirs))
 
 	sdkVersion := (j.SdkVersion(ctx)).Kind
-	defaultTrace := ((sdkVersion == android.SdkSystemServer) || (sdkVersion == android.SdkCore) || (sdkVersion == android.SdkCorePlatform))
+	defaultTrace := ((sdkVersion == android.SdkSystemServer) || (sdkVersion == android.SdkCore) || (sdkVersion == android.SdkCorePlatform) || (sdkVersion == android.SdkModule))
 	if proptools.BoolDefault(j.deviceProperties.Aidl.Generate_traces, defaultTrace) {
 		flags = append(flags, "-t")
 	}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index b3faae8..3effff6 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -752,6 +752,10 @@
 		cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
 	}
 
+	if global.EnableUffdGc {
+		cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+	}
+
 	if global.BootFlags != "" {
 		cmd.Flag(global.BootFlags)
 	}
diff --git a/java/fuzz_test.go b/java/fuzz_test.go
index 0a2c945..6e5d912 100644
--- a/java/fuzz_test.go
+++ b/java/fuzz_test.go
@@ -65,9 +65,8 @@
 
 	osCommonTarget := result.Config.BuildOSCommonTarget.String()
 
-	osCommonTargetWithSan := osCommonTarget + "_asan" + "_fuzzer"
-	javac := result.ModuleForTests("foo", osCommonTargetWithSan).Rule("javac")
-	combineJar := result.ModuleForTests("foo", osCommonTargetWithSan).Description("for javac")
+	javac := result.ModuleForTests("foo", osCommonTarget).Rule("javac")
+	combineJar := result.ModuleForTests("foo", osCommonTarget).Description("for javac")
 
 	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
 		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
@@ -85,9 +84,9 @@
 	}
 
 	ctx := result.TestContext
-	foo := ctx.ModuleForTests("foo", osCommonTargetWithSan).Module().(*JavaFuzzLibrary)
+	foo := ctx.ModuleForTests("foo", osCommonTarget).Module().(*JavaFuzzLibrary)
 
-	expected := "libjni.so"
+	expected := "lib64/libjni.so"
 	if runtime.GOOS == "darwin" {
 		expected = "libjni.dylib"
 	}
diff --git a/java/java.go b/java/java.go
index b6fc6b8..25b6349 100644
--- a/java/java.go
+++ b/java/java.go
@@ -25,6 +25,7 @@
 
 	"android/soong/bazel"
 	"android/soong/bazel/cquery"
+	"android/soong/remoteexec"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -59,6 +60,8 @@
 	ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
 	ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
 	ctx.RegisterModuleType("dex_import", DexImportFactory)
+	ctx.RegisterModuleType("java_api_library", ApiLibraryFactory)
+	ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory)
 
 	// This mutator registers dependencies on dex2oat for modules that should be
 	// dexpreopted. This is done late when the final variants have been
@@ -1501,6 +1504,177 @@
 	return module
 }
 
+type JavaApiContribution struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties struct {
+		// name of the API surface
+		Api_surface *string
+
+		// relative path to the API signature text file
+		Api_file *string `android:"path"`
+	}
+}
+
+func ApiContributionFactory() android.Module {
+	module := &JavaApiContribution{}
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	return module
+}
+
+type JavaApiImportInfo struct {
+	ApiFile android.Path
+}
+
+var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{})
+
+func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	apiFile := android.PathForModuleSrc(ctx, String(ap.properties.Api_file))
+	ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{
+		ApiFile: apiFile,
+	})
+}
+
+type ApiLibrary struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties JavaApiLibraryProperties
+
+	stubsSrcJar android.WritablePath
+	stubsJar    android.WritablePath
+}
+
+type JavaApiLibraryProperties struct {
+	// name of the API surface
+	Api_surface *string
+
+	// list of Java API contribution modules that consists this API surface
+	Api_contributions []string
+
+	// List of flags to be passed to the javac compiler to generate jar file
+	Javacflags []string
+}
+
+func ApiLibraryFactory() android.Module {
+	module := &ApiLibrary{}
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	return module
+}
+
+func (al *ApiLibrary) ApiSurface() *string {
+	return al.properties.Api_surface
+}
+
+func (al *ApiLibrary) StubsJar() android.Path {
+	return al.stubsJar
+}
+
+func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
+	srcs android.Paths, homeDir android.WritablePath) *android.RuleBuilderCommand {
+	rule.Command().Text("rm -rf").Flag(homeDir.String())
+	rule.Command().Text("mkdir -p").Flag(homeDir.String())
+
+	cmd := rule.Command()
+	cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
+
+	if metalavaUseRbe(ctx) {
+		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
+		execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+		labels := map[string]string{"type": "tool", "name": "metalava"}
+
+		pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
+		rule.Rewrapper(&remoteexec.REParams{
+			Labels:          labels,
+			ExecStrategy:    execStrategy,
+			ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+			Platform:        map[string]string{remoteexec.PoolKey: pool},
+		})
+	}
+
+	cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
+		Flag(config.JavacVmFlags).
+		Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
+		FlagWithArg("-encoding ", "UTF-8").
+		FlagWithInputList("--source-files ", srcs, " ")
+
+	cmd.Flag("--no-banner").
+		Flag("--color").
+		Flag("--quiet").
+		Flag("--format=v2").
+		FlagWithArg("--repeat-errors-max ", "10").
+		FlagWithArg("--hide ", "UnresolvedImport").
+		FlagWithArg("--hide ", "InvalidNullabilityOverride").
+		FlagWithArg("--hide ", "ChangedDefault")
+
+	return cmd
+}
+
+func (al *ApiLibrary) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
+	if stubsDir.Valid() {
+		cmd.FlagWithArg("--stubs ", stubsDir.String())
+	}
+}
+
+var javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
+
+func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+	apiContributions := al.properties.Api_contributions
+	for _, apiContributionName := range apiContributions {
+		ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
+	}
+}
+
+func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+
+	rule := android.NewRuleBuilder(pctx, ctx)
+
+	rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
+		android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
+		SandboxInputs()
+
+	var stubsDir android.OptionalPath
+	stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
+	rule.Command().Text("rm -rf").Text(stubsDir.String())
+	rule.Command().Text("mkdir -p").Text(stubsDir.String())
+
+	homeDir := android.PathForModuleOut(ctx, "metalava", "home")
+
+	var srcFiles []android.Path
+	ctx.VisitDirectDepsWithTag(javaApiContributionTag, func(dep android.Module) {
+		provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo)
+		srcFiles = append(srcFiles, android.PathForModuleSrc(ctx, provider.ApiFile.String()))
+	})
+
+	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
+
+	al.stubsFlags(ctx, cmd, stubsDir)
+
+	al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
+	rule.Command().
+		BuiltTool("soong_zip").
+		Flag("-write_if_changed").
+		Flag("-jar").
+		FlagWithOutput("-o ", al.stubsSrcJar).
+		FlagWithArg("-C ", stubsDir.String()).
+		FlagWithArg("-D ", stubsDir.String())
+
+	rule.Build("metalava", "metalava merged")
+
+	al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), "android.jar")
+
+	var flags javaBuilderFlags
+	flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
+
+	TransformJavaToClasses(ctx, al.stubsJar, 0, android.Paths{},
+		android.Paths{al.stubsSrcJar}, flags, android.Paths{})
+}
+
 //
 // Java prebuilts
 //
@@ -2307,11 +2481,21 @@
 	Deps bazel.LabelListAttribute
 }
 
-// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules
-// and also separates dependencies into dynamic dependencies and static dependencies.
-// Each corresponding Bazel target type, can have a different method for handling
-// dynamic vs. static dependencies, and so these are returned to the calling function.
-func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) {
+// bp2BuildJavaInfo has information needed for the conversion of  java*_modules
+// that is needed bor Bp2Build conversion but that requires different handling
+// depending on the module type.
+type bp2BuildJavaInfo struct {
+	// separates dependencies into dynamic dependencies and static dependencies.
+	DepLabels     *javaDependencyLabels
+	hasKotlinSrcs bool
+}
+
+// convertLibraryAttrsBp2Build returns a javaCommonAttributes struct with
+// converted attributes shared across java_* modules and a bp2BuildJavaInfo struct
+// which has other non-attribute information needed for bp2build conversion
+// that needs different handling depending on the module types, and thus needs
+// to be returned to the calling function.
+func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo) {
 	var srcs bazel.LabelListAttribute
 	var deps bazel.LabelList
 	var staticDeps bazel.LabelList
@@ -2330,14 +2514,18 @@
 	protoSrcPartition := "proto"
 	logtagSrcPartition := "logtag"
 	aidlSrcPartition := "aidl"
+	kotlinPartition := "kotlin"
 	srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
 		javaSrcPartition:   bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
 		logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
 		protoSrcPartition:  android.ProtoSrcLabelPartition,
 		aidlSrcPartition:   android.AidlSrcLabelPartition,
+		kotlinPartition:    bazel.LabelPartition{Extensions: []string{".kt"}},
 	})
 
 	javaSrcs := srcPartitions[javaSrcPartition]
+	kotlinSrcs := srcPartitions[kotlinPartition]
+	javaSrcs.Append(kotlinSrcs)
 
 	if !srcPartitions[logtagSrcPartition].IsEmpty() {
 		logtagsLibName := m.Name() + "_logtags"
@@ -2447,18 +2635,25 @@
 	depLabels.Deps = bazel.MakeLabelListAttribute(deps)
 	depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
 
-	return commonAttrs, depLabels
+	bp2BuildInfo := &bp2BuildJavaInfo{
+		DepLabels:     depLabels,
+		hasKotlinSrcs: !kotlinSrcs.IsEmpty(),
+	}
+
+	return commonAttrs, bp2BuildInfo
 }
 
 type javaLibraryAttributes struct {
 	*javaCommonAttributes
-	Deps      bazel.LabelListAttribute
-	Exports   bazel.LabelListAttribute
-	Neverlink bazel.BoolAttribute
+	Deps        bazel.LabelListAttribute
+	Exports     bazel.LabelListAttribute
+	Neverlink   bazel.BoolAttribute
+	Common_srcs bazel.LabelListAttribute
 }
 
 func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
-	commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx)
+	commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx)
+	depLabels := bp2BuildInfo.DepLabels
 
 	deps := depLabels.Deps
 	if !commonAttrs.Srcs.IsEmpty() {
@@ -2473,15 +2668,25 @@
 		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
 	}
 
+	var props bazel.BazelTargetModuleProperties
 	attrs := &javaLibraryAttributes{
 		javaCommonAttributes: commonAttrs,
 		Deps:                 deps,
 		Exports:              depLabels.StaticDeps,
 	}
 
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class:        "java_library",
-		Bzl_load_location: "//build/bazel/rules/java:library.bzl",
+	if !bp2BuildInfo.hasKotlinSrcs && len(m.properties.Common_srcs) == 0 {
+		props = bazel.BazelTargetModuleProperties{
+			Rule_class:        "java_library",
+			Bzl_load_location: "//build/bazel/rules/java:library.bzl",
+		}
+	} else {
+		attrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs))
+
+		props = bazel.BazelTargetModuleProperties{
+			Rule_class:        "kt_jvm_library",
+			Bzl_load_location: "@rules_kotlin//kotlin:jvm_library.bzl",
+		}
 	}
 
 	name := m.Name()
@@ -2498,7 +2703,8 @@
 
 // JavaBinaryHostBp2Build is for java_binary_host bp2build.
 func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
-	commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx)
+	commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx)
+	depLabels := bp2BuildInfo.DepLabels
 
 	deps := depLabels.Deps
 	deps.Append(depLabels.StaticDeps)
diff --git a/java/java_test.go b/java/java_test.go
index f06b520..62c2845 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1806,3 +1806,108 @@
 			srcs: ["foo.java"],
 		}`)
 }
+
+func TestJavaApiLibraryAndProviderLink(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",
+	}
+	`
+	ctx, _ := testJavaWithFS(t, `
+		java_api_library {
+			name: "bar1",
+			api_surface: "public",
+			api_contributions: ["foo1"],
+		}
+
+		java_api_library {
+			name: "bar2",
+			api_surface: "system",
+			api_contributions: ["foo1", "foo2"],
+		}
+		`,
+		map[string][]byte{
+			"a/Android.bp": []byte(provider_bp_a),
+			"b/Android.bp": []byte(provider_bp_b),
+		})
+
+	testcases := []struct {
+		moduleName         string
+		sourceTextFileDirs []string
+	}{
+		{
+			moduleName:         "bar1",
+			sourceTextFileDirs: []string{"a/foo1.txt"},
+		},
+		{
+			moduleName:         "bar2",
+			sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt"},
+		},
+	}
+	for _, c := range testcases {
+		m := ctx.ModuleForTests(c.moduleName, "android_common")
+		manifest := m.Output("metalava.sbox.textproto")
+		sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+		manifestCommand := sboxProto.Commands[0].GetCommand()
+		sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
+		android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
+	}
+}
+
+func TestJavaApiLibraryJarGeneration(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",
+	}
+	`
+	ctx, _ := testJavaWithFS(t, `
+		java_api_library {
+			name: "bar1",
+			api_surface: "public",
+			api_contributions: ["foo1"],
+		}
+
+		java_api_library {
+			name: "bar2",
+			api_surface: "system",
+			api_contributions: ["foo1", "foo2"],
+		}
+		`,
+		map[string][]byte{
+			"a/Android.bp": []byte(provider_bp_a),
+			"b/Android.bp": []byte(provider_bp_b),
+		})
+
+	testcases := []struct {
+		moduleName    string
+		outputJarName string
+	}{
+		{
+			moduleName:    "bar1",
+			outputJarName: "bar1/android.jar",
+		},
+		{
+			moduleName:    "bar2",
+			outputJarName: "bar2/android.jar",
+		},
+	}
+	for _, c := range testcases {
+		m := ctx.ModuleForTests(c.moduleName, "android_common")
+		outputs := fmt.Sprint(m.AllOutputs())
+		if !strings.Contains(outputs, c.outputJarName) {
+			t.Errorf("Module output does not contain expected jar %s", c.outputJarName)
+		}
+	}
+}
diff --git a/java/lint.go b/java/lint.go
index 9827159..7a6e5d9 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -190,10 +190,8 @@
 
 	extraCheckModules := l.properties.Lint.Extra_check_modules
 
-	if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
-		if checkOnlyModules := ctx.Config().Getenv("ANDROID_LINT_CHECK_EXTRA_MODULES"); checkOnlyModules != "" {
-			extraCheckModules = strings.Split(checkOnlyModules, ",")
-		}
+	if extraCheckModulesEnv := ctx.Config().Getenv("ANDROID_LINT_CHECK_EXTRA_MODULES"); extraCheckModulesEnv != "" {
+		extraCheckModules = append(extraCheckModules, strings.Split(extraCheckModulesEnv, ",")...)
 	}
 
 	ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
diff --git a/java/plugin.go b/java/plugin.go
index 123dbd4..731dfda 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -66,7 +66,8 @@
 // ConvertWithBp2build is used to convert android_app to Bazel.
 func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
 	pluginName := p.Name()
-	commonAttrs, depLabels := p.convertLibraryAttrsBp2Build(ctx)
+	commonAttrs, bp2BuildInfo := p.convertLibraryAttrsBp2Build(ctx)
+	depLabels := bp2BuildInfo.DepLabels
 
 	deps := depLabels.Deps
 	deps.Append(depLabels.StaticDeps)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index fad1df7..56e5550 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1648,6 +1648,7 @@
 	// shared libs and static libs. So we need to add both of these libs to Libs property.
 	props.Libs = module.properties.Libs
 	props.Libs = append(props.Libs, module.properties.Static_libs...)
+	props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
 	props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
 	props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
 	props.Java_version = module.properties.Java_version
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 096bca8..210bfc3 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -1385,3 +1385,29 @@
 			}
 		`)
 }
+
+func TestJavaSdkLibrary_StubOnlyLibs_PassedToDroidstubs(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForJavaTest,
+		PrepareForTestWithJavaSdkLibraryFiles,
+		FixtureWithLastReleaseApis("foo"),
+	).RunTestWithBp(t, `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			public: {
+				enabled: true,
+			},
+			stub_only_libs: ["bar-lib"],
+		}
+
+		java_library {
+			name: "bar-lib",
+			srcs: ["b.java"],
+		}
+		`)
+
+	// The foo.stubs.source should depend on bar-lib
+	fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
+	android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib")
+}
diff --git a/rust/library.go b/rust/library.go
index c2ce9de..bc9c9aa 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -267,84 +267,94 @@
 var _ libraryInterface = (*libraryDecorator)(nil)
 var _ exportedFlagsProducer = (*libraryDecorator)(nil)
 
-// rust_library produces all rust variants.
+// rust_library produces all Rust variants (rust_library_dylib and
+// rust_library_rlib).
 func RustLibraryFactory() android.Module {
 	module, library := NewRustLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyRust()
 	return module.Init()
 }
 
-// rust_ffi produces all ffi variants.
+// rust_ffi produces all FFI variants (rust_ffi_shared and
+// rust_ffi_static).
 func RustFFIFactory() android.Module {
 	module, library := NewRustLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyFFI()
 	return module.Init()
 }
 
-// rust_library_dylib produces a dylib.
+// rust_library_dylib produces a Rust dylib (Rust crate type "dylib").
 func RustLibraryDylibFactory() android.Module {
 	module, library := NewRustLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyDylib()
 	return module.Init()
 }
 
-// rust_library_rlib produces an rlib.
+// rust_library_rlib produces an rlib (Rust crate type "rlib").
 func RustLibraryRlibFactory() android.Module {
 	module, library := NewRustLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyRlib()
 	return module.Init()
 }
 
-// rust_ffi_shared produces a shared library.
+// rust_ffi_shared produces a shared library (Rust crate type
+// "cdylib").
 func RustFFISharedFactory() android.Module {
 	module, library := NewRustLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyShared()
 	return module.Init()
 }
 
-// rust_ffi_static produces a static library.
+// rust_ffi_static produces a static library (Rust crate type
+// "staticlib").
 func RustFFIStaticFactory() android.Module {
 	module, library := NewRustLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyStatic()
 	return module.Init()
 }
 
-// rust_library_host produces all rust variants.
+// rust_library_host produces all Rust variants for the host
+// (rust_library_dylib_host and rust_library_rlib_host).
 func RustLibraryHostFactory() android.Module {
 	module, library := NewRustLibrary(android.HostSupported)
 	library.BuildOnlyRust()
 	return module.Init()
 }
 
-// rust_ffi_host produces all FFI variants.
+// rust_ffi_host produces all FFI variants for the host
+// (rust_ffi_static_host and rust_ffi_shared_host).
 func RustFFIHostFactory() android.Module {
 	module, library := NewRustLibrary(android.HostSupported)
 	library.BuildOnlyFFI()
 	return module.Init()
 }
 
-// rust_library_dylib_host produces a dylib.
+// rust_library_dylib_host produces a dylib for the host (Rust crate
+// type "dylib").
 func RustLibraryDylibHostFactory() android.Module {
 	module, library := NewRustLibrary(android.HostSupported)
 	library.BuildOnlyDylib()
 	return module.Init()
 }
 
-// rust_library_rlib_host produces an rlib.
+// rust_library_rlib_host produces an rlib for the host (Rust crate
+// type "rlib").
 func RustLibraryRlibHostFactory() android.Module {
 	module, library := NewRustLibrary(android.HostSupported)
 	library.BuildOnlyRlib()
 	return module.Init()
 }
 
-// rust_ffi_static_host produces a static library.
+// rust_ffi_static_host produces a static library for the host (Rust
+// crate type "staticlib").
 func RustFFIStaticHostFactory() android.Module {
 	module, library := NewRustLibrary(android.HostSupported)
 	library.BuildOnlyStatic()
 	return module.Init()
 }
 
-// rust_ffi_shared_host produces an shared library.
+// rust_ffi_shared_host produces an shared library for the host (Rust
+// crate type "cdylib").
 func RustFFISharedHostFactory() android.Module {
 	module, library := NewRustLibrary(android.HostSupported)
 	library.BuildOnlyShared()
diff --git a/rust/library_test.go b/rust/library_test.go
index 4633cc7..e3e4d0f 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -30,11 +30,11 @@
 			srcs: ["foo.rs"],
 			crate_name: "foo",
 		}
-                rust_ffi_host {
-                        name: "libfoo.ffi",
-                        srcs: ["foo.rs"],
-                        crate_name: "foo"
-                }`)
+		rust_ffi_host {
+			name: "libfoo.ffi",
+			srcs: ["foo.rs"],
+			crate_name: "foo"
+		}`)
 
 	// Test all variants are being built.
 	libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
@@ -45,7 +45,7 @@
 	rlibCrateType := "rlib"
 	dylibCrateType := "dylib"
 	sharedCrateType := "cdylib"
-	staticCrateType := "static"
+	staticCrateType := "staticlib"
 
 	// Test crate type for rlib is correct.
 	if !strings.Contains(libfooRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 2f9aee9..108a664 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -409,60 +409,6 @@
 		)
 	})
 
-	t.Run("SOONG_SDK_SNAPSHOT_PREFER=true", func(t *testing.T) {
-		result := android.GroupFixturePreparers(
-			preparer,
-			android.FixtureMergeEnv(map[string]string{
-				"SOONG_SDK_SNAPSHOT_PREFER": "true",
-			}),
-		).RunTest(t)
-
-		checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip")
-
-		CheckSnapshot(t, result, "mysdk", "",
-			checkAndroidBpContents(`
-// This is auto-generated. DO NOT EDIT.
-
-java_import {
-    name: "myjavalib",
-    prefer: true,
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    jars: ["java/myjavalib.jar"],
-}
-			`),
-		)
-	})
-
-	t.Run("SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR=module:build_from_source", func(t *testing.T) {
-		result := android.GroupFixturePreparers(
-			preparer,
-			android.FixtureMergeEnv(map[string]string{
-				"SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR": "module:build_from_source",
-			}),
-		).RunTest(t)
-
-		checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip")
-
-		CheckSnapshot(t, result, "mysdk", "",
-			checkAndroidBpContents(`
-// This is auto-generated. DO NOT EDIT.
-
-java_import {
-    name: "myjavalib",
-    prefer: false,
-    use_source_config_var: {
-        config_namespace: "module",
-        var_name: "build_from_source",
-    },
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    jars: ["java/myjavalib.jar"],
-}
-			`),
-		)
-	})
-
 	t.Run("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE=S", func(t *testing.T) {
 		result := android.GroupFixturePreparers(
 			prepareForSdkTestWithJava,
diff --git a/sdk/update.go b/sdk/update.go
index 92a13fa..baa2033 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -34,41 +34,6 @@
 // Environment variables that affect the generated snapshot
 // ========================================================
 //
-// SOONG_SDK_SNAPSHOT_PREFER
-//     By default every module in the generated snapshot has prefer: false. Building it
-//     with SOONG_SDK_SNAPSHOT_PREFER=true will force them to use prefer: true.
-//
-// SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR
-//     If set this specifies the Soong config var that can be used to control whether the prebuilt
-//     modules from the generated snapshot or the original source modules. Values must be a colon
-//     separated pair of strings, the first of which is the Soong config namespace, and the second
-//     is the name of the variable within that namespace.
-//
-//     The config namespace and var name are used to set the `use_source_config_var` property. That
-//     in turn will cause the generated prebuilts to use the soong config variable to select whether
-//     source or the prebuilt is used.
-//     e.g. If an sdk snapshot is built using:
-//       m SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR=acme:build_from_source sdkextensions-sdk
-//     Then the resulting snapshot will include:
-//       use_source_config_var: {
-//         config_namespace: "acme",
-//         var_name: "build_from_source",
-//       }
-//
-//     Assuming that the config variable is defined in .mk using something like:
-//       $(call add_soong_config_namespace,acme)
-//       $(call add_soong_config_var_value,acme,build_from_source,true)
-//
-//     Then when the snapshot is unpacked in the repository it will have the following behavior:
-//       m droid - will use the sdkextensions-sdk prebuilts if present. Otherwise, it will use the
-//           sources.
-//       m SOONG_CONFIG_acme_build_from_source=true droid - will use the sdkextensions-sdk
-//            sources, if present. Otherwise, it will use the prebuilts.
-//
-//     This is a temporary mechanism to control the prefer flags and will be removed once a more
-//     maintainable solution has been implemented.
-//     TODO(b/174997203): Remove when no longer necessary.
-//
 // SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE
 //     This allows the target build release (i.e. the release version of the build within which
 //     the snapshot will be used) of the snapshot to be specified. If unspecified then it defaults
@@ -2019,29 +1984,12 @@
 
 	// Do not add the prefer property if the member snapshot module is a source module type.
 	moduleCtx := ctx.sdkMemberContext
-	config := moduleCtx.Config()
 	if !memberType.UsesSourceModuleTypeInSnapshot() {
-		// Set the prefer based on the environment variable. This is a temporary work around to allow a
-		// snapshot to be created that sets prefer: true.
-		// TODO(b/174997203): Remove once the ability to select the modules to prefer can be done
-		//  dynamically at build time not at snapshot generation time.
-		prefer := config.IsEnvTrue("SOONG_SDK_SNAPSHOT_PREFER")
-
 		// Set prefer. Setting this to false is not strictly required as that is the default but it does
 		// provide a convenient hook to post-process the generated Android.bp file, e.g. in tests to
 		// check the behavior when a prebuilt is preferred. It also makes it explicit what the default
 		// behavior is for the module.
-		bpModule.insertAfter("name", "prefer", prefer)
-
-		configVar := config.Getenv("SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR")
-		if configVar != "" {
-			parts := strings.Split(configVar, ":")
-			cfp := android.ConfigVarProperties{
-				Config_namespace: proptools.StringPtr(parts[0]),
-				Var_name:         proptools.StringPtr(parts[1]),
-			}
-			bpModule.insertAfter("prefer", "use_source_config_var", cfp)
-		}
+		bpModule.insertAfter("name", "prefer", false)
 	}
 
 	variants := selectApexVariantsWhereAvailable(ctx, member.variants)
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index cfcf804..7a8fca9 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -46,7 +46,6 @@
         "soong-ui-tracer",
     ],
     srcs: [
-        "bazel.go",
         "build.go",
         "cleanbuild.go",
         "config.go",
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
deleted file mode 100644
index bd469a4..0000000
--- a/ui/build/bazel.go
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright 2020 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 build
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"android/soong/bazel"
-	"android/soong/shared"
-	"android/soong/ui/metrics"
-)
-
-func getBazelInfo(ctx Context, config Config, bazelExecutable string, bazelEnv map[string]string, query string) string {
-	infoCmd := Command(ctx, config, "bazel", bazelExecutable)
-
-	if extraStartupArgs, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
-		infoCmd.Args = append(infoCmd.Args, strings.Fields(extraStartupArgs)...)
-	}
-
-	// Obtain the output directory path in the execution root.
-	infoCmd.Args = append(infoCmd.Args,
-		"info",
-		query,
-	)
-
-	for k, v := range bazelEnv {
-		infoCmd.Environment.Set(k, v)
-	}
-
-	infoCmd.Dir = filepath.Join(config.OutDir(), "..")
-
-	queryResult := strings.TrimSpace(string(infoCmd.OutputOrFatal()))
-	return queryResult
-}
-
-// Main entry point to construct the Bazel build command line, environment
-// variables and post-processing steps (e.g. converge output directories)
-func runBazel(ctx Context, config Config) {
-	ctx.BeginTrace(metrics.RunBazel, "bazel")
-	defer ctx.EndTrace()
-
-	// "droid" is the default ninja target.
-	// TODO(b/160568333): stop hardcoding 'droid' to support building any
-	// Ninja target.
-	outputGroups := "droid"
-	if len(config.ninjaArgs) > 0 {
-		// At this stage, the residue slice of args passed to ninja
-		// are the ninja targets to build, which can correspond directly
-		// to ninja_build's output_groups.
-		outputGroups = strings.Join(config.ninjaArgs, ",")
-	}
-
-	// Environment variables are the primary mechanism to pass information from
-	// soong_ui configuration or context to Bazel.
-	bazelEnv := make(map[string]string)
-
-	// Use *_NINJA variables to pass the root-relative path of the combined,
-	// kati-generated, soong-generated, and packaging Ninja files to Bazel.
-	// Bazel reads these from the lunch() repository rule.
-	bazelEnv["COMBINED_NINJA"] = config.CombinedNinjaFile()
-	bazelEnv["KATI_NINJA"] = config.KatiBuildNinjaFile()
-	bazelEnv["PACKAGE_NINJA"] = config.KatiPackageNinjaFile()
-	bazelEnv["SOONG_NINJA"] = config.SoongNinjaFile()
-
-	// NOTE: When Bazel is used, config.DistDir() is rigged to return a fake distdir under config.OutDir()
-	// This is to ensure that Bazel can actually write there. See config.go for more details.
-	bazelEnv["DIST_DIR"] = config.DistDir()
-
-	bazelEnv["SHELL"] = "/bin/bash"
-
-	// `build/bazel/bin/bazel` is the default entry point for executing Bazel in the AOSP
-	// source tree.
-	bazelExecutable := filepath.Join("build", "bazel", "bin", "bazel")
-	cmd := Command(ctx, config, "bazel", bazelExecutable)
-
-	// Append custom startup flags to the Bazel command. Startup flags affect
-	// the Bazel server itself, and any changes to these flags would incur a
-	// restart of the server, losing much of the in-memory incrementality.
-	if extraStartupArgs, ok := cmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
-		cmd.Args = append(cmd.Args, strings.Fields(extraStartupArgs)...)
-	}
-
-	// Start constructing the `build` command.
-	actionName := bazel.BazelNinjaExecRunName
-	cmd.Args = append(cmd.Args,
-		"build",
-		// Use output_groups to select the set of outputs to produce from a
-		// ninja_build target.
-		"--output_groups="+outputGroups,
-		// Generate a performance profile
-		"--profile="+filepath.Join(shared.BazelMetricsFilename(config, actionName)),
-		"--slim_profile=true",
-	)
-
-	if config.UseRBE() {
-		for _, envVar := range []string{
-			// RBE client
-			"RBE_compare",
-			"RBE_exec_strategy",
-			"RBE_invocation_id",
-			"RBE_log_dir",
-			"RBE_num_retries_if_mismatched",
-			"RBE_platform",
-			"RBE_remote_accept_cache",
-			"RBE_remote_update_cache",
-			"RBE_server_address",
-			// TODO: remove old FLAG_ variables.
-			"FLAG_compare",
-			"FLAG_exec_root",
-			"FLAG_exec_strategy",
-			"FLAG_invocation_id",
-			"FLAG_log_dir",
-			"FLAG_platform",
-			"FLAG_remote_accept_cache",
-			"FLAG_remote_update_cache",
-			"FLAG_server_address",
-		} {
-			cmd.Args = append(cmd.Args,
-				"--action_env="+envVar)
-		}
-
-		// We need to calculate --RBE_exec_root ourselves
-		ctx.Println("Getting Bazel execution_root...")
-		cmd.Args = append(cmd.Args, "--action_env=RBE_exec_root="+getBazelInfo(ctx, config, bazelExecutable, bazelEnv, "execution_root"))
-	}
-
-	// Ensure that the PATH environment variable value used in the action
-	// environment is the restricted set computed from soong_ui, and not a
-	// user-provided one, for hermeticity reasons.
-	if pathEnvValue, ok := config.environ.Get("PATH"); ok {
-		cmd.Environment.Set("PATH", pathEnvValue)
-		cmd.Args = append(cmd.Args, "--action_env=PATH="+pathEnvValue)
-	}
-
-	// Allow Bazel actions to see the SHELL variable (passed to Bazel above)
-	cmd.Args = append(cmd.Args, "--action_env=SHELL")
-
-	// Append custom build flags to the Bazel command. Changes to these flags
-	// may invalidate Bazel's analysis cache.
-	// These should be appended as the final args, so that they take precedence.
-	if extraBuildArgs, ok := cmd.Environment.Get("BAZEL_BUILD_ARGS"); ok {
-		cmd.Args = append(cmd.Args, strings.Fields(extraBuildArgs)...)
-	}
-
-	// Append the label of the default ninja_build target.
-	cmd.Args = append(cmd.Args,
-		"//:"+config.TargetProduct()+"-"+config.TargetBuildVariant(),
-	)
-
-	// Execute the command at the root of the directory.
-	cmd.Dir = filepath.Join(config.OutDir(), "..")
-
-	for k, v := range bazelEnv {
-		cmd.Environment.Set(k, v)
-	}
-
-	// Make a human-readable version of the bazelEnv map
-	bazelEnvStringBuffer := new(bytes.Buffer)
-	for k, v := range bazelEnv {
-		fmt.Fprintf(bazelEnvStringBuffer, "%s=%s ", k, v)
-	}
-
-	// Print the implicit command line
-	ctx.Println("Bazel implicit command line: " + strings.Join(cmd.Environment.Environ(), " ") + " " + cmd.Cmd.String() + "\n")
-
-	// Print the explicit command line too
-	ctx.Println("Bazel explicit command line: " + bazelEnvStringBuffer.String() + cmd.Cmd.String() + "\n")
-
-	// Execute the build command.
-	cmd.RunAndStreamOrFatal()
-
-	// Post-processing steps start here. Once the Bazel build completes, the
-	// output files are still stored in the execution root, not in $OUT_DIR.
-	// Ensure that the $OUT_DIR contains the expected set of files by symlinking
-	// the files from the execution root's output direction into $OUT_DIR.
-
-	ctx.Println("Getting Bazel output_path...")
-	outputBasePath := getBazelInfo(ctx, config, bazelExecutable, bazelEnv, "output_path")
-	// TODO: Don't hardcode out/ as the bazel output directory. This is
-	// currently hardcoded as ninja_build.output_root.
-	bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")
-
-	ctx.Println("Populating output directory...")
-	populateOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".")
-}
-
-// For all files F recursively under rootPath/relativePath, creates symlinks
-// such that OutDir/F resolves to rootPath/F via symlinks.
-// NOTE: For distdir paths we rename files instead of creating symlinks, so that the distdir is independent.
-func populateOutdir(ctx Context, config Config, rootPath string, relativePath string) {
-	destDir := filepath.Join(rootPath, relativePath)
-	os.MkdirAll(destDir, 0755)
-	files, err := ioutil.ReadDir(destDir)
-	if err != nil {
-		ctx.Fatal(err)
-	}
-
-	for _, f := range files {
-		// The original Bazel file path
-		destPath := filepath.Join(destDir, f.Name())
-
-		// The desired Soong file path
-		srcPath := filepath.Join(config.OutDir(), relativePath, f.Name())
-
-		destLstatResult, destLstatErr := os.Lstat(destPath)
-		if destLstatErr != nil {
-			ctx.Fatalf("Unable to Lstat dest %s: %s", destPath, destLstatErr)
-		}
-
-		srcLstatResult, srcLstatErr := os.Lstat(srcPath)
-
-		if srcLstatErr == nil {
-			if srcLstatResult.IsDir() && destLstatResult.IsDir() {
-				// src and dest are both existing dirs - recurse on the dest dir contents...
-				populateOutdir(ctx, config, rootPath, filepath.Join(relativePath, f.Name()))
-			} else {
-				// Ignore other pre-existing src files (could be pre-existing files, directories, symlinks, ...)
-				// This can arise for files which are generated under OutDir outside of soong_build, such as .bootstrap files.
-				// FIXME: This might cause a problem later e.g. if a symlink in the build graph changes...
-			}
-		} else {
-			if !os.IsNotExist(srcLstatErr) {
-				ctx.Fatalf("Unable to Lstat src %s: %s", srcPath, srcLstatErr)
-			}
-
-			if strings.Contains(destDir, config.DistDir()) {
-				// We need to make a "real" file/dir instead of making a symlink (because the distdir can't have symlinks)
-				// Rename instead of copy in order to save disk space.
-				if err := os.Rename(destPath, srcPath); err != nil {
-					ctx.Fatalf("Unable to rename %s -> %s due to error %s", srcPath, destPath, err)
-				}
-			} else {
-				// src does not exist, so try to create a src -> dest symlink (i.e. a Soong path -> Bazel path symlink)
-				if err := os.Symlink(destPath, srcPath); err != nil {
-					ctx.Fatalf("Unable to create symlink %s -> %s due to error %s", srcPath, destPath, err)
-				}
-			}
-		}
-	}
-}
diff --git a/ui/build/build.go b/ui/build/build.go
index b9bd898..d49a754 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -90,7 +90,7 @@
 	}
 }
 
-// These are bitmasks which can be used to check whether various flags are set e.g. whether to use Bazel.
+// These are bitmasks which can be used to check whether various flags are set
 const (
 	_ = iota
 	// Whether to run the kati config step.
@@ -102,9 +102,7 @@
 	// Whether to include the kati-generated ninja file in the combined ninja.
 	RunKatiNinja = 1 << iota
 	// Whether to run ninja on the combined ninja.
-	RunNinja = 1 << iota
-	// Whether to run bazel on the combined ninja.
-	RunBazel      = 1 << iota
+	RunNinja      = 1 << iota
 	RunBuildTests = 1 << iota
 	RunAll        = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja
 )
@@ -324,11 +322,6 @@
 
 		runNinjaForBuild(ctx, config)
 	}
-
-	// Currently, using Bazel requires Kati and Soong to run first, so check whether to run Bazel last.
-	if what&RunBazel != 0 {
-		runBazel(ctx, config)
-	}
 }
 
 func evaluateWhatToRun(config Config, verboseln func(v ...interface{})) int {
diff --git a/ui/build/config.go b/ui/build/config.go
index de10112..c98601e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -82,6 +82,7 @@
 	skipSoong       bool
 	skipNinja       bool
 	skipSoongTests  bool
+	searchApiDir    bool // Scan the Android.bp files generated in out/api_surfaces
 
 	// From the product config
 	katiArgs        []string
@@ -738,6 +739,8 @@
 			c.bazelDevMode = true
 		} else if arg == "--bazel-mode-staging" {
 			c.bazelStagingMode = true
+		} else if arg == "--search-api-dir" {
+			c.searchApiDir = true
 		} else if len(arg) > 0 && arg[0] == '-' {
 			parseArgNum := func(def int) int {
 				if len(arg) > 2 {
@@ -896,10 +899,18 @@
 	return filepath.Join(c.OutDir(), "bazel")
 }
 
+func (c *configImpl) bazelOutputBase() string {
+	return filepath.Join(c.BazelOutDir(), "output")
+}
+
 func (c *configImpl) SoongOutDir() string {
 	return filepath.Join(c.OutDir(), "soong")
 }
 
+func (c *configImpl) ApiSurfacesOutDir() string {
+	return filepath.Join(c.OutDir(), "api_surfaces")
+}
+
 func (c *configImpl) PrebuiltOS() string {
 	switch runtime.GOOS {
 	case "linux":
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index adc56ac..b3b3866 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -154,10 +154,7 @@
 	"HOST_CROSS_OS",
 	"BUILD_ID",
 	"OUT_DIR",
-	"SOONG_SDK_SNAPSHOT_PREFER",
 	"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE",
-	"SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR",
-	"SOONG_SDK_SNAPSHOT_VERSION",
 }
 
 func Banner(make_vars map[string]string) string {
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 4d6ad42..3f628cf 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -63,7 +63,7 @@
 	// Set up configuration parameters for the Finder cache.
 	cacheParams := finder.CacheParams{
 		WorkingDirectory: dir,
-		RootDirs:         []string{"."},
+		RootDirs:         androidBpSearchDirs(config),
 		FollowSymlinks:   config.environ.IsEnvTrue("ALLOW_BP_UNDER_SYMLINKS"),
 		ExcludeDirs:      []string{".git", ".repo"},
 		PruneFiles:       pruneFiles,
@@ -100,6 +100,15 @@
 	return f
 }
 
+func androidBpSearchDirs(config Config) []string {
+	dirs := []string{"."} // always search from root of source tree.
+	if config.searchApiDir {
+		// Search in out/api_surfaces
+		dirs = append(dirs, config.ApiSurfacesOutDir())
+	}
+	return dirs
+}
+
 // Finds the list of Bazel-related files (BUILD, WORKSPACE and Starlark) in the tree.
 func findBazelFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
 	matches := []string{}
diff --git a/ui/build/sandbox_config.go b/ui/build/sandbox_config.go
index 1b46459..1d32d86 100644
--- a/ui/build/sandbox_config.go
+++ b/ui/build/sandbox_config.go
@@ -27,6 +27,15 @@
 	return sc.srcDirIsRO
 }
 
+// Return the mount flag of the source directory in the nsjail command
+func (sc *SandboxConfig) SrcDirMountFlag() string {
+	ret := "-B" // Read-write
+	if sc.SrcDirIsRO() {
+		ret = "-R" // Read-only
+	}
+	return ret
+}
+
 func (sc *SandboxConfig) SetSrcDirRWAllowlist(allowlist []string) {
 	sc.srcDirRWAllowlist = allowlist
 }
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 5b2046e..edb3b66 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -101,7 +101,7 @@
 			// srcDir is /tmp/.* in integration tests, which is a child dir of /tmp
 			// nsjail throws an error if a child dir is mounted before its parent
 			"-B", "/tmp",
-			"-B", sandboxConfig.srcDir,
+			c.config.sandboxConfig.SrcDirMountFlag(), sandboxConfig.srcDir,
 			"-B", sandboxConfig.outDir,
 		}
 
@@ -148,13 +148,6 @@
 func (c *Cmd) wrapSandbox() {
 	wd, _ := os.Getwd()
 
-	var srcDirMountFlag string
-	if c.config.sandboxConfig.SrcDirIsRO() {
-		srcDirMountFlag = "-R"
-	} else {
-		srcDirMountFlag = "-B" //Read-Write
-	}
-
 	sandboxArgs := []string{
 		// The executable to run
 		"-x", c.Path,
@@ -195,7 +188,7 @@
 		"-B", "/tmp",
 
 		// Mount source
-		srcDirMountFlag, sandboxConfig.srcDir,
+		c.config.sandboxConfig.SrcDirMountFlag(), sandboxConfig.srcDir,
 
 		//Mount out dir as read-write
 		"-B", sandboxConfig.outDir,
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 4aded17..c0bee4e 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -302,7 +302,7 @@
 	)
 
 	bp2buildWorkspaceInvocation.Inputs = append(bp2buildWorkspaceInvocation.Inputs,
-		config.Bp2BuildFilesMarkerFile())
+		config.Bp2BuildFilesMarkerFile(), filepath.Join(config.FileListDir(), "bazel.list"))
 
 	jsonModuleGraphInvocation := primaryBuilderInvocation(
 		config,
@@ -418,7 +418,7 @@
 	// Bazel's HOME var is set to an output subdirectory which doesn't exist. This
 	// prevents Bazel from file I/O in the actual user HOME directory.
 	soongBuildEnv.Set("BAZEL_HOME", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazelhome")))
-	soongBuildEnv.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
+	soongBuildEnv.Set("BAZEL_OUTPUT_BASE", config.bazelOutputBase())
 	soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
 	soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
 	soongBuildEnv.Set("LOG_DIR", config.LogsDir())
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 86c8568..2efc732 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -18,14 +18,44 @@
 	"bufio"
 	"fmt"
 	"path/filepath"
+	"regexp"
 	"runtime"
 	"sort"
 	"strings"
+	"sync"
 
 	"android/soong/ui/metrics"
 	"android/soong/ui/status"
 )
 
+var (
+	// bazel output paths are in __main__/bazel-out/<config-specific-path>/bin
+	bazelOutputPathRegexOnce sync.Once
+	bazelOutputPathRegexp    *regexp.Regexp
+)
+
+func bazelOutputPathPattern(config Config) *regexp.Regexp {
+	bazelOutputPathRegexOnce.Do(func() {
+		// Bazel output files are in <Bazel output base>/execroot/__main__/bazel-out/<config>/bin
+		bazelOutRoot := filepath.Join(regexp.QuoteMeta(config.bazelOutputBase()), "execroot", "__main__", "bazel-out")
+		bazelOutputPathRegexp = regexp.MustCompile(bazelOutRoot + "/[^/]+/bin")
+	})
+	return bazelOutputPathRegexp
+}
+
+func ignoreBazelPath(config Config, path string) bool {
+	bazelRoot := filepath.Join(config.bazelOutputBase(), "execroot")
+	// Don't check bazel output regexp unless it is Bazel path
+	if strings.HasPrefix(path, bazelRoot) {
+		bazelOutputRegexp := bazelOutputPathPattern(config)
+		// if the file is a bazel path that is _not_ a Bazel generated file output, we rely on Bazel to
+		// ensure the paths to exist. If it _is_ a Bazel output path, we expect that it should be built
+		// by Ninja.
+		return !bazelOutputRegexp.MatchString(path)
+	}
+	return false
+}
+
 // Checks for files in the out directory that have a rule that depends on them but no rule to
 // create them. This catches a common set of build failures where a rule to generate a file is
 // deleted (either by deleting a module in an Android.mk file, or by modifying the build system
@@ -97,6 +127,10 @@
 			// full build rules in the primary build.ninja file.
 			continue
 		}
+
+		if ignoreBazelPath(config, line) {
+			continue
+		}
 		danglingRules[line] = true
 	}