Merge "Merge rust_protobuf and rust_grpcio module types."
diff --git a/android/apex.go b/android/apex.go
index 4a71b40..f6eca86 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -153,13 +153,12 @@
 	// run.
 	DirectlyInAnyApex() bool
 
-	// Returns true in the primary variant of a module if _any_ variant of the module is
-	// directly in any apex. This includes host, arch, asan, etc. variants. It is unused in any
-	// variant that is not the primary variant. Ideally this wouldn't be used, as it incorrectly
-	// mixes arch variants if only one arch is in an apex, but a few places depend on it, for
-	// example when an ASAN variant is created before the apexMutator. Call this after
-	// apex.apexMutator is run.
-	AnyVariantDirectlyInAnyApex() bool
+	// NotInPlatform tells whether or not this module is included in an APEX and therefore
+	// shouldn't be exposed to the platform (i.e. outside of the APEX) directly. A module is
+	// considered to be included in an APEX either when there actually is an APEX that
+	// explicitly has the module as its dependency or the module is not available to the
+	// platform, which indicates that the module belongs to at least one or more other APEXes.
+	NotInPlatform() bool
 
 	// Tests if this module could have APEX variants. Even when a module type implements
 	// ApexModule interface, APEX variants are created only for the module instances that return
@@ -221,7 +220,12 @@
 	// See ApexModule.DirectlyInAnyApex()
 	DirectlyInAnyApex bool `blueprint:"mutated"`
 
-	// See ApexModule.AnyVariantDirectlyInAnyApex()
+	// AnyVariantDirectlyInAnyApex is true in the primary variant of a module if _any_ variant
+	// of the module is directly in any apex. This includes host, arch, asan, etc. variants. It
+	// is unused in any variant that is not the primary variant. Ideally this wouldn't be used,
+	// as it incorrectly mixes arch variants if only one arch is in an apex, but a few places
+	// depend on it, for example when an ASAN variant is created before the apexMutator. Call
+	// this after apex.apexMutator is run.
 	AnyVariantDirectlyInAnyApex bool `blueprint:"mutated"`
 
 	// See ApexModule.NotAvailableForPlatform()
@@ -302,8 +306,8 @@
 }
 
 // Implements ApexModule
-func (m *ApexModuleBase) AnyVariantDirectlyInAnyApex() bool {
-	return m.ApexProperties.AnyVariantDirectlyInAnyApex
+func (m *ApexModuleBase) NotInPlatform() bool {
+	return m.ApexProperties.AnyVariantDirectlyInAnyApex || !m.AvailableFor(AvailableToPlatform)
 }
 
 // Implements ApexModule
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 7d8d12f..d810726 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -26,6 +26,8 @@
 	"strings"
 	"sync"
 
+	"android/soong/bazel"
+	"android/soong/shared"
 	"github.com/google/blueprint/bootstrap"
 )
 
@@ -68,6 +70,7 @@
 	outputBase   string
 	workspaceDir string
 	buildDir     string
+	metricsDir   string
 
 	requests     map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
 	requestMutex sync.Mutex         // requests can be written in parallel
@@ -153,6 +156,11 @@
 	} else {
 		missingEnvVars = append(missingEnvVars, "BAZEL_WORKSPACE")
 	}
+	if len(c.Getenv("BAZEL_METRICS_DIR")) > 1 {
+		bazelCtx.metricsDir = c.Getenv("BAZEL_METRICS_DIR")
+	} else {
+		missingEnvVars = append(missingEnvVars, "BAZEL_METRICS_DIR")
+	}
 	if len(missingEnvVars) > 0 {
 		return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars))
 	} else {
@@ -160,6 +168,10 @@
 	}
 }
 
+func (context *bazelContext) BazelMetricsDir() string {
+	return context.metricsDir
+}
+
 func (context *bazelContext) BazelEnabled() bool {
 	return true
 }
@@ -189,12 +201,13 @@
 	return ""
 }
 
-func (context *bazelContext) issueBazelCommand(command string, labels []string,
+func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command string, labels []string,
 	extraFlags ...string) (string, error) {
 
 	cmdFlags := []string{"--output_base=" + context.outputBase, command}
 	cmdFlags = append(cmdFlags, labels...)
 	cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir())
+	cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(context, runName))
 	cmdFlags = append(cmdFlags, extraFlags...)
 
 	bazelCmd := exec.Command(context.bazelPath, cmdFlags...)
@@ -341,7 +354,7 @@
 		return err
 	}
 	buildroot_label := "//:buildroot"
-	cqueryOutput, err = context.issueBazelCommand("cquery",
+	cqueryOutput, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
 		[]string{fmt.Sprintf("deps(%s)", buildroot_label)},
 		"--output=starlark",
 		"--starlark:file="+cquery_file_relpath)
@@ -371,7 +384,7 @@
 	// bazel actions should either be added to the Ninja file and executed later,
 	// or bazel should handle execution.
 	// TODO(cparsons): Use --target_pattern_file to avoid command line limits.
-	_, err = context.issueBazelCommand("build", []string{buildroot_label})
+	_, err = context.issueBazelCommand(bazel.BazelBuildPhonyRootRunName, "build", []string{buildroot_label})
 
 	if err != nil {
 		return err
diff --git a/android/config.go b/android/config.go
index 453e074..89467d8 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1324,10 +1324,6 @@
 	return c.productVariables.ProductPrivateSepolicyDirs
 }
 
-func (c *config) ProductCompatibleProperty() bool {
-	return Bool(c.productVariables.ProductCompatibleProperty)
-}
-
 func (c *config) MissingUsesLibraries() []string {
 	return c.productVariables.MissingUsesLibraries
 }
diff --git a/android/defs.go b/android/defs.go
index f5bd362..38ecb05 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -20,7 +20,7 @@
 	"testing"
 
 	"github.com/google/blueprint"
-	_ "github.com/google/blueprint/bootstrap"
+	"github.com/google/blueprint/bootstrap"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -200,3 +200,8 @@
 
 	return content
 }
+
+// GlobToListFileRule creates a rule that writes a list of files matching a pattern to a file.
+func GlobToListFileRule(ctx ModuleContext, pattern string, excludes []string, file WritablePath) {
+	bootstrap.GlobFile(ctx.blueprintModuleContext(), pattern, excludes, file.String())
+}
diff --git a/android/module.go b/android/module.go
index 0bd64ed..429f311 100644
--- a/android/module.go
+++ b/android/module.go
@@ -331,6 +331,8 @@
 type ModuleContext interface {
 	BaseModuleContext
 
+	blueprintModuleContext() blueprint.ModuleContext
+
 	// Deprecated: use ModuleContext.Build instead.
 	ModuleBuild(pctx PackageContext, params ModuleBuildParams)
 
@@ -2596,6 +2598,10 @@
 	m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
 }
 
+func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
+	return m.bp
+}
+
 // SrcIsModule decodes module references in the format ":name" into the module name, or empty string if the input
 // was not a module reference.
 func SrcIsModule(s string) (module string) {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index bb98ed4..8114a65 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"reflect"
+	"strings"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -74,6 +75,12 @@
 	srcsPropertyName string
 }
 
+// RemoveOptionalPrebuiltPrefix returns the result of removing the "prebuilt_" prefix from the
+// supplied name if it has one, or returns the name unmodified if it does not.
+func RemoveOptionalPrebuiltPrefix(name string) string {
+	return strings.TrimPrefix(name, "prebuilt_")
+}
+
 func (p *Prebuilt) Name(name string) string {
 	return "prebuilt_" + name
 }
diff --git a/android/variable.go b/android/variable.go
index aed145c..93dac3d 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -338,7 +338,6 @@
 
 	ProductPublicSepolicyDirs  []string `json:",omitempty"`
 	ProductPrivateSepolicyDirs []string `json:",omitempty"`
-	ProductCompatibleProperty  *bool    `json:",omitempty"`
 
 	ProductVndkVersion *string `json:",omitempty"`
 
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index a2f8797..c5f2bf8 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -209,6 +209,7 @@
 libadbd(minSdkVersion:(no version))
 libadbd_core(minSdkVersion:(no version))
 libadbd_services(minSdkVersion:(no version))
+liballoc.rust_sysroot(minSdkVersion:29)
 libamrextractor(minSdkVersion:29)
 libapp_processes_protos_lite(minSdkVersion:(no version))
 libarect(minSdkVersion:29)
@@ -223,6 +224,8 @@
 libavcenc(minSdkVersion:29)
 libavservices_minijail(minSdkVersion:29)
 libbacktrace_headers(minSdkVersion:apex_inherit)
+libbacktrace_rs.rust_sysroot(minSdkVersion:29)
+libbacktrace_sys.rust_sysroot(minSdkVersion:29)
 libbase(minSdkVersion:29)
 libbase_headers(minSdkVersion:29)
 libbinder_headers(minSdkVersion:29)
@@ -238,6 +241,8 @@
 libc_headers(minSdkVersion:apex_inherit)
 libc_headers_arch(minSdkVersion:apex_inherit)
 libcap(minSdkVersion:29)
+libcfg_if(minSdkVersion:29)
+libcfg_if.rust_sysroot(minSdkVersion:29)
 libclang_rt.hwasan-aarch64-android.llndk(minSdkVersion:(no version))
 libcodec2(minSdkVersion:29)
 libcodec2_headers(minSdkVersion:29)
@@ -276,6 +281,8 @@
 libcodec2_soft_vp9dec(minSdkVersion:29)
 libcodec2_soft_vp9enc(minSdkVersion:29)
 libcodec2_vndk(minSdkVersion:29)
+libcompiler_builtins.rust_sysroot(minSdkVersion:29)
+libcore.rust_sysroot(minSdkVersion:29)
 libcrypto(minSdkVersion:29)
 libcrypto_static(minSdkVersion:(no version))
 libcrypto_utils(minSdkVersion:(no version))
@@ -295,7 +302,9 @@
 libfmq-base(minSdkVersion:29)
 libFraunhoferAAC(minSdkVersion:29)
 libgav1(minSdkVersion:29)
+libgcc(minSdkVersion:(no version))
 libgcc_stripped(minSdkVersion:(no version))
+libgetopts(minSdkVersion:29)
 libgralloctypes(minSdkVersion:29)
 libgrallocusage(minSdkVersion:29)
 libgsm(minSdkVersion:apex_inherit)
@@ -304,6 +313,7 @@
 libgui_headers(minSdkVersion:29)
 libhardware(minSdkVersion:29)
 libhardware_headers(minSdkVersion:29)
+libhashbrown.rust_sysroot(minSdkVersion:29)
 libhevcdec(minSdkVersion:29)
 libhevcenc(minSdkVersion:29)
 libhidlbase(minSdkVersion:29)
@@ -313,9 +323,14 @@
 libion(minSdkVersion:29)
 libjavacrypto(minSdkVersion:29)
 libjsoncpp(minSdkVersion:29)
+liblazy_static(minSdkVersion:29)
+liblibc(minSdkVersion:29)
+liblibc.rust_sysroot(minSdkVersion:29)
 libLibGuiProperties(minSdkVersion:29)
+liblibm(minSdkVersion:29)
 liblog(minSdkVersion:(no version))
 liblog_headers(minSdkVersion:29)
+liblog_rust(minSdkVersion:29)
 liblua(minSdkVersion:(no version))
 liblz4(minSdkVersion:(no version))
 libm(minSdkVersion:(no version))
@@ -346,23 +361,32 @@
 libnetd_resolv(minSdkVersion:29)
 libnetdbinder_utils_headers(minSdkVersion:29)
 libnetdutils(minSdkVersion:29)
+libnetjniutils(minSdkVersion:29)
 libnetworkstackutilsjni(minSdkVersion:29)
 libneuralnetworks(minSdkVersion:(no version))
 libneuralnetworks_common(minSdkVersion:(no version))
 libneuralnetworks_headers(minSdkVersion:(no version))
 liboggextractor(minSdkVersion:29)
+libonce_cell(minSdkVersion:29)
 libopus(minSdkVersion:29)
+libpanic_unwind.rust_sysroot(minSdkVersion:29)
 libprocessgroup(minSdkVersion:29)
 libprocessgroup_headers(minSdkVersion:29)
 libprocpartition(minSdkVersion:(no version))
+libprofiler_builtins.rust_sysroot(minSdkVersion:29)
 libprotobuf-cpp-lite(minSdkVersion:29)
 libprotobuf-java-lite(minSdkVersion:current)
 libprotobuf-java-nano(minSdkVersion:9)
 libprotoutil(minSdkVersion:(no version))
 libqemu_pipe(minSdkVersion:(no version))
+libquiche_ffi(minSdkVersion:29)
+libring(minSdkVersion:29)
+libring-core(minSdkVersion:29)
+librustc_demangle.rust_sysroot(minSdkVersion:29)
 libsfplugin_ccodec_utils(minSdkVersion:29)
 libsonivoxwithoutjet(minSdkVersion:29)
 libspeexresampler(minSdkVersion:29)
+libspin(minSdkVersion:29)
 libssl(minSdkVersion:29)
 libstagefright_amrnb_common(minSdkVersion:29)
 libstagefright_amrnbdec(minSdkVersion:29)
@@ -383,6 +407,7 @@
 libstagefright_m4vh263enc(minSdkVersion:29)
 libstagefright_metadatautils(minSdkVersion:29)
 libstagefright_mp3dec(minSdkVersion:29)
+libstagefright_mp3dec_headers(minSdkVersion:29)
 libstagefright_mpeg2extractor(minSdkVersion:29)
 libstagefright_mpeg2support_nocrypto(minSdkVersion:29)
 libstats_jni(minSdkVersion:(no version))
@@ -392,8 +417,11 @@
 libstatspush_compat(minSdkVersion:29)
 libstatssocket(minSdkVersion:(no version))
 libstatssocket_headers(minSdkVersion:29)
+libstd(minSdkVersion:29)
 libsystem_headers(minSdkVersion:apex_inherit)
 libsysutils(minSdkVersion:apex_inherit)
+libterm(minSdkVersion:29)
+libtest(minSdkVersion:29)
 libtetherutilsjni(minSdkVersion:30)
 libtetherutilsjni(minSdkVersion:current)
 libtextclassifier(minSdkVersion:(no version))
@@ -404,6 +432,9 @@
 libtflite_static(minSdkVersion:(no version))
 libui(minSdkVersion:29)
 libui_headers(minSdkVersion:29)
+libunicode_width.rust_sysroot(minSdkVersion:29)
+libuntrusted(minSdkVersion:29)
+libunwind.rust_sysroot(minSdkVersion:29)
 libunwind_llvm(minSdkVersion:apex_inherit)
 libutf(minSdkVersion:(no version))
 libutils(minSdkVersion:apex_inherit)
@@ -420,6 +451,7 @@
 media_plugin_headers(minSdkVersion:29)
 mediaswcodec(minSdkVersion:29)
 metrics-constants-protos(minSdkVersion:29)
+modules-utils-build(minSdkVersion:29)
 ndk_crtbegin_so.19(minSdkVersion:(no version))
 ndk_crtbegin_so.21(minSdkVersion:(no version))
 ndk_crtbegin_so.27(minSdkVersion:(no version))
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 6c76ad3f..e7f8b7f 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -425,6 +425,15 @@
 				for _, dist := range data.Entries.GetDistForGoals(a) {
 					fmt.Fprintf(w, dist)
 				}
+
+				if a.coverageOutputPath.String() != "" {
+					goal := "apps_only"
+					distFile := a.coverageOutputPath.String()
+					fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
+						" $(call dist-for-goals,%s,%s:ndk_apis_usedby_apex/$(notdir %s))\n"+
+						"endif",
+						goal, distFile, distFile)
+				}
 			}
 		}}
 }
diff --git a/apex/apex.go b/apex/apex.go
index 2a81b9b..261284c 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -728,7 +728,9 @@
 
 var ApexBundleInfoProvider = blueprint.NewMutatorProvider(ApexBundleInfo{}, "apex_info")
 
-// apexInfoMutator is responsible for collecting modules that need to have apex variants. They are
+var _ ApexInfoMutator = (*apexBundle)(nil)
+
+// ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are
 // identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and
 // indirect) dependencies are collected. But a few types of modules that shouldn't be included in
 // the apexBundle (e.g. stub libraries) are not collected. Note that a single module can be depended
@@ -739,15 +741,7 @@
 // The apexMutator uses that list to create module variants for the apexes to which it belongs.
 // The relationship between module variants and apexes is not one-to-one as variants will be
 // shared between compatible apexes.
-func apexInfoMutator(mctx android.TopDownMutatorContext) {
-	if !mctx.Module().Enabled() {
-		return
-	}
-
-	a, ok := mctx.Module().(*apexBundle)
-	if !ok {
-		return
-	}
+func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
 
 	// The VNDK APEX is special. For the APEX, the membership is described in a very different
 	// way. There is no dependency from the VNDK APEX to the VNDK libraries. Instead, VNDK
@@ -826,6 +820,25 @@
 	})
 }
 
+type ApexInfoMutator interface {
+	// ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are
+	// depended upon by an apex and which require an apex specific variant.
+	ApexInfoMutator(android.TopDownMutatorContext)
+}
+
+// apexInfoMutator delegates the work of identifying which modules need an ApexInfo and apex
+// specific variant to modules that support the ApexInfoMutator.
+func apexInfoMutator(mctx android.TopDownMutatorContext) {
+	if !mctx.Module().Enabled() {
+		return
+	}
+
+	if a, ok := mctx.Module().(ApexInfoMutator); ok {
+		a.ApexInfoMutator(mctx)
+		return
+	}
+}
+
 // apexUniqueVariationsMutator checks if any dependencies use unique apex variations. If so, use
 // unique apex variations for this module. See android/apex.go for more about unique apex variant.
 // TODO(jiyong): move this to android/apex.go?
@@ -2165,7 +2178,7 @@
 func normalizeModuleName(moduleName string) string {
 	// Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build
 	// system. Trim the prefix for the check since they are confusing
-	moduleName = strings.TrimPrefix(moduleName, "prebuilt_")
+	moduleName = android.RemoveOptionalPrebuiltPrefix(moduleName)
 	if strings.HasPrefix(moduleName, "libclang_rt.") {
 		// This module has many arch variants that depend on the product being built.
 		// We don't want to list them all
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ab8ae16..f71e7ef 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -15,6 +15,7 @@
 package apex
 
 import (
+	"fmt"
 	"io/ioutil"
 	"os"
 	"path"
@@ -6411,6 +6412,160 @@
 	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
 }
 
+func TestPrebuiltStubLibDep(t *testing.T) {
+	bpBase := `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib"],
+		}
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			apex_available: ["myapex"],
+			shared_libs: ["stublib"],
+			system_shared_libs: [],
+		}
+		apex {
+			name: "otherapex",
+			enabled: %s,
+			key: "myapex.key",
+			native_shared_libs: ["stublib"],
+		}
+	`
+
+	stublibSourceBp := `
+		cc_library {
+			name: "stublib",
+			srcs: ["mylib.cpp"],
+			apex_available: ["otherapex"],
+			system_shared_libs: [],
+			stl: "none",
+			stubs: {
+				versions: ["1"],
+			},
+		}
+	`
+
+	stublibPrebuiltBp := `
+		cc_prebuilt_library_shared {
+			name: "stublib",
+			srcs: ["prebuilt.so"],
+			apex_available: ["otherapex"],
+			stubs: {
+				versions: ["1"],
+			},
+			%s
+		}
+	`
+
+	tests := []struct {
+		name             string
+		stublibBp        string
+		usePrebuilt      bool
+		modNames         []string // Modules to collect AndroidMkEntries for
+		otherApexEnabled []string
+	}{
+		{
+			name:             "only_source",
+			stublibBp:        stublibSourceBp,
+			usePrebuilt:      false,
+			modNames:         []string{"stublib"},
+			otherApexEnabled: []string{"true", "false"},
+		},
+		{
+			name:             "source_preferred",
+			stublibBp:        stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, ""),
+			usePrebuilt:      false,
+			modNames:         []string{"stublib", "prebuilt_stublib"},
+			otherApexEnabled: []string{"true", "false"},
+		},
+		{
+			name:             "prebuilt_preferred",
+			stublibBp:        stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, "prefer: true,"),
+			usePrebuilt:      true,
+			modNames:         []string{"stublib", "prebuilt_stublib"},
+			otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt.
+		},
+		{
+			name:             "only_prebuilt",
+			stublibBp:        fmt.Sprintf(stublibPrebuiltBp, ""),
+			usePrebuilt:      true,
+			modNames:         []string{"stublib"},
+			otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt.
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			for _, otherApexEnabled := range test.otherApexEnabled {
+				t.Run("otherapex_enabled_"+otherApexEnabled, func(t *testing.T) {
+					ctx, config := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
+
+					type modAndMkEntries struct {
+						mod       *cc.Module
+						mkEntries android.AndroidMkEntries
+					}
+					entries := []*modAndMkEntries{}
+
+					// Gather shared lib modules that are installable
+					for _, modName := range test.modNames {
+						for _, variant := range ctx.ModuleVariantsForTests(modName) {
+							if !strings.HasPrefix(variant, "android_arm64_armv8-a_shared") {
+								continue
+							}
+							mod := ctx.ModuleForTests(modName, variant).Module().(*cc.Module)
+							if !mod.Enabled() || mod.IsSkipInstall() {
+								continue
+							}
+							for _, ent := range android.AndroidMkEntriesForTest(t, config, "", mod) {
+								if ent.Disabled {
+									continue
+								}
+								entries = append(entries, &modAndMkEntries{
+									mod:       mod,
+									mkEntries: ent,
+								})
+							}
+						}
+					}
+
+					var entry *modAndMkEntries = nil
+					for _, ent := range entries {
+						if strings.Join(ent.mkEntries.EntryMap["LOCAL_MODULE"], ",") == "stublib" {
+							if entry != nil {
+								t.Errorf("More than one AndroidMk entry for \"stublib\": %s and %s", entry.mod, ent.mod)
+							} else {
+								entry = ent
+							}
+						}
+					}
+
+					if entry == nil {
+						t.Errorf("AndroidMk entry for \"stublib\" missing")
+					} else {
+						isPrebuilt := entry.mod.Prebuilt() != nil
+						if isPrebuilt != test.usePrebuilt {
+							t.Errorf("Wrong module for \"stublib\" AndroidMk entry: got prebuilt %t, want prebuilt %t", isPrebuilt, test.usePrebuilt)
+						}
+						if !entry.mod.IsStubs() {
+							t.Errorf("Module for \"stublib\" AndroidMk entry isn't a stub: %s", entry.mod)
+						}
+						if entry.mkEntries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"] != nil {
+							t.Errorf("AndroidMk entry for \"stublib\" has LOCAL_NOT_AVAILABLE_FOR_PLATFORM set: %+v", entry.mkEntries)
+						}
+					}
+				})
+			}
+		})
+	}
+}
+
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
diff --git a/bazel/Android.bp b/bazel/Android.bp
index 0113726..d557be5 100644
--- a/bazel/Android.bp
+++ b/bazel/Android.bp
@@ -2,6 +2,7 @@
     name: "soong-bazel",
     pkgPath: "android/soong/bazel",
     srcs: [
+        "constants.go",
         "properties.go",
     ],
     pluginFor: [
diff --git a/bazel/constants.go b/bazel/constants.go
new file mode 100644
index 0000000..15c75cf
--- /dev/null
+++ b/bazel/constants.go
@@ -0,0 +1,26 @@
+package bazel
+
+type RunName string
+
+// Below is a list bazel execution run names used through out the
+// Platform Build systems. Each run name represents an unique key
+// to query the bazel metrics.
+const (
+	// Perform a bazel build of the phony root to generate symlink forests
+	// for dependencies of the bazel build.
+	BazelBuildPhonyRootRunName = RunName("bazel-build-phony-root")
+
+	// Perform aquery of the bazel build root to retrieve action information.
+	AqueryBuildRootRunName = RunName("aquery-buildroot")
+
+	// Perform cquery of the Bazel build root and its dependencies.
+	CqueryBuildRootRunName = RunName("cquery-buildroot")
+
+	// Run bazel as a ninja executer
+	BazelNinjaExecRunName = RunName("bazel-ninja-exec")
+)
+
+// String returns the name of the run.
+func (c RunName) String() string {
+	return string(c)
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 4f4b047..187a2ff 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -46,7 +46,7 @@
 	InRamdisk() bool
 	InVendorRamdisk() bool
 	InRecovery() bool
-	AnyVariantDirectlyInAnyApex() bool
+	NotInPlatform() bool
 }
 
 type subAndroidMkProvider interface {
@@ -281,10 +281,15 @@
 			}
 		})
 	}
-	if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.AnyVariantDirectlyInAnyApex() &&
+	// If a library providing a stub is included in an APEX, the private APIs of the library
+	// is accessible only inside the APEX. From outside of the APEX, clients can only use the
+	// public APIs via the stub. To enforce this, the (latest version of the) stub gets the
+	// name of the library. The impl library instead gets the `.bootstrap` suffix to so that
+	// they can be exceptionally used directly when APEXes are not available (e.g. during the
+	// very early stage in the boot process).
+	if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.NotInPlatform() &&
 		!ctx.InRamdisk() && !ctx.InVendorRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() && !ctx.static() {
 		if library.buildStubs() && library.isLatestStubVersion() {
-			// reference the latest version via its name without suffix when it is provided by apex
 			entries.SubName = ""
 		}
 		if !library.buildStubs() {
diff --git a/cc/cc.go b/cc/cc.go
index 9383e39..89f32f1 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -79,7 +79,6 @@
 		ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator).Parallel()
 
 		ctx.BottomUp("coverage", coverageMutator).Parallel()
-		ctx.TopDown("vndk_deps", sabiDepsMutator)
 
 		ctx.TopDown("lto_deps", ltoDepsMutator)
 		ctx.BottomUp("lto", ltoMutator).Parallel()
@@ -88,6 +87,11 @@
 		ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
 	})
 
+	ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		// sabi mutator needs to be run after apex mutator finishes.
+		ctx.TopDown("sabi_deps", sabiDepsMutator)
+	})
+
 	ctx.RegisterSingletonType("kythe_extract_all", kytheExtractAllFactory)
 }
 
@@ -415,7 +419,6 @@
 	inRamdisk() bool
 	inVendorRamdisk() bool
 	inRecovery() bool
-	shouldCreateSourceAbiDump() bool
 	selectedStl() string
 	baseModuleName() string
 	getVndkExtendsModuleName() string
@@ -1279,42 +1282,6 @@
 	return ctx.mod.MustUseVendorVariant()
 }
 
-// Check whether ABI dumps should be created for this module.
-func (ctx *moduleContextImpl) shouldCreateSourceAbiDump() bool {
-	if ctx.ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
-		return false
-	}
-
-	// Coverage builds have extra symbols.
-	if ctx.mod.isCoverageVariant() {
-		return false
-	}
-
-	if ctx.ctx.Fuchsia() {
-		return false
-	}
-
-	if sanitize := ctx.mod.sanitize; sanitize != nil {
-		if !sanitize.isVariantOnProductionDevice() {
-			return false
-		}
-	}
-	if !ctx.ctx.Device() {
-		// Host modules do not need ABI dumps.
-		return false
-	}
-	if ctx.isNDKStubLibrary() {
-		// Stubs do not need ABI dumps.
-		return false
-	}
-	if lib := ctx.mod.library; lib != nil && lib.buildStubs() {
-		// Stubs do not need ABI dumps.
-		return false
-	}
-
-	return true
-}
-
 func (ctx *moduleContextImpl) selectedStl() string {
 	if stl := ctx.mod.stl; stl != nil {
 		return stl.Properties.SelectedStl
@@ -1586,13 +1553,14 @@
 		}
 		c.outputFile = android.OptionalPathForPath(outputFile)
 
-		// If a lib is directly included in any of the APEXes, unhide the stubs
-		// variant having the latest version gets visible to make. In addition,
-		// the non-stubs variant is renamed to <libname>.bootstrap. This is to
-		// force anything in the make world to link against the stubs library.
-		// (unless it is explicitly referenced via .bootstrap suffix or the
-		// module is marked with 'bootstrap: true').
-		if c.HasStubsVariants() && c.AnyVariantDirectlyInAnyApex() && !c.InRamdisk() &&
+		// If a lib is directly included in any of the APEXes or is not available to the
+		// platform (which is often the case when the stub is provided as a prebuilt),
+		// unhide the stubs variant having the latest version gets visible to make. In
+		// addition, the non-stubs variant is renamed to <libname>.bootstrap. This is to
+		// force anything in the make world to link against the stubs library.  (unless it
+		// is explicitly referenced via .bootstrap suffix or the module is marked with
+		// 'bootstrap: true').
+		if c.HasStubsVariants() && c.NotInPlatform() && !c.InRamdisk() &&
 			!c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() &&
 			c.IsStubs() && !c.InVendorRamdisk() {
 			c.Properties.HideFromMake = false // unhide
@@ -2443,7 +2411,14 @@
 
 			switch {
 			case libDepTag.header():
-				// nothing
+				if !ctx.OtherModuleHasProvider(dep, HeaderLibraryInfoProvider) {
+					if !ctx.Config().AllowMissingDependencies() {
+						ctx.ModuleErrorf("module %q is not a header library", depName)
+					} else {
+						ctx.AddMissingDependencies([]string{depName})
+					}
+					return
+				}
 			case libDepTag.shared():
 				if !ctx.OtherModuleHasProvider(dep, SharedLibraryInfoProvider) {
 					if !ctx.Config().AllowMissingDependencies() {
@@ -2472,7 +2447,7 @@
 						// an APEX (and not from platform)
 						// However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules,
 						// always link to non-stub variant
-						useStubs = dep.(android.ApexModule).AnyVariantDirectlyInAnyApex() && !c.bootstrap()
+						useStubs = dep.(android.ApexModule).NotInPlatform() && !c.bootstrap()
 						// Another exception: if this module is bundled with an APEX, then
 						// it is linked with the non-stub variant of a module in the APEX
 						// as if this is part of the APEX.
@@ -2749,7 +2724,7 @@
 func baseLibName(depName string) string {
 	libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
 	libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix)
-	libName = strings.TrimPrefix(libName, "prebuilt_")
+	libName = android.RemoveOptionalPrebuiltPrefix(libName)
 	return libName
 }
 
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 441bff2..519a9e2 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -249,6 +249,10 @@
 	return result
 }
 
+func ClangLibToolingFilterUnknownCflags(libToolingFlags []string) []string {
+	return android.RemoveListFromList(libToolingFlags, ClangLibToolingUnknownCflags)
+}
+
 func inListSorted(s string, list []string) bool {
 	for _, l := range list {
 		if s == l {
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index a548452..4bcad4b 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -21,10 +21,11 @@
 	"android.hardware.automotive.occupant_awareness-ndk_platform",
 	"android.hardware.light-ndk_platform",
 	"android.hardware.identity-ndk_platform",
-	"android.hardware.keymint-unstable-ndk_platform",
 	"android.hardware.nfc@1.2",
+	"android.hardware.memtrack-unstable-ndk_platform",
 	"android.hardware.power-ndk_platform",
 	"android.hardware.rebootescrow-ndk_platform",
+	"android.hardware.security.keymint-unstable-ndk_platform",
 	"android.hardware.vibrator-ndk_platform",
 	"android.system.keystore2-unstable-ndk_platform",
 	"libbinder",
diff --git a/cc/library.go b/cc/library.go
index 06b9905..01fcb74 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -594,59 +594,12 @@
 	return flags
 }
 
-// Returns a string that represents the class of the ABI dump.
-// Returns an empty string if ABI check is disabled for this library.
-func (library *libraryDecorator) classifySourceAbiDump(ctx ModuleContext) string {
-	enabled := library.Properties.Header_abi_checker.Enabled
-	if enabled != nil && !Bool(enabled) {
-		return ""
-	}
-	// Return NDK if the library is both NDK and LLNDK.
-	if ctx.isNdk(ctx.Config()) {
-		return "NDK"
-	}
-	if ctx.isLlndkPublic(ctx.Config()) {
-		return "LLNDK"
-	}
-	if ctx.useVndk() && ctx.isVndk() && !ctx.isVndkPrivate(ctx.Config()) {
-		if ctx.isVndkSp() {
-			if ctx.IsVndkExt() {
-				return "VNDK-SP-ext"
-			} else {
-				return "VNDK-SP"
-			}
-		} else {
-			if ctx.IsVndkExt() {
-				return "VNDK-ext"
-			} else {
-				return "VNDK-core"
-			}
-		}
-	}
-	if Bool(enabled) || library.hasStubsVariants() {
-		return "PLATFORM"
-	}
-	return ""
+func (library *libraryDecorator) headerAbiCheckerEnabled() bool {
+	return Bool(library.Properties.Header_abi_checker.Enabled)
 }
 
-func (library *libraryDecorator) shouldCreateSourceAbiDump(ctx ModuleContext) bool {
-	if !ctx.shouldCreateSourceAbiDump() {
-		return false
-	}
-	if !ctx.isForPlatform() {
-		if !library.hasStubsVariants() {
-			// Skip ABI checks if this library is for APEX but isn't exported.
-			return false
-		}
-		if !Bool(library.Properties.Header_abi_checker.Enabled) {
-			// Skip ABI checks if this library is for APEX and did not explicitly enable
-			// ABI checks.
-			// TODO(b/145608479): ABI checks should be enabled by default. Remove this
-			// after evaluating the extra build time.
-			return false
-		}
-	}
-	return library.classifySourceAbiDump(ctx) != ""
+func (library *libraryDecorator) headerAbiCheckerExplicitlyDisabled() bool {
+	return !BoolDefault(library.Properties.Header_abi_checker.Enabled, true)
 }
 
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
@@ -668,7 +621,7 @@
 		}
 		return Objects{}
 	}
-	if library.shouldCreateSourceAbiDump(ctx) || library.sabi.Properties.CreateSAbiDumps {
+	if library.sabi.shouldCreateSourceAbiDump() {
 		exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
 		var SourceAbiFlags []string
 		for _, dir := range exportIncludeDirs.Strings() {
@@ -718,6 +671,10 @@
 	setStatic()
 	setShared()
 
+	// Check whether header_abi_checker is enabled or explicitly disabled.
+	headerAbiCheckerEnabled() bool
+	headerAbiCheckerExplicitlyDisabled() bool
+
 	// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
 	androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
 
@@ -940,16 +897,22 @@
 
 	ctx.CheckbuildFile(outputFile)
 
-	ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
-		StaticLibrary: outputFile,
-		ReuseObjects:  library.reuseObjects,
-		Objects:       library.objects,
+	if library.static() {
+		ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+			StaticLibrary: outputFile,
+			ReuseObjects:  library.reuseObjects,
+			Objects:       library.objects,
 
-		TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
-			Direct(outputFile).
-			Transitive(deps.TranstiveStaticLibrariesForOrdering).
-			Build(),
-	})
+			TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
+				Direct(outputFile).
+				Transitive(deps.TranstiveStaticLibrariesForOrdering).
+				Build(),
+		})
+	}
+
+	if library.header() {
+		ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
+	}
 
 	return outputFile
 }
@@ -1158,7 +1121,7 @@
 }
 
 func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
-	if library.shouldCreateSourceAbiDump(ctx) {
+	if library.sabi.shouldCreateSourceAbiDump() {
 		var vndkVersion string
 
 		if ctx.useVndk() {
@@ -1183,7 +1146,7 @@
 			library.Properties.Header_abi_checker.Exclude_symbol_versions,
 			library.Properties.Header_abi_checker.Exclude_symbol_tags)
 
-		addLsdumpPath(library.classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
+		addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
 
 		refAbiDumpFile := getRefAbiDumpFile(ctx, vndkVersion, fileName)
 		if refAbiDumpFile != nil {
diff --git a/cc/linkable.go b/cc/linkable.go
index 4efe2a7..d010985 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -130,6 +130,13 @@
 
 var StaticLibraryInfoProvider = blueprint.NewProvider(StaticLibraryInfo{})
 
+// HeaderLibraryInfo is a marker provider that identifies a module as a header library.
+type HeaderLibraryInfo struct {
+}
+
+// HeaderLibraryInfoProvider is a marker provider that identifies a module as a header library.
+var HeaderLibraryInfoProvider = blueprint.NewProvider(HeaderLibraryInfo{})
+
 // FlagExporterInfo is a provider to propagate transitive library information
 // pertaining to exported include paths and flags.
 type FlagExporterInfo struct {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 37df4ba..df71340 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -190,6 +190,12 @@
 		}
 	}
 
+	if p.header() {
+		ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
+
+		return nil
+	}
+
 	return nil
 }
 
diff --git a/cc/sabi.go b/cc/sabi.go
index ef6bead..99e718e 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -15,7 +15,6 @@
 package cc
 
 import (
-	"strings"
 	"sync"
 
 	"android/soong/android"
@@ -23,12 +22,18 @@
 )
 
 var (
-	lsdumpPaths []string
-	sabiLock    sync.Mutex
+	lsdumpPaths     []string
+	lsdumpPathsLock sync.Mutex
 )
 
 type SAbiProperties struct {
-	CreateSAbiDumps    bool     `blueprint:"mutated"`
+	// Whether ABI dump should be created for this module.
+	// Set by `sabiDepsMutator` if this module is a shared library that needs ABI check, or a static
+	// library that is depended on by an ABI checked library.
+	ShouldCreateSourceAbiDump bool `blueprint:"mutated"`
+
+	// Include directories that may contain ABI information exported by a library.
+	// These directories are passed to the header-abi-dumper.
 	ReexportedIncludes []string `blueprint:"mutated"`
 }
 
@@ -36,66 +41,172 @@
 	Properties SAbiProperties
 }
 
-func (sabimod *sabi) props() []interface{} {
-	return []interface{}{&sabimod.Properties}
+func (sabi *sabi) props() []interface{} {
+	return []interface{}{&sabi.Properties}
 }
 
-func (sabimod *sabi) begin(ctx BaseModuleContext) {}
+func (sabi *sabi) begin(ctx BaseModuleContext) {}
 
-func (sabimod *sabi) deps(ctx BaseModuleContext, deps Deps) Deps {
+func (sabi *sabi) deps(ctx BaseModuleContext, deps Deps) Deps {
 	return deps
 }
 
-func inListWithPrefixSearch(flag string, filter []string) bool {
-	// Assuming the filter is small enough.
-	// If the suffix of a filter element is *, try matching prefixes as well.
-	for _, f := range filter {
-		if (f == flag) || (strings.HasSuffix(f, "*") && strings.HasPrefix(flag, strings.TrimSuffix(f, "*"))) {
-			return true
-		}
-	}
-	return false
-}
-
-func filterOutWithPrefix(list []string, filter []string) (remainder []string) {
-	// Go through the filter, matching and optionally doing a prefix search for list elements.
-	for _, l := range list {
-		if !inListWithPrefixSearch(l, filter) {
-			remainder = append(remainder, l)
-		}
-	}
-	return
-}
-
-func (sabimod *sabi) flags(ctx ModuleContext, flags Flags) Flags {
-	// Assuming that the cflags which clang LibTooling tools cannot
-	// understand have not been converted to ninja variables yet.
-	flags.Local.ToolingCFlags = filterOutWithPrefix(flags.Local.CFlags, config.ClangLibToolingUnknownCflags)
-	flags.Global.ToolingCFlags = filterOutWithPrefix(flags.Global.CFlags, config.ClangLibToolingUnknownCflags)
-	flags.Local.ToolingCppFlags = filterOutWithPrefix(flags.Local.CppFlags, config.ClangLibToolingUnknownCflags)
-	flags.Global.ToolingCppFlags = filterOutWithPrefix(flags.Global.CppFlags, config.ClangLibToolingUnknownCflags)
-
+func (sabi *sabi) flags(ctx ModuleContext, flags Flags) Flags {
+	// Filter out flags which libTooling don't understand.
+	// This is here for legacy reasons and future-proof, in case the version of libTooling and clang
+	// diverge.
+	flags.Local.ToolingCFlags = config.ClangLibToolingFilterUnknownCflags(flags.Local.CFlags)
+	flags.Global.ToolingCFlags = config.ClangLibToolingFilterUnknownCflags(flags.Global.CFlags)
+	flags.Local.ToolingCppFlags = config.ClangLibToolingFilterUnknownCflags(flags.Local.CppFlags)
+	flags.Global.ToolingCppFlags = config.ClangLibToolingFilterUnknownCflags(flags.Global.CppFlags)
 	return flags
 }
 
-func sabiDepsMutator(mctx android.TopDownMutatorContext) {
-	if c, ok := mctx.Module().(*Module); ok &&
-		((c.IsVndk() && c.UseVndk()) || c.isLlndk(mctx.Config()) ||
-			(c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) {
-		mctx.VisitDirectDeps(func(m android.Module) {
-			if tag, ok := mctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok && tag.static() {
-				cc, _ := m.(*Module)
-				if cc == nil {
-					return
-				}
-				cc.sabi.Properties.CreateSAbiDumps = true
+// Returns true if ABI dump should be created for this library, either because library is ABI
+// checked or is depended on by an ABI checked library.
+// Could be called as a nil receiver.
+func (sabi *sabi) shouldCreateSourceAbiDump() bool {
+	return sabi != nil && sabi.Properties.ShouldCreateSourceAbiDump
+}
+
+// Returns a string that represents the class of the ABI dump.
+// Returns an empty string if ABI check is disabled for this library.
+func classifySourceAbiDump(ctx android.BaseModuleContext) string {
+	m := ctx.Module().(*Module)
+	if m.library.headerAbiCheckerExplicitlyDisabled() {
+		return ""
+	}
+	// Return NDK if the library is both NDK and LLNDK.
+	if m.IsNdk(ctx.Config()) {
+		return "NDK"
+	}
+	if m.isLlndkPublic(ctx.Config()) {
+		return "LLNDK"
+	}
+	if m.UseVndk() && m.IsVndk() && !m.IsVndkPrivate(ctx.Config()) {
+		if m.isVndkSp() {
+			if m.IsVndkExt() {
+				return "VNDK-SP-ext"
+			} else {
+				return "VNDK-SP"
 			}
-		})
+		} else {
+			if m.IsVndkExt() {
+				return "VNDK-ext"
+			} else {
+				return "VNDK-core"
+			}
+		}
+	}
+	if m.library.headerAbiCheckerEnabled() || m.library.hasStubsVariants() {
+		return "PLATFORM"
+	}
+	return ""
+}
+
+// Called from sabiDepsMutator to check whether ABI dumps should be created for this module.
+// ctx should be wrapping a native library type module.
+func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool {
+	if ctx.Fuchsia() {
+		return false
+	}
+
+	// Only generate ABI dump for device modules.
+	if !ctx.Device() {
+		return false
+	}
+
+	m := ctx.Module().(*Module)
+
+	// Only create ABI dump for native library module types.
+	if m.library == nil {
+		return false
+	}
+
+	// Create ABI dump for static libraries only if they are dependencies of ABI checked libraries.
+	if m.library.static() {
+		return m.sabi.shouldCreateSourceAbiDump()
+	}
+
+	// Module is shared library type.
+
+	// Don't check uninstallable modules.
+	if m.IsSkipInstall() {
+		return false
+	}
+
+	// Don't check ramdisk or recovery variants. Only check core, vendor or product variants.
+	if m.InRamdisk() || m.InVendorRamdisk() || m.InRecovery() {
+		return false
+	}
+
+	// Don't create ABI dump for prebuilts.
+	if m.Prebuilt() != nil || m.isSnapshotPrebuilt() {
+		return false
+	}
+
+	// Coverage builds have extra symbols.
+	if m.isCoverageVariant() {
+		return false
+	}
+
+	// Some sanitizer variants may have different ABI.
+	if m.sanitize != nil && !m.sanitize.isVariantOnProductionDevice() {
+		return false
+	}
+
+	// Don't create ABI dump for stubs.
+	if m.isNDKStubLibrary() || m.IsStubs() {
+		return false
+	}
+
+	isPlatformVariant := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+	if isPlatformVariant {
+		// Bionic libraries that are installed to the bootstrap directory are not ABI checked.
+		// Only the runtime APEX variants, which are the implementation libraries of bionic NDK stubs,
+		// are checked.
+		if InstallToBootstrap(m.BaseModuleName(), ctx.Config()) {
+			return false
+		}
+	} else {
+		// Don't create ABI dump if this library is for APEX but isn't exported.
+		if !m.HasStubsVariants() {
+			return false
+		}
+	}
+	return classifySourceAbiDump(ctx) != ""
+}
+
+// Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps
+// of their dependencies would be generated.
+func sabiDepsMutator(mctx android.TopDownMutatorContext) {
+	// Escape hatch to not check any ABI dump.
+	if mctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
+		return
+	}
+	// Only create ABI dump for native shared libraries and their static library dependencies.
+	if m, ok := mctx.Module().(*Module); ok && m.sabi != nil {
+		if shouldCreateSourceAbiDumpForLibrary(mctx) {
+			// Mark this module so that .sdump / .lsdump for this library can be generated.
+			m.sabi.Properties.ShouldCreateSourceAbiDump = true
+			// Mark all of its static library dependencies.
+			mctx.VisitDirectDeps(func(child android.Module) {
+				depTag := mctx.OtherModuleDependencyTag(child)
+				if libDepTag, ok := depTag.(libraryDependencyTag); ok && libDepTag.static() {
+					if c, ok := child.(*Module); ok && c.sabi != nil {
+						// Mark this module so that .sdump for this static library can be generated.
+						c.sabi.Properties.ShouldCreateSourceAbiDump = true
+					}
+				}
+			})
+		}
 	}
 }
 
+// Add an entry to the global list of lsdump. The list is exported to a Make variable by
+// `cc.makeVarsProvider`.
 func addLsdumpPath(lsdumpPath string) {
-	sabiLock.Lock()
+	lsdumpPathsLock.Lock()
+	defer lsdumpPathsLock.Unlock()
 	lsdumpPaths = append(lsdumpPaths, lsdumpPath)
-	sabiLock.Unlock()
 }
diff --git a/java/aar.go b/java/aar.go
index 3b6b34e..3750f72 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"path/filepath"
+	"strconv"
 	"strings"
 
 	"android/soong/android"
@@ -192,22 +193,31 @@
 		rroDirs = append(rroDirs, resRRODirs...)
 	}
 
-	var assetFiles android.Paths
-	for _, dir := range assetDirs {
-		assetFiles = append(assetFiles, androidResourceGlob(ctx, dir)...)
+	var assetDeps android.Paths
+	for i, dir := range assetDirs {
+		// Add a dependency on every file in the asset directory.  This ensures the aapt2
+		// rule will be rerun if one of the files in the asset directory is modified.
+		assetDeps = append(assetDeps, androidResourceGlob(ctx, dir)...)
+
+		// Add a dependency on a file that contains a list of all the files in the asset directory.
+		// This ensures the aapt2 rule will be run if a file is removed from the asset directory,
+		// or a file is added whose timestamp is older than the output of aapt2.
+		assetFileListFile := android.PathForModuleOut(ctx, "asset_dir_globs", strconv.Itoa(i)+".glob")
+		androidResourceGlobList(ctx, dir, assetFileListFile)
+		assetDeps = append(assetDeps, assetFileListFile)
 	}
 
 	assetDirStrings := assetDirs.Strings()
 	if a.noticeFile.Valid() {
 		assetDirStrings = append(assetDirStrings, filepath.Dir(a.noticeFile.Path().String()))
-		assetFiles = append(assetFiles, a.noticeFile.Path())
+		assetDeps = append(assetDeps, a.noticeFile.Path())
 	}
 
 	linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
 	linkDeps = append(linkDeps, manifestPath)
 
 	linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirStrings, "-A "))
-	linkDeps = append(linkDeps, assetFiles...)
+	linkDeps = append(linkDeps, assetDeps...)
 
 	// SDK version flags
 	minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersionString(ctx)
diff --git a/java/android_resources.go b/java/android_resources.go
index 720d3a5..4d420cf 100644
--- a/java/android_resources.go
+++ b/java/android_resources.go
@@ -38,10 +38,21 @@
 	"*~",
 }
 
+// androidResourceGlob returns the list of files in the given directory, using the standard
+// exclusion patterns for Android resources.
 func androidResourceGlob(ctx android.ModuleContext, dir android.Path) android.Paths {
 	return ctx.GlobFiles(filepath.Join(dir.String(), "**/*"), androidResourceIgnoreFilenames)
 }
 
+// androidResourceGlobList creates a rule to write the list of files in the given directory, using
+// the standard exclusion patterns for Android resources, to the given output file.
+func androidResourceGlobList(ctx android.ModuleContext, dir android.Path,
+	fileListFile android.WritablePath) {
+
+	android.GlobToListFileRule(ctx, filepath.Join(dir.String(), "**/*"),
+		androidResourceIgnoreFilenames, fileListFile)
+}
+
 type overlayType int
 
 const (
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
index de22c45..1be3b8a 100755
--- a/scripts/build-aml-prebuilts.sh
+++ b/scripts/build-aml-prebuilts.sh
@@ -54,6 +54,11 @@
 PLATFORM_VERSION_ALL_CODENAMES="${PLATFORM_VERSION_ALL_CODENAMES/,/'","'}"
 PLATFORM_VERSION_ALL_CODENAMES="[\"${PLATFORM_VERSION_ALL_CODENAMES}\"]"
 
+# Get the list of missing <uses-library> modules and convert it to a JSON array
+# (quote module names, add comma separator and wrap in brackets).
+MISSING_USES_LIBRARIES="$(my_get_build_var INTERNAL_PLATFORM_MISSING_USES_LIBRARIES)"
+MISSING_USES_LIBRARIES="[$(echo $MISSING_USES_LIBRARIES | sed -e 's/\([^ ]\+\)/\"\1\"/g' -e 's/[ ]\+/, /g')]"
+
 # Logic from build/make/core/goma.mk
 if [ "${USE_GOMA}" = true ]; then
   if [ -n "${GOMA_DIR}" ]; then
@@ -81,6 +86,7 @@
 {
     "BuildNumberFile": "build_number.txt",
 
+    "Platform_version_name": "${PLATFORM_VERSION}",
     "Platform_sdk_version": ${PLATFORM_SDK_VERSION},
     "Platform_sdk_codename": "${PLATFORM_VERSION}",
     "Platform_version_active_codenames": ${PLATFORM_VERSION_ALL_CODENAMES},
@@ -100,7 +106,9 @@
         "art_module": {
             "source_build": "${ENABLE_ART_SOURCE_BUILD:-false}"
         }
-    }
+    },
+
+    "MissingUsesLibraries": ${MISSING_USES_LIBRARIES}
 }
 EOF
 
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index b8dd7aa..6db870f 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -16,15 +16,16 @@
 MODULES_SDK_AND_EXPORTS=(
   art-module-sdk
   art-module-test-exports
+  conscrypt-module-host-exports
   conscrypt-module-sdk
   conscrypt-module-test-exports
-  conscrypt-module-host-exports
-  runtime-module-sdk
-  runtime-module-host-exports
-  i18n-module-test-exports
+  i18n-module-host-exports
   i18n-module-sdk
+  i18n-module-test-exports
   platform-mainline-sdk
   platform-mainline-test-exports
+  runtime-module-host-exports
+  runtime-module-sdk
 )
 
 # List of libraries installed on the platform that are needed for ART chroot
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index b6ed659..1a33219 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -30,6 +30,11 @@
 PLATFORM_VERSION_ALL_CODENAMES=${PLATFORM_VERSION_ALL_CODENAMES/,/'","'}
 PLATFORM_VERSION_ALL_CODENAMES="[\"${PLATFORM_VERSION_ALL_CODENAMES}\"]"
 
+# Get the list of missing <uses-library> modules and convert it to a JSON array
+# (quote module names, add comma separator and wrap in brackets).
+MISSING_USES_LIBRARIES="$(get_build_var INTERNAL_PLATFORM_MISSING_USES_LIBRARIES)"
+MISSING_USES_LIBRARIES="[$(echo $MISSING_USES_LIBRARIES | sed -e 's/\([^ ]\+\)/\"\1\"/g' -e 's/[ ]\+/, /g')]"
+
 SOONG_OUT=${OUT_DIR}/soong
 SOONG_NDK_OUT=${OUT_DIR}/soong/ndk
 rm -rf ${SOONG_OUT}
@@ -49,7 +54,9 @@
     "Safestack": false,
 
     "Ndk_abis": true,
-    "Exclude_draft_ndk_apis": true
+    "Exclude_draft_ndk_apis": true,
+
+    "MissingUsesLibraries": ${MISSING_USES_LIBRARIES}
 }
 EOF
 m --skip-make ${SOONG_OUT}/ndk.timestamp
diff --git a/shared/Android.bp b/shared/Android.bp
index 07dfe11..2a4f56f 100644
--- a/shared/Android.bp
+++ b/shared/Android.bp
@@ -4,4 +4,7 @@
     srcs: [
         "paths.go",
     ],
+    deps: [
+        "soong-bazel",
+    ],
 }
diff --git a/shared/paths.go b/shared/paths.go
index f5dc5dd..1b9ff60 100644
--- a/shared/paths.go
+++ b/shared/paths.go
@@ -18,6 +18,8 @@
 
 import (
 	"path/filepath"
+
+	"android/soong/bazel"
 )
 
 // A SharedPaths represents a list of paths that are shared between
@@ -37,6 +39,6 @@
 // on the action name. This is to help to store a set of bazel
 // profiles since bazel may execute multiple times during a single
 // build.
-func BazelMetricsFilename(s SharedPaths, actionName string) string {
-	return filepath.Join(s.BazelMetricsDir(), actionName+"_bazel_profile.gz")
+func BazelMetricsFilename(s SharedPaths, actionName bazel.RunName) string {
+	return filepath.Join(s.BazelMetricsDir(), actionName.String()+"_bazel_profile.gz")
 }
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index 4f2d645..81ce939 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -22,6 +22,7 @@
 	"path/filepath"
 	"strings"
 
+	"android/soong/bazel"
 	"android/soong/shared"
 	"android/soong/ui/metrics"
 )
@@ -97,9 +98,9 @@
 	}
 
 	// Start constructing the `build` command.
-	actionName := "build"
+	actionName := bazel.BazelNinjaExecRunName
 	cmd.Args = append(cmd.Args,
-		actionName,
+		"build",
 		// Use output_groups to select the set of outputs to produce from a
 		// ninja_build target.
 		"--output_groups="+outputGroups,
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 08c2ee1..6a93672 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -156,6 +156,7 @@
 		cmd.Environment.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
 		cmd.Environment.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
 		cmd.Environment.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
+		cmd.Environment.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
 
 		cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
 		cmd.Sandbox = soongSandbox
diff --git a/ui/metrics/event.go b/ui/metrics/event.go
index 6becfd1..87c1b84 100644
--- a/ui/metrics/event.go
+++ b/ui/metrics/event.go
@@ -14,6 +14,17 @@
 
 package metrics
 
+// This file contains the functionality to represent a build event in respect
+// to the metric system. A build event corresponds to a block of scoped code
+// that contains a "Begin()" and immediately followed by "defer End()" trace.
+// When defined, the duration of the scoped code is measure along with other
+// performance measurements such as memory.
+//
+// As explained in the metrics package, the metrics system is a stacked based
+// system since the collected metrics is considered to be topline metrics.
+// The steps of the build system in the UI layer is sequential. Hence, the
+// functionality defined below follows the stack data structure operations.
+
 import (
 	"os"
 	"syscall"
@@ -21,54 +32,97 @@
 
 	"android/soong/ui/metrics/metrics_proto"
 	"android/soong/ui/tracer"
+
 	"github.com/golang/protobuf/proto"
 )
 
-// for testing purpose only
-var _now = now
-
-type event struct {
-	desc string
-	name string
-
-	// the time that the event started to occur.
-	start time.Time
-
-	// The list of process resource information that was executed
-	procResInfo []*soong_metrics_proto.ProcessResourceInfo
-}
-
-type EventTracer interface {
-	Begin(name, desc string, thread tracer.Thread)
-	End(thread tracer.Thread) soong_metrics_proto.PerfInfo
-	AddProcResInfo(string, *os.ProcessState)
-}
-
-type eventTracerImpl struct {
-	activeEvents []event
-}
-
-var _ EventTracer = &eventTracerImpl{}
-
-func now() time.Time {
+// _now wraps the time.Now() function. _now is declared for unit testing purpose.
+var _now = func() time.Time {
 	return time.Now()
 }
 
-// AddProcResInfo adds information on an executed process such as max resident set memory
-// and the number of voluntary context switches.
-func (t *eventTracerImpl) AddProcResInfo(name string, state *os.ProcessState) {
-	if len(t.activeEvents) < 1 {
+// event holds the performance metrics data of a single build event.
+type event struct {
+	// The event name (mostly used for grouping a set of events)
+	name string
+
+	// The description of the event (used to uniquely identify an event
+	// for metrics analysis).
+	desc string
+
+	// The time that the event started to occur.
+	start time.Time
+
+	// The list of process resource information that was executed.
+	procResInfo []*soong_metrics_proto.ProcessResourceInfo
+}
+
+// newEvent returns an event with start populated with the now time.
+func newEvent(name, desc string) *event {
+	return &event{
+		name:  name,
+		desc:  desc,
+		start: _now(),
+	}
+}
+
+func (e event) perfInfo() soong_metrics_proto.PerfInfo {
+	realTime := uint64(_now().Sub(e.start).Nanoseconds())
+	return soong_metrics_proto.PerfInfo{
+		Desc:                  proto.String(e.desc),
+		Name:                  proto.String(e.name),
+		StartTime:             proto.Uint64(uint64(e.start.UnixNano())),
+		RealTime:              proto.Uint64(realTime),
+		ProcessesResourceInfo: e.procResInfo,
+	}
+}
+
+// EventTracer is an array of events that provides functionality to trace a
+// block of code on time and performance. The End call expects the Begin is
+// invoked, otherwise panic is raised.
+type EventTracer []*event
+
+// empty returns true if there are no pending events.
+func (t *EventTracer) empty() bool {
+	return len(*t) == 0
+}
+
+// lastIndex returns the index of the last element of events.
+func (t *EventTracer) lastIndex() int {
+	return len(*t) - 1
+}
+
+// peek returns the active build event.
+func (t *EventTracer) peek() *event {
+	return (*t)[t.lastIndex()]
+}
+
+// push adds the active build event in the stack.
+func (t *EventTracer) push(e *event) {
+	*t = append(*t, e)
+}
+
+// pop removes the active event from the stack since the event has completed.
+// A panic is raised if there are no pending events.
+func (t *EventTracer) pop() *event {
+	if t.empty() {
+		panic("Internal error: No pending events")
+	}
+	e := (*t)[t.lastIndex()]
+	*t = (*t)[:t.lastIndex()]
+	return e
+}
+
+// AddProcResInfo adds information on an executed process such as max resident
+// set memory and the number of voluntary context switches.
+func (t *EventTracer) AddProcResInfo(name string, state *os.ProcessState) {
+	if t.empty() {
 		return
 	}
 
 	rusage := state.SysUsage().(*syscall.Rusage)
-	// The implementation of the metrics system is a stacked based system. The steps of the
-	// build system in the UI layer is sequential so the Begin function is invoked when a
-	// function (or scoped code) is invoked. That is translated to a new event which is added
-	// at the end of the activeEvents array. When the invoking function is completed, End is
-	// invoked which is a pop operation from activeEvents.
-	curEvent := &t.activeEvents[len(t.activeEvents)-1]
-	curEvent.procResInfo = append(curEvent.procResInfo, &soong_metrics_proto.ProcessResourceInfo{
+	e := t.peek()
+	e.procResInfo = append(e.procResInfo, &soong_metrics_proto.ProcessResourceInfo{
 		Name:             proto.String(name),
 		UserTimeMicros:   proto.Uint64(uint64(rusage.Utime.Usec)),
 		SystemTimeMicros: proto.Uint64(uint64(rusage.Stime.Usec)),
@@ -82,23 +136,13 @@
 	})
 }
 
-func (t *eventTracerImpl) Begin(name, desc string, _ tracer.Thread) {
-	t.activeEvents = append(t.activeEvents, event{name: name, desc: desc, start: _now()})
+// Begin starts tracing the event.
+func (t *EventTracer) Begin(name, desc string, _ tracer.Thread) {
+	t.push(newEvent(name, desc))
 }
 
-func (t *eventTracerImpl) End(tracer.Thread) soong_metrics_proto.PerfInfo {
-	if len(t.activeEvents) < 1 {
-		panic("Internal error: No pending events for endAt to end!")
-	}
-	lastEvent := t.activeEvents[len(t.activeEvents)-1]
-	t.activeEvents = t.activeEvents[:len(t.activeEvents)-1]
-	realTime := uint64(_now().Sub(lastEvent.start).Nanoseconds())
-
-	return soong_metrics_proto.PerfInfo{
-		Desc:                  proto.String(lastEvent.desc),
-		Name:                  proto.String(lastEvent.name),
-		StartTime:             proto.Uint64(uint64(lastEvent.start.UnixNano())),
-		RealTime:              proto.Uint64(realTime),
-		ProcessesResourceInfo: lastEvent.procResInfo,
-	}
+// End performs post calculations such as duration of the event, aggregates
+// the collected performance information into PerfInfo protobuf message.
+func (t *EventTracer) End(tracer.Thread) soong_metrics_proto.PerfInfo {
+	return t.pop().perfInfo()
 }
diff --git a/ui/metrics/event_test.go b/ui/metrics/event_test.go
index 6fc0b50..043450b 100644
--- a/ui/metrics/event_test.go
+++ b/ui/metrics/event_test.go
@@ -28,14 +28,14 @@
 	_now = func() time.Time { return startTime.Add(dur) }
 	defer func() { _now = initialNow }()
 
-	eventTracer := &eventTracerImpl{}
-	eventTracer.activeEvents = append(eventTracer.activeEvents, event{
+	et := &EventTracer{}
+	et.push(&event{
 		desc:  "test",
 		name:  "test",
 		start: startTime,
 	})
 
-	perf := eventTracer.End(tracer.Thread(0))
+	perf := et.End(tracer.Thread(0))
 	if perf.GetRealTime() != uint64(dur.Nanoseconds()) {
 		t.Errorf("got %d, want %d nanoseconds for event duration", perf.GetRealTime(), dur.Nanoseconds())
 	}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 7031042..2a09461 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -39,13 +39,13 @@
 
 type Metrics struct {
 	metrics     soong_metrics_proto.MetricsBase
-	EventTracer EventTracer
+	EventTracer *EventTracer
 }
 
 func New() (metrics *Metrics) {
 	m := &Metrics{
 		metrics:     soong_metrics_proto.MetricsBase{},
-		EventTracer: &eventTracerImpl{},
+		EventTracer: &EventTracer{},
 	}
 	return m
 }