Merge "Deprecate both USE_GOMA and FORCE_USE_GOMA flags"
diff --git a/OWNERS b/OWNERS
index 8355d10..3a5a8a7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,13 +1,20 @@
-per-file * = asmundak@google.com
-per-file * = ccross@android.com
-per-file * = dwillemsen@google.com
-per-file * = eakammer@google.com
-per-file * = jungjw@google.com
-per-file * = patricearruda@google.com
-per-file * = paulduffin@google.com
+# This file is included by several other projects as the list of people
+# approving build related projects.
 
-per-file ndk_*.go = danalbert@google.com
-per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
-per-file tidy.go = srhines@google.com, chh@google.com
-per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
-per-file docs/map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
+ahumesky@google.com
+asmundak@google.com
+ccross@android.com
+cparsons@google.com
+dwillemsen@google.com
+eakammer@google.com
+jingwen@google.com
+joeo@google.com
+jungjw@google.com
+lberki@google.com
+patricearruda@google.com
+ruperts@google.com
+
+# To expedite LON reviews
+hansson@google.com
+paulduffin@google.com
+
diff --git a/android/Android.bp b/android/Android.bp
index 4ba5241..2de0ca9 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -15,6 +15,7 @@
         "apex.go",
         "api_levels.go",
         "arch.go",
+        "bazel_handler.go",
         "bazel_overlay.go",
         "config.go",
         "csuite_config.go",
@@ -54,7 +55,6 @@
         "util.go",
         "variable.go",
         "visibility.go",
-        "vts_config.go",
         "writedocs.go",
 
         // Lock down environment access last
@@ -83,6 +83,5 @@
         "util_test.go",
         "variable_test.go",
         "visibility_test.go",
-        "vts_config_test.go",
     ],
 }
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
index 8574dc9..a558f45 100644
--- a/android/androidmk_test.go
+++ b/android/androidmk_test.go
@@ -68,7 +68,6 @@
 }
 
 func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testing.T) {
-	t.Parallel()
 	bp := `
 	custom {
 		name: "foo",
@@ -104,7 +103,6 @@
 }
 
 func TestGetDistForGoals(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		bp                     string
 		expectedAndroidMkLines []string
diff --git a/android/apex.go b/android/apex.go
index c01b716..3039e79 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -145,11 +145,6 @@
 	// check-platform-availability mutator in the apex package.
 	SetNotAvailableForPlatform()
 
-	// Returns the highest version which is <= maxSdkVersion.
-	// For example, with maxSdkVersion is 10 and versionList is [9,11]
-	// it returns 9 as string
-	ChooseSdkVersion(ctx BaseModuleContext, versionList []string, maxSdkVersion ApiLevel) (string, error)
-
 	// List of APEXes that this module tests. The module has access to
 	// the private part of the listed APEXes even when it is not included in the
 	// APEXes.
@@ -310,20 +305,6 @@
 	return true
 }
 
-func (m *ApexModuleBase) ChooseSdkVersion(ctx BaseModuleContext, versionList []string, maxSdkVersion ApiLevel) (string, error) {
-	for i := range versionList {
-		version := versionList[len(versionList)-i-1]
-		ver, err := ApiLevelFromUser(ctx, version)
-		if err != nil {
-			return "", err
-		}
-		if ver.LessThanOrEqualTo(maxSdkVersion) {
-			return version, nil
-		}
-	}
-	return "", fmt.Errorf("not found a version(<=%s) in versionList: %v", maxSdkVersion, versionList)
-}
-
 func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
 	for _, n := range m.ApexProperties.Apex_available {
 		if n == AvailableToPlatform || n == AvailableToAnyApex || n == AvailableToGkiApex {
diff --git a/android/apex_test.go b/android/apex_test.go
index 7507628..512b50f 100644
--- a/android/apex_test.go
+++ b/android/apex_test.go
@@ -20,7 +20,6 @@
 )
 
 func Test_mergeApexVariations(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name        string
 		in          []ApexInfo
diff --git a/android/arch.go b/android/arch.go
index f4b0d66..f505ec6 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -811,10 +811,16 @@
 	}
 }
 
-// Identifies the dependency from CommonOS variant to the os specific variants.
-type commonOSTag struct{ blueprint.BaseDependencyTag }
+type archDepTag struct {
+	blueprint.BaseDependencyTag
+	name string
+}
 
-var commonOsToOsSpecificVariantTag = commonOSTag{}
+// Identifies the dependency from CommonOS variant to the os specific variants.
+var commonOsToOsSpecificVariantTag = archDepTag{name: "common os to os specific"}
+
+// Identifies the dependency from arch variant to the common variant for a "common_first" multilib.
+var firstArchToCommonArchDepTag = archDepTag{name: "first arch to common arch"}
 
 // Get the OsType specific variants for the current CommonOS variant.
 //
@@ -831,7 +837,6 @@
 			}
 		}
 	})
-
 	return variants
 }
 
@@ -955,6 +960,12 @@
 		addTargetProperties(m, targets[i], multiTargets, i == 0)
 		m.base().setArchProperties(mctx)
 	}
+
+	if multilib == "common_first" && len(modules) >= 2 {
+		for i := range modules[1:] {
+			mctx.AddInterVariantDependency(firstArchToCommonArchDepTag, modules[i+1], modules[0])
+		}
+	}
 }
 
 func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) {
diff --git a/android/arch_test.go b/android/arch_test.go
index 7ec050f..8525b03 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -36,7 +36,6 @@
 }
 
 func TestFilterArchStruct(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name     string
 		in       interface{}
@@ -275,7 +274,6 @@
 }
 
 func TestArchMutator(t *testing.T) {
-	t.Parallel()
 	var buildOSVariants []string
 	var buildOS32Variants []string
 	switch runtime.GOOS {
@@ -387,7 +385,6 @@
 }
 
 func TestArchMutatorNativeBridge(t *testing.T) {
-	t.Parallel()
 	bp := `
 		// This module is only enabled for x86.
 		module {
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
new file mode 100644
index 0000000..210d67a8
--- /dev/null
+++ b/android/bazel_handler.go
@@ -0,0 +1,268 @@
+// 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 android
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"sync"
+
+	"github.com/google/blueprint/bootstrap"
+)
+
+// Map key to describe bazel cquery requests.
+type cqueryKey struct {
+	label        string
+	starlarkExpr string
+}
+
+type BazelContext interface {
+	// The below methods involve queuing cquery requests to be later invoked
+	// by bazel. If any of these methods return (_, false), then the request
+	// has been queued to be run later.
+
+	// Returns result files built by building the given bazel target label.
+	GetAllFiles(label string) ([]string, bool)
+
+	// TODO(cparsons): Other cquery-related methods should be added here.
+	// ** End cquery methods
+
+	// Issues commands to Bazel to receive results for all cquery requests
+	// queued in the BazelContext.
+	InvokeBazel() error
+
+	// Returns true if bazel is enabled for the given configuration.
+	BazelEnabled() bool
+}
+
+// A context object which tracks queued requests that need to be made to Bazel,
+// and their results after the requests have been made.
+type bazelContext struct {
+	homeDir      string
+	bazelPath    string
+	outputBase   string
+	workspaceDir string
+
+	requests     map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
+	requestMutex sync.Mutex         // requests can be written in parallel
+
+	results map[cqueryKey]string // Results of cquery requests after Bazel invocations
+}
+
+var _ BazelContext = &bazelContext{}
+
+// A bazel context to use when Bazel is disabled.
+type noopBazelContext struct{}
+
+var _ BazelContext = noopBazelContext{}
+
+// A bazel context to use for tests.
+type MockBazelContext struct {
+	AllFiles map[string][]string
+}
+
+func (m MockBazelContext) GetAllFiles(label string) ([]string, bool) {
+	result, ok := m.AllFiles[label]
+	return result, ok
+}
+
+func (m MockBazelContext) InvokeBazel() error {
+	panic("unimplemented")
+}
+
+func (m MockBazelContext) BazelEnabled() bool {
+	return true
+}
+
+var _ BazelContext = MockBazelContext{}
+
+func (bazelCtx *bazelContext) GetAllFiles(label string) ([]string, bool) {
+	starlarkExpr := "', '.join([f.path for f in target.files.to_list()])"
+	result, ok := bazelCtx.cquery(label, starlarkExpr)
+	if ok {
+		bazelOutput := strings.TrimSpace(result)
+		return strings.Split(bazelOutput, ", "), true
+	} else {
+		return nil, false
+	}
+}
+
+func (n noopBazelContext) GetAllFiles(label string) ([]string, bool) {
+	panic("unimplemented")
+}
+
+func (n noopBazelContext) InvokeBazel() error {
+	panic("unimplemented")
+}
+
+func (n noopBazelContext) BazelEnabled() bool {
+	return false
+}
+
+func NewBazelContext(c *config) (BazelContext, error) {
+	if c.Getenv("USE_BAZEL") != "1" {
+		return noopBazelContext{}, nil
+	}
+
+	bazelCtx := bazelContext{requests: make(map[cqueryKey]bool)}
+	missingEnvVars := []string{}
+	if len(c.Getenv("BAZEL_HOME")) > 1 {
+		bazelCtx.homeDir = c.Getenv("BAZEL_HOME")
+	} else {
+		missingEnvVars = append(missingEnvVars, "BAZEL_HOME")
+	}
+	if len(c.Getenv("BAZEL_PATH")) > 1 {
+		bazelCtx.bazelPath = c.Getenv("BAZEL_PATH")
+	} else {
+		missingEnvVars = append(missingEnvVars, "BAZEL_PATH")
+	}
+	if len(c.Getenv("BAZEL_OUTPUT_BASE")) > 1 {
+		bazelCtx.outputBase = c.Getenv("BAZEL_OUTPUT_BASE")
+	} else {
+		missingEnvVars = append(missingEnvVars, "BAZEL_OUTPUT_BASE")
+	}
+	if len(c.Getenv("BAZEL_WORKSPACE")) > 1 {
+		bazelCtx.workspaceDir = c.Getenv("BAZEL_WORKSPACE")
+	} else {
+		missingEnvVars = append(missingEnvVars, "BAZEL_WORKSPACE")
+	}
+	if len(missingEnvVars) > 0 {
+		return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars))
+	} else {
+		return &bazelCtx, nil
+	}
+}
+
+func (context *bazelContext) BazelEnabled() bool {
+	return true
+}
+
+// Adds a cquery request to the Bazel request queue, to be later invoked, or
+// returns the result of the given request if the request was already made.
+// If the given request was already made (and the results are available), then
+// returns (result, true). If the request is queued but no results are available,
+// then returns ("", false).
+func (context *bazelContext) cquery(label string, starlarkExpr string) (string, bool) {
+	key := cqueryKey{label, starlarkExpr}
+	if result, ok := context.results[key]; ok {
+		return result, true
+	} else {
+		context.requestMutex.Lock()
+		defer context.requestMutex.Unlock()
+		context.requests[key] = true
+		return "", false
+	}
+}
+
+func pwdPrefix() string {
+	// Darwin doesn't have /proc
+	if runtime.GOOS != "darwin" {
+		return "PWD=/proc/self/cwd"
+	}
+	return ""
+}
+
+func (context *bazelContext) issueBazelCommand(command string, labels []string,
+	extraFlags ...string) (string, error) {
+
+	cmdFlags := []string{"--output_base=" + context.outputBase, command}
+	cmdFlags = append(cmdFlags, labels...)
+	cmdFlags = append(cmdFlags, extraFlags...)
+
+	bazelCmd := exec.Command(context.bazelPath, cmdFlags...)
+	bazelCmd.Dir = context.workspaceDir
+	bazelCmd.Env = append(os.Environ(), "HOME="+context.homeDir, pwdPrefix())
+
+	stderr := &bytes.Buffer{}
+	bazelCmd.Stderr = stderr
+
+	if output, err := bazelCmd.Output(); err != nil {
+		return "", fmt.Errorf("bazel command failed. command: [%s], error [%s]", bazelCmd, stderr)
+	} else {
+		return string(output), nil
+	}
+}
+
+// Issues commands to Bazel to receive results for all cquery requests
+// queued in the BazelContext.
+func (context *bazelContext) InvokeBazel() error {
+	context.results = make(map[cqueryKey]string)
+
+	var labels []string
+	var cqueryOutput string
+	var err error
+	for val, _ := range context.requests {
+		labels = append(labels, val.label)
+
+		// TODO(cparsons): Combine requests into a batch cquery request.
+		// TODO(cparsons): Use --query_file to avoid command line limits.
+		cqueryOutput, err = context.issueBazelCommand("cquery", []string{val.label},
+			"--output=starlark",
+			"--starlark:expr="+val.starlarkExpr)
+
+		if err != nil {
+			return err
+		} else {
+			context.results[val] = string(cqueryOutput)
+		}
+	}
+
+	// Issue a build command.
+	// TODO(cparsons): Invoking bazel execution during soong_build should be avoided;
+	// 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", labels)
+
+	if err != nil {
+		return err
+	}
+
+	// Clear requests.
+	context.requests = map[cqueryKey]bool{}
+	return nil
+}
+
+// Singleton used for registering BUILD file ninja dependencies (needed
+// for correctness of builds which use Bazel.
+func BazelSingleton() Singleton {
+	return &bazelSingleton{}
+}
+
+type bazelSingleton struct{}
+
+func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
+	if ctx.Config().BazelContext.BazelEnabled() {
+		bazelBuildList := absolutePath(filepath.Join(
+			filepath.Dir(bootstrap.ModuleListFile), "bazel.list"))
+		ctx.AddNinjaFileDeps(bazelBuildList)
+
+		data, err := ioutil.ReadFile(bazelBuildList)
+		if err != nil {
+			ctx.Errorf(err.Error())
+		}
+		files := strings.Split(strings.TrimSpace(string(data)), "\n")
+		for _, file := range files {
+			ctx.AddNinjaFileDeps(file)
+		}
+	}
+}
diff --git a/android/config.go b/android/config.go
index 8df65f7..cf6d596 100644
--- a/android/config.go
+++ b/android/config.go
@@ -85,14 +85,17 @@
 	// Only available on configs created by TestConfig
 	TestProductVariables *productVariables
 
+	BazelContext BazelContext
+
 	PrimaryBuilder           string
 	ConfigFileName           string
 	ProductVariablesFileName string
 
-	Targets             map[OsType][]Target
-	BuildOSTarget       Target // the Target for tools run on the build machine
-	BuildOSCommonTarget Target // the Target for common (java) tools run on the build machine
-	AndroidCommonTarget Target // the Target for common modules for the Android device
+	Targets                  map[OsType][]Target
+	BuildOSTarget            Target // the Target for tools run on the build machine
+	BuildOSCommonTarget      Target // the Target for common (java) tools run on the build machine
+	AndroidCommonTarget      Target // the Target for common modules for the Android device
+	AndroidFirstDeviceTarget Target // the first Target for modules for the Android device
 
 	// multilibConflicts for an ArchType is true if there is earlier configured device architecture with the same
 	// multilib value.
@@ -248,6 +251,8 @@
 		// Set testAllowNonExistentPaths so that test contexts don't need to specify every path
 		// passed to PathForSource or PathForModuleSrc.
 		testAllowNonExistentPaths: true,
+
+		BazelContext: noopBazelContext{},
 	}
 	config.deviceConfig = &deviceConfig{
 		config: config,
@@ -316,6 +321,7 @@
 	config.BuildOSTarget = config.Targets[BuildOs][0]
 	config.BuildOSCommonTarget = getCommonTargets(config.Targets[BuildOs])[0]
 	config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
+	config.AndroidFirstDeviceTarget = firstTarget(config.Targets[Android], "lib64", "lib32")[0]
 	config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
 	config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
 	config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
@@ -324,6 +330,20 @@
 	return testConfig
 }
 
+// Returns a config object which is "reset" for another bootstrap run.
+// Only per-run data is reset. Data which needs to persist across multiple
+// runs in the same program execution is carried over (such as Bazel context
+// or environment deps).
+func ConfigForAdditionalRun(c Config) (Config, error) {
+	newConfig, err := NewConfig(c.srcDir, c.buildDir, c.moduleListFile)
+	if err != nil {
+		return Config{}, err
+	}
+	newConfig.BazelContext = c.BazelContext
+	newConfig.envDeps = c.envDeps
+	return newConfig, nil
+}
+
 // New creates a new Config object.  The srcDir argument specifies the path to
 // the root source directory. It also loads the config file, if found.
 func NewConfig(srcDir, buildDir string, moduleListFile string) (Config, error) {
@@ -411,6 +431,7 @@
 	config.BuildOSCommonTarget = getCommonTargets(config.Targets[BuildOs])[0]
 	if len(config.Targets[Android]) > 0 {
 		config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
+		config.AndroidFirstDeviceTarget = firstTarget(config.Targets[Android], "lib64", "lib32")[0]
 	}
 
 	if err := config.fromEnv(); err != nil {
@@ -425,6 +446,10 @@
 		Bool(config.productVariables.GcovCoverage) ||
 			Bool(config.productVariables.ClangCoverage))
 
+	config.BazelContext, err = NewBazelContext(config)
+	if err != nil {
+		return Config{}, err
+	}
 	return Config{config}, nil
 }
 
@@ -916,6 +941,10 @@
 	return false
 }
 
+func (c *config) EnforceRROExemptedForModule(name string) bool {
+	return InList(name, c.productVariables.EnforceRROExemptedTargets)
+}
+
 func (c *config) EnforceRROExcludedOverlay(path string) bool {
 	excluded := c.productVariables.EnforceRROExcludedOverlays
 	if len(excluded) > 0 {
@@ -1116,12 +1145,12 @@
 	return c.config.productVariables.BoardOdmSepolicyDirs
 }
 
-func (c *deviceConfig) PlatPublicSepolicyDirs() []string {
-	return c.config.productVariables.BoardPlatPublicSepolicyDirs
+func (c *deviceConfig) SystemExtPublicSepolicyDirs() []string {
+	return c.config.productVariables.SystemExtPublicSepolicyDirs
 }
 
-func (c *deviceConfig) PlatPrivateSepolicyDirs() []string {
-	return c.config.productVariables.BoardPlatPrivateSepolicyDirs
+func (c *deviceConfig) SystemExtPrivateSepolicyDirs() []string {
+	return c.config.productVariables.SystemExtPrivateSepolicyDirs
 }
 
 func (c *deviceConfig) SepolicyM4Defs() []string {
diff --git a/android/config_test.go b/android/config_test.go
index 0c907b7..274d59f 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -58,7 +58,6 @@
 
 // tests that ValidateConfigAnnotation works
 func TestValidateConfigAnnotations(t *testing.T) {
-	t.Parallel()
 	config := configType{}
 	err := validateConfigAnnotations(&config)
 	expectedError := `Field configType.PopulateMe has tag json:"omitempty" which specifies to change its json field name to "omitempty".
@@ -75,7 +74,6 @@
 
 // run validateConfigAnnotations against each type that might have json annotations
 func TestProductConfigAnnotations(t *testing.T) {
-	t.Parallel()
 	err := validateConfigAnnotations(&productVariables{})
 	if err != nil {
 		t.Errorf(err.Error())
@@ -88,7 +86,6 @@
 }
 
 func TestMissingVendorConfig(t *testing.T) {
-	t.Parallel()
 	c := &config{}
 	if c.VendorConfig("test").Bool("not_set") {
 		t.Errorf("Expected false")
diff --git a/android/csuite_config_test.go b/android/csuite_config_test.go
index ec93ed6..bf1a19a 100644
--- a/android/csuite_config_test.go
+++ b/android/csuite_config_test.go
@@ -32,7 +32,6 @@
 }
 
 func TestCSuiteConfig(t *testing.T) {
-	t.Parallel()
 	ctx := testCSuiteConfig(t, `
 csuite_config { name: "plain"}
 csuite_config { name: "with_manifest", test_config: "manifest.xml" }
diff --git a/android/defaults.go b/android/defaults.go
index 0892adf..eb013d7 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -95,6 +95,8 @@
 	module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties)
 
 	module.AddProperties(module.defaults())
+
+	module.base().customizableProperties = module.GetProperties()
 }
 
 // A restricted subset of context methods, similar to LoadHookContext.
diff --git a/android/defaults_test.go b/android/defaults_test.go
index a6abe8f..d096b2f 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -59,7 +59,6 @@
 }
 
 func TestDefaults(t *testing.T) {
-	t.Parallel()
 	bp := `
 		defaults {
 			name: "transitive",
@@ -103,7 +102,6 @@
 }
 
 func TestDefaultsAllowMissingDependencies(t *testing.T) {
-	t.Parallel()
 	bp := `
 		defaults {
 			name: "defaults",
diff --git a/android/depset.go b/android/depset.go
index f707094..60ebcac 100644
--- a/android/depset.go
+++ b/android/depset.go
@@ -71,24 +71,26 @@
 // NewDepSet returns an immutable DepSet with the given order, direct and transitive contents.
 func NewDepSet(order DepSetOrder, direct Paths, transitive []*DepSet) *DepSet {
 	var directCopy Paths
-	var transitiveCopy []*DepSet
+	transitiveCopy := make([]*DepSet, 0, len(transitive))
+
+	for _, dep := range transitive {
+		if dep != nil {
+			if dep.order != order {
+				panic(fmt.Errorf("incompatible order, new DepSet is %s but transitive DepSet is %s",
+					order, dep.order))
+			}
+			transitiveCopy = append(transitiveCopy, dep)
+		}
+	}
+
 	if order == TOPOLOGICAL {
 		directCopy = ReversePaths(direct)
-		transitiveCopy = reverseDepSets(transitive)
+		reverseDepSetsInPlace(transitiveCopy)
 	} else {
 		// Use copy instead of append(nil, ...) to make a slice that is exactly the size of the input
 		// slice.  The DepSet is immutable, there is no need for additional capacity.
 		directCopy = make(Paths, len(direct))
 		copy(directCopy, direct)
-		transitiveCopy = make([]*DepSet, len(transitive))
-		copy(transitiveCopy, transitive)
-	}
-
-	for _, dep := range transitive {
-		if dep.order != order {
-			panic(fmt.Errorf("incompatible order, new DepSet is %s but transitive DepSet is %s",
-				order, dep.order))
-		}
 	}
 
 	return &DepSet{
@@ -157,6 +159,9 @@
 // its transitive dependencies, in which case the ordering of the duplicated element is not
 // guaranteed).
 func (d *DepSet) ToList() Paths {
+	if d == nil {
+		return nil
+	}
 	var list Paths
 	d.walk(func(paths Paths) {
 		list = append(list, paths...)
@@ -181,10 +186,9 @@
 	}
 }
 
-func reverseDepSets(list []*DepSet) []*DepSet {
-	ret := make([]*DepSet, len(list))
-	for i := range list {
-		ret[i] = list[len(list)-1-i]
+func reverseDepSetsInPlace(list []*DepSet) {
+	for i, j := 0, len(list)-1; i < j; i, j = i+1, j-1 {
+		list[i], list[j] = list[j], list[i]
 	}
-	return ret
+
 }
diff --git a/android/depset_test.go b/android/depset_test.go
index 1ad27eb..c328127 100644
--- a/android/depset_test.go
+++ b/android/depset_test.go
@@ -64,7 +64,6 @@
 // Tests based on Bazel's ExpanderTestBase.java to ensure compatibility
 // https://github.com/bazelbuild/bazel/blob/master/src/test/java/com/google/devtools/build/lib/collect/nestedset/ExpanderTestBase.java
 func TestDepSet(t *testing.T) {
-	t.Parallel()
 	a := PathForTesting("a")
 	b := PathForTesting("b")
 	c := PathForTesting("c")
@@ -275,7 +274,6 @@
 }
 
 func TestDepSetInvalidOrder(t *testing.T) {
-	t.Parallel()
 	orders := []DepSetOrder{POSTORDER, PREORDER, TOPOLOGICAL}
 
 	run := func(t *testing.T, order1, order2 DepSetOrder) {
diff --git a/android/expand_test.go b/android/expand_test.go
index 7992288..12179ed 100644
--- a/android/expand_test.go
+++ b/android/expand_test.go
@@ -163,7 +163,6 @@
 }
 
 func TestExpand(t *testing.T) {
-	t.Parallel()
 	for _, test := range expandTestCases {
 		got, err := Expand(test.in, func(s string) (string, error) {
 			s, _, err := expander(s)
@@ -180,7 +179,6 @@
 }
 
 func TestExpandNinjaEscaped(t *testing.T) {
-	t.Parallel()
 	for _, test := range expandTestCases {
 		got, err := ExpandNinjaEscaped(test.in, expander)
 		if err != nil && !test.err {
diff --git a/android/makevars.go b/android/makevars.go
index 374986e..3ca7792 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -128,7 +128,7 @@
 type MakeVarsProvider func(ctx MakeVarsContext)
 
 func RegisterMakeVarsProvider(pctx PackageContext, provider MakeVarsProvider) {
-	makeVarsProviders = append(makeVarsProviders, makeVarsProvider{pctx, provider})
+	makeVarsInitProviders = append(makeVarsInitProviders, makeVarsProvider{pctx, provider})
 }
 
 // SingletonMakeVarsProvider is a Singleton with an extra method to provide extra values to be exported to Make.
@@ -142,7 +142,8 @@
 // registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to the list of
 // MakeVarsProviders to run.
 func registerSingletonMakeVarsProvider(singleton SingletonMakeVarsProvider) {
-	makeVarsProviders = append(makeVarsProviders, makeVarsProvider{pctx, SingletonmakeVarsProviderAdapter(singleton)})
+	singletonMakeVarsProviders = append(singletonMakeVarsProviders,
+		makeVarsProvider{pctx, SingletonmakeVarsProviderAdapter(singleton)})
 }
 
 // SingletonmakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
@@ -171,7 +172,11 @@
 	call MakeVarsProvider
 }
 
-var makeVarsProviders []makeVarsProvider
+// Collection of makevars providers that are registered in init() methods.
+var makeVarsInitProviders []makeVarsProvider
+
+// Collection of singleton makevars providers that are not registered as part of init() methods.
+var singletonMakeVarsProviders []makeVarsProvider
 
 type makeVarsContext struct {
 	SingletonContext
@@ -219,7 +224,7 @@
 	var vars []makeVarsVariable
 	var dists []dist
 	var phonies []phony
-	for _, provider := range makeVarsProviders {
+	for _, provider := range append(makeVarsInitProviders) {
 		mctx := &makeVarsContext{
 			SingletonContext: ctx,
 			pctx:             provider.pctx,
@@ -232,6 +237,25 @@
 		dists = append(dists, mctx.dists...)
 	}
 
+	for _, provider := range append(singletonMakeVarsProviders) {
+		mctx := &makeVarsContext{
+			SingletonContext: ctx,
+			pctx:             provider.pctx,
+		}
+
+		provider.call(mctx)
+
+		vars = append(vars, mctx.vars...)
+		phonies = append(phonies, mctx.phonies...)
+		dists = append(dists, mctx.dists...)
+	}
+
+	// Clear singleton makevars providers after use. Since these are in-memory
+	// singletons, this ensures state is reset if the build tree is processed
+	// multiple times.
+	// TODO(cparsons): Clean up makeVarsProviders to be part of the context.
+	singletonMakeVarsProviders = nil
+
 	ctx.VisitAllModules(func(m Module) {
 		if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled() {
 			mctx := &makeVarsContext{
diff --git a/android/module.go b/android/module.go
index 056b0a5..822e5bd 100644
--- a/android/module.go
+++ b/android/module.go
@@ -435,7 +435,7 @@
 	HostRequiredModuleNames() []string
 	TargetRequiredModuleNames() []string
 
-	filesToInstall() InstallPaths
+	FilesToInstall() InstallPaths
 }
 
 // Qualified id for a module
@@ -1241,14 +1241,14 @@
 	// TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
 	ctx.VisitDepsDepthFirst(func(m blueprint.Module) {
 		if a, ok := m.(Module); ok {
-			result = append(result, a.filesToInstall()...)
+			result = append(result, a.FilesToInstall()...)
 		}
 	})
 
 	return result
 }
 
-func (m *ModuleBase) filesToInstall() InstallPaths {
+func (m *ModuleBase) FilesToInstall() InstallPaths {
 	return m.installFiles
 }
 
diff --git a/android/module_test.go b/android/module_test.go
index b2a41e4..6e648d7 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -19,7 +19,6 @@
 )
 
 func TestSrcIsModule(t *testing.T) {
-	t.Parallel()
 	type args struct {
 		s string
 	}
@@ -67,7 +66,6 @@
 }
 
 func TestSrcIsModuleWithTag(t *testing.T) {
-	t.Parallel()
 	type args struct {
 		s string
 	}
@@ -166,7 +164,6 @@
 }
 
 func TestErrorDependsOnDisabledModule(t *testing.T) {
-	t.Parallel()
 	ctx := NewTestContext()
 	ctx.RegisterModuleType("deps", depsModuleFactory)
 
diff --git a/android/mutator_test.go b/android/mutator_test.go
index ce073bf..191b535 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -59,7 +59,6 @@
 }
 
 func TestMutatorAddMissingDependencies(t *testing.T) {
-	t.Parallel()
 	bp := `
 		test {
 			name: "foo",
@@ -93,7 +92,6 @@
 }
 
 func TestModuleString(t *testing.T) {
-	t.Parallel()
 	ctx := NewTestContext()
 
 	var moduleStrings []string
@@ -192,7 +190,6 @@
 }
 
 func TestFinalDepsPhase(t *testing.T) {
-	t.Parallel()
 	ctx := NewTestContext()
 
 	finalGot := map[string]int{}
@@ -270,7 +267,6 @@
 }
 
 func TestNoCreateVariationsInFinalDeps(t *testing.T) {
-	t.Parallel()
 	ctx := NewTestContext()
 
 	checkErr := func() {
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 5cce3e4..66c0d89 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -24,7 +24,6 @@
 )
 
 func TestDependingOnModuleInSameNamespace(t *testing.T) {
-	t.Parallel()
 	ctx := setupTest(t,
 		map[string]string{
 			"dir1": `
@@ -49,7 +48,6 @@
 }
 
 func TestDependingOnModuleInRootNamespace(t *testing.T) {
-	t.Parallel()
 	ctx := setupTest(t,
 		map[string]string{
 			".": `
@@ -72,7 +70,6 @@
 }
 
 func TestImplicitlyImportRootNamespace(t *testing.T) {
-	t.Parallel()
 	_ = setupTest(t,
 		map[string]string{
 			".": `
@@ -95,7 +92,6 @@
 }
 
 func TestDependingOnBlueprintModuleInRootNamespace(t *testing.T) {
-	t.Parallel()
 	_ = setupTest(t,
 		map[string]string{
 			".": `
@@ -118,7 +114,6 @@
 }
 
 func TestDependingOnModuleInImportedNamespace(t *testing.T) {
-	t.Parallel()
 	ctx := setupTest(t,
 		map[string]string{
 			"dir1": `
@@ -148,7 +143,6 @@
 }
 
 func TestDependingOnModuleInNonImportedNamespace(t *testing.T) {
-	t.Parallel()
 	_, errs := setupTestExpectErrs(
 		map[string]string{
 			"dir1": `
@@ -189,7 +183,6 @@
 }
 
 func TestDependingOnModuleByFullyQualifiedReference(t *testing.T) {
-	t.Parallel()
 	ctx := setupTest(t,
 		map[string]string{
 			"dir1": `
@@ -217,7 +210,6 @@
 }
 
 func TestSameNameInTwoNamespaces(t *testing.T) {
-	t.Parallel()
 	ctx := setupTest(t,
 		map[string]string{
 			"dir1": `
@@ -268,7 +260,6 @@
 }
 
 func TestSearchOrder(t *testing.T) {
-	t.Parallel()
 	ctx := setupTest(t,
 		map[string]string{
 			"dir1": `
@@ -357,7 +348,6 @@
 }
 
 func TestTwoNamespacesCanImportEachOther(t *testing.T) {
-	t.Parallel()
 	_ = setupTest(t,
 		map[string]string{
 			"dir1": `
@@ -388,7 +378,6 @@
 }
 
 func TestImportingNonexistentNamespace(t *testing.T) {
-	t.Parallel()
 	_, errs := setupTestExpectErrs(
 		map[string]string{
 			"dir1": `
@@ -413,7 +402,6 @@
 }
 
 func TestNamespacesDontInheritParentNamespaces(t *testing.T) {
-	t.Parallel()
 	_, errs := setupTestExpectErrs(
 		map[string]string{
 			"dir1": `
@@ -445,7 +433,6 @@
 }
 
 func TestModulesDoReceiveParentNamespace(t *testing.T) {
-	t.Parallel()
 	_ = setupTest(t,
 		map[string]string{
 			"dir1": `
@@ -468,7 +455,6 @@
 }
 
 func TestNamespaceImportsNotTransitive(t *testing.T) {
-	t.Parallel()
 	_, errs := setupTestExpectErrs(
 		map[string]string{
 			"dir1": `
@@ -510,7 +496,6 @@
 }
 
 func TestTwoNamepacesInSameDir(t *testing.T) {
-	t.Parallel()
 	_, errs := setupTestExpectErrs(
 		map[string]string{
 			"dir1": `
@@ -531,7 +516,6 @@
 }
 
 func TestNamespaceNotAtTopOfFile(t *testing.T) {
-	t.Parallel()
 	_, errs := setupTestExpectErrs(
 		map[string]string{
 			"dir1": `
@@ -553,7 +537,6 @@
 }
 
 func TestTwoModulesWithSameNameInSameNamespace(t *testing.T) {
-	t.Parallel()
 	_, errs := setupTestExpectErrs(
 		map[string]string{
 			"dir1": `
@@ -579,7 +562,6 @@
 }
 
 func TestDeclaringNamespaceInNonAndroidBpFile(t *testing.T) {
-	t.Parallel()
 	_, errs := setupTestFromFiles(
 		map[string][]byte{
 			"Android.bp": []byte(`
@@ -603,7 +585,6 @@
 
 // so that the generated .ninja file will have consistent names
 func TestConsistentNamespaceNames(t *testing.T) {
-	t.Parallel()
 	ctx := setupTest(t,
 		map[string]string{
 			"dir1": "soong_namespace{}",
@@ -623,7 +604,6 @@
 
 // so that the generated .ninja file will have consistent names
 func TestRename(t *testing.T) {
-	t.Parallel()
 	_ = setupTest(t,
 		map[string]string{
 			"dir1": `
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 306c509..56a07dc 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -343,7 +343,6 @@
 }
 
 func TestNeverallow(t *testing.T) {
-	t.Parallel()
 	for _, test := range neverallowTests {
 		// Create a test per config to allow for test specific config, e.g. test rules.
 		config := TestConfig(buildDir, nil, "", test.fs)
diff --git a/android/onceper_test.go b/android/onceper_test.go
index da0b10d..1a55ff4 100644
--- a/android/onceper_test.go
+++ b/android/onceper_test.go
@@ -20,7 +20,6 @@
 )
 
 func TestOncePer_Once(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key := NewOnceKey("key")
 
@@ -37,7 +36,6 @@
 }
 
 func TestOncePer_Once_wait(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key := NewOnceKey("key")
 
@@ -53,7 +51,6 @@
 }
 
 func TestOncePer_Get(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key := NewOnceKey("key")
 
@@ -70,7 +67,6 @@
 }
 
 func TestOncePer_Get_panic(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key := NewOnceKey("key")
 
@@ -86,7 +82,6 @@
 }
 
 func TestOncePer_Get_wait(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key := NewOnceKey("key")
 
@@ -102,7 +97,6 @@
 }
 
 func TestOncePer_OnceStringSlice(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key := NewOnceKey("key")
 
@@ -119,7 +113,6 @@
 }
 
 func TestOncePer_Once2StringSlice(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key := NewOnceKey("key")
 
@@ -136,7 +129,6 @@
 }
 
 func TestNewOnceKey(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key1 := NewOnceKey("key")
 	key2 := NewOnceKey("key")
@@ -154,7 +146,6 @@
 }
 
 func TestNewCustomOnceKey(t *testing.T) {
-	t.Parallel()
 	type key struct {
 		key string
 	}
@@ -175,7 +166,6 @@
 }
 
 func TestOncePerReentrant(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key1 := NewOnceKey("key")
 	key2 := NewOnceKey("key")
@@ -188,7 +178,6 @@
 
 // Test that a recovered panic in a Once function doesn't deadlock
 func TestOncePerPanic(t *testing.T) {
-	t.Parallel()
 	once := OncePer{}
 	key := NewOnceKey("key")
 
diff --git a/android/package_test.go b/android/package_test.go
index a4b4c60..04dfc08 100644
--- a/android/package_test.go
+++ b/android/package_test.go
@@ -56,7 +56,6 @@
 }
 
 func TestPackage(t *testing.T) {
-	t.Parallel()
 	for _, test := range packageTests {
 		t.Run(test.name, func(t *testing.T) {
 			_, errs := testPackage(test.fs)
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index 9bbb571..f367b82 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -59,7 +59,6 @@
 }
 
 func TestPathDepsMutator(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		bp   string
diff --git a/android/paths_test.go b/android/paths_test.go
index 03e1410..108bd6c 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -110,7 +110,6 @@
 }...)
 
 func TestValidateSafePath(t *testing.T) {
-	t.Parallel()
 	for _, testCase := range validateSafePathTestCases {
 		t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
 			ctx := &configErrorWrapper{}
@@ -124,7 +123,6 @@
 }
 
 func TestValidatePath(t *testing.T) {
-	t.Parallel()
 	for _, testCase := range validatePathTestCases {
 		t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
 			ctx := &configErrorWrapper{}
@@ -138,7 +136,6 @@
 }
 
 func TestOptionalPath(t *testing.T) {
-	t.Parallel()
 	var path OptionalPath
 	checkInvalidOptionalPath(t, path)
 
@@ -256,7 +253,6 @@
 }
 
 func TestPathForModuleInstall(t *testing.T) {
-	t.Parallel()
 	testConfig := pathTestConfig("")
 
 	hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
@@ -661,7 +657,6 @@
 }
 
 func TestDirectorySortedPaths(t *testing.T) {
-	t.Parallel()
 	config := TestConfig("out", nil, "", map[string][]byte{
 		"Android.bp": nil,
 		"a.txt":      nil,
@@ -744,7 +739,6 @@
 }
 
 func TestMaybeRel(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name   string
 		base   string
@@ -802,7 +796,6 @@
 }
 
 func TestPathForSource(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name     string
 		buildDir string
@@ -1035,7 +1028,6 @@
 }
 
 func TestPathsForModuleSrc(t *testing.T) {
-	t.Parallel()
 	tests := []pathForModuleSrcTestCase{
 		{
 			name: "path",
@@ -1131,7 +1123,6 @@
 }
 
 func TestPathForModuleSrc(t *testing.T) {
-	t.Parallel()
 	tests := []pathForModuleSrcTestCase{
 		{
 			name: "path",
@@ -1199,7 +1190,6 @@
 }
 
 func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
-	t.Parallel()
 	bp := `
 		test {
 			name: "foo",
@@ -1270,7 +1260,7 @@
 	// boot.art boot.oat
 }
 
-func ExampleOutputPath_FileInSameDir() {
+func ExampleOutputPath_InSameDir() {
 	ctx := &configErrorWrapper{
 		config: TestConfig("out", nil, "", nil),
 	}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 734871b..294a6e0 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -93,7 +93,7 @@
 // more modules like this.
 func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
 	if p.srcsSupplier != nil {
-		srcs := p.srcsSupplier()
+		srcs := p.srcsSupplier(ctx)
 
 		if len(srcs) == 0 {
 			ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file")
@@ -122,7 +122,7 @@
 // Called to provide the srcs value for the prebuilt module.
 //
 // Return the src value or nil if it is not available.
-type PrebuiltSrcsSupplier func() []string
+type PrebuiltSrcsSupplier func(ctx BaseModuleContext) []string
 
 // Initialize the module as a prebuilt module that uses the provided supplier to access the
 // prebuilt sources of the module.
@@ -156,7 +156,7 @@
 		panic(fmt.Errorf("srcs must not be nil"))
 	}
 
-	srcsSupplier := func() []string {
+	srcsSupplier := func(ctx BaseModuleContext) []string {
 		return *srcs
 	}
 
@@ -177,7 +177,7 @@
 	srcFieldIndex := srcStructField.Index
 	srcPropertyName := proptools.PropertyNameForField(srcField)
 
-	srcsSupplier := func() []string {
+	srcsSupplier := func(ctx BaseModuleContext) []string {
 		value := srcPropsValue.FieldByIndex(srcFieldIndex)
 		if value.Kind() == reflect.Ptr {
 			value = value.Elem()
@@ -287,7 +287,7 @@
 // usePrebuilt returns true if a prebuilt should be used instead of the source module.  The prebuilt
 // will be used if it is marked "prefer" or if the source module is disabled.
 func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
-	if p.srcsSupplier != nil && len(p.srcsSupplier()) == 0 {
+	if p.srcsSupplier != nil && len(p.srcsSupplier(ctx)) == 0 {
 		return false
 	}
 
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 40fced8..854395e 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -262,7 +262,6 @@
 }
 
 func TestPrebuilts(t *testing.T) {
-	t.Parallel()
 	fs := map[string][]byte{
 		"prebuilt_file": nil,
 		"source_file":   nil,
diff --git a/android/register.go b/android/register.go
index 036a811..ad3df7e 100644
--- a/android/register.go
+++ b/android/register.go
@@ -104,6 +104,8 @@
 
 	registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
 
+	ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(BazelSingleton))
+
 	// Register phony just before makevars so it can write out its phony rules as Make rules
 	ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory))
 
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index d205a5b..c41b067 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -264,7 +264,6 @@
 }
 
 func TestRuleBuilder(t *testing.T) {
-	t.Parallel()
 	fs := map[string][]byte{
 		"dep_fixer":  nil,
 		"input":      nil,
@@ -456,7 +455,6 @@
 }
 
 func TestRuleBuilder_Build(t *testing.T) {
-	t.Parallel()
 	fs := map[string][]byte{
 		"bar": nil,
 		"cp":  nil,
@@ -548,7 +546,6 @@
 }
 
 func Test_ninjaEscapeExceptForSpans(t *testing.T) {
-	t.Parallel()
 	type args struct {
 		s     string
 		spans [][2]int
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index f0f1462..9677f34 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -19,8 +19,24 @@
 	"testing"
 )
 
+type soongConfigTestDefaultsModuleProperties struct {
+}
+
+type soongConfigTestDefaultsModule struct {
+	ModuleBase
+	DefaultsModuleBase
+}
+
+func soongConfigTestDefaultsModuleFactory() Module {
+	m := &soongConfigTestDefaultsModule{}
+	m.AddProperties(&soongConfigTestModuleProperties{})
+	InitDefaultsModule(m)
+	return m
+}
+
 type soongConfigTestModule struct {
 	ModuleBase
+	DefaultableModuleBase
 	props soongConfigTestModuleProperties
 }
 
@@ -32,22 +48,22 @@
 	m := &soongConfigTestModule{}
 	m.AddProperties(&m.props)
 	InitAndroidModule(m)
+	InitDefaultableModule(m)
 	return m
 }
 
 func (t soongConfigTestModule) GenerateAndroidBuildActions(ModuleContext) {}
 
 func TestSoongConfigModule(t *testing.T) {
-	t.Parallel()
 	configBp := `
 		soong_config_module_type {
-			name: "acme_test_defaults",
-			module_type: "test_defaults",
+			name: "acme_test",
+			module_type: "test",
 			config_namespace: "acme",
 			variables: ["board", "feature1", "FEATURE3"],
 			bool_variables: ["feature2"],
 			value_variables: ["size"],
-			properties: ["cflags", "srcs"],
+			properties: ["cflags", "srcs", "defaults"],
 		}
 
 		soong_config_string_variable {
@@ -67,14 +83,20 @@
 	importBp := `
 		soong_config_module_type_import {
 			from: "SoongConfig.bp",
-			module_types: ["acme_test_defaults"],
+			module_types: ["acme_test"],
 		}
 	`
 
 	bp := `
-		acme_test_defaults {
+		test_defaults {
+			name: "foo_defaults",
+			cflags: ["DEFAULT"],
+		}
+
+		acme_test {
 			name: "foo",
 			cflags: ["-DGENERIC"],
+			defaults: ["foo_defaults"],
 			soong_config_variables: {
 				board: {
 					soc_a: {
@@ -98,6 +120,46 @@
 				},
 			},
 		}
+
+		test_defaults {
+			name: "foo_defaults_a",
+			cflags: ["DEFAULT_A"],
+		}
+
+		test_defaults {
+			name: "foo_defaults_b",
+			cflags: ["DEFAULT_B"],
+		}
+
+		acme_test {
+			name: "foo_with_defaults",
+			cflags: ["-DGENERIC"],
+			defaults: ["foo_defaults"],
+			soong_config_variables: {
+				board: {
+					soc_a: {
+						cflags: ["-DSOC_A"],
+						defaults: ["foo_defaults_a"],
+					},
+					soc_b: {
+						cflags: ["-DSOC_B"],
+						defaults: ["foo_defaults_b"],
+					},
+				},
+				size: {
+					cflags: ["-DSIZE=%s"],
+				},
+				feature1: {
+					cflags: ["-DFEATURE1"],
+				},
+				feature2: {
+					cflags: ["-DFEATURE2"],
+				},
+				FEATURE3: {
+					cflags: ["-DFEATURE3"],
+				},
+			},
+		}
     `
 
 	run := func(t *testing.T, bp string, fs map[string][]byte) {
@@ -118,7 +180,9 @@
 		ctx.RegisterModuleType("soong_config_module_type", soongConfigModuleTypeFactory)
 		ctx.RegisterModuleType("soong_config_string_variable", soongConfigStringVariableDummyFactory)
 		ctx.RegisterModuleType("soong_config_bool_variable", soongConfigBoolVariableDummyFactory)
-		ctx.RegisterModuleType("test_defaults", soongConfigTestModuleFactory)
+		ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
+		ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
+		ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
 		ctx.Register(config)
 
 		_, errs := ctx.ParseBlueprintsFiles("Android.bp")
@@ -126,10 +190,18 @@
 		_, errs = ctx.PrepareBuildActions(config)
 		FailIfErrored(t, errs)
 
+		basicCFlags := []string{"DEFAULT", "-DGENERIC", "-DSIZE=42", "-DSOC_A", "-DFEATURE1"}
+
 		foo := ctx.ModuleForTests("foo", "").Module().(*soongConfigTestModule)
-		if g, w := foo.props.Cflags, []string{"-DGENERIC", "-DSIZE=42", "-DSOC_A", "-DFEATURE1"}; !reflect.DeepEqual(g, w) {
+		if g, w := foo.props.Cflags, basicCFlags; !reflect.DeepEqual(g, w) {
 			t.Errorf("wanted foo cflags %q, got %q", w, g)
 		}
+
+		fooDefaults := ctx.ModuleForTests("foo_with_defaults", "").Module().(*soongConfigTestModule)
+		if g, w := fooDefaults.props.Cflags, append([]string{"DEFAULT_A"}, basicCFlags...); !reflect.DeepEqual(g, w) {
+			t.Errorf("wanted foo_with_defaults cflags %q, got %q", w, g)
+		}
+
 	}
 
 	t.Run("single file", func(t *testing.T) {
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index ff4883e..4190016 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -20,7 +20,6 @@
 )
 
 func Test_CanonicalizeToProperty(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		arg  string
@@ -67,7 +66,6 @@
 }
 
 func Test_typeForPropertyFromPropertyStruct(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name     string
 		ps       interface{}
@@ -188,7 +186,6 @@
 }
 
 func Test_createAffectablePropertiesType(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name                 string
 		affectableProperties []string
diff --git a/android/test_suites.go b/android/test_suites.go
index 34e487e..19444a8 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -41,7 +41,7 @@
 					files[testSuite] = make(map[string]InstallPaths)
 				}
 				name := ctx.ModuleName(m)
-				files[testSuite][name] = append(files[testSuite][name], tsm.filesToInstall()...)
+				files[testSuite][name] = append(files[testSuite][name], tsm.FilesToInstall()...)
 			}
 		}
 	})
diff --git a/android/util_test.go b/android/util_test.go
index 8c42157..25b52ca 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -60,7 +60,6 @@
 }
 
 func TestFirstUniqueStrings(t *testing.T) {
-	t.Parallel()
 	f := func(t *testing.T, imp func([]string) []string, in, want []string) {
 		t.Helper()
 		out := imp(in)
@@ -121,7 +120,6 @@
 }
 
 func TestLastUniqueStrings(t *testing.T) {
-	t.Parallel()
 	for _, testCase := range lastUniqueStringsTestCases {
 		out := LastUniqueStrings(testCase.in)
 		if !reflect.DeepEqual(out, testCase.out) {
@@ -134,7 +132,6 @@
 }
 
 func TestJoinWithPrefix(t *testing.T) {
-	t.Parallel()
 	testcases := []struct {
 		name     string
 		input    []string
@@ -174,7 +171,6 @@
 }
 
 func TestIndexList(t *testing.T) {
-	t.Parallel()
 	input := []string{"a", "b", "c"}
 
 	testcases := []struct {
@@ -214,7 +210,6 @@
 }
 
 func TestInList(t *testing.T) {
-	t.Parallel()
 	input := []string{"a"}
 
 	testcases := []struct {
@@ -246,7 +241,6 @@
 }
 
 func TestPrefixInList(t *testing.T) {
-	t.Parallel()
 	prefixes := []string{"a", "b"}
 
 	testcases := []struct {
@@ -282,7 +276,6 @@
 }
 
 func TestFilterList(t *testing.T) {
-	t.Parallel()
 	input := []string{"a", "b", "c", "c", "b", "d", "a"}
 	filter := []string{"a", "c"}
 	remainder, filtered := FilterList(input, filter)
@@ -307,7 +300,6 @@
 }
 
 func TestRemoveListFromList(t *testing.T) {
-	t.Parallel()
 	input := []string{"a", "b", "c", "d", "a", "c", "d"}
 	filter := []string{"a", "c"}
 	expected := []string{"b", "d", "d"}
@@ -322,7 +314,6 @@
 }
 
 func TestRemoveFromList(t *testing.T) {
-	t.Parallel()
 	testcases := []struct {
 		name          string
 		key           string
@@ -426,7 +417,6 @@
 }
 
 func TestSplitFileExt(t *testing.T) {
-	t.Parallel()
 	t.Run("soname with version", func(t *testing.T) {
 		root, suffix, ext := SplitFileExt("libtest.so.1.0.30")
 		expected := "libtest"
@@ -492,7 +482,6 @@
 }
 
 func Test_Shard(t *testing.T) {
-	t.Parallel()
 	type args struct {
 		strings   []string
 		shardSize int
diff --git a/android/variable.go b/android/variable.go
index ce523ed..a9495cc 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -304,8 +304,8 @@
 
 	BoardVendorSepolicyDirs      []string `json:",omitempty"`
 	BoardOdmSepolicyDirs         []string `json:",omitempty"`
-	BoardPlatPublicSepolicyDirs  []string `json:",omitempty"`
-	BoardPlatPrivateSepolicyDirs []string `json:",omitempty"`
+	SystemExtPublicSepolicyDirs  []string `json:",omitempty"`
+	SystemExtPrivateSepolicyDirs []string `json:",omitempty"`
 	BoardSepolicyM4Defs          []string `json:",omitempty"`
 
 	VendorVars map[string]map[string]string `json:",omitempty"`
@@ -390,7 +390,7 @@
 		AAPTPrebuiltDPI:     []string{"xhdpi", "xxhdpi"},
 
 		Malloc_not_svelte:            boolPtr(true),
-		Malloc_zero_contents:         boolPtr(false),
+		Malloc_zero_contents:         boolPtr(true),
 		Malloc_pattern_fill_contents: boolPtr(false),
 		Safestack:                    boolPtr(false),
 	}
diff --git a/android/variable_test.go b/android/variable_test.go
index 9348b0d..9cafedd 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -112,7 +112,6 @@
 }
 
 func TestPrintfIntoProperty(t *testing.T) {
-	t.Parallel()
 	for _, testCase := range printfIntoPropertyTestCases {
 		s := testCase.in
 		v := reflect.ValueOf(&s).Elem()
@@ -158,7 +157,6 @@
 }
 
 func TestProductVariables(t *testing.T) {
-	t.Parallel()
 	ctx := NewTestContext()
 	// A module type that has a srcs property but not a cflags property.
 	ctx.RegisterModuleType("module1", testProductVariableModuleFactoryFactory(&struct {
@@ -267,7 +265,6 @@
 
 // Test a defaults module that supports more product variable properties than the target module.
 func TestProductVariablesDefaults(t *testing.T) {
-	t.Parallel()
 	bp := `
 		defaults {
 			name: "defaults",
diff --git a/android/visibility.go b/android/visibility.go
index 51d5611..7eac471 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -351,7 +351,10 @@
 			case "__subpackages__":
 				r = subpackagesRule{pkg}
 			default:
-				continue
+				ctx.PropertyErrorf(property, "invalid visibility pattern %q. Must match "+
+					" //<package>:<scope>, //<package> or :<scope> "+
+					"where <scope> is one of \"__pkg__\", \"__subpackages__\"",
+					v)
 			}
 		}
 
@@ -397,7 +400,8 @@
 		// ensure all the rules on this module are checked.
 		ctx.PropertyErrorf(property,
 			"invalid visibility pattern %q must match"+
-				" //<package>:<module>, //<package> or :<module>",
+				" //<package>:<scope>, //<package> or :<scope> "+
+				"where <scope> is one of \"__pkg__\", \"__subpackages__\"",
 			ruleExpression)
 		return false, "", ""
 	}
@@ -443,7 +447,7 @@
 
 		rule := effectiveVisibilityRules(ctx.Config(), depQualified)
 		if !rule.matches(qualified) {
-			ctx.ModuleErrorf("depends on %s which is not visible to this module", depQualified)
+			ctx.ModuleErrorf("depends on %s which is not visible to this module\nYou may need to add %q to its visibility", depQualified, "//"+ctx.ModuleDir())
 		}
 	})
 }
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 8de5fa9..cb5ef35 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -731,7 +731,7 @@
 				}`),
 		},
 		expectedErrors: []string{
-			`module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+			`module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module\nYou may need to add "//namespace" to its visibility`,
 		},
 	},
 	{
@@ -760,7 +760,7 @@
 				}`),
 		},
 		expectedErrors: []string{
-			`module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+			`module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module\nYou may need to add "//namespace" to its visibility`,
 		},
 	},
 	{
@@ -1140,7 +1140,6 @@
 }
 
 func TestVisibility(t *testing.T) {
-	t.Parallel()
 	for _, test := range visibilityTests {
 		t.Run(test.name, func(t *testing.T) {
 			ctx, errs := testVisibility(buildDir, test.fs)
diff --git a/android/vts_config.go b/android/vts_config.go
deleted file mode 100644
index 77fb9fe..0000000
--- a/android/vts_config.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2016 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 android
-
-import (
-	"fmt"
-	"io"
-	"strings"
-)
-
-func init() {
-	RegisterModuleType("vts_config", VtsConfigFactory)
-}
-
-type vtsConfigProperties struct {
-	// Override the default (AndroidTest.xml) test manifest file name.
-	Test_config *string
-	// Additional test suites to add the test to.
-	Test_suites []string `android:"arch_variant"`
-}
-
-type VtsConfig struct {
-	ModuleBase
-	properties     vtsConfigProperties
-	OutputFilePath OutputPath
-}
-
-func (me *VtsConfig) GenerateAndroidBuildActions(ctx ModuleContext) {
-	me.OutputFilePath = PathForModuleOut(ctx, me.BaseModuleName()).OutputPath
-}
-
-func (me *VtsConfig) AndroidMk() AndroidMkData {
-	androidMkData := AndroidMkData{
-		Class:      "FAKE",
-		Include:    "$(BUILD_SYSTEM)/suite_host_config.mk",
-		OutputFile: OptionalPathForPath(me.OutputFilePath),
-	}
-	androidMkData.Extra = []AndroidMkExtraFunc{
-		func(w io.Writer, outputFile Path) {
-			if me.properties.Test_config != nil {
-				fmt.Fprintf(w, "LOCAL_TEST_CONFIG := %s\n",
-					*me.properties.Test_config)
-			}
-			fmt.Fprintf(w, "LOCAL_COMPATIBILITY_SUITE := vts10 %s\n",
-				strings.Join(me.properties.Test_suites, " "))
-		},
-	}
-	return androidMkData
-}
-
-func InitVtsConfigModule(me *VtsConfig) {
-	me.AddProperties(&me.properties)
-}
-
-// vts_config generates a Vendor Test Suite (VTS10) configuration file from the
-// <test_config> xml file and stores it in a subdirectory of $(HOST_OUT).
-func VtsConfigFactory() Module {
-	module := &VtsConfig{}
-	InitVtsConfigModule(module)
-	InitAndroidArchModule(module /*TODO: or HostAndDeviceSupported? */, HostSupported, MultilibFirst)
-	return module
-}
diff --git a/android/vts_config_test.go b/android/vts_config_test.go
deleted file mode 100644
index a95e589..0000000
--- a/android/vts_config_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2018 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 android
-
-import (
-	"testing"
-)
-
-func testVtsConfig(test *testing.T, bpFileContents string) *TestContext {
-	config := TestArchConfig(buildDir, nil, bpFileContents, nil)
-
-	ctx := NewTestArchContext()
-	ctx.RegisterModuleType("vts_config", VtsConfigFactory)
-	ctx.Register(config)
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	FailIfErrored(test, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	FailIfErrored(test, errs)
-	return ctx
-}
-
-func TestVtsConfig(t *testing.T) {
-	t.Parallel()
-	ctx := testVtsConfig(t, `
-vts_config { name: "plain"}
-vts_config { name: "with_manifest", test_config: "manifest.xml" }
-`)
-
-	variants := ctx.ModuleVariantsForTests("plain")
-	if len(variants) > 1 {
-		t.Errorf("expected 1, got %d", len(variants))
-	}
-	expectedOutputFilename := ctx.ModuleForTests(
-		"plain", variants[0]).Module().(*VtsConfig).OutputFilePath.Base()
-	if expectedOutputFilename != "plain" {
-		t.Errorf("expected plain, got %q", expectedOutputFilename)
-	}
-}
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index eaf06c5..739a965 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -953,8 +953,7 @@
 var soongModuleTypes = map[string]bool{}
 
 var includePathToModule = map[string]string{
-	"test/vts/tools/build/Android.host_config.mk": "vts_config",
-	// The rest will be populated dynamically in androidScope below
+	// The content will be populated dynamically in androidScope below
 }
 
 func mapIncludePath(path string) (string, bool) {
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 560ea13..16cb138 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1257,19 +1257,6 @@
 `,
 	},
 	{
-		desc: "vts_config",
-		in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := vtsconf
-include test/vts/tools/build/Android.host_config.mk
-`,
-		expected: `
-vts_config {
-	name: "vtsconf",
-}
-`,
-	},
-	{
 		desc: "comment with ESC",
 		in: `
 # Comment line 1 \
@@ -1462,7 +1449,6 @@
 }
 
 func TestEndToEnd(t *testing.T) {
-	t.Parallel()
 	for i, test := range testCases {
 		expected, err := bpfix.Reformat(test.expected)
 		if err != nil {
diff --git a/androidmk/parser/make_strings_test.go b/androidmk/parser/make_strings_test.go
index 9622068..6995e89 100644
--- a/androidmk/parser/make_strings_test.go
+++ b/androidmk/parser/make_strings_test.go
@@ -89,7 +89,6 @@
 }
 
 func TestMakeStringSplitN(t *testing.T) {
-	t.Parallel()
 	for _, test := range splitNTestCases {
 		got := test.in.SplitN(test.sep, test.n)
 		gotString := dumpArray(got)
@@ -119,7 +118,6 @@
 }
 
 func TestMakeStringValue(t *testing.T) {
-	t.Parallel()
 	for _, test := range valueTestCases {
 		got := test.in.Value(nil)
 		if got != test.expected {
@@ -163,7 +161,6 @@
 }
 
 func TestMakeStringWords(t *testing.T) {
-	t.Parallel()
 	for _, test := range splitWordsTestCases {
 		got := test.in.Words()
 		gotString := dumpArray(got)
diff --git a/androidmk/parser/parser_test.go b/androidmk/parser/parser_test.go
index 7c05a0c..f562c29 100644
--- a/androidmk/parser/parser_test.go
+++ b/androidmk/parser/parser_test.go
@@ -37,7 +37,6 @@
 }
 
 func TestParse(t *testing.T) {
-	t.Parallel()
 	for _, test := range parserTestCases {
 		t.Run(test.name, func(t *testing.T) {
 			p := NewParser(test.name, bytes.NewBufferString(test.in))
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 87e96ea..cd4b056 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -124,6 +124,7 @@
 apache-commons-compress(minSdkVersion:current)
 art.module.public.api.stubs(minSdkVersion:(no version))
 bcm_object(minSdkVersion:29)
+bionic_libc_platform_headers(minSdkVersion:29)
 boringssl_self_test(minSdkVersion:29)
 bouncycastle_ike_digests(minSdkVersion:current)
 brotli-java(minSdkVersion:current)
@@ -138,12 +139,19 @@
 conscrypt.module.public.api.stubs(minSdkVersion:(no version))
 core-lambda-stubs(minSdkVersion:(no version))
 core.current.stubs(minSdkVersion:(no version))
+crtbegin_dynamic(minSdkVersion:16)
 crtbegin_dynamic(minSdkVersion:apex_inherit)
+crtbegin_dynamic1(minSdkVersion:16)
 crtbegin_dynamic1(minSdkVersion:apex_inherit)
+crtbegin_so(minSdkVersion:16)
 crtbegin_so(minSdkVersion:apex_inherit)
+crtbegin_so1(minSdkVersion:16)
 crtbegin_so1(minSdkVersion:apex_inherit)
+crtbrand(minSdkVersion:16)
 crtbrand(minSdkVersion:apex_inherit)
+crtend_android(minSdkVersion:16)
 crtend_android(minSdkVersion:apex_inherit)
+crtend_so(minSdkVersion:16)
 crtend_so(minSdkVersion:apex_inherit)
 datastallprotosnano(minSdkVersion:29)
 derive_sdk(minSdkVersion:current)
@@ -186,6 +194,7 @@
 libadb_pairing_connection(minSdkVersion:(no version))
 libadb_pairing_server(minSdkVersion:(no version))
 libadb_protos(minSdkVersion:(no version))
+libadb_sysdeps(minSdkVersion:apex_inherit)
 libadb_tls_connection(minSdkVersion:(no version))
 libadbconnection_client(minSdkVersion:(no version))
 libadbconnection_server(minSdkVersion:(no version))
@@ -273,6 +282,7 @@
 libFLAC-headers(minSdkVersion:29)
 libflacextractor(minSdkVersion:29)
 libfmq(minSdkVersion:29)
+libfmq-base(minSdkVersion:29)
 libFraunhoferAAC(minSdkVersion:29)
 libgav1(minSdkVersion:29)
 libgcc_stripped(minSdkVersion:(no version))
@@ -289,6 +299,7 @@
 libhidlbase(minSdkVersion:29)
 libhidlmemory(minSdkVersion:29)
 libhwbinder-impl-internal(minSdkVersion:29)
+libhwbinder_headers(minSdkVersion:29)
 libion(minSdkVersion:29)
 libjavacrypto(minSdkVersion:29)
 libjsoncpp(minSdkVersion:29)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 5a9a3b1..c52fd04 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -345,7 +345,6 @@
 
 // Minimal test
 func TestBasicApex(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex_defaults {
 			name: "myapex-defaults",
@@ -598,7 +597,6 @@
 }
 
 func TestDefaults(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_defaults {
 			name: "myapex-defaults",
@@ -673,7 +671,6 @@
 }
 
 func TestApexManifest(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -695,7 +692,6 @@
 }
 
 func TestBasicZipApex(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -746,7 +742,6 @@
 }
 
 func TestApexWithStubs(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -939,7 +934,6 @@
 }
 
 func TestApexWithExplicitStubsDependency(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex2",
@@ -1027,7 +1021,6 @@
 }
 
 func TestApexWithRuntimeLibsDependency(t *testing.T) {
-	t.Parallel()
 	/*
 		myapex
 		  |
@@ -1097,7 +1090,6 @@
 }
 
 func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
 		bp := `
 		apex {
@@ -1161,7 +1153,6 @@
 }
 
 func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
 		bp := `
 		apex {
@@ -1223,7 +1214,6 @@
 }
 
 func TestApexDependsOnLLNDKTransitively(t *testing.T) {
-	t.Parallel()
 	testcases := []struct {
 		name          string
 		minSdkVersion string
@@ -1313,7 +1303,6 @@
 }
 
 func TestApexWithSystemLibsStubs(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -1330,6 +1319,7 @@
 		cc_library {
 			name: "mylib",
 			srcs: ["mylib.cpp"],
+			system_shared_libs: ["libc", "libm"],
 			shared_libs: ["libdl#27"],
 			stl: "none",
 			apex_available: [ "myapex" ],
@@ -1404,7 +1394,6 @@
 }
 
 func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T) {
-	t.Parallel()
 	// there are three links between liba --> libz
 	// 1) myapex -> libx -> liba -> libz    : this should be #29 link, but fallback to #28
 	// 2) otherapex -> liby -> liba -> libz : this should be #30 link
@@ -1491,7 +1480,6 @@
 }
 
 func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -1541,7 +1529,6 @@
 }
 
 func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -1587,7 +1574,6 @@
 }
 
 func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -1635,7 +1621,6 @@
 }
 
 func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -1675,7 +1660,6 @@
 }
 
 func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -1706,7 +1690,6 @@
 }
 
 func TestApexMinSdkVersion_ErrorIfIncompatibleStubs(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `"libz" .*: not found a version\(<=29\)`, `
 		apex {
 			name: "myapex",
@@ -1742,7 +1725,6 @@
 }
 
 func TestApexMinSdkVersion_ErrorIfIncompatibleVersion(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `module "mylib".*: should support min_sdk_version\(29\)`, `
 		apex {
 			name: "myapex",
@@ -1771,7 +1753,6 @@
 }
 
 func TestApexMinSdkVersion_Okay(t *testing.T) {
-	t.Parallel()
 	testApex(t, `
 		apex {
 			name: "myapex",
@@ -1822,7 +1803,6 @@
 }
 
 func TestJavaStableSdkVersion(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name          string
 		expectedError string
@@ -1940,7 +1920,6 @@
 }
 
 func TestApexMinSdkVersion_ErrorIfDepIsNewer(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `module "mylib2".*: should support min_sdk_version\(29\) for "myapex"`, `
 		apex {
 			name: "myapex",
@@ -1982,7 +1961,6 @@
 }
 
 func TestApexMinSdkVersion_ErrorIfDepIsNewer_Java(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `module "bar".*: should support min_sdk_version\(29\) for "myapex"`, `
 		apex {
 			name: "myapex",
@@ -2018,7 +1996,6 @@
 }
 
 func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2072,7 +2049,6 @@
 }
 
 func TestFilesInSubDir(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2135,7 +2111,6 @@
 }
 
 func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2194,7 +2169,6 @@
 }
 
 func TestUseVendor(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2249,7 +2223,6 @@
 }
 
 func TestUseVendorNotAllowedForSystemApexes(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `module "myapex" .*: use_vendor: not allowed`, `
 		apex {
 			name: "myapex",
@@ -2282,7 +2255,6 @@
 }
 
 func TestUseVendorFailsIfNotVendorAvailable(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `dependency "mylib" of "myapex" missing variant:\n.*image:vendor`, `
 		apex {
 			name: "myapex",
@@ -2307,7 +2279,6 @@
 }
 
 func TestVendorApex(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2353,7 +2324,6 @@
 }
 
 func TestVendorApex_use_vndk_as_stable(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2407,7 +2377,6 @@
 }
 
 func TestApex_withPrebuiltFirmware(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name           string
 		additionalProp string
@@ -2444,7 +2413,6 @@
 }
 
 func TestAndroidMk_UseVendorRequired(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2479,7 +2447,6 @@
 }
 
 func TestAndroidMk_VendorApexRequired(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2511,7 +2478,6 @@
 }
 
 func TestAndroidMkWritesCommonProperties(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2541,7 +2507,6 @@
 }
 
 func TestStaticLinking(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2586,7 +2551,6 @@
 }
 
 func TestKeys(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex_keytest",
@@ -2643,7 +2607,6 @@
 }
 
 func TestCertificate(t *testing.T) {
-	t.Parallel()
 	t.Run("if unspecified, it defaults to DefaultAppCertificate", func(t *testing.T) {
 		ctx, _ := testApex(t, `
 			apex {
@@ -2772,7 +2735,6 @@
 }
 
 func TestMacro(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -2900,7 +2862,6 @@
 }
 
 func TestHeaderLibsDependency(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -3044,7 +3005,6 @@
 }
 
 func TestVndkApexCurrent(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_vndk {
 			name: "myapex",
@@ -3098,7 +3058,6 @@
 }
 
 func TestVndkApexWithPrebuilt(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_vndk {
 			name: "myapex",
@@ -3181,7 +3140,6 @@
 }
 
 func TestVndkApexVersion(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_vndk {
 			name: "myapex_v27",
@@ -3248,7 +3206,6 @@
 }
 
 func TestVndkApexErrorWithDuplicateVersion(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `module "myapex_v27.*" .*: vndk_version: 27 is already defined in "myapex_v27.*"`, `
 		apex_vndk {
 			name: "myapex_v27",
@@ -3295,7 +3252,6 @@
 }
 
 func TestVndkApexNameRule(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_vndk {
 			name: "myapex",
@@ -3327,7 +3283,6 @@
 }
 
 func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_vndk {
 			name: "myapex",
@@ -3366,7 +3321,6 @@
 }
 
 func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `module "myapex" .*: native_bridge_supported: .* doesn't support native bridge binary`, `
 		apex_vndk {
 			name: "myapex",
@@ -3397,7 +3351,6 @@
 }
 
 func TestVndkApexWithBinder32(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_vndk {
 			name: "myapex_v27",
@@ -3464,7 +3417,6 @@
 }
 
 func TestVndkApexShouldNotProvideNativeLibs(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_vndk {
 			name: "myapex",
@@ -3499,7 +3451,6 @@
 }
 
 func TestDependenciesInApexManifest(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex_nodep",
@@ -3604,7 +3555,6 @@
 }
 
 func TestApexName(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
@@ -3649,7 +3599,6 @@
 }
 
 func TestNonTestApex(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -3702,7 +3651,6 @@
 }
 
 func TestTestApex(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_test {
 			name: "myapex",
@@ -3751,7 +3699,6 @@
 }
 
 func TestApexWithTarget(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -3842,7 +3789,6 @@
 }
 
 func TestApexWithShBinary(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -3871,7 +3817,6 @@
 }
 
 func TestApexInVariousPartition(t *testing.T) {
-	t.Parallel()
 	testcases := []struct {
 		propName, parition, flattenedPartition string
 	}{
@@ -3916,7 +3861,6 @@
 }
 
 func TestFileContexts_FindInDefaultLocationIfNotSet(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -3935,7 +3879,6 @@
 }
 
 func TestFileContexts_ShouldBeUnderSystemSepolicyForSystemApexes(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `"myapex" .*: file_contexts: should be under system/sepolicy`, `
 		apex {
 			name: "myapex",
@@ -3954,7 +3897,6 @@
 }
 
 func TestFileContexts_ProductSpecificApexes(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `"myapex" .*: file_contexts: cannot find`, `
 		apex {
 			name: "myapex",
@@ -3992,7 +3934,6 @@
 }
 
 func TestFileContexts_SetViaFileGroup(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -4020,7 +3961,6 @@
 }
 
 func TestApexKeyFromOtherModule(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_key {
 			name: "myapex.key",
@@ -4054,7 +3994,6 @@
 }
 
 func TestPrebuilt(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		prebuilt_apex {
 			name: "myapex",
@@ -4078,7 +4017,6 @@
 }
 
 func TestPrebuiltFilenameOverride(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		prebuilt_apex {
 			name: "myapex",
@@ -4096,7 +4034,6 @@
 }
 
 func TestPrebuiltOverrides(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		prebuilt_apex {
 			name: "myapex.prebuilt",
@@ -4117,7 +4054,6 @@
 }
 
 func TestApexWithTests(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex_test {
 			name: "myapex",
@@ -4229,7 +4165,6 @@
 }
 
 func TestInstallExtraFlattenedApexes(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
@@ -4253,7 +4188,6 @@
 }
 
 func TestApexUsesOtherApex(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -4314,7 +4248,6 @@
 }
 
 func TestApexUsesFailsIfNotProvided(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `uses: "commonapex" does not provide native_shared_libs`, `
 		apex {
 			name: "myapex",
@@ -4355,7 +4288,6 @@
 }
 
 func TestApexUsesFailsIfUseVenderMismatch(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `use_vendor: "commonapex" has different value of use_vendor`, `
 		apex {
 			name: "myapex",
@@ -4381,7 +4313,6 @@
 }
 
 func TestErrorsIfDepsAreNotEnabled(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `module "myapex" .* depends on disabled module "libfoo"`, `
 		apex {
 			name: "myapex",
@@ -4428,7 +4359,6 @@
 }
 
 func TestApexWithApps(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -4507,7 +4437,6 @@
 }
 
 func TestApexWithAppImports(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -4556,7 +4485,6 @@
 }
 
 func TestApexWithAppImportsPrefer(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -4598,7 +4526,6 @@
 }
 
 func TestApexWithTestHelperApp(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -4630,7 +4557,6 @@
 }
 
 func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
-	t.Parallel()
 	// libfoo's apex_available comes from cc_defaults
 	testApexError(t, `requires "libfoo" that is not available for the APEX`, `
 	apex {
@@ -4665,7 +4591,6 @@
 }
 
 func TestApexAvailable_DirectDep(t *testing.T) {
-	t.Parallel()
 	// libfoo is not available to myapex, but only to otherapex
 	testApexError(t, "requires \"libfoo\" that is not available for the APEX", `
 	apex {
@@ -4701,7 +4626,6 @@
 }
 
 func TestApexAvailable_IndirectDep(t *testing.T) {
-	t.Parallel()
 	// libbbaz is an indirect dep
 	testApexError(t, `requires "libbaz" that is not available for the APEX. Dependency path:
 .*via tag apex\.dependencyTag.*name:sharedLib.*
@@ -4746,7 +4670,6 @@
 }
 
 func TestApexAvailable_InvalidApexName(t *testing.T) {
-	t.Parallel()
 	testApexError(t, "\"otherapex\" is not a valid module name", `
 	apex {
 		name: "myapex",
@@ -4806,7 +4729,6 @@
 }
 
 func TestApexAvailable_CheckForPlatform(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 	apex {
 		name: "myapex",
@@ -4869,7 +4791,6 @@
 }
 
 func TestApexAvailable_CreatedForApex(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 	apex {
 		name: "myapex",
@@ -4904,7 +4825,6 @@
 }
 
 func TestOverrideApex(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
@@ -4988,7 +4908,6 @@
 }
 
 func TestLegacyAndroid10Support(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5044,7 +4963,6 @@
 }
 
 func TestJavaSDKLibrary(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5077,7 +4995,6 @@
 }
 
 func TestJavaSDKLibrary_WithinApex(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5125,7 +5042,6 @@
 }
 
 func TestJavaSDKLibrary_CrossBoundary(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5171,7 +5087,6 @@
 }
 
 func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, ``,
 		withFiles(map[string][]byte{
 			"apex/a.java":             nil,
@@ -5257,7 +5172,6 @@
 }
 
 func TestJavaSDKLibrary_ImportOnly(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `java_libs: "foo" is not configured to be compiled into dex`, `
 		apex {
 			name: "myapex",
@@ -5284,7 +5198,6 @@
 }
 
 func TestCompatConfig(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5319,7 +5232,6 @@
 }
 
 func TestRejectNonInstallableJavaLibrary(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `"myjar" is not configured to be compiled into dex`, `
 		apex {
 			name: "myapex",
@@ -5345,7 +5257,6 @@
 }
 
 func TestCarryRequiredModuleNames(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5384,7 +5295,6 @@
 }
 
 func TestSymlinksFromApexToSystem(t *testing.T) {
-	t.Parallel()
 	bp := `
 		apex {
 			name: "myapex",
@@ -5514,7 +5424,6 @@
 }
 
 func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5566,7 +5475,6 @@
 }
 
 func TestApexWithJniLibs(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5608,7 +5516,6 @@
 }
 
 func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5630,7 +5537,6 @@
 }
 
 func TestAppBundle(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5661,7 +5567,6 @@
 }
 
 func TestAppSetBundle(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -5693,6 +5598,36 @@
 	ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet .*/AppSet.zip$")
 }
 
+func TestAppSetBundlePrebuilt(t *testing.T) {
+	ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+		bp := `
+		apex_set {
+			name: "myapex",
+			filename: "foo_v2.apex",
+			sanitized: {
+				none: { set: "myapex.apks", },
+				hwaddress: { set: "myapex.hwasan.apks", },
+			},
+		}`
+		fs["Android.bp"] = []byte(bp)
+
+		config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
+	})
+
+	m := ctx.ModuleForTests("myapex", "android_common")
+	extractedApex := m.Output(buildDir + "/.intermediates/myapex/android_common/foo_v2.apex")
+
+	actual := extractedApex.Inputs
+	if len(actual) != 1 {
+		t.Errorf("expected a single input")
+	}
+
+	expected := "myapex.hwasan.apks"
+	if actual[0].String() != expected {
+		t.Errorf("expected %s, got %s", expected, actual[0].String())
+	}
+}
+
 func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) {
 	t.Helper()
 
@@ -5836,7 +5771,6 @@
 }
 
 func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
 		apex {
 			name: "myapex",
@@ -5853,7 +5787,6 @@
 }
 
 func TestNoUpdatableJarsInBootImage(t *testing.T) {
-	t.Parallel()
 	var err string
 	var transform func(*dexpreopt.GlobalConfig)
 
@@ -5990,7 +5923,6 @@
 }
 
 func TestApexPermittedPackagesRules(t *testing.T) {
-	t.Parallel()
 	testcases := []struct {
 		name            string
 		expectedError   string
@@ -6074,7 +6006,6 @@
 }
 
 func TestTestFor(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -6132,7 +6063,6 @@
 }
 
 func TestApexSet(t *testing.T) {
-	t.Parallel()
 	ctx, config := testApex(t, `
 		apex_set {
 			name: "myapex",
@@ -6172,7 +6102,6 @@
 }
 
 func TestNoStaticLinkingToStubsLib(t *testing.T) {
-	t.Parallel()
 	testApexError(t, `.*required by "mylib" is a native library providing stub.*`, `
 		apex {
 			name: "myapex",
@@ -6209,7 +6138,6 @@
 }
 
 func TestApexKeysTxt(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -6250,7 +6178,6 @@
 }
 
 func TestAllowedFiles(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
@@ -6306,7 +6233,6 @@
 }
 
 func TestNonPreferredPrebuiltDependency(t *testing.T) {
-	t.Parallel()
 	_, _ = testApex(t, `
 		apex {
 			name: "myapex",
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 9f6c8ad..ce16d73 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -50,6 +50,10 @@
 	properties prebuiltCommonProperties
 }
 
+type sanitizedPrebuilt interface {
+	hasSanitizedSource(sanitizer string) bool
+}
+
 type prebuiltCommonProperties struct {
 	ForceDisable bool `blueprint:"mutated"`
 }
@@ -75,9 +79,10 @@
 	forceDisable = forceDisable || ctx.DeviceConfig().NativeCoverageEnabled()
 	forceDisable = forceDisable || ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
 
-	// b/137216042 don't use prebuilts when address sanitizer is on
-	forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) ||
-		android.InList("hwaddress", ctx.Config().SanitizeDevice())
+	// b/137216042 don't use prebuilts when address sanitizer is on, unless the prebuilt has a sanitized source
+	sanitized := ctx.Module().(sanitizedPrebuilt)
+	forceDisable = forceDisable || (android.InList("address", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("address"))
+	forceDisable = forceDisable || (android.InList("hwaddress", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("hwaddress"))
 
 	if forceDisable && p.prebuilt.SourceExists() {
 		p.properties.ForceDisable = true
@@ -135,6 +140,10 @@
 	Overrides []string
 }
 
+func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool {
+	return false
+}
+
 func (p *Prebuilt) installable() bool {
 	return p.properties.Installable == nil || proptools.Bool(p.properties.Installable)
 }
@@ -266,6 +275,18 @@
 	// the .apks file path that contains prebuilt apex files to be extracted.
 	Set *string
 
+	Sanitized struct {
+		None struct {
+			Set *string
+		}
+		Address struct {
+			Set *string
+		}
+		Hwaddress struct {
+			Set *string
+		}
+	}
+
 	// whether the extracted apex file installable.
 	Installable *bool
 
@@ -284,6 +305,41 @@
 	Prerelease *bool
 }
 
+func (a *ApexSet) prebuiltSrcs(ctx android.BaseModuleContext) []string {
+	var srcs []string
+	if a.properties.Set != nil {
+		srcs = append(srcs, *a.properties.Set)
+	}
+
+	var sanitizers []string
+	if ctx.Host() {
+		sanitizers = ctx.Config().SanitizeHost()
+	} else {
+		sanitizers = ctx.Config().SanitizeDevice()
+	}
+
+	if android.InList("address", sanitizers) && a.properties.Sanitized.Address.Set != nil {
+		srcs = append(srcs, *a.properties.Sanitized.Address.Set)
+	} else if android.InList("hwaddress", sanitizers) && a.properties.Sanitized.Hwaddress.Set != nil {
+		srcs = append(srcs, *a.properties.Sanitized.Hwaddress.Set)
+	} else if a.properties.Sanitized.None.Set != nil {
+		srcs = append(srcs, *a.properties.Sanitized.None.Set)
+	}
+
+	return srcs
+}
+
+func (a *ApexSet) hasSanitizedSource(sanitizer string) bool {
+	if sanitizer == "address" {
+		return a.properties.Sanitized.Address.Set != nil
+	}
+	if sanitizer == "hwaddress" {
+		return a.properties.Sanitized.Hwaddress.Set != nil
+	}
+
+	return false
+}
+
 func (a *ApexSet) installable() bool {
 	return a.properties.Installable == nil || proptools.Bool(a.properties.Installable)
 }
@@ -304,7 +360,12 @@
 func apexSetFactory() android.Module {
 	module := &ApexSet{}
 	module.AddProperties(&module.properties)
-	android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set")
+
+	srcsSupplier := func(ctx android.BaseModuleContext) []string {
+		return module.prebuiltSrcs(ctx)
+	}
+
+	android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "set")
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	return module
 }
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index e623990..60b6ed5 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -9,7 +9,6 @@
 )
 
 func TestVndkApexForVndkLite(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testApex(t, `
 		apex_vndk {
 			name: "myapex",
@@ -63,7 +62,6 @@
 }
 
 func TestVndkApexUsesVendorVariant(t *testing.T) {
-	t.Parallel()
 	bp := `
 		apex_vndk {
 			name: "myapex",
diff --git a/bazel/bazelenv.sh b/bazel/bazelenv.sh
new file mode 100755
index 0000000..2ca8baf
--- /dev/null
+++ b/bazel/bazelenv.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+# 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.
+
+# Helper script for setting environment variables required for Bazel/Soong
+# mixed builds prototype. For development use only.
+#
+# Usage:
+#   export BAZEL_PATH=[some_bazel_path] && source bazelenv.sh
+#
+# If BAZEL_PATH is not set, `which bazel` will be used
+# to locate the appropriate bazel to use.
+
+
+# Function to find top of the source tree (if $TOP isn't set) by walking up the
+# tree.
+function gettop
+{
+    local TOPFILE=build/soong/root.bp
+    if [ -n "${TOP-}" -a -f "${TOP-}/${TOPFILE}" ] ; then
+        # The following circumlocution ensures we remove symlinks from TOP.
+        (cd $TOP; PWD= /bin/pwd)
+    else
+        if [ -f $TOPFILE ] ; then
+            # The following circumlocution (repeated below as well) ensures
+            # that we record the true directory name and not one that is
+            # faked up with symlink names.
+            PWD= /bin/pwd
+        else
+            local HERE=$PWD
+            T=
+            while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
+                \cd ..
+                T=`PWD= /bin/pwd -P`
+            done
+            \cd $HERE
+            if [ -f "$T/$TOPFILE" ]; then
+                echo $T
+            fi
+        fi
+    fi
+}
+
+BASE_DIR="$(mktemp -d)"
+
+if [ -z "$BAZEL_PATH" ] ; then
+    export BAZEL_PATH="$(which bazel)"
+fi
+
+export USE_BAZEL=1
+export BAZEL_HOME="$BASE_DIR/bazelhome"
+export BAZEL_OUTPUT_BASE="$BASE_DIR/output"
+export BAZEL_WORKSPACE="$(gettop)"
+
+echo "USE_BAZEL=${USE_BAZEL}"
+echo "BAZEL_PATH=${BAZEL_PATH}"
+echo "BAZEL_HOME=${BAZEL_HOME}"
+echo "BAZEL_OUTPUT_BASE=${BAZEL_OUTPUT_BASE}"
+echo "BAZEL_WORKSPACE=${BAZEL_WORKSPACE}"
+
+mkdir -p $BAZEL_HOME
+mkdir -p $BAZEL_OUTPUT_BASE
diff --git a/bazel/master.WORKSPACE.bazel b/bazel/master.WORKSPACE.bazel
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bazel/master.WORKSPACE.bazel
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index 44d4cc3..d06d7d1 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -66,7 +66,6 @@
 }
 
 func TestBpfDataDependency(t *testing.T) {
-	t.Parallel()
 	bp := `
 		bpf {
 			name: "bpf.o",
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 2bbbd7f..ef9814f 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -116,7 +116,6 @@
 }
 
 func TestSimplifyKnownVariablesDuplicatingEachOther(t *testing.T) {
-	t.Parallel()
 	// TODO use []Expression{} once buildTree above can support it (which is after b/38325146 is done)
 	implFilterListTest(t, []string{"include"}, []string{"include"}, nil)
 	implFilterListTest(t, []string{"include1"}, []string{"include2"}, []string{"include1"})
@@ -170,7 +169,6 @@
 }
 
 func TestMergeMatchingProperties(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -260,7 +258,6 @@
 }
 
 func TestReorderCommonProperties(t *testing.T) {
-	t.Parallel()
 	var tests = []struct {
 		name string
 		in   string
@@ -347,7 +344,6 @@
 }
 
 func TestRemoveMatchingModuleListProperties(t *testing.T) {
-	t.Parallel()
 	var tests = []struct {
 		name string
 		in   string
@@ -503,7 +499,6 @@
 }
 
 func TestReplaceJavaStaticLibs(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -562,7 +557,6 @@
 }
 
 func TestRewritePrebuilts(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -629,7 +623,6 @@
 }
 
 func TestRewriteCtsModuleTypes(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -701,7 +694,6 @@
 }
 
 func TestRewritePrebuiltEtc(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -777,7 +769,6 @@
 }
 
 func TestRewriteAndroidTest(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -811,7 +802,6 @@
 }
 
 func TestRewriteAndroidAppImport(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -861,7 +851,6 @@
 }
 
 func TestRemoveEmptyLibDependencies(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -916,7 +905,6 @@
 }
 
 func TestRemoveHidlInterfaceTypes(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -948,7 +936,6 @@
 }
 
 func TestRemoveSoongConfigBoolVariable(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
@@ -1013,7 +1000,6 @@
 }
 
 func TestRemovePdkProperty(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name string
 		in   string
diff --git a/cc/OWNERS b/cc/OWNERS
new file mode 100644
index 0000000..6d7c30a
--- /dev/null
+++ b/cc/OWNERS
@@ -0,0 +1,4 @@
+per-file ndk_*.go = danalbert@google.com
+per-file tidy.go = srhines@google.com, chh@google.com
+per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
+
diff --git a/cc/androidmk.go b/cc/androidmk.go
index a2549b8..e58a172 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -186,17 +186,17 @@
 }
 
 func (library *libraryDecorator) androidMkWriteExportedFlags(entries *android.AndroidMkEntries) {
-	exportedFlags := library.exportedFlags()
-	for _, dir := range library.exportedDirs() {
+	exportedFlags := library.flagExporter.flags
+	for _, dir := range library.flagExporter.dirs {
 		exportedFlags = append(exportedFlags, "-I"+dir.String())
 	}
-	for _, dir := range library.exportedSystemDirs() {
+	for _, dir := range library.flagExporter.systemDirs {
 		exportedFlags = append(exportedFlags, "-isystem "+dir.String())
 	}
 	if len(exportedFlags) > 0 {
 		entries.AddStrings("LOCAL_EXPORT_CFLAGS", exportedFlags...)
 	}
-	exportedDeps := library.exportedDeps()
+	exportedDeps := library.flagExporter.deps
 	if len(exportedDeps) > 0 {
 		entries.AddStrings("LOCAL_EXPORT_C_INCLUDE_DEPS", exportedDeps.Strings()...)
 	}
@@ -442,6 +442,11 @@
 	entries.SubName = ndkLibrarySuffix + "." + c.apiLevel.String()
 	entries.Class = "SHARED_LIBRARIES"
 
+	if !c.buildStubs() {
+		entries.Disabled = true
+		return
+	}
+
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		path, file := filepath.Split(c.installPath.String())
 		stem, suffix, _ := android.SplitFileExt(file)
diff --git a/cc/builder.go b/cc/builder.go
index 81c09b1..8c8aa17 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -44,14 +44,14 @@
 		blueprint.RuleParams{
 			Depfile:     "${out}.d",
 			Deps:        blueprint.DepsGCC,
-			Command:     "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in",
+			Command:     "${config.CcWrapper}$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in",
 			CommandDeps: []string{"$ccCmd"},
 		},
 		"ccCmd", "cFlags")
 
 	ccNoDeps = pctx.AndroidStaticRule("ccNoDeps",
 		blueprint.RuleParams{
-			Command:     "$relPwd $ccCmd -c $cFlags -o $out $in",
+			Command:     "$ccCmd -c $cFlags -o $out $in",
 			CommandDeps: []string{"$ccCmd"},
 		},
 		"ccCmd", "cFlags")
@@ -220,7 +220,7 @@
 			Labels:       map[string]string{"type": "abi-dump", "tool": "header-abi-dumper"},
 			ExecStrategy: "${config.REAbiDumperExecStrategy}",
 			Platform: map[string]string{
-				remoteexec.PoolKey:      "${config.RECXXPool}",
+				remoteexec.PoolKey: "${config.RECXXPool}",
 			},
 		}, []string{"cFlags", "exportDirs"}, nil)
 
diff --git a/cc/cc.go b/cc/cc.go
index 8188550..dbe6346 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -45,7 +45,6 @@
 		ctx.BottomUp("sdk", sdkMutator).Parallel()
 		ctx.BottomUp("vndk", VndkMutator).Parallel()
 		ctx.BottomUp("link", LinkageMutator).Parallel()
-		ctx.BottomUp("ndk_api", NdkApiMutator).Parallel()
 		ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("version_selector", versionSelectorMutator).Parallel()
 		ctx.BottomUp("version", versionMutator).Parallel()
@@ -130,6 +129,9 @@
 	// Paths to .a files
 	StaticLibs, LateStaticLibs, WholeStaticLibs android.Paths
 
+	// Transitive static library dependencies of static libraries for use in ordering.
+	TranstiveStaticLibrariesForOrdering *android.DepSet
+
 	// Paths to .o files
 	Objs Objects
 	// Paths to .o files in dependencies that provide them. Note that these lists
@@ -546,9 +548,7 @@
 	dataLibDepTag         = dependencyTag{name: "data lib"}
 	runtimeDepTag         = dependencyTag{name: "runtime lib"}
 	testPerSrcDepTag      = dependencyTag{name: "test_per_src"}
-	testForDepTag         = dependencyTag{name: "test for apex"}
-
-	stubImplDepTag = copyDirectlyInAnyApexDependencyTag{name: "stub_impl"}
+	stubImplDepTag        = dependencyTag{name: "stub_impl"}
 )
 
 type copyDirectlyInAnyApexDependencyTag dependencyTag
@@ -618,13 +618,8 @@
 	// Flags used to compile this module
 	flags Flags
 
-	// When calling a linker, if module A depends on module B, then A must precede B in its command
-	// line invocation. depsInLinkOrder stores the proper ordering of all of the transitive
-	// deps of this module
-	depsInLinkOrder android.Paths
-
 	// only non-nil when this is a shared library that reuses the objects of a static library
-	staticVariant LinkableInterface
+	staticAnalogue *StaticLibraryInfo
 
 	makeLinkType string
 	// Kythe (source file indexer) paths for this compilation module
@@ -722,42 +717,9 @@
 	return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only)
 }
 
-func (c *Module) IncludeDirs() android.Paths {
-	if c.linker != nil {
-		if library, ok := c.linker.(exportedFlagsProducer); ok {
-			return library.exportedDirs()
-		}
-	}
-	panic(fmt.Errorf("IncludeDirs called on non-exportedFlagsProducer module: %q", c.BaseModuleName()))
-}
-
-func (c *Module) HasStaticVariant() bool {
-	if c.staticVariant != nil {
-		return true
-	}
-	return false
-}
-
-func (c *Module) GetStaticVariant() LinkableInterface {
-	return c.staticVariant
-}
-
-func (c *Module) SetDepsInLinkOrder(depsInLinkOrder []android.Path) {
-	c.depsInLinkOrder = depsInLinkOrder
-}
-
-func (c *Module) GetDepsInLinkOrder() []android.Path {
-	return c.depsInLinkOrder
-}
-
-func (c *Module) StubsVersions() []string {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			return library.Properties.Stubs.Versions
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			return library.Properties.Stubs.Versions
-		}
+func (c *Module) StubsVersions(ctx android.BaseMutatorContext) []string {
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.stubsVersions(ctx)
 	}
 	panic(fmt.Errorf("StubsVersions called on non-library module: %q", c.BaseModuleName()))
 }
@@ -786,100 +748,48 @@
 }
 
 func (c *Module) SetBuildStubs() {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			library.MutatedProperties.BuildStubs = true
-			c.Properties.HideFromMake = true
-			c.sanitize = nil
-			c.stl = nil
-			c.Properties.PreventInstall = true
-			return
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			library.MutatedProperties.BuildStubs = true
-			c.Properties.HideFromMake = true
-			c.sanitize = nil
-			c.stl = nil
-			c.Properties.PreventInstall = true
-			return
-		}
-		if _, ok := c.linker.(*llndkStubDecorator); ok {
-			c.Properties.HideFromMake = true
-			return
-		}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		versioned.setBuildStubs()
+		c.Properties.HideFromMake = true
+		c.sanitize = nil
+		c.stl = nil
+		c.Properties.PreventInstall = true
+		return
 	}
 	panic(fmt.Errorf("SetBuildStubs called on non-library module: %q", c.BaseModuleName()))
 }
 
 func (c *Module) BuildStubs() bool {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			return library.buildStubs()
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			return library.buildStubs()
-		}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.buildStubs()
 	}
 	panic(fmt.Errorf("BuildStubs called on non-library module: %q", c.BaseModuleName()))
 }
 
 func (c *Module) SetAllStubsVersions(versions []string) {
-	if library, ok := c.linker.(*libraryDecorator); ok {
-		library.MutatedProperties.AllStubsVersions = versions
-		return
-	}
-	if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-		library.MutatedProperties.AllStubsVersions = versions
-		return
-	}
-	if llndk, ok := c.linker.(*llndkStubDecorator); ok {
-		llndk.libraryDecorator.MutatedProperties.AllStubsVersions = versions
-		return
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		versioned.setAllStubsVersions(versions)
 	}
 }
 
 func (c *Module) AllStubsVersions() []string {
-	if library, ok := c.linker.(*libraryDecorator); ok {
-		return library.MutatedProperties.AllStubsVersions
-	}
-	if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-		return library.MutatedProperties.AllStubsVersions
-	}
-	if llndk, ok := c.linker.(*llndkStubDecorator); ok {
-		return llndk.libraryDecorator.MutatedProperties.AllStubsVersions
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.allStubsVersions()
 	}
 	return nil
 }
 
 func (c *Module) SetStubsVersion(version string) {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			library.MutatedProperties.StubsVersion = version
-			return
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			library.MutatedProperties.StubsVersion = version
-			return
-		}
-		if llndk, ok := c.linker.(*llndkStubDecorator); ok {
-			llndk.libraryDecorator.MutatedProperties.StubsVersion = version
-			return
-		}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		versioned.setStubsVersion(version)
+		return
 	}
 	panic(fmt.Errorf("SetStubsVersion called on non-library module: %q", c.BaseModuleName()))
 }
 
 func (c *Module) StubsVersion() string {
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			return library.MutatedProperties.StubsVersion
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			return library.MutatedProperties.StubsVersion
-		}
-		if llndk, ok := c.linker.(*llndkStubDecorator); ok {
-			return llndk.libraryDecorator.MutatedProperties.StubsVersion
-		}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.stubsVersion()
 	}
 	panic(fmt.Errorf("StubsVersion called on non-library module: %q", c.BaseModuleName()))
 }
@@ -1117,22 +1027,15 @@
 }
 
 func (c *Module) IsStubs() bool {
-	if library, ok := c.linker.(*libraryDecorator); ok {
-		return library.buildStubs()
-	} else if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-		return library.buildStubs()
-	} else if _, ok := c.linker.(*llndkStubDecorator); ok {
-		return true
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.buildStubs()
 	}
 	return false
 }
 
 func (c *Module) HasStubsVariants() bool {
-	if library, ok := c.linker.(*libraryDecorator); ok {
-		return len(library.Properties.Stubs.Versions) > 0
-	}
-	if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-		return len(library.Properties.Stubs.Versions) > 0
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		return versioned.hasStubsVariants()
 	}
 	return false
 }
@@ -1156,41 +1059,6 @@
 	return false
 }
 
-func (c *Module) ExportedIncludeDirs() android.Paths {
-	if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
-		return flagsProducer.exportedDirs()
-	}
-	return nil
-}
-
-func (c *Module) ExportedSystemIncludeDirs() android.Paths {
-	if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
-		return flagsProducer.exportedSystemDirs()
-	}
-	return nil
-}
-
-func (c *Module) ExportedFlags() []string {
-	if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
-		return flagsProducer.exportedFlags()
-	}
-	return nil
-}
-
-func (c *Module) ExportedDeps() android.Paths {
-	if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
-		return flagsProducer.exportedDeps()
-	}
-	return nil
-}
-
-func (c *Module) ExportedGeneratedHeaders() android.Paths {
-	if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
-		return flagsProducer.exportedGeneratedHeaders()
-	}
-	return nil
-}
-
 func (c *Module) ExcludeFromVendorSnapshot() bool {
 	return Bool(c.Properties.Exclude_from_vendor_snapshot)
 }
@@ -1454,65 +1322,6 @@
 	return nil
 }
 
-// orderDeps reorders dependencies into a list such that if module A depends on B, then
-// A will precede B in the resultant list.
-// This is convenient for passing into a linker.
-// Note that directSharedDeps should be the analogous static library for each shared lib dep
-func orderDeps(directStaticDeps []android.Path, directSharedDeps []android.Path, allTransitiveDeps map[android.Path][]android.Path) (orderedAllDeps []android.Path, orderedDeclaredDeps []android.Path) {
-	// If A depends on B, then
-	//   Every list containing A will also contain B later in the list
-	//   So, after concatenating all lists, the final instance of B will have come from the same
-	//     original list as the final instance of A
-	//   So, the final instance of B will be later in the concatenation than the final A
-	//   So, keeping only the final instance of A and of B ensures that A is earlier in the output
-	//     list than B
-	for _, dep := range directStaticDeps {
-		orderedAllDeps = append(orderedAllDeps, dep)
-		orderedAllDeps = append(orderedAllDeps, allTransitiveDeps[dep]...)
-	}
-	for _, dep := range directSharedDeps {
-		orderedAllDeps = append(orderedAllDeps, dep)
-		orderedAllDeps = append(orderedAllDeps, allTransitiveDeps[dep]...)
-	}
-
-	orderedAllDeps = android.LastUniquePaths(orderedAllDeps)
-
-	// We don't want to add any new dependencies into directStaticDeps (to allow the caller to
-	// intentionally exclude or replace any unwanted transitive dependencies), so we limit the
-	// resultant list to only what the caller has chosen to include in directStaticDeps
-	_, orderedDeclaredDeps = android.FilterPathList(orderedAllDeps, directStaticDeps)
-
-	return orderedAllDeps, orderedDeclaredDeps
-}
-
-func orderStaticModuleDeps(module LinkableInterface, staticDeps []LinkableInterface, sharedDeps []LinkableInterface) (results []android.Path) {
-	// convert Module to Path
-	var depsInLinkOrder []android.Path
-	allTransitiveDeps := make(map[android.Path][]android.Path, len(staticDeps))
-	staticDepFiles := []android.Path{}
-	for _, dep := range staticDeps {
-		// The OutputFile may not be valid for a variant not present, and the AllowMissingDependencies flag is set.
-		if dep.OutputFile().Valid() {
-			allTransitiveDeps[dep.OutputFile().Path()] = dep.GetDepsInLinkOrder()
-			staticDepFiles = append(staticDepFiles, dep.OutputFile().Path())
-		}
-	}
-	sharedDepFiles := []android.Path{}
-	for _, sharedDep := range sharedDeps {
-		if sharedDep.HasStaticVariant() {
-			staticAnalogue := sharedDep.GetStaticVariant()
-			allTransitiveDeps[staticAnalogue.OutputFile().Path()] = staticAnalogue.GetDepsInLinkOrder()
-			sharedDepFiles = append(sharedDepFiles, staticAnalogue.OutputFile().Path())
-		}
-	}
-
-	// reorder the dependencies based on transitive dependencies
-	depsInLinkOrder, results = orderDeps(staticDepFiles, sharedDepFiles, allTransitiveDeps)
-	module.SetDepsInLinkOrder(depsInLinkOrder)
-
-	return results
-}
-
 func (c *Module) IsTestPerSrcAllTestsVariation() bool {
 	test, ok := c.linker.(testPerSrc)
 	return ok && test.isAllTestsVariation()
@@ -1878,7 +1687,7 @@
 	if m.UseSdk() {
 		return []blueprint.Variation{
 			{Mutator: "sdk", Variation: "sdk"},
-			{Mutator: "ndk_api", Variation: m.SdkVersion()},
+			{Mutator: "version", Variation: m.SdkVersion()},
 		}
 	}
 	return []blueprint.Variation{
@@ -1896,29 +1705,11 @@
 		variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
 		depTag.explicitlyVersioned = true
 	}
-	var deps []blueprint.Module
-	if far {
-		deps = ctx.AddFarVariationDependencies(variations, depTag, name)
-	} else {
-		deps = ctx.AddVariationDependencies(variations, depTag, name)
-	}
 
-	// If the version is not specified, add dependency to all stubs libraries.
-	// The stubs library will be used when the depending module is built for APEX and
-	// the dependent module is not in the same APEX.
-	if version == "" && CanBeOrLinkAgainstVersionVariants(c) {
-		if dep, ok := deps[0].(*Module); ok {
-			for _, ver := range dep.AllStubsVersions() {
-				// Note that depTag.ExplicitlyVersioned is false in this case.
-				versionVariations := append(variations,
-					blueprint.Variation{Mutator: "version", Variation: ver})
-				if far {
-					ctx.AddFarVariationDependencies(versionVariations, depTag, name)
-				} else {
-					ctx.AddVariationDependencies(versionVariations, depTag, name)
-				}
-			}
-		}
+	if far {
+		ctx.AddFarVariationDependencies(variations, depTag, name)
+	} else {
+		ctx.AddVariationDependencies(variations, depTag, name)
 	}
 }
 
@@ -2016,16 +1807,9 @@
 	}
 
 	buildStubs := false
-	if c.linker != nil {
-		if library, ok := c.linker.(*libraryDecorator); ok {
-			if library.buildStubs() {
-				buildStubs = true
-			}
-		}
-		if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
-			if library.buildStubs() {
-				buildStubs = true
-			}
+	if versioned, ok := c.linker.(versionedInterface); ok {
+		if versioned.buildStubs() {
+			buildStubs = true
 		}
 	}
 
@@ -2169,11 +1953,10 @@
 		actx.AddDependency(c, depTag, gen)
 	}
 
-	actx.AddVariationDependencies(nil, objDepTag, deps.ObjFiles...)
-
 	vendorSnapshotObjects := vendorSnapshotObjects(actx.Config())
 
 	crtVariations := GetCrtVariations(ctx, c)
+	actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
 	if deps.CrtBegin != "" {
 		actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
 			rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
@@ -2193,13 +1976,13 @@
 
 	ndkStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, ndk: true, makeSuffix: "." + version}
 	actx.AddVariationDependencies([]blueprint.Variation{
-		{Mutator: "ndk_api", Variation: version},
+		{Mutator: "version", Variation: version},
 		{Mutator: "link", Variation: "shared"},
 	}, ndkStubDepTag, variantNdkLibs...)
 
 	ndkLateStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, ndk: true, makeSuffix: "." + version}
 	actx.AddVariationDependencies([]blueprint.Variation{
-		{Mutator: "ndk_api", Variation: version},
+		{Mutator: "version", Variation: version},
 		{Mutator: "link", Variation: "shared"},
 	}, ndkLateStubDepTag, variantLateNdkLibs...)
 
@@ -2384,19 +2167,49 @@
 	}
 }
 
+// Returns the highest version which is <= maxSdkVersion.
+// For example, with maxSdkVersion is 10 and versionList is [9,11]
+// it returns 9 as string.  The list of stubs must be in order from
+// oldest to newest.
+func (c *Module) chooseSdkVersion(ctx android.PathContext, stubsInfo []SharedLibraryStubsInfo,
+	maxSdkVersion android.ApiLevel) (SharedLibraryStubsInfo, error) {
+
+	for i := range stubsInfo {
+		stubInfo := stubsInfo[len(stubsInfo)-i-1]
+		var ver android.ApiLevel
+		if stubInfo.Version == "" {
+			ver = android.FutureApiLevel
+		} else {
+			var err error
+			ver, err = android.ApiLevelFromUser(ctx, stubInfo.Version)
+			if err != nil {
+				return SharedLibraryStubsInfo{}, err
+			}
+		}
+		if ver.LessThanOrEqualTo(maxSdkVersion) {
+			return stubInfo, nil
+		}
+	}
+	var versionList []string
+	for _, stubInfo := range stubsInfo {
+		versionList = append(versionList, stubInfo.Version)
+	}
+	return SharedLibraryStubsInfo{}, fmt.Errorf("not found a version(<=%s) in versionList: %v", maxSdkVersion.String(), versionList)
+}
+
 // Convert dependencies to paths.  Returns a PathDeps containing paths
 func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
 	var depPaths PathDeps
 
-	directStaticDeps := []LinkableInterface{}
-	directSharedDeps := []LinkableInterface{}
+	var directStaticDeps []StaticLibraryInfo
+	var directSharedDeps []SharedLibraryInfo
 
-	reexportExporter := func(exporter exportedFlagsProducer) {
-		depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.exportedDirs()...)
-		depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.exportedSystemDirs()...)
-		depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, exporter.exportedFlags()...)
-		depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, exporter.exportedDeps()...)
-		depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders, exporter.exportedGeneratedHeaders()...)
+	reexportExporter := func(exporter FlagExporterInfo) {
+		depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.IncludeDirs...)
+		depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.SystemIncludeDirs...)
+		depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, exporter.Flags...)
+		depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, exporter.Deps...)
+		depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders, exporter.GeneratedHeaders...)
 	}
 
 	// For the dependency from platform to apex, use the latest stubs
@@ -2481,24 +2294,14 @@
 			return
 		}
 
-		// re-exporting flags
 		if depTag == reuseObjTag {
 			// reusing objects only make sense for cc.Modules.
-			if ccReuseDep, ok := ccDep.(*Module); ok && ccDep.CcLibraryInterface() {
-				c.staticVariant = ccDep
-				objs, exporter := ccReuseDep.compiler.(libraryInterface).reuseObjs()
-				depPaths.Objs = depPaths.Objs.Append(objs)
-				reexportExporter(exporter)
-				return
-			}
-		}
-
-		if depTag == staticVariantTag {
-			// staticVariants are a cc.Module specific concept.
-			if _, ok := ccDep.(*Module); ok && ccDep.CcLibraryInterface() {
-				c.staticVariant = ccDep
-				return
-			}
+			staticAnalogue := ctx.OtherModuleProvider(dep, StaticLibraryInfoProvider).(StaticLibraryInfo)
+			objs := staticAnalogue.ReuseObjects
+			depPaths.Objs = depPaths.Objs.Append(objs)
+			depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
+			reexportExporter(depExporterInfo)
+			return
 		}
 
 		checkLinkType(ctx, c, ccDep, depTag)
@@ -2511,103 +2314,7 @@
 				return
 			}
 
-			if ccDep.CcLibrary() && !libDepTag.static() {
-				depIsStubs := ccDep.BuildStubs()
-				depHasStubs := CanBeOrLinkAgainstVersionVariants(c) && ccDep.HasStubsVariants()
-				depInSameApexes := android.DirectlyInAllApexes(apexInfo, depName)
-				depInPlatform := !dep.(android.ApexModule).AnyVariantDirectlyInAnyApex()
-
-				var useThisDep bool
-				if depIsStubs && libDepTag.explicitlyVersioned {
-					// Always respect dependency to the versioned stubs (i.e. libX#10)
-					useThisDep = true
-				} else if !depHasStubs {
-					// Use non-stub variant if that is the only choice
-					// (i.e. depending on a lib without stubs.version property)
-					useThisDep = true
-				} else if apexInfo.IsForPlatform() {
-					// If not building for APEX, use stubs only when it is from
-					// an APEX (and not from platform)
-					useThisDep = (depInPlatform != depIsStubs)
-					if c.bootstrap() {
-						// However, for host, ramdisk, recovery or bootstrap modules,
-						// always link to non-stub variant
-						useThisDep = !depIsStubs
-					}
-					// 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.
-					testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
-					for _, apexContents := range testFor.ApexContents {
-						if apexContents.DirectlyInApex(depName) {
-							useThisDep = !depIsStubs
-							break
-						}
-					}
-				} else {
-					// If building for APEX, use stubs when the parent is in any APEX that
-					// the child is not in.
-					useThisDep = (depInSameApexes != depIsStubs)
-				}
-
-				// when to use (unspecified) stubs, check min_sdk_version and choose the right one
-				if useThisDep && depIsStubs && !libDepTag.explicitlyVersioned {
-					versionToUse, err := c.ChooseSdkVersion(ctx, ccDep.StubsVersions(), c.apexSdkVersion)
-					if err != nil {
-						ctx.OtherModuleErrorf(dep, err.Error())
-						return
-					}
-					if versionToUse != ccDep.StubsVersion() {
-						useThisDep = false
-					}
-				}
-
-				if !useThisDep {
-					return // stop processing this dep
-				}
-			}
-			if c.UseVndk() {
-				if m, ok := ccDep.(*Module); ok && m.IsStubs() { // LLNDK
-					// by default, use current version of LLNDK
-					versionToUse := ""
-					versions := m.AllStubsVersions()
-					if apexInfo.ApexVariationName != "" && len(versions) > 0 {
-						// if this is for use_vendor apex && dep has stubsVersions
-						// apply the same rule of apex sdk enforcement to choose right version
-						var err error
-						versionToUse, err = c.ChooseSdkVersion(ctx, versions, c.apexSdkVersion)
-						if err != nil {
-							ctx.OtherModuleErrorf(dep, err.Error())
-							return
-						}
-					}
-					if versionToUse != ccDep.StubsVersion() {
-						return
-					}
-				}
-			}
-
-			depPaths.IncludeDirs = append(depPaths.IncludeDirs, ccDep.IncludeDirs()...)
-
-			// Exporting flags only makes sense for cc.Modules
-			if _, ok := ccDep.(*Module); ok {
-				if i, ok := ccDep.(*Module).linker.(exportedFlagsProducer); ok {
-					depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, i.exportedSystemDirs()...)
-					depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, i.exportedDeps()...)
-					depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...)
-
-					if libDepTag.reexportFlags {
-						reexportExporter(i)
-						// Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library.
-						// Re-exported shared library headers must be included as well since they can help us with type information
-						// about template instantiations (instantiated from their headers).
-						// -isystem headers are not included since for bionic libraries, abi-filtering is taken care of by version
-						// scripts.
-						c.sabi.Properties.ReexportedIncludes = append(
-							c.sabi.Properties.ReexportedIncludes, i.exportedDirs().Strings()...)
-					}
-				}
-			}
+			depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
 
 			var ptr *android.Paths
 			var depPtr *android.Paths
@@ -2618,6 +2325,64 @@
 			case libDepTag.header():
 				// nothing
 			case libDepTag.shared():
+				if !ctx.OtherModuleHasProvider(dep, SharedLibraryInfoProvider) {
+					if !ctx.Config().AllowMissingDependencies() {
+						ctx.ModuleErrorf("module %q is not a shared library", depName)
+					} else {
+						ctx.AddMissingDependencies([]string{depName})
+					}
+					return
+				}
+				sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
+				sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryImplementationStubsInfoProvider).(SharedLibraryImplementationStubsInfo)
+
+				if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedLibraryStubsInfos) > 0 {
+					useStubs := false
+					if m, ok := ccDep.(*Module); ok && m.IsStubs() && c.UseVndk() { // LLNDK
+						if !apexInfo.IsForPlatform() {
+							// For platform libraries, use current version of LLNDK
+							// If this is for use_vendor apex we will apply the same rules
+							// of apex sdk enforcement below to choose right version.
+							useStubs = true
+						}
+					} else if apexInfo.IsForPlatform() {
+						// If not building for APEX, use stubs only when it is from
+						// an APEX (and not from platform)
+						// However, for host, ramdisk, recovery or bootstrap modules,
+						// always link to non-stub variant
+						useStubs = dep.(android.ApexModule).AnyVariantDirectlyInAnyApex() && !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.
+						testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
+						for _, apexContents := range testFor.ApexContents {
+							if apexContents.DirectlyInApex(depName) {
+								useStubs = false
+								break
+							}
+						}
+					} else {
+						// If building for APEX, use stubs when the parent is in any APEX that
+						// the child is not in.
+						useStubs = !android.DirectlyInAllApexes(apexInfo, depName)
+					}
+
+					// when to use (unspecified) stubs, check min_sdk_version and choose the right one
+					if useStubs {
+						sharedLibraryStubsInfo, err :=
+							c.chooseSdkVersion(ctx, sharedLibraryStubsInfo.SharedLibraryStubsInfos, c.apexSdkVersion)
+						if err != nil {
+							ctx.OtherModuleErrorf(dep, err.Error())
+							return
+						}
+						sharedLibraryInfo = sharedLibraryStubsInfo.SharedLibraryInfo
+						depExporterInfo = sharedLibraryStubsInfo.FlagExporterInfo
+					}
+				}
+
+				linkFile = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary)
+				depFile = sharedLibraryInfo.TableOfContents
+
 				ptr = &depPaths.SharedLibs
 				switch libDepTag.Order {
 				case earlyLibraryDependency:
@@ -2626,47 +2391,41 @@
 				case normalLibraryDependency:
 					ptr = &depPaths.SharedLibs
 					depPtr = &depPaths.SharedLibsDeps
-					directSharedDeps = append(directSharedDeps, ccDep)
+					directSharedDeps = append(directSharedDeps, sharedLibraryInfo)
 				case lateLibraryDependency:
 					ptr = &depPaths.LateSharedLibs
 					depPtr = &depPaths.LateSharedLibsDeps
 				default:
 					panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
 				}
-				depFile = ccDep.Toc()
 			case libDepTag.static():
+				if !ctx.OtherModuleHasProvider(dep, StaticLibraryInfoProvider) {
+					if !ctx.Config().AllowMissingDependencies() {
+						ctx.ModuleErrorf("module %q is not a static library", depName)
+					} else {
+						ctx.AddMissingDependencies([]string{depName})
+					}
+					return
+				}
+				staticLibraryInfo := ctx.OtherModuleProvider(dep, StaticLibraryInfoProvider).(StaticLibraryInfo)
+				linkFile = android.OptionalPathForPath(staticLibraryInfo.StaticLibrary)
 				if libDepTag.wholeStatic {
 					ptr = &depPaths.WholeStaticLibs
-					if !ccDep.CcLibraryInterface() || !ccDep.Static() {
-						ctx.ModuleErrorf("module %q not a static library", depName)
-						return
-					}
-
-					// Because the static library objects are included, this only makes sense
-					// in the context of proper cc.Modules.
-					if ccWholeStaticLib, ok := ccDep.(*Module); ok {
-						staticLib := ccWholeStaticLib.linker.(libraryInterface)
-						if objs := staticLib.objs(); len(objs.objFiles) > 0 {
-							depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(objs)
-						} else {
-							// This case normally catches prebuilt static
-							// libraries, but it can also occur when
-							// AllowMissingDependencies is on and the
-							// dependencies has no sources of its own
-							// but has a whole_static_libs dependency
-							// on a missing library.  We want to depend
-							// on the .a file so that there is something
-							// in the dependency tree that contains the
-							// error rule for the missing transitive
-							// dependency.
-							depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path())
-						}
+					if len(staticLibraryInfo.Objects.objFiles) > 0 {
+						depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLibraryInfo.Objects)
 					} else {
-						ctx.ModuleErrorf(
-							"non-cc.Modules cannot be included as whole static libraries.", depName)
-						return
+						// This case normally catches prebuilt static
+						// libraries, but it can also occur when
+						// AllowMissingDependencies is on and the
+						// dependencies has no sources of its own
+						// but has a whole_static_libs dependency
+						// on a missing library.  We want to depend
+						// on the .a file so that there is something
+						// in the dependency tree that contains the
+						// error rule for the missing transitive
+						// dependency.
+						depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path())
 					}
-
 				} else {
 					switch libDepTag.Order {
 					case earlyLibraryDependency:
@@ -2675,7 +2434,7 @@
 						// static dependencies will be handled separately so they can be ordered
 						// using transitive dependencies.
 						ptr = nil
-						directStaticDeps = append(directStaticDeps, ccDep)
+						directStaticDeps = append(directStaticDeps, staticLibraryInfo)
 					case lateLibraryDependency:
 						ptr = &depPaths.LateStaticLibs
 					default:
@@ -2699,10 +2458,10 @@
 						staticLib.objs().coverageFiles...)
 					depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles,
 						staticLib.objs().sAbiDumpFiles...)
-				} else if c, ok := ccDep.(LinkableInterface); ok {
+				} else {
 					// Handle non-CC modules here
 					depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles,
-						c.CoverageFiles()...)
+						ccDep.CoverageFiles()...)
 				}
 			}
 
@@ -2726,6 +2485,22 @@
 				*depPtr = append(*depPtr, dep.Path())
 			}
 
+			depPaths.IncludeDirs = append(depPaths.IncludeDirs, depExporterInfo.IncludeDirs...)
+			depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, depExporterInfo.SystemIncludeDirs...)
+			depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, depExporterInfo.Deps...)
+			depPaths.Flags = append(depPaths.Flags, depExporterInfo.Flags...)
+
+			if libDepTag.reexportFlags {
+				reexportExporter(depExporterInfo)
+				// Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library.
+				// Re-exported shared library headers must be included as well since they can help us with type information
+				// about template instantiations (instantiated from their headers).
+				// -isystem headers are not included since for bionic libraries, abi-filtering is taken care of by version
+				// scripts.
+				c.sabi.Properties.ReexportedIncludes = append(
+					c.sabi.Properties.ReexportedIncludes, depExporterInfo.IncludeDirs.Strings()...)
+			}
+
 			makeLibName := c.makeLibName(ctx, ccDep, depName) + libDepTag.makeSuffix
 			switch {
 			case libDepTag.header():
@@ -2779,7 +2554,9 @@
 	})
 
 	// use the ordered dependencies as this module's dependencies
-	depPaths.StaticLibs = append(depPaths.StaticLibs, orderStaticModuleDeps(c, directStaticDeps, directSharedDeps)...)
+	orderedStaticPaths, transitiveStaticLibs := orderStaticModuleDeps(directStaticDeps, directSharedDeps)
+	depPaths.TranstiveStaticLibrariesForOrdering = transitiveStaticLibs
+	depPaths.StaticLibs = append(depPaths.StaticLibs, orderedStaticPaths...)
 
 	// Dedup exported flags from dependencies
 	depPaths.Flags = android.FirstUniqueStrings(depPaths.Flags)
@@ -2799,6 +2576,38 @@
 	return depPaths
 }
 
+// orderStaticModuleDeps rearranges the order of the static library dependencies of the module
+// to match the topological order of the dependency tree, including any static analogues of
+// direct shared libraries.  It returns the ordered static dependencies, and an android.DepSet
+// of the transitive dependencies.
+func orderStaticModuleDeps(staticDeps []StaticLibraryInfo, sharedDeps []SharedLibraryInfo) (ordered android.Paths, transitive *android.DepSet) {
+	transitiveStaticLibsBuilder := android.NewDepSetBuilder(android.TOPOLOGICAL)
+	var staticPaths android.Paths
+	for _, staticDep := range staticDeps {
+		staticPaths = append(staticPaths, staticDep.StaticLibrary)
+		transitiveStaticLibsBuilder.Transitive(staticDep.TransitiveStaticLibrariesForOrdering)
+	}
+	for _, sharedDep := range sharedDeps {
+		if sharedDep.StaticAnalogue != nil {
+			transitiveStaticLibsBuilder.Transitive(sharedDep.StaticAnalogue.TransitiveStaticLibrariesForOrdering)
+		}
+	}
+	transitiveStaticLibs := transitiveStaticLibsBuilder.Build()
+
+	orderedTransitiveStaticLibs := transitiveStaticLibs.ToList()
+
+	// reorder the dependencies based on transitive dependencies
+	staticPaths = android.FirstUniquePaths(staticPaths)
+	_, orderedStaticPaths := android.FilterPathList(orderedTransitiveStaticLibs, staticPaths)
+
+	if len(orderedStaticPaths) != len(staticPaths) {
+		missing, _ := android.FilterPathList(staticPaths, orderedStaticPaths)
+		panic(fmt.Errorf("expected %d ordered static paths , got %d, missing %q %q %q", len(staticPaths), len(orderedStaticPaths), missing, orderedStaticPaths, staticPaths))
+	}
+
+	return orderedStaticPaths, transitiveStaticLibs
+}
+
 // baseLibName trims known prefixes and suffixes
 func baseLibName(depName string) string {
 	libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
@@ -3096,8 +2905,8 @@
 			return false
 		}
 	}
-	if depTag == llndkImplDep {
-		// We don't track beyond LLNDK
+	if depTag == stubImplDepTag || depTag == llndkImplDep {
+		// We don't track beyond LLNDK or from an implementation library to its stubs.
 		return false
 	}
 	return true
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 8d00239..c3caac8 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -20,7 +20,6 @@
 	"os"
 	"path/filepath"
 	"reflect"
-	"sort"
 	"strings"
 	"testing"
 
@@ -128,7 +127,6 @@
 )
 
 func TestFuchsiaDeps(t *testing.T) {
-	t.Parallel()
 	t.Helper()
 
 	bp := `
@@ -166,7 +164,6 @@
 }
 
 func TestFuchsiaTargetDecl(t *testing.T) {
-	t.Parallel()
 	t.Helper()
 
 	bp := `
@@ -193,7 +190,6 @@
 }
 
 func TestVendorSrc(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 		cc_library {
 			name: "libTest",
@@ -324,7 +320,6 @@
 }
 
 func TestVndk(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libvndk",
@@ -451,7 +446,6 @@
 }
 
 func TestVndkWithHostSupported(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 		cc_library {
 			name: "libvndk_host_supported",
@@ -486,7 +480,6 @@
 }
 
 func TestVndkLibrariesTxtAndroidMk(t *testing.T) {
-	t.Parallel()
 	bp := `
 		vndk_libraries_txt {
 			name: "llndk.libraries.txt",
@@ -502,7 +495,6 @@
 }
 
 func TestVndkUsingCoreVariant(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libvndk",
@@ -550,7 +542,6 @@
 }
 
 func TestDataLibs(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_test_library {
 			name: "test_lib",
@@ -601,7 +592,6 @@
 }
 
 func TestDataLibsRelativeInstallPath(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_test_library {
 			name: "test_lib",
@@ -649,7 +639,6 @@
 }
 
 func TestVndkWhenVndkVersionIsNotSet(t *testing.T) {
-	t.Parallel()
 	ctx := testCcNoVndk(t, `
 		cc_library {
 			name: "libvndk",
@@ -673,7 +662,6 @@
 }
 
 func TestVndkDepError(t *testing.T) {
-	t.Parallel()
 	// Check whether an error is emitted when a VNDK lib depends on a system lib.
 	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
 		cc_library {
@@ -853,7 +841,6 @@
 }
 
 func TestDoubleLoadbleDep(t *testing.T) {
-	t.Parallel()
 	// okay to link : LLNDK -> double_loadable VNDK
 	testCc(t, `
 		cc_library {
@@ -959,7 +946,6 @@
 }
 
 func TestVendorSnapshotCapture(t *testing.T) {
-	t.Parallel()
 	bp := `
 	cc_library {
 		name: "libvndk",
@@ -1093,7 +1079,6 @@
 }
 
 func TestVendorSnapshotUse(t *testing.T) {
-	t.Parallel()
 	frameworkBp := `
 	cc_library {
 		name: "libvndk",
@@ -1138,6 +1123,7 @@
 		arch: {
 			arm64: {
 				srcs: ["libvndk.so"],
+				export_include_dirs: ["include/libvndk"],
 			},
 		},
 	}
@@ -1164,6 +1150,7 @@
 		shared_libs: ["libvndk"],
 		static_libs: ["libvendor", "libvendor_without_snapshot"],
 		compile_multilib: "64",
+		srcs: ["client.cpp"],
 	}
 
 	cc_binary {
@@ -1175,6 +1162,7 @@
 		system_shared_libs: [],
 		static_libs: ["libvndk"],
 		compile_multilib: "64",
+		srcs: ["bin.cpp"],
 	}
 
 	vendor_snapshot_static {
@@ -1185,6 +1173,7 @@
 		arch: {
 			arm64: {
 				src: "libvndk.a",
+				export_include_dirs: ["include/libvndk"],
 			},
 		},
 	}
@@ -1197,6 +1186,7 @@
 		arch: {
 			arm64: {
 				src: "libvendor.so",
+				export_include_dirs: ["include/libvendor"],
 			},
 		},
 	}
@@ -1209,6 +1199,7 @@
 		arch: {
 			arm64: {
 				src: "libvendor.a",
+				export_include_dirs: ["include/libvendor"],
 			},
 		},
 	}
@@ -1228,15 +1219,20 @@
 	depsBp := GatherRequiredDepsForTest(android.Android)
 
 	mockFS := map[string][]byte{
-		"deps/Android.bp":      []byte(depsBp),
-		"framework/Android.bp": []byte(frameworkBp),
-		"vendor/Android.bp":    []byte(vendorProprietaryBp),
-		"vendor/libvndk.a":     nil,
-		"vendor/libvendor.a":   nil,
-		"vendor/libvendor.so":  nil,
-		"vendor/bin":           nil,
-		"vndk/Android.bp":      []byte(vndkBp),
-		"vndk/libvndk.so":      nil,
+		"deps/Android.bp":              []byte(depsBp),
+		"framework/Android.bp":         []byte(frameworkBp),
+		"vendor/Android.bp":            []byte(vendorProprietaryBp),
+		"vendor/bin":                   nil,
+		"vendor/bin.cpp":               nil,
+		"vendor/client.cpp":            nil,
+		"vendor/include/libvndk/a.h":   nil,
+		"vendor/include/libvendor/b.h": nil,
+		"vendor/libvndk.a":             nil,
+		"vendor/libvendor.a":           nil,
+		"vendor/libvendor.so":          nil,
+		"vndk/Android.bp":              []byte(vndkBp),
+		"vndk/include/libvndk/a.h":     nil,
+		"vndk/libvndk.so":              nil,
 	}
 
 	config := TestConfig(buildDir, android.Android, nil, "", mockFS)
@@ -1255,27 +1251,41 @@
 	binaryVariant := "android_vendor.BOARD_arm64_armv8-a"
 
 	// libclient uses libvndk.vndk.BOARD.arm64, libvendor.vendor_static.BOARD.arm64, libvendor_without_snapshot
-	libclientLdRule := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld")
-	libclientFlags := libclientLdRule.Args["libFlags"]
+	libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"]
+	for _, includeFlags := range []string{
+		"-Ivndk/include/libvndk",     // libvndk
+		"-Ivendor/include/libvendor", // libvendor
+	} {
+		if !strings.Contains(libclientCcFlags, includeFlags) {
+			t.Errorf("flags for libclient must contain %#v, but was %#v.",
+				includeFlags, libclientCcFlags)
+		}
+	}
 
+	libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"]
 	for _, input := range [][]string{
 		[]string{sharedVariant, "libvndk.vndk.BOARD.arm64"},
 		[]string{staticVariant, "libvendor.vendor_static.BOARD.arm64"},
 		[]string{staticVariant, "libvendor_without_snapshot"},
 	} {
 		outputPaths := getOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
-		if !strings.Contains(libclientFlags, outputPaths[0].String()) {
-			t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientFlags)
+		if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
+			t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
 		}
 	}
 
 	// bin_without_snapshot uses libvndk.vendor_static.BOARD.arm64
-	binWithoutSnapshotLdRule := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld")
-	binWithoutSnapshotFlags := binWithoutSnapshotLdRule.Args["libFlags"]
+	binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"]
+	if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivendor/include/libvndk") {
+		t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.",
+			"-Ivendor/include/libvndk", binWithoutSnapshotCcFlags)
+	}
+
+	binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"]
 	libVndkStaticOutputPaths := getOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.BOARD.arm64"})
-	if !strings.Contains(binWithoutSnapshotFlags, libVndkStaticOutputPaths[0].String()) {
+	if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
 		t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
-			libVndkStaticOutputPaths[0], binWithoutSnapshotFlags)
+			libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
 	}
 
 	// libvendor.so is installed by libvendor.vendor_shared.BOARD.arm64
@@ -1303,7 +1313,6 @@
 }
 
 func TestVendorSnapshotSanitizer(t *testing.T) {
-	t.Parallel()
 	bp := `
 	vendor_snapshot_static {
 		name: "libsnapshot",
@@ -1344,7 +1353,6 @@
 }
 
 func TestVendorSnapshotExclude(t *testing.T) {
-	t.Parallel()
 
 	// This test verifies that the exclude_from_vendor_snapshot property
 	// makes its way from the Android.bp source file into the module data
@@ -1452,7 +1460,6 @@
 }
 
 func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) {
-	t.Parallel()
 
 	// This test verifies that using the exclude_from_vendor_snapshot
 	// property on a module in a vendor proprietary path generates an
@@ -1493,7 +1500,6 @@
 }
 
 func TestVendorSnapshotExcludeWithVendorAvailable(t *testing.T) {
-	t.Parallel()
 
 	// This test verifies that using the exclude_from_vendor_snapshot
 	// property on a module that is vendor available generates an error. A
@@ -1537,7 +1543,6 @@
 }
 
 func TestDoubleLoadableDepError(t *testing.T) {
-	t.Parallel()
 	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
 	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
 		cc_library {
@@ -1658,7 +1663,6 @@
 }
 
 func TestVndkExt(t *testing.T) {
-	t.Parallel()
 	// This test checks the VNDK-Ext properties.
 	bp := `
 		cc_library {
@@ -1741,7 +1745,6 @@
 }
 
 func TestVndkExtWithoutBoardVndkVersion(t *testing.T) {
-	t.Parallel()
 	// This test checks the VNDK-Ext properties when BOARD_VNDK_VERSION is not set.
 	ctx := testCcNoVndk(t, `
 		cc_library {
@@ -1772,7 +1775,6 @@
 }
 
 func TestVndkExtWithoutProductVndkVersion(t *testing.T) {
-	t.Parallel()
 	// This test checks the VNDK-Ext properties when PRODUCT_PRODUCT_VNDK_VERSION is not set.
 	ctx := testCc(t, `
 		cc_library {
@@ -1803,7 +1805,6 @@
 }
 
 func TestVndkExtError(t *testing.T) {
-	t.Parallel()
 	// This test ensures an error is emitted in ill-formed vndk-ext definition.
 	testCcError(t, "must set `vendor: true` or `product_specific: true` to set `extends: \".*\"`", `
 		cc_library {
@@ -1889,7 +1890,6 @@
 }
 
 func TestVndkExtInconsistentSupportSystemProcessError(t *testing.T) {
-	t.Parallel()
 	// This test ensures an error is emitted for inconsistent support_system_process.
 	testCcError(t, "module \".*\" with mismatched support_system_process", `
 		cc_library {
@@ -1937,7 +1937,6 @@
 }
 
 func TestVndkExtVendorAvailableFalseError(t *testing.T) {
-	t.Parallel()
 	// This test ensures an error is emitted when a VNDK-Ext library extends a VNDK library
 	// with `vendor_available: false`.
 	testCcError(t, "`extends` refers module \".*\" which does not have `vendor_available: true`", `
@@ -1984,7 +1983,6 @@
 }
 
 func TestVendorModuleUseVndkExt(t *testing.T) {
-	t.Parallel()
 	// This test ensures a vendor module can depend on a VNDK-Ext library.
 	testCc(t, `
 		cc_library {
@@ -2037,7 +2035,6 @@
 }
 
 func TestVndkExtUseVendorLib(t *testing.T) {
-	t.Parallel()
 	// This test ensures a VNDK-Ext library can depend on a vendor library.
 	testCc(t, `
 		cc_library {
@@ -2100,7 +2097,6 @@
 }
 
 func TestProductVndkExtDependency(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libvndk",
@@ -2166,7 +2162,6 @@
 }
 
 func TestVndkSpExtUseVndkError(t *testing.T) {
-	t.Parallel()
 	// This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK
 	// library.
 	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
@@ -2249,7 +2244,6 @@
 }
 
 func TestVndkUseVndkExtError(t *testing.T) {
-	t.Parallel()
 	// This test ensures an error is emitted if a VNDK/VNDK-SP library depends on a
 	// VNDK-Ext/VNDK-SP-Ext library.
 	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
@@ -2389,7 +2383,6 @@
 }
 
 func TestEnforceProductVndkVersion(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libllndk",
@@ -2464,7 +2457,6 @@
 }
 
 func TestEnforceProductVndkVersionErrors(t *testing.T) {
-	t.Parallel()
 	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
 		cc_library {
 			name: "libprod",
@@ -2545,7 +2537,6 @@
 }
 
 func TestMakeLinkType(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libvndk",
@@ -2739,7 +2730,6 @@
 }
 
 func TestSplitListForSize(t *testing.T) {
-	t.Parallel()
 	for _, testCase := range splitListForSizeTestCases {
 		out, _ := splitListForSize(android.PathsForTesting(testCase.in...), testCase.size)
 
@@ -2924,60 +2914,6 @@
 	return modulesInOrder, allDeps
 }
 
-func TestLinkReordering(t *testing.T) {
-	t.Parallel()
-	for _, testCase := range staticLinkDepOrderTestCases {
-		errs := []string{}
-
-		// parse testcase
-		_, givenTransitiveDeps := parseModuleDeps(testCase.inStatic)
-		expectedModuleNames, expectedTransitiveDeps := parseModuleDeps(testCase.outOrdered)
-		if testCase.allOrdered == "" {
-			// allow the test case to skip specifying allOrdered
-			testCase.allOrdered = testCase.outOrdered
-		}
-		_, expectedAllDeps := parseModuleDeps(testCase.allOrdered)
-		_, givenAllSharedDeps := parseModuleDeps(testCase.inShared)
-
-		// For each module whose post-reordered dependencies were specified, validate that
-		// reordering the inputs produces the expected outputs.
-		for _, moduleName := range expectedModuleNames {
-			moduleDeps := givenTransitiveDeps[moduleName]
-			givenSharedDeps := givenAllSharedDeps[moduleName]
-			orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenSharedDeps, givenTransitiveDeps)
-
-			correctAllOrdered := expectedAllDeps[moduleName]
-			if !reflect.DeepEqual(orderedAllDeps, correctAllOrdered) {
-				errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedAllDeps."+
-					"\nin static:%q"+
-					"\nin shared:%q"+
-					"\nmodule:   %v"+
-					"\nexpected: %s"+
-					"\nactual:   %s",
-					testCase.inStatic, testCase.inShared, moduleName, correctAllOrdered, orderedAllDeps))
-			}
-
-			correctOutputDeps := expectedTransitiveDeps[moduleName]
-			if !reflect.DeepEqual(correctOutputDeps, orderedDeclaredDeps) {
-				errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedDeclaredDeps."+
-					"\nin static:%q"+
-					"\nin shared:%q"+
-					"\nmodule:   %v"+
-					"\nexpected: %s"+
-					"\nactual:   %s",
-					testCase.inStatic, testCase.inShared, moduleName, correctOutputDeps, orderedDeclaredDeps))
-			}
-		}
-
-		if len(errs) > 0 {
-			sort.Strings(errs)
-			for _, err := range errs {
-				t.Error(err)
-			}
-		}
-	}
-}
-
 func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
 	for _, moduleName := range moduleNames {
 		module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
@@ -2988,7 +2924,6 @@
 }
 
 func TestStaticLibDepReordering(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 	cc_library {
 		name: "a",
@@ -3013,8 +2948,8 @@
 
 	variant := "android_arm64_armv8-a_static"
 	moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
-	actual := moduleA.depsInLinkOrder
-	expected := getOutputPaths(ctx, variant, []string{"c", "b", "d"})
+	actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).TransitiveStaticLibrariesForOrdering.ToList()
+	expected := getOutputPaths(ctx, variant, []string{"a", "c", "b", "d"})
 
 	if !reflect.DeepEqual(actual, expected) {
 		t.Errorf("staticDeps orderings were not propagated correctly"+
@@ -3027,7 +2962,6 @@
 }
 
 func TestStaticLibDepReorderingWithShared(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 	cc_library {
 		name: "a",
@@ -3048,8 +2982,8 @@
 
 	variant := "android_arm64_armv8-a_static"
 	moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
-	actual := moduleA.depsInLinkOrder
-	expected := getOutputPaths(ctx, variant, []string{"c", "b"})
+	actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).TransitiveStaticLibrariesForOrdering.ToList()
+	expected := getOutputPaths(ctx, variant, []string{"a", "c", "b"})
 
 	if !reflect.DeepEqual(actual, expected) {
 		t.Errorf("staticDeps orderings did not account for shared libs"+
@@ -3074,7 +3008,6 @@
 }
 
 func TestLlndkLibrary(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 	cc_library {
 		name: "libllndk",
@@ -3086,12 +3019,12 @@
 	`)
 	actual := ctx.ModuleVariantsForTests("libllndk.llndk")
 	expected := []string{
-		"android_vendor.VER_arm64_armv8-a_shared",
 		"android_vendor.VER_arm64_armv8-a_shared_1",
 		"android_vendor.VER_arm64_armv8-a_shared_2",
-		"android_vendor.VER_arm_armv7-a-neon_shared",
+		"android_vendor.VER_arm64_armv8-a_shared",
 		"android_vendor.VER_arm_armv7-a-neon_shared_1",
 		"android_vendor.VER_arm_armv7-a-neon_shared_2",
+		"android_vendor.VER_arm_armv7-a-neon_shared",
 	}
 	checkEquals(t, "variants for llndk stubs", expected, actual)
 
@@ -3103,7 +3036,6 @@
 }
 
 func TestLlndkHeaders(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 	llndk_headers {
 		name: "libllndk_headers",
@@ -3197,7 +3129,6 @@
 `
 
 func TestRuntimeLibs(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, runtimeLibAndroidBp)
 
 	// runtime_libs for core variants use the module names without suffixes.
@@ -3221,7 +3152,6 @@
 }
 
 func TestExcludeRuntimeLibs(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, runtimeLibAndroidBp)
 
 	variant := "android_arm64_armv8-a_shared"
@@ -3234,7 +3164,6 @@
 }
 
 func TestRuntimeLibsNoVndk(t *testing.T) {
-	t.Parallel()
 	ctx := testCcNoVndk(t, runtimeLibAndroidBp)
 
 	// If DeviceVndkVersion is not defined, then runtime_libs are copied as-is.
@@ -3272,7 +3201,6 @@
 `
 
 func TestStaticLibDepExport(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, staticLibAndroidBp)
 
 	// Check the shared version of lib2.
@@ -3360,7 +3288,6 @@
 }
 
 func TestCompilerFlags(t *testing.T) {
-	t.Parallel()
 	for _, testCase := range compilerFlagsTestCases {
 		ctx := &mockContext{result: true}
 		CheckBadCompilerFlags(ctx, "", []string{testCase.in})
@@ -3374,7 +3301,6 @@
 }
 
 func TestVendorPublicLibraries(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 	cc_library_headers {
 		name: "libvendorpublic_headers",
@@ -3441,7 +3367,6 @@
 }
 
 func TestRecovery(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 		cc_library_shared {
 			name: "librecovery",
@@ -3477,7 +3402,6 @@
 }
 
 func TestDataLibsPrebuiltSharedTestLibrary(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_prebuilt_test_library_shared {
 			name: "test_lib",
@@ -3524,7 +3448,6 @@
 }
 
 func TestVersionedStubs(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 		cc_library_shared {
 			name: "libFoo",
@@ -3589,7 +3512,6 @@
 }
 
 func TestVersioningMacro(t *testing.T) {
-	t.Parallel()
 	for _, tc := range []struct{ moduleName, expected string }{
 		{"libc", "__LIBC_API__"},
 		{"libfoo", "__LIBFOO_API__"},
@@ -3602,7 +3524,6 @@
 }
 
 func TestStaticExecutable(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 		cc_binary {
 			name: "static_test",
@@ -3628,12 +3549,11 @@
 }
 
 func TestStaticDepsOrderWithStubs(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 		cc_binary {
 			name: "mybin",
 			srcs: ["foo.c"],
-			static_libs: ["libfooB"],
+			static_libs: ["libfooC", "libfooB"],
 			static_executable: true,
 			stl: "none",
 		}
@@ -3654,8 +3574,8 @@
 			},
 		}`)
 
-	mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Module().(*Module)
-	actual := mybin.depsInLinkOrder
+	mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Rule("ld")
+	actual := mybin.Implicits[:2]
 	expected := getOutputPaths(ctx, "android_arm64_armv8-a_static", []string{"libfooB", "libfooC"})
 
 	if !reflect.DeepEqual(actual, expected) {
@@ -3669,7 +3589,6 @@
 }
 
 func TestErrorsIfAModuleDependsOnDisabled(t *testing.T) {
-	t.Parallel()
 	testCcError(t, `module "libA" .* depends on disabled module "libB"`, `
 		cc_library {
 			name: "libA",
@@ -3690,7 +3609,6 @@
 // Simple smoke test for the cc_fuzz target that ensures the rule compiles
 // correctly.
 func TestFuzzTarget(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 		cc_fuzz {
 			name: "fuzz_smoke_test",
@@ -3702,7 +3620,6 @@
 }
 
 func TestAidl(t *testing.T) {
-	t.Parallel()
 }
 
 func assertString(t *testing.T, got, expected string) {
@@ -3733,7 +3650,6 @@
 }
 
 func TestDefaults(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 		cc_defaults {
 			name: "defaults",
@@ -3798,7 +3714,6 @@
 }
 
 func TestProductVariableDefaults(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_defaults {
 			name: "libfoo_defaults",
diff --git a/cc/compiler_test.go b/cc/compiler_test.go
index cf553bd..c301388 100644
--- a/cc/compiler_test.go
+++ b/cc/compiler_test.go
@@ -19,7 +19,6 @@
 )
 
 func TestIsThirdParty(t *testing.T) {
-	t.Parallel()
 	shouldFail := []string{
 		"external/foo/",
 		"vendor/bar/",
diff --git a/cc/config/OWNERS b/cc/config/OWNERS
index b2f54e5..701db92 100644
--- a/cc/config/OWNERS
+++ b/cc/config/OWNERS
@@ -1 +1,3 @@
 per-file vndk.go = smoreland@google.com, victoryang@google.com
+per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
+
diff --git a/cc/config/global.go b/cc/config/global.go
index 97e423a..1aa2621 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -53,6 +53,13 @@
 		"-Werror=pragma-pack",
 		"-Werror=pragma-pack-suspicious-include",
 		"-Werror=unreachable-code-loop-increment",
+
+		// -fdebug-compilation-dir=. is used to make both the action command line and the output
+		// independent of the working directory of the action.
+		// Using cc1 flags since RBE's input processor does not yet have the updated version
+		// of LLVM that promotes the cc1 flag to driver level flag.
+		// See: https://reviews.llvm.org/D63387
+		"-Xclang,-fdebug-compilation-dir,.",
 	}
 
 	commonGlobalConlyflags = []string{}
@@ -150,10 +157,6 @@
 var pctx = android.NewPackageContext("android/soong/cc/config")
 
 func init() {
-	if android.BuildOs == android.Linux {
-		commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
-	}
-
 	pctx.StaticVariable("CommonGlobalConlyflags", strings.Join(commonGlobalConlyflags, " "))
 	pctx.StaticVariable("DeviceGlobalCppflags", strings.Join(deviceGlobalCppflags, " "))
 	pctx.StaticVariable("DeviceGlobalLdflags", strings.Join(deviceGlobalLdflags, " "))
@@ -205,7 +208,7 @@
 	pctx.PrefixedExistentPathsForSourcesVariable("CommonGlobalIncludes", "-I",
 		[]string{
 			"system/core/include",
-			"system/core/liblog/include",
+			"system/logging/liblog/include",
 			"system/media/audio/include",
 			"hardware/libhardware/include",
 			"hardware/libhardware_legacy/include",
diff --git a/cc/config/tidy_test.go b/cc/config/tidy_test.go
index 3ea2f6b..4ed8b23 100644
--- a/cc/config/tidy_test.go
+++ b/cc/config/tidy_test.go
@@ -19,7 +19,6 @@
 )
 
 func TestTidyChecksForDir(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		input    string
 		expected string
diff --git a/cc/gen_test.go b/cc/gen_test.go
index ee89873..4b9a36e 100644
--- a/cc/gen_test.go
+++ b/cc/gen_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestGen(t *testing.T) {
-	t.Parallel()
 	t.Run("simple", func(t *testing.T) {
 		ctx := testCc(t, `
 		cc_library_shared {
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index 6623d20..a366f76 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -30,7 +30,6 @@
 }
 
 func TestArchGenruleCmd(t *testing.T) {
-	t.Parallel()
 	fs := map[string][]byte{
 		"tool": nil,
 		"foo":  nil,
@@ -79,7 +78,6 @@
 }
 
 func TestLibraryGenruleCmd(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libboth",
diff --git a/cc/image.go b/cc/image.go
index ea6f567..6710e94 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -63,12 +63,12 @@
 
 func (ctx *moduleContext) ProductSpecific() bool {
 	return ctx.ModuleContext.ProductSpecific() ||
-		(ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
+		(ctx.mod.HasVendorVariant() && ctx.mod.inProduct())
 }
 
 func (ctx *moduleContext) SocSpecific() bool {
 	return ctx.ModuleContext.SocSpecific() ||
-		(ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
+		(ctx.mod.HasVendorVariant() && ctx.mod.inVendor())
 }
 
 func (ctx *moduleContextImpl) inProduct() bool {
diff --git a/cc/kernel_headers.go b/cc/kernel_headers.go
index 796de62..9ea988a 100644
--- a/cc/kernel_headers.go
+++ b/cc/kernel_headers.go
@@ -26,6 +26,7 @@
 	if ctx.Device() {
 		f := &stub.libraryDecorator.flagExporter
 		f.reexportSystemDirs(android.PathsForSource(ctx, ctx.DeviceConfig().DeviceKernelHeaderDirs())...)
+		f.setProvider(ctx)
 	}
 	return stub.libraryDecorator.linkStatic(ctx, flags, deps, objs)
 }
diff --git a/cc/library.go b/cc/library.go
index 35828aa..090abf9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -121,7 +121,10 @@
 }
 
 type StaticOrSharedProperties struct {
-	Srcs   []string `android:"path,arch_variant"`
+	Srcs []string `android:"path,arch_variant"`
+
+	Sanitized Sanitized `android:"arch_variant"`
+
 	Cflags []string `android:"arch_variant"`
 
 	Enabled            *bool    `android:"arch_variant"`
@@ -291,36 +294,16 @@
 	f.headers = append(f.headers, headers...)
 }
 
-func (f *flagExporter) exportedDirs() android.Paths {
-	return f.dirs
+func (f *flagExporter) setProvider(ctx android.ModuleContext) {
+	ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
+		IncludeDirs:       f.dirs,
+		SystemIncludeDirs: f.systemDirs,
+		Flags:             f.flags,
+		Deps:              f.deps,
+		GeneratedHeaders:  f.headers,
+	})
 }
 
-func (f *flagExporter) exportedSystemDirs() android.Paths {
-	return f.systemDirs
-}
-
-func (f *flagExporter) exportedFlags() []string {
-	return f.flags
-}
-
-func (f *flagExporter) exportedDeps() android.Paths {
-	return f.deps
-}
-
-func (f *flagExporter) exportedGeneratedHeaders() android.Paths {
-	return f.headers
-}
-
-type exportedFlagsProducer interface {
-	exportedDirs() android.Paths
-	exportedSystemDirs() android.Paths
-	exportedFlags() []string
-	exportedDeps() android.Paths
-	exportedGeneratedHeaders() android.Paths
-}
-
-var _ exportedFlagsProducer = (*flagExporter)(nil)
-
 // libraryDecorator wraps baseCompiler, baseLinker and baseInstaller to provide library-specific
 // functionality: static vs. shared linkage, reusing object files for shared libraries
 type libraryDecorator struct {
@@ -366,7 +349,7 @@
 	// Location of the file that should be copied to dist dir when requested
 	distFile android.Path
 
-	versionScriptPath android.ModuleGenPath
+	versionScriptPath android.OptionalPath
 
 	post_install_cmds []string
 
@@ -375,6 +358,8 @@
 	useCoreVariant       bool
 	checkSameCoreVariant bool
 
+	skipAPIDefine bool
+
 	// Decorated interfaces
 	*baseCompiler
 	*baseLinker
@@ -396,7 +381,7 @@
 	// can't be globbed, and they should be manually collected.
 	// So, we first filter out intermediate directories (which contains generated headers)
 	// from exported directories, and then glob headers under remaining directories.
-	for _, path := range append(l.exportedDirs(), l.exportedSystemDirs()...) {
+	for _, path := range append(android.CopyOfPaths(l.flagExporter.dirs), l.flagExporter.systemDirs...) {
 		dir := path.String()
 		// Skip if dir is for generated headers
 		if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
@@ -448,7 +433,7 @@
 	}
 
 	// Collect generated headers
-	for _, header := range append(l.exportedGeneratedHeaders(), l.exportedDeps()...) {
+	for _, header := range append(android.CopyOfPaths(l.flagExporter.headers), l.flagExporter.deps...) {
 		// TODO(b/148123511): remove exportedDeps after cleaning up genrule
 		if strings.HasSuffix(header.Base(), "-phony") {
 			continue
@@ -628,7 +613,7 @@
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
 	if library.buildStubs() {
 		objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "--apex")
-		library.versionScriptPath = versionScript
+		library.versionScriptPath = android.OptionalPathForPath(versionScript)
 		return objs
 	}
 
@@ -678,10 +663,12 @@
 }
 
 type libraryInterface interface {
+	versionedInterface
+
 	static() bool
 	shared() bool
 	objs() Objects
-	reuseObjs() (Objects, exportedFlagsProducer)
+	reuseObjs() Objects
 	toc() android.OptionalPath
 
 	// Returns true if the build options for the module have selected a static or shared build
@@ -698,6 +685,21 @@
 	availableFor(string) bool
 }
 
+type versionedInterface interface {
+	buildStubs() bool
+	setBuildStubs()
+	hasStubsVariants() bool
+	setStubsVersion(string)
+	stubsVersion() string
+
+	stubsVersions(ctx android.BaseMutatorContext) []string
+	setAllStubsVersions([]string)
+	allStubsVersions() []string
+}
+
+var _ libraryInterface = (*libraryDecorator)(nil)
+var _ versionedInterface = (*libraryDecorator)(nil)
+
 func (library *libraryDecorator) getLibNameHelper(baseModuleName string, useVndk bool) string {
 	name := library.libName
 	if name == "" {
@@ -886,6 +888,17 @@
 
 	ctx.CheckbuildFile(outputFile)
 
+	ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+		StaticLibrary: outputFile,
+		ReuseObjects:  library.reuseObjects,
+		Objects:       library.objects,
+
+		TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
+			Direct(outputFile).
+			Transitive(deps.TranstiveStaticLibrariesForOrdering).
+			Build(),
+	})
+
 	return outputFile
 }
 
@@ -922,15 +935,15 @@
 			linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
 		}
 	}
-	if library.buildStubs() {
+	if library.versionScriptPath.Valid() {
 		linkerScriptFlags := "-Wl,--version-script," + library.versionScriptPath.String()
 		flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlags)
-		linkerDeps = append(linkerDeps, library.versionScriptPath)
+		linkerDeps = append(linkerDeps, library.versionScriptPath.Path())
 	}
 
 	fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
 	outputFile := android.PathForModuleOut(ctx, fileName)
-	ret := outputFile
+	unstrippedOutputFile := outputFile
 
 	var implicitOutputs android.WritablePaths
 	if ctx.Windows() {
@@ -1012,9 +1025,42 @@
 	objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...)
 
 	library.coverageOutputFile = TransformCoverageFilesToZip(ctx, objs, library.getLibName(ctx))
-	library.linkSAbiDumpFiles(ctx, objs, fileName, ret)
+	library.linkSAbiDumpFiles(ctx, objs, fileName, unstrippedOutputFile)
 
-	return ret
+	var staticAnalogue *StaticLibraryInfo
+	if static := ctx.GetDirectDepsWithTag(staticVariantTag); len(static) > 0 {
+		s := ctx.OtherModuleProvider(static[0], StaticLibraryInfoProvider).(StaticLibraryInfo)
+		staticAnalogue = &s
+	}
+
+	ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+		TableOfContents:         android.OptionalPathForPath(tocFile),
+		SharedLibrary:           unstrippedOutputFile,
+		UnstrippedSharedLibrary: library.unstrippedOutputFile,
+		CoverageSharedLibrary:   library.coverageOutputFile,
+		StaticAnalogue:          staticAnalogue,
+	})
+
+	stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
+	if len(stubs) > 0 {
+		var stubsInfo []SharedLibraryStubsInfo
+		for _, stub := range stubs {
+			stubInfo := ctx.OtherModuleProvider(stub, SharedLibraryInfoProvider).(SharedLibraryInfo)
+			flagInfo := ctx.OtherModuleProvider(stub, FlagExporterInfoProvider).(FlagExporterInfo)
+			stubsInfo = append(stubsInfo, SharedLibraryStubsInfo{
+				Version:           stub.(*Module).StubsVersion(),
+				SharedLibraryInfo: stubInfo,
+				FlagExporterInfo:  flagInfo,
+			})
+		}
+		ctx.SetProvider(SharedLibraryImplementationStubsInfoProvider, SharedLibraryImplementationStubsInfo{
+			SharedLibraryStubsInfos: stubsInfo,
+
+			IsLLNDK: ctx.isLlndk(ctx.Config()),
+		})
+	}
+
+	return unstrippedOutputFile
 }
 
 func (library *libraryDecorator) unstrippedOutputFilePath() android.Path {
@@ -1158,10 +1204,12 @@
 		library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
 	}
 
-	if library.buildStubs() {
-		library.reexportFlags("-D" + versioningMacroName(ctx.ModuleName()) + "=" + library.stubsVersion())
+	if library.buildStubs() && !library.skipAPIDefine {
+		library.reexportFlags("-D" + versioningMacroName(ctx.baseModuleName()) + "=" + library.stubsVersion())
 	}
 
+	library.flagExporter.setProvider(ctx)
+
 	return out
 }
 
@@ -1179,8 +1227,8 @@
 	return library.objects
 }
 
-func (library *libraryDecorator) reuseObjs() (Objects, exportedFlagsProducer) {
-	return library.reuseObjects, &library.flagExporter
+func (library *libraryDecorator) reuseObjs() Objects {
+	return library.reuseObjects
 }
 
 func (library *libraryDecorator) toc() android.OptionalPath {
@@ -1324,10 +1372,34 @@
 	return nil
 }
 
+func (library *libraryDecorator) hasStubsVariants() bool {
+	return len(library.Properties.Stubs.Versions) > 0
+}
+
+func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+	return library.Properties.Stubs.Versions
+}
+
+func (library *libraryDecorator) setStubsVersion(version string) {
+	library.MutatedProperties.StubsVersion = version
+}
+
 func (library *libraryDecorator) stubsVersion() string {
 	return library.MutatedProperties.StubsVersion
 }
 
+func (library *libraryDecorator) setBuildStubs() {
+	library.MutatedProperties.BuildStubs = true
+}
+
+func (library *libraryDecorator) setAllStubsVersions(versions []string) {
+	library.MutatedProperties.AllStubsVersions = versions
+}
+
+func (library *libraryDecorator) allStubsVersions() []string {
+	return library.MutatedProperties.AllStubsVersions
+}
+
 func (library *libraryDecorator) isLatestStubVersion() bool {
 	versions := library.Properties.Stubs.Versions
 	return versions[len(versions)-1] == library.stubsVersion()
@@ -1423,10 +1495,10 @@
 				sharedCompiler.baseCompiler.Properties.Srcs
 			sharedCompiler.baseCompiler.Properties.Srcs = nil
 			sharedCompiler.baseCompiler.Properties.Generated_sources = nil
-		} else {
-			// This dep is just to reference static variant from shared variant
-			mctx.AddInterVariantDependency(staticVariantTag, shared, static)
 		}
+
+		// This dep is just to reference static variant from shared variant
+		mctx.AddInterVariantDependency(staticVariantTag, shared, static)
 	}
 }
 
@@ -1525,15 +1597,15 @@
 
 func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) {
 	// "" is for the non-stubs (implementation) variant.
-	variants := append([]string{""}, versions...)
+	variants := append(android.CopyOf(versions), "")
 
 	modules := mctx.CreateLocalVariations(variants...)
 	for i, m := range modules {
 		if variants[i] != "" {
 			m.(LinkableInterface).SetBuildStubs()
 			m.(LinkableInterface).SetStubsVersion(variants[i])
-			// The stubs depend on the implementation
-			mctx.AddInterVariantDependency(stubImplDepTag, modules[i], modules[0])
+			// The implementation depends on the stubs
+			mctx.AddInterVariantDependency(stubImplDepTag, modules[len(modules)-1], modules[i])
 		}
 	}
 	mctx.AliasVariation("")
@@ -1544,20 +1616,33 @@
 	mctx.CreateAliasVariation("latest", latestVersion)
 }
 
+func createPerApiVersionVariations(mctx android.BottomUpMutatorContext, minSdkVersion string) {
+	from, err := nativeApiLevelFromUser(mctx, minSdkVersion)
+	if err != nil {
+		mctx.PropertyErrorf("min_sdk_version", err.Error())
+		return
+	}
+
+	versionStrs := ndkLibraryVersions(mctx, from)
+	modules := mctx.CreateLocalVariations(versionStrs...)
+
+	for i, module := range modules {
+		module.(*Module).Properties.Sdk_version = StringPtr(versionStrs[i])
+	}
+}
+
 func CanBeOrLinkAgainstVersionVariants(module interface {
 	Host() bool
 	InRamdisk() bool
 	InRecovery() bool
-	UseSdk() bool
 }) bool {
-	return !module.Host() && !module.InRamdisk() && !module.InRecovery() && !module.UseSdk()
+	return !module.Host() && !module.InRamdisk() && !module.InRecovery()
 }
 
 func CanBeVersionVariant(module interface {
 	Host() bool
 	InRamdisk() bool
 	InRecovery() bool
-	UseSdk() bool
 	CcLibraryInterface() bool
 	Shared() bool
 	Static() bool
@@ -1570,29 +1655,18 @@
 // and propagates the value from implementation libraries to llndk libraries with the same name.
 func versionSelectorMutator(mctx android.BottomUpMutatorContext) {
 	if library, ok := mctx.Module().(LinkableInterface); ok && CanBeVersionVariant(library) {
-
-		if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 &&
-			!library.IsSdkVariant() {
-
-			versions := library.StubsVersions()
-			normalizeVersions(mctx, versions)
-			if mctx.Failed() {
+		if library.CcLibraryInterface() && library.BuildSharedVariant() {
+			versions := library.StubsVersions(mctx)
+			if len(versions) > 0 {
+				normalizeVersions(mctx, versions)
+				if mctx.Failed() {
+					return
+				}
+				// Set the versions on the pre-mutated module so they can be read by any llndk modules that
+				// depend on the implementation library and haven't been mutated yet.
+				library.SetAllStubsVersions(versions)
 				return
 			}
-			// Set the versions on the pre-mutated module so they can be read by any llndk modules that
-			// depend on the implementation library and haven't been mutated yet.
-			library.SetAllStubsVersions(versions)
-			return
-		}
-
-		if c, ok := library.(*Module); ok && c.IsStubs() {
-			// Get the versions from the implementation module.
-			impls := mctx.GetDirectDepsWithTag(llndkImplDep)
-			if len(impls) > 1 {
-				panic(fmt.Errorf("Expected single implmenetation library, got %d", len(impls)))
-			} else if len(impls) == 1 {
-				c.SetAllStubsVersions(impls[0].(*Module).AllStubsVersions())
-			}
 		}
 	}
 }
@@ -1602,6 +1676,16 @@
 func versionMutator(mctx android.BottomUpMutatorContext) {
 	if library, ok := mctx.Module().(LinkableInterface); ok && CanBeVersionVariant(library) {
 		createVersionVariations(mctx, library.AllStubsVersions())
+		return
+	}
+
+	if m, ok := mctx.Module().(*Module); ok {
+		if m.SplitPerApiLevel() && m.IsSdkVariant() {
+			if mctx.Os() != android.Android {
+				return
+			}
+			createPerApiVersionVariations(mctx, m.MinSdkVersion())
+		}
 	}
 }
 
diff --git a/cc/library_headers_test.go b/cc/library_headers_test.go
index db42d25..564ef61 100644
--- a/cc/library_headers_test.go
+++ b/cc/library_headers_test.go
@@ -20,7 +20,6 @@
 )
 
 func TestLibraryHeaders(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 	cc_library_headers {
 		name: "headers",
@@ -42,7 +41,6 @@
 }
 
 func TestPrebuiltLibraryHeaders(t *testing.T) {
-	t.Parallel()
 	ctx := testCc(t, `
 	cc_prebuilt_library_headers {
 		name: "headers",
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 765fe71..fcf6069 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -391,10 +391,12 @@
 		p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
 	}
 
+	exportedInfo := ctx.SdkModuleContext().OtherModuleProvider(variant, FlagExporterInfoProvider).(FlagExporterInfo)
+
 	// Separate out the generated include dirs (which are arch specific) from the
 	// include dirs (which may not be).
 	exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate(
-		ccModule.ExportedIncludeDirs(), isGeneratedHeaderDirectory)
+		exportedInfo.IncludeDirs, isGeneratedHeaderDirectory)
 
 	p.name = variant.Name()
 	p.archType = ccModule.Target().Arch.ArchType.String()
@@ -405,10 +407,10 @@
 
 	// Take a copy before filtering out duplicates to avoid changing the slice owned by the
 	// ccModule.
-	dirs := append(android.Paths(nil), ccModule.ExportedSystemIncludeDirs()...)
+	dirs := append(android.Paths(nil), exportedInfo.SystemIncludeDirs...)
 	p.ExportedSystemIncludeDirs = android.FirstUniquePaths(dirs)
 
-	p.ExportedFlags = ccModule.ExportedFlags()
+	p.ExportedFlags = exportedInfo.Flags
 	if ccModule.linker != nil {
 		specifiedDeps := specifiedDeps{}
 		specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
@@ -419,7 +421,7 @@
 		}
 		p.SystemSharedLibs = specifiedDeps.systemSharedLibs
 	}
-	p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders()
+	p.exportedGeneratedHeaders = exportedInfo.GeneratedHeaders
 
 	if ccModule.HasStubsVariants() {
 		// TODO(b/169373910): 1. Only output the specific version (from
diff --git a/cc/library_test.go b/cc/library_test.go
index d42f073..49838b4 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -22,7 +22,6 @@
 )
 
 func TestLibraryReuse(t *testing.T) {
-	t.Parallel()
 	t.Run("simple", func(t *testing.T) {
 		ctx := testCc(t, `
 		cc_library {
@@ -191,7 +190,6 @@
 }
 
 func TestStubsVersions(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libfoo",
@@ -215,7 +213,6 @@
 }
 
 func TestStubsVersions_NotSorted(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libfoo",
@@ -231,7 +228,6 @@
 }
 
 func TestStubsVersions_ParseError(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libfoo",
diff --git a/cc/linkable.go b/cc/linkable.go
index a67cd4e..4eb7220 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -14,16 +14,9 @@
 	OutputFile() android.OptionalPath
 	CoverageFiles() android.Paths
 
-	IncludeDirs() android.Paths
-	SetDepsInLinkOrder([]android.Path)
-	GetDepsInLinkOrder() []android.Path
-
-	HasStaticVariant() bool
-	GetStaticVariant() LinkableInterface
-
 	NonCcVariants() bool
 
-	StubsVersions() []string
+	StubsVersions(android.BaseMutatorContext) []string
 	BuildStubs() bool
 	SetBuildStubs()
 	SetStubsVersion(string)
@@ -80,3 +73,54 @@
 func StaticDepTag() blueprint.DependencyTag {
 	return libraryDependencyTag{Kind: staticLibraryDependency}
 }
+
+type SharedLibraryInfo struct {
+	SharedLibrary           android.Path
+	UnstrippedSharedLibrary android.Path
+
+	TableOfContents       android.OptionalPath
+	CoverageSharedLibrary android.OptionalPath
+
+	StaticAnalogue *StaticLibraryInfo
+}
+
+var SharedLibraryInfoProvider = blueprint.NewProvider(SharedLibraryInfo{})
+
+type SharedLibraryImplementationStubsInfo struct {
+	SharedLibraryStubsInfos []SharedLibraryStubsInfo
+
+	IsLLNDK bool
+}
+
+var SharedLibraryImplementationStubsInfoProvider = blueprint.NewProvider(SharedLibraryImplementationStubsInfo{})
+
+type SharedLibraryStubsInfo struct {
+	Version           string
+	SharedLibraryInfo SharedLibraryInfo
+	FlagExporterInfo  FlagExporterInfo
+}
+
+var SharedLibraryStubsInfoProvider = blueprint.NewProvider(SharedLibraryStubsInfo{})
+
+type StaticLibraryInfo struct {
+	StaticLibrary android.Path
+	Objects       Objects
+	ReuseObjects  Objects
+
+	// This isn't the actual transitive DepSet, shared library dependencies have been
+	// converted into static library analogues.  It is only used to order the static
+	// library dependencies that were specified for the current module.
+	TransitiveStaticLibrariesForOrdering *android.DepSet
+}
+
+var StaticLibraryInfoProvider = blueprint.NewProvider(StaticLibraryInfo{})
+
+type FlagExporterInfo struct {
+	IncludeDirs       android.Paths
+	SystemIncludeDirs android.Paths
+	Flags             []string
+	Deps              android.Paths
+	GeneratedHeaders  android.Paths
+}
+
+var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{})
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index a429063..4425a10 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -15,17 +15,14 @@
 package cc
 
 import (
+	"fmt"
 	"path/filepath"
 	"strings"
 
 	"android/soong/android"
-
-	"github.com/google/blueprint"
 )
 
-var llndkImplDep = struct {
-	blueprint.DependencyTag
-}{}
+var llndkImplDep = dependencyTag{name: "llndk impl"}
 
 var (
 	llndkLibrarySuffix = ".llndk"
@@ -72,9 +69,6 @@
 
 	Properties llndkLibraryProperties
 
-	exportHeadersTimestamp android.OptionalPath
-	versionScriptPath      android.ModuleGenPath
-
 	movedToApex bool
 }
 
@@ -93,7 +87,9 @@
 		vndkVer = stub.stubsVersion()
 	}
 	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndkVer, "--llndk")
-	stub.versionScriptPath = versionScript
+	if !Bool(stub.Properties.Unversioned) {
+		stub.versionScriptPath = android.OptionalPathForPath(versionScript)
+	}
 	return objs
 }
 
@@ -142,12 +138,6 @@
 		stub.movedToApex = implApexModule.DirectlyInAnyApex()
 	}
 
-	if !Bool(stub.Properties.Unversioned) {
-		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
-		flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag)
-		flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
-	}
-
 	if len(stub.Properties.Export_preprocessed_headers) > 0 {
 		genHeaderOutDir := android.PathForModuleGen(ctx, "include")
 
@@ -170,10 +160,6 @@
 		stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{}
 	}
 
-	if stub.stubsVersion() != "" {
-		stub.reexportFlags("-D" + versioningMacroName(ctx.baseModuleName()) + "=" + stub.stubsVersion())
-	}
-
 	return stub.libraryDecorator.link(ctx, flags, deps, objs)
 }
 
@@ -181,6 +167,21 @@
 	return false
 }
 
+func (stub *llndkStubDecorator) buildStubs() bool {
+	return true
+}
+
+func (stub *llndkStubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+	// Get the versions from the implementation module.
+	impls := ctx.GetDirectDepsWithTag(llndkImplDep)
+	if len(impls) > 1 {
+		panic(fmt.Errorf("Expected single implmenetation library, got %d", len(impls)))
+	} else if len(impls) == 1 {
+		return impls[0].(*Module).AllStubsVersions()
+	}
+	return nil
+}
+
 func NewLLndkStubLibrary() *Module {
 	module, library := NewLibrary(android.DeviceSupported)
 	library.BuildOnlyShared()
diff --git a/cc/lto.go b/cc/lto.go
index abd8dfb..a3b28d9 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -71,7 +71,8 @@
 	} else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") {
 		staticLib := ctx.static() && !ctx.staticBinary()
 		hostBin := ctx.Host()
-		if !staticLib && !hostBin {
+		vndk := ctx.isVndk() // b/169217596
+		if !staticLib && !hostBin && !vndk {
 			if !lto.Never() && !lto.FullLTO() {
 				lto.Properties.Lto.Thin = boolPtr(true)
 			}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 5682d1c..f2ad652 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -80,9 +80,6 @@
 	// https://github.com/android-ndk/ndk/issues/265.
 	Unversioned_until *string
 
-	// Use via apiLevel on the stubDecorator.
-	ApiLevel string `blueprint:"mutated"`
-
 	// True if this API is not yet ready to be shipped in the NDK. It will be
 	// available in the platform for testing, but will be excluded from the
 	// sysroot provided to the NDK proper.
@@ -107,9 +104,7 @@
 	return stub.apiLevel.GreaterThanOrEqualTo(stub.unversionedUntil)
 }
 
-func generatePerApiVariants(ctx android.BottomUpMutatorContext, m *Module,
-	from android.ApiLevel, perSplit func(*Module, android.ApiLevel)) {
-
+func ndkLibraryVersions(ctx android.BaseMutatorContext, from android.ApiLevel) []string {
 	var versions []android.ApiLevel
 	versionStrs := []string{}
 	for _, version := range ctx.Config().AllSupportedApiLevels() {
@@ -118,56 +113,26 @@
 			versionStrs = append(versionStrs, version.String())
 		}
 	}
-	versions = append(versions, android.FutureApiLevel)
 	versionStrs = append(versionStrs, android.FutureApiLevel.String())
 
-	modules := ctx.CreateVariations(versionStrs...)
-	for i, module := range modules {
-		perSplit(module.(*Module), versions[i])
-	}
+	return versionStrs
 }
 
-func NdkApiMutator(ctx android.BottomUpMutatorContext) {
-	if m, ok := ctx.Module().(*Module); ok {
-		if m.Enabled() {
-			if compiler, ok := m.compiler.(*stubDecorator); ok {
-				if ctx.Os() != android.Android {
-					// These modules are always android.DeviceEnabled only, but
-					// those include Fuchsia devices, which we don't support.
-					ctx.Module().Disable()
-					return
-				}
-				firstVersion, err := nativeApiLevelFromUser(ctx,
-					String(compiler.properties.First_version))
-				if err != nil {
-					ctx.PropertyErrorf("first_version", err.Error())
-					return
-				}
-				generatePerApiVariants(ctx, m, firstVersion,
-					func(m *Module, version android.ApiLevel) {
-						m.compiler.(*stubDecorator).properties.ApiLevel =
-							version.String()
-					})
-			} else if m.SplitPerApiLevel() && m.IsSdkVariant() {
-				if ctx.Os() != android.Android {
-					return
-				}
-				from, err := nativeApiLevelFromUser(ctx, m.MinSdkVersion())
-				if err != nil {
-					ctx.PropertyErrorf("min_sdk_version", err.Error())
-					return
-				}
-				generatePerApiVariants(ctx, m, from,
-					func(m *Module, version android.ApiLevel) {
-						m.Properties.Sdk_version = StringPtr(version.String())
-					})
-			}
-		}
+func (this *stubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+	if !ctx.Module().Enabled() {
+		return nil
 	}
+	firstVersion, err := nativeApiLevelFromUser(ctx,
+		String(this.properties.First_version))
+	if err != nil {
+		ctx.PropertyErrorf("first_version", err.Error())
+		return nil
+	}
+	return ndkLibraryVersions(ctx, firstVersion)
 }
 
 func (this *stubDecorator) initializeProperties(ctx BaseModuleContext) bool {
-	this.apiLevel = nativeApiLevelOrPanic(ctx, this.properties.ApiLevel)
+	this.apiLevel = nativeApiLevelOrPanic(ctx, this.stubsVersion())
 
 	var err error
 	this.firstVersion, err = nativeApiLevelFromUser(ctx,
@@ -280,6 +245,11 @@
 		ctx.PropertyErrorf("symbol_file", "must end with .map.txt")
 	}
 
+	if !c.buildStubs() {
+		// NDK libraries have no implementation variant, nothing to do
+		return Objects{}
+	}
+
 	if !c.initializeProperties(ctx) {
 		// Emits its own errors, so we don't need to.
 		return Objects{}
@@ -311,12 +281,18 @@
 func (stub *stubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
 	objs Objects) android.Path {
 
+	if !stub.buildStubs() {
+		// NDK libraries have no implementation variant, nothing to do
+		return nil
+	}
+
 	if shouldUseVersionScript(ctx, stub) {
 		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
 		flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag)
 		flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
 	}
 
+	stub.libraryDecorator.skipAPIDefine = true
 	return stub.libraryDecorator.link(ctx, flags, deps, objs)
 }
 
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index acdc581..793ab37 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -166,7 +166,7 @@
 		ctx.ModuleErrorf("NDK prebuilt libraries must have an ndk_lib prefixed name")
 	}
 
-	ndk.exportIncludesAsSystem(ctx)
+	ndk.libraryDecorator.flagExporter.exportIncludesAsSystem(ctx)
 
 	libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
 	libExt := flags.Toolchain.ShlibSuffix()
@@ -175,5 +175,23 @@
 	}
 
 	libDir := getNdkStlLibDir(ctx)
-	return libDir.Join(ctx, libName+libExt)
+	lib := libDir.Join(ctx, libName+libExt)
+
+	ndk.libraryDecorator.flagExporter.setProvider(ctx)
+
+	if ndk.static() {
+		depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(lib).Build()
+		ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+			StaticLibrary: lib,
+
+			TransitiveStaticLibrariesForOrdering: depSet,
+		})
+	} else {
+		ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+			SharedLibrary:           lib,
+			UnstrippedSharedLibrary: lib,
+		})
+	}
+
+	return lib
 }
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 56fd54b..b6733c2 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -131,7 +131,7 @@
 		}
 
 		if m, ok := module.(*Module); ok {
-			if installer, ok := m.installer.(*stubDecorator); ok {
+			if installer, ok := m.installer.(*stubDecorator); ok && m.BuildStubs() {
 				if ctx.Config().ExcludeDraftNdkApis() &&
 					installer.properties.Draft {
 					return
diff --git a/cc/object_test.go b/cc/object_test.go
index a006044..6ff8a00 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -19,7 +19,6 @@
 )
 
 func TestLinkerScript(t *testing.T) {
-	t.Parallel()
 	t.Run("script", func(t *testing.T) {
 		testCc(t, `
 		cc_object {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 9d1b016..45d3eb1 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -38,10 +38,11 @@
 }
 
 type prebuiltLinkerProperties struct {
-
 	// a prebuilt library or binary. Can reference a genrule module that generates an executable file.
 	Srcs []string `android:"path,arch_variant"`
 
+	Sanitized Sanitized `android:"arch_variant"`
+
 	// Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined
 	// symbols, etc), default true.
 	Check_elf_files *bool
@@ -97,15 +98,17 @@
 func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
 	flags Flags, deps PathDeps, objs Objects) android.Path {
 
-	p.libraryDecorator.exportIncludes(ctx)
-	p.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
-	p.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
-	p.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
-	p.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
-	p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
+	p.libraryDecorator.flagExporter.exportIncludes(ctx)
+	p.libraryDecorator.flagExporter.reexportDirs(deps.ReexportedDirs...)
+	p.libraryDecorator.flagExporter.reexportSystemDirs(deps.ReexportedSystemDirs...)
+	p.libraryDecorator.flagExporter.reexportFlags(deps.ReexportedFlags...)
+	p.libraryDecorator.flagExporter.reexportDeps(deps.ReexportedDeps...)
+	p.libraryDecorator.flagExporter.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
+
+	p.libraryDecorator.flagExporter.setProvider(ctx)
 
 	// TODO(ccross): verify shared library dependencies
-	srcs := p.prebuiltSrcs()
+	srcs := p.prebuiltSrcs(ctx)
 	if len(srcs) > 0 {
 		builderFlags := flagsToBuilderFlags(flags)
 
@@ -117,6 +120,12 @@
 		in := android.PathForModuleSrc(ctx, srcs[0])
 
 		if p.static() {
+			depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(in).Build()
+			ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+				StaticLibrary: in,
+
+				TransitiveStaticLibrariesForOrdering: depSet,
+			})
 			return in
 		}
 
@@ -170,6 +179,13 @@
 				},
 			})
 
+			ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+				SharedLibrary:           outputFile,
+				UnstrippedSharedLibrary: p.unstrippedOutputFile,
+
+				TableOfContents: p.tocFile,
+			})
+
 			return outputFile
 		}
 	}
@@ -177,15 +193,18 @@
 	return nil
 }
 
-func (p *prebuiltLibraryLinker) prebuiltSrcs() []string {
+func (p *prebuiltLibraryLinker) prebuiltSrcs(ctx android.BaseModuleContext) []string {
+	sanitize := ctx.Module().(*Module).sanitize
 	srcs := p.properties.Srcs
+	srcs = append(srcs, srcsForSanitizer(sanitize, p.properties.Sanitized)...)
 	if p.static() {
 		srcs = append(srcs, p.libraryDecorator.StaticProperties.Static.Srcs...)
+		srcs = append(srcs, srcsForSanitizer(sanitize, p.libraryDecorator.StaticProperties.Static.Sanitized)...)
 	}
 	if p.shared() {
 		srcs = append(srcs, p.libraryDecorator.SharedProperties.Shared.Srcs...)
+		srcs = append(srcs, srcsForSanitizer(sanitize, p.libraryDecorator.SharedProperties.Shared.Sanitized)...)
 	}
-
 	return srcs
 }
 
@@ -212,8 +231,8 @@
 
 	module.AddProperties(&prebuilt.properties)
 
-	srcsSupplier := func() []string {
-		return prebuilt.prebuiltSrcs()
+	srcsSupplier := func(ctx android.BaseModuleContext) []string {
+		return prebuilt.prebuiltSrcs(ctx)
 	}
 
 	android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
@@ -425,3 +444,28 @@
 	android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
 	return module, binary
 }
+
+type Sanitized struct {
+	None struct {
+		Srcs []string `android:"path,arch_variant"`
+	} `android:"arch_variant"`
+	Address struct {
+		Srcs []string `android:"path,arch_variant"`
+	} `android:"arch_variant"`
+	Hwaddress struct {
+		Srcs []string `android:"path,arch_variant"`
+	} `android:"arch_variant"`
+}
+
+func srcsForSanitizer(sanitize *sanitize, sanitized Sanitized) []string {
+	if sanitize == nil {
+		return nil
+	}
+	if Bool(sanitize.Properties.Sanitize.Address) && sanitized.Address.Srcs != nil {
+		return sanitized.Address.Srcs
+	}
+	if Bool(sanitize.Properties.Sanitize.Hwaddress) && sanitized.Hwaddress.Srcs != nil {
+		return sanitized.Hwaddress.Srcs
+	}
+	return sanitized.None.Srcs
+}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index afae261..1f070a5 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -23,7 +23,7 @@
 	"github.com/google/blueprint"
 )
 
-func testPrebuilt(t *testing.T, bp string, fs map[string][]byte) *android.TestContext {
+func testPrebuilt(t *testing.T, bp string, fs map[string][]byte, handlers ...configCustomizer) *android.TestContext {
 	config := TestConfig(buildDir, android.Android, nil, bp, fs)
 	ctx := CreateTestContext()
 
@@ -34,6 +34,10 @@
 	android.RegisterAndroidMkBuildComponents(ctx)
 	android.SetInMakeForTests(config)
 
+	for _, handler := range handlers {
+		handler(config)
+	}
+
 	ctx.Register(config)
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
 	android.FailIfErrored(t, errs)
@@ -42,8 +46,9 @@
 	return ctx
 }
 
+type configCustomizer func(config android.Config)
+
 func TestPrebuilt(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "liba",
@@ -173,7 +178,6 @@
 }
 
 func TestPrebuiltLibraryShared(t *testing.T) {
-	t.Parallel()
 	ctx := testPrebuilt(t, `
 	cc_prebuilt_library_shared {
 		name: "libtest",
@@ -191,7 +195,6 @@
 }
 
 func TestPrebuiltLibraryStatic(t *testing.T) {
-	t.Parallel()
 	ctx := testPrebuilt(t, `
 	cc_prebuilt_library_static {
 		name: "libtest",
@@ -206,7 +209,6 @@
 }
 
 func TestPrebuiltLibrary(t *testing.T) {
-	t.Parallel()
 	ctx := testPrebuilt(t, `
 	cc_prebuilt_library {
 		name: "libtest",
@@ -233,7 +235,6 @@
 }
 
 func TestPrebuiltLibraryStem(t *testing.T) {
-	t.Parallel()
 	ctx := testPrebuilt(t, `
 	cc_prebuilt_library {
 		name: "libfoo",
@@ -261,7 +262,6 @@
 }
 
 func TestPrebuiltLibrarySharedStem(t *testing.T) {
-	t.Parallel()
 	ctx := testPrebuilt(t, `
 	cc_prebuilt_library_shared {
 		name: "libfoo",
@@ -280,7 +280,6 @@
 }
 
 func TestPrebuiltSymlinkedHostBinary(t *testing.T) {
-	t.Parallel()
 	if android.BuildOs != android.Linux {
 		t.Skipf("Skipping host prebuilt testing that is only supported on %s not %s", android.Linux, android.BuildOs)
 	}
@@ -328,3 +327,62 @@
 	assertString(t, libfooDep.String(),
 		filepath.Join(buildDir, ".intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so"))
 }
+
+func TestPrebuiltLibrarySanitized(t *testing.T) {
+	bp := `cc_prebuilt_library {
+	name: "libtest",
+		static: {
+                        sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
+		},
+		shared: {
+                        sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
+		},
+	}
+	cc_prebuilt_library_static {
+		name: "libtest_static",
+                sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
+	}
+	cc_prebuilt_library_shared {
+		name: "libtest_shared",
+                sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
+	}`
+
+	fs := map[string][]byte{
+		"libf.a":         nil,
+		"libf.hwasan.a":  nil,
+		"libf.so":        nil,
+		"hwasan/libf.so": nil,
+	}
+
+	// Without SANITIZE_TARGET.
+	ctx := testPrebuilt(t, bp, fs)
+
+	shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
+	assertString(t, shared_rule.Input.String(), "libf.so")
+
+	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
+	assertString(t, static.OutputFile().Path().Base(), "libf.a")
+
+	shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
+	assertString(t, shared_rule2.Input.String(), "libf.so")
+
+	static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module)
+	assertString(t, static2.OutputFile().Path().Base(), "libf.a")
+
+	// With SANITIZE_TARGET=hwaddress
+	ctx = testPrebuilt(t, bp, fs, func(config android.Config) {
+		config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
+	})
+
+	shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
+	assertString(t, shared_rule.Input.String(), "hwasan/libf.so")
+
+	static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
+	assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a")
+
+	shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
+	assertString(t, shared_rule2.Input.String(), "hwasan/libf.so")
+
+	static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
+	assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
+}
diff --git a/cc/proto_test.go b/cc/proto_test.go
index 2d059eb..f8bbd26 100644
--- a/cc/proto_test.go
+++ b/cc/proto_test.go
@@ -22,7 +22,6 @@
 )
 
 func TestProto(t *testing.T) {
-	t.Parallel()
 	t.Run("simple", func(t *testing.T) {
 		ctx := testCc(t, `
 		cc_library_shared {
diff --git a/cc/sdk_test.go b/cc/sdk_test.go
index 7b9867c..5a3c181 100644
--- a/cc/sdk_test.go
+++ b/cc/sdk_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestSdkMutator(t *testing.T) {
-	t.Parallel()
 	bp := `
 		cc_library {
 			name: "libsdk",
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index b72af44..238508d 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -22,7 +22,6 @@
 )
 
 type snapshotLibraryInterface interface {
-	exportedFlagsProducer
 	libraryInterface
 	collectHeadersForSnapshot(ctx android.ModuleContext)
 	snapshotHeaders() android.Paths
diff --git a/cc/test_data_test.go b/cc/test_data_test.go
index 7908aa0..ae59e2f 100644
--- a/cc/test_data_test.go
+++ b/cc/test_data_test.go
@@ -109,7 +109,6 @@
 }
 
 func TestDataTests(t *testing.T) {
-	t.Parallel()
 	buildDir, err := ioutil.TempDir("", "soong_test_test")
 	if err != nil {
 		t.Fatal(err)
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index 19f5ea4..8c546c5 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -84,24 +84,31 @@
 	}
 
 	srcPath := android.PathForSource(ctx, *library.Properties.Src)
-
-	if library.stripper.StripProperties.Strip.Keep_symbols_list != nil {
-		fileName := ctx.ModuleName() + staticLibraryExtension
-		outputFile := android.PathForModuleOut(ctx, fileName)
-		stripFlags := flagsToStripFlags(flags)
-		library.stripper.StripStaticLib(ctx, srcPath, outputFile, stripFlags)
-		return outputFile
-	}
+	outputFile := android.Path(srcPath)
 
 	if library.Properties.Repack_objects_to_keep != nil {
 		fileName := ctx.ModuleName() + staticLibraryExtension
-		outputFile := android.PathForModuleOut(ctx, fileName)
-		TransformArchiveRepack(ctx, srcPath, outputFile, library.Properties.Repack_objects_to_keep)
-
-		return outputFile
+		repackedPath := android.PathForModuleOut(ctx, fileName)
+		TransformArchiveRepack(ctx, outputFile, repackedPath, library.Properties.Repack_objects_to_keep)
+		outputFile = repackedPath
 	}
 
-	return srcPath
+	if library.stripper.StripProperties.Strip.Keep_symbols_list != nil {
+		fileName := ctx.ModuleName() + staticLibraryExtension
+		strippedPath := android.PathForModuleOut(ctx, fileName)
+		stripFlags := flagsToStripFlags(flags)
+		library.stripper.StripStaticLib(ctx, outputFile, strippedPath, stripFlags)
+		outputFile = strippedPath
+	}
+
+	depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build()
+	ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+		StaticLibrary: outputFile,
+
+		TransitiveStaticLibrariesForOrdering: depSet,
+	})
+
+	return outputFile
 }
 
 func (library *toolchainLibraryDecorator) nativeCoverage() bool {
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 529ed60..64e3ea8 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -223,8 +223,26 @@
 		tocFile := android.PathForModuleOut(ctx, libName+".toc")
 		p.tocFile = android.OptionalPathForPath(tocFile)
 		TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
+
+		ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+			SharedLibrary:           in,
+			UnstrippedSharedLibrary: p.unstrippedOutputFile,
+
+			TableOfContents: p.tocFile,
+		})
 	}
 
+	if p.static() {
+		depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(in).Build()
+		ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+			StaticLibrary: in,
+
+			TransitiveStaticLibrariesForOrdering: depSet,
+		})
+	}
+
+	p.libraryDecorator.flagExporter.setProvider(ctx)
+
 	return in
 }
 
@@ -735,13 +753,14 @@
 		var propOut string
 
 		if l, ok := m.linker.(snapshotLibraryInterface); ok {
+			exporterInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
 
 			// library flags
-			prop.ExportedFlags = l.exportedFlags()
-			for _, dir := range l.exportedDirs() {
+			prop.ExportedFlags = exporterInfo.Flags
+			for _, dir := range exporterInfo.IncludeDirs {
 				prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String()))
 			}
-			for _, dir := range l.exportedSystemDirs() {
+			for _, dir := range exporterInfo.SystemIncludeDirs {
 				prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String()))
 			}
 			// shared libs dependencies aren't meaningful on static or header libs
diff --git a/cc/vndk.go b/cc/vndk.go
index 4169e21..981e039 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -620,7 +620,7 @@
 
 	var headers android.Paths
 
-	installVndkSnapshotLib := func(m *Module, l snapshotLibraryInterface, vndkType string) (android.Paths, bool) {
+	installVndkSnapshotLib := func(m *Module, vndkType string) (android.Paths, bool) {
 		var ret android.Paths
 
 		targetArch := "arch-" + m.Target().Arch.ArchType.String()
@@ -639,9 +639,10 @@
 				ExportedFlags       []string `json:",omitempty"`
 				RelativeInstallPath string   `json:",omitempty"`
 			}{}
-			prop.ExportedFlags = l.exportedFlags()
-			prop.ExportedDirs = l.exportedDirs().Strings()
-			prop.ExportedSystemDirs = l.exportedSystemDirs().Strings()
+			exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
+			prop.ExportedFlags = exportedInfo.Flags
+			prop.ExportedDirs = exportedInfo.IncludeDirs.Strings()
+			prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings()
 			prop.RelativeInstallPath = m.RelativeInstallPath()
 
 			propOut := snapshotLibOut + ".json"
@@ -671,7 +672,7 @@
 
 		// install .so files for appropriate modules.
 		// Also install .json files if VNDK_SNAPSHOT_BUILD_ARTIFACTS
-		libs, ok := installVndkSnapshotLib(m, l, vndkType)
+		libs, ok := installVndkSnapshotLib(m, vndkType)
 		if !ok {
 			return
 		}
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 9484760..3556d94 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -162,6 +162,15 @@
 			p.androidMkSuffix = ""
 		}
 
+		ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+			SharedLibrary:           in,
+			UnstrippedSharedLibrary: p.unstrippedOutputFile,
+
+			TableOfContents: p.tocFile,
+		})
+
+		p.libraryDecorator.flagExporter.setProvider(ctx)
+
 		return in
 	}
 
diff --git a/cmd/diff_target_files/allow_list_test.go b/cmd/diff_target_files/allow_list_test.go
index 9f89657..8410e5a 100644
--- a/cmd/diff_target_files/allow_list_test.go
+++ b/cmd/diff_target_files/allow_list_test.go
@@ -58,7 +58,6 @@
 var f2 = bytesToZipArtifactFile("dir/f2", nil)
 
 func Test_applyAllowLists(t *testing.T) {
-	t.Parallel()
 	type args struct {
 		diff       zipDiff
 		allowLists []allowList
diff --git a/cmd/diff_target_files/compare_test.go b/cmd/diff_target_files/compare_test.go
index 7621246..9d3f8a5 100644
--- a/cmd/diff_target_files/compare_test.go
+++ b/cmd/diff_target_files/compare_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestDiffTargetFilesLists(t *testing.T) {
-	t.Parallel()
 	zipArtifactFile := func(name string, crc32 uint32, size uint64) *ZipArtifactFile {
 		return &ZipArtifactFile{
 			File: &zip.File{
diff --git a/cmd/diff_target_files/glob_test.go b/cmd/diff_target_files/glob_test.go
index f2c6c6a..63df68d 100644
--- a/cmd/diff_target_files/glob_test.go
+++ b/cmd/diff_target_files/glob_test.go
@@ -19,7 +19,6 @@
 )
 
 func TestMatch(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		pattern, name string
 		match         bool
diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go
index 40f3882..c3e6a2d 100644
--- a/cmd/extract_apks/main_test.go
+++ b/cmd/extract_apks/main_test.go
@@ -37,7 +37,6 @@
 }
 
 func TestSelectApks_ApkSet(t *testing.T) {
-	t.Parallel()
 	testCases := []testDesc{
 		{
 			protoText: `
@@ -267,7 +266,6 @@
 }
 
 func TestSelectApks_ApexSet(t *testing.T) {
-	t.Parallel()
 	testCases := []testDesc{
 		{
 			protoText: `
@@ -444,7 +442,6 @@
 }
 
 func TestWriteApks(t *testing.T) {
-	t.Parallel()
 	testCases := []testCaseWriteApks{
 		{
 			name:       "splits",
diff --git a/cmd/extract_linker/main_test.go b/cmd/extract_linker/main_test.go
index 4e1ed02..6ac4ec6 100644
--- a/cmd/extract_linker/main_test.go
+++ b/cmd/extract_linker/main_test.go
@@ -51,7 +51,6 @@
 }
 
 func TestBytesToAsm(t *testing.T) {
-	t.Parallel()
 	for _, testcase := range bytesToAsmTestCases {
 		t.Run(testcase.name, func(t *testing.T) {
 			buf := bytes.Buffer{}
diff --git a/cmd/host_bionic_inject/host_bionic_inject_test.go b/cmd/host_bionic_inject/host_bionic_inject_test.go
index ef5120b..b415b34 100644
--- a/cmd/host_bionic_inject/host_bionic_inject_test.go
+++ b/cmd/host_bionic_inject/host_bionic_inject_test.go
@@ -100,7 +100,6 @@
 }
 
 func TestCheckLinker(t *testing.T) {
-	t.Parallel()
 	cases := []struct {
 		name   string
 		err    error
diff --git a/cmd/javac_wrapper/javac_wrapper_test.go b/cmd/javac_wrapper/javac_wrapper_test.go
index a1812fb..ad23001 100644
--- a/cmd/javac_wrapper/javac_wrapper_test.go
+++ b/cmd/javac_wrapper/javac_wrapper_test.go
@@ -93,7 +93,6 @@
 }
 
 func TestJavacColorize(t *testing.T) {
-	t.Parallel()
 	for i, test := range testCases {
 		t.Run(strconv.Itoa(i), func(t *testing.T) {
 			buf := new(bytes.Buffer)
@@ -111,7 +110,6 @@
 }
 
 func TestSubprocess(t *testing.T) {
-	t.Parallel()
 	t.Run("failure", func(t *testing.T) {
 		exitCode, err := Main(ioutil.Discard, "test", []string{"sh", "-c", "exit 9"})
 		if err != nil {
diff --git a/cmd/merge_zips/merge_zips_test.go b/cmd/merge_zips/merge_zips_test.go
index 78ffb76..cb58436 100644
--- a/cmd/merge_zips/merge_zips_test.go
+++ b/cmd/merge_zips/merge_zips_test.go
@@ -85,7 +85,6 @@
 }
 
 func TestMergeZips(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name             string
 		in               [][]testZipEntry
@@ -362,7 +361,6 @@
 }
 
 func TestInputZipsManager(t *testing.T) {
-	t.Parallel()
 	const nInputZips = 20
 	const nMaxOpenZips = 10
 	izm := NewInputZipsManager(20, 10)
diff --git a/cmd/multiproduct_kati/main_test.go b/cmd/multiproduct_kati/main_test.go
index e3ddfd7..263a124 100644
--- a/cmd/multiproduct_kati/main_test.go
+++ b/cmd/multiproduct_kati/main_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestSplitList(t *testing.T) {
-	t.Parallel()
 	testcases := []struct {
 		inputCount int
 		shardCount int
diff --git a/cmd/path_interposer/main_test.go b/cmd/path_interposer/main_test.go
index 3f1a5e1..c89d623 100644
--- a/cmd/path_interposer/main_test.go
+++ b/cmd/path_interposer/main_test.go
@@ -61,7 +61,6 @@
 }
 
 func TestInterposer(t *testing.T) {
-	t.Parallel()
 	interposer := setup(t)
 
 	logConfig := func(name string) paths.PathConfig {
@@ -181,7 +180,6 @@
 }
 
 func TestMissingPath(t *testing.T) {
-	t.Parallel()
 	interposer := setup(t)
 	err := os.Remove(interposer + "_origpath")
 	if err != nil {
diff --git a/cmd/soong_build/bazel_overlay.go b/cmd/soong_build/bazel_overlay.go
index 72e0fbd..cdc5775 100644
--- a/cmd/soong_build/bazel_overlay.go
+++ b/cmd/soong_build/bazel_overlay.go
@@ -31,7 +31,7 @@
 const (
 	// The default `load` preamble for every generated BUILD file.
 	soongModuleLoad = `package(default_visibility = ["//visibility:public"])
-load("//:soong_module.bzl", "soong_module")
+load("//build/bazel/overlay_rules:soong_module.bzl", "soong_module")
 
 `
 
@@ -62,7 +62,7 @@
 	soongModuleBzl = `
 %s
 
-load(":providers.bzl", "SoongModuleInfo")
+load("//build/bazel/overlay_rules:providers.bzl", "SoongModuleInfo")
 
 def _generic_soong_module_impl(ctx):
     return [
@@ -149,31 +149,6 @@
 		"string":      true, // e.g. "a"
 	}
 
-	// TODO(b/166563303): Specific properties of some module types aren't
-	// recognized by the documentation generator. As a workaround, hardcode a
-	// mapping of the module type to prop name to prop type here, and ultimately
-	// fix the documentation generator to also parse these properties correctly.
-	additionalPropTypes = map[string]map[string]string{
-		// sdk and module_exports props are created at runtime using reflection.
-		// bpdocs isn't wired up to read runtime generated structs.
-		"sdk": {
-			"java_header_libs":    "string_list",
-			"java_sdk_libs":       "string_list",
-			"java_system_modules": "string_list",
-			"native_header_libs":  "string_list",
-			"native_libs":         "string_list",
-			"native_objects":      "string_list",
-			"native_shared_libs":  "string_list",
-			"native_static_libs":  "string_list",
-		},
-		"module_exports": {
-			"java_libs":          "string_list",
-			"java_tests":         "string_list",
-			"native_binaries":    "string_list",
-			"native_shared_libs": "string_list",
-		},
-	}
-
 	// Certain module property names are blocklisted/ignored here, for the reasons commented.
 	ignoredPropNames = map[string]bool{
 		"name":       true, // redundant, since this is explicitly generated for every target
@@ -421,7 +396,7 @@
 
 	ruleShims := map[string]RuleShim{}
 	for _, pkg := range packages {
-		content := "load(\":providers.bzl\", \"SoongModuleInfo\")\n"
+		content := "load(\"//build/bazel/overlay_rules:providers.bzl\", \"SoongModuleInfo\")\n"
 
 		bzlFileName := strings.ReplaceAll(pkg.Path, "android/soong/", "")
 		bzlFileName = strings.ReplaceAll(bzlFileName, ".", "_")
@@ -439,8 +414,19 @@
 				attrs += propToAttr(prop, prop.Name)
 			}
 
-			for propName, propType := range additionalPropTypes[moduleTypeTemplate.Name] {
-				attrs += fmt.Sprintf("        %q: attr.%s(),\n", propName, propType)
+			moduleTypeName := moduleTypeTemplate.Name
+
+			// Certain SDK-related module types dynamically inject properties, instead of declaring
+			// them as structs. These properties are registered in an SdkMemberTypesRegistry. If
+			// the module type name matches, add these properties into the rule definition.
+			var registeredTypes []android.SdkMemberType
+			if moduleTypeName == "module_exports" || moduleTypeName == "module_exports_snapshot" {
+				registeredTypes = android.ModuleExportsMemberTypes.RegisteredTypes()
+			} else if moduleTypeName == "sdk" || moduleTypeName == "sdk_snapshot" {
+				registeredTypes = android.SdkMemberTypes.RegisteredTypes()
+			}
+			for _, memberType := range registeredTypes {
+				attrs += fmt.Sprintf("        %q: attr.string_list(),\n", memberType.SdkPropertyName())
 			}
 
 			attrs += "    },"
@@ -466,16 +452,15 @@
 		buildFile.Write([]byte(generateSoongModuleTarget(blueprintCtx, module) + "\n\n"))
 		buildFile.Close()
 	})
+	var err error
 
-	if err := writeReadOnlyFile(bazelOverlayDir, "WORKSPACE", ""); err != nil {
+	// Write top level files: WORKSPACE and BUILD. These files are empty.
+	if err = writeReadOnlyFile(bazelOverlayDir, "WORKSPACE", ""); err != nil {
 		return err
 	}
 
-	if err := writeReadOnlyFile(bazelOverlayDir, "BUILD", ""); err != nil {
-		return err
-	}
-
-	if err := writeReadOnlyFile(bazelOverlayDir, "providers.bzl", providersBzl); err != nil {
+	// Used to denote that the top level directory is a package.
+	if err = writeReadOnlyFile(bazelOverlayDir, "BUILD", ""); err != nil {
 		return err
 	}
 
@@ -488,13 +473,22 @@
 		return err
 	}
 
+	// Write .bzl Starlark files into the bazel_rules top level directory (provider and rule definitions)
+	bazelRulesDir := bazelOverlayDir + "/build/bazel/overlay_rules"
+	if err = writeReadOnlyFile(bazelRulesDir, "BUILD", ""); err != nil {
+		return err
+	}
+	if err = writeReadOnlyFile(bazelRulesDir, "providers.bzl", providersBzl); err != nil {
+		return err
+	}
+
 	for bzlFileName, ruleShim := range ruleShims {
-		if err := writeReadOnlyFile(bazelOverlayDir, bzlFileName+".bzl", ruleShim.content); err != nil {
+		if err = writeReadOnlyFile(bazelRulesDir, bzlFileName+".bzl", ruleShim.content); err != nil {
 			return err
 		}
 	}
 
-	return writeReadOnlyFile(bazelOverlayDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims))
+	return writeReadOnlyFile(bazelRulesDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims))
 }
 
 // Generate the content of soong_module.bzl with the rule shim load statements
@@ -503,7 +497,7 @@
 	var loadStmts string
 	var moduleRuleMap string
 	for bzlFileName, ruleShim := range bzlLoads {
-		loadStmt := "load(\"//:"
+		loadStmt := "load(\"//build/bazel/overlay_rules:"
 		loadStmt += bzlFileName
 		loadStmt += ".bzl\""
 		for _, rule := range ruleShim.rules {
@@ -572,9 +566,7 @@
 func buildFileForModule(ctx *blueprint.Context, module blueprint.Module) (*os.File, error) {
 	// Create nested directories for the BUILD file
 	dirPath := filepath.Join(bazelOverlayDir, packagePath(ctx, module))
-	if _, err := os.Stat(dirPath); os.IsNotExist(err) {
-		os.MkdirAll(dirPath, os.ModePerm)
-	}
+	createDirectoryIfNonexistent(dirPath)
 	// Open the file for appending, and create it if it doesn't exist
 	f, err := os.OpenFile(
 		filepath.Join(dirPath, "BUILD.bazel"),
@@ -596,10 +588,17 @@
 	return f, nil
 }
 
+func createDirectoryIfNonexistent(dir string) {
+	if _, err := os.Stat(dir); os.IsNotExist(err) {
+		os.MkdirAll(dir, os.ModePerm)
+	}
+}
+
 // The overlay directory should be read-only, sufficient for bazel query. The files
 // are not intended to be edited by end users.
 func writeReadOnlyFile(dir string, baseName string, content string) error {
-	pathToFile := filepath.Join(bazelOverlayDir, baseName)
+	createDirectoryIfNonexistent(dir)
+	pathToFile := filepath.Join(dir, baseName)
 	// 0444 is read-only
 	return ioutil.WriteFile(pathToFile, []byte(content), 0444)
 }
diff --git a/cmd/soong_build/bazel_overlay_test.go b/cmd/soong_build/bazel_overlay_test.go
index ceb342f..de060bb 100644
--- a/cmd/soong_build/bazel_overlay_test.go
+++ b/cmd/soong_build/bazel_overlay_test.go
@@ -64,7 +64,6 @@
 }
 
 func TestGenerateBazelOverlayFromBlueprint(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		bp                  string
 		expectedBazelTarget string
@@ -363,7 +362,7 @@
 		}
 	}
 
-	expectedBzl := `load(":providers.bzl", "SoongModuleInfo")
+	expectedBzl := `load("//build/bazel/overlay_rules:providers.bzl", "SoongModuleInfo")
 
 def _foo_binary_impl(ctx):
     return [SoongModuleInfo()]
@@ -441,7 +440,7 @@
 	}
 	actualSoongModuleBzl := generateSoongModuleBzl(ruleShims)
 
-	expectedLoad := "load(\"//:foo.bzl\", \"foo_binary\", \"foo_library\", \"foo_test_\")"
+	expectedLoad := "load(\"//build/bazel/overlay_rules:foo.bzl\", \"foo_binary\", \"foo_library\", \"foo_test_\")"
 	expectedRuleMap := `soong_module_rule_map = {
     "foo_binary": foo_binary,
     "foo_library": foo_library,
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 01a39a2..7ae1c37 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -51,30 +51,34 @@
 	return android.NewNameResolver(exportFilter)
 }
 
+func newContext(srcDir string, configuration android.Config) *android.Context {
+	ctx := android.NewContext()
+	ctx.Register()
+	if !shouldPrepareBuildActions() {
+		configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
+	}
+	ctx.SetNameInterface(newNameResolver(configuration))
+	ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
+	return ctx
+}
+
+func newConfig(srcDir string) android.Config {
+	configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir, bootstrap.ModuleListFile)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "%s", err)
+		os.Exit(1)
+	}
+	return configuration
+}
+
 func main() {
 	android.ReexecWithDelveMaybe()
 	flag.Parse()
 
 	// The top-level Blueprints file is passed as the first argument.
 	srcDir := filepath.Dir(flag.Arg(0))
-
-	ctx := android.NewContext()
-	ctx.Register()
-
-	configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir, bootstrap.ModuleListFile)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "%s", err)
-		os.Exit(1)
-	}
-
-	if !shouldPrepareBuildActions() {
-		configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
-	}
-
-	ctx.SetNameInterface(newNameResolver(configuration))
-
-	ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
-
+	var ctx *android.Context
+	configuration := newConfig(srcDir)
 	extraNinjaDeps := []string{configuration.ConfigFileName, configuration.ProductVariablesFileName}
 
 	// Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
@@ -84,9 +88,31 @@
 		// enabled even if it completed successfully.
 		extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
 	}
-
-	bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
-
+	if configuration.BazelContext.BazelEnabled() {
+		// Bazel-enabled mode. Soong runs in two passes.
+		// First pass: Analyze the build tree, but only store all bazel commands
+		// needed to correctly evaluate the tree in the second pass.
+		// TODO(cparsons): Don't output any ninja file, as the second pass will overwrite
+		// the incorrect results from the first pass, and file I/O is expensive.
+		firstCtx := newContext(srcDir, configuration)
+		bootstrap.Main(firstCtx.Context, configuration, extraNinjaDeps...)
+		// Invoke bazel commands and save results for second pass.
+		if err := configuration.BazelContext.InvokeBazel(); err != nil {
+			fmt.Fprintf(os.Stderr, "%s", err)
+			os.Exit(1)
+		}
+		// Second pass: Full analysis, using the bazel command results. Output ninja file.
+		secondPassConfig, err := android.ConfigForAdditionalRun(configuration)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "%s", err)
+			os.Exit(1)
+		}
+		ctx = newContext(srcDir, secondPassConfig)
+		bootstrap.Main(ctx.Context, secondPassConfig, extraNinjaDeps...)
+	} else {
+		ctx = newContext(srcDir, configuration)
+		bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
+	}
 	if bazelOverlayDir != "" {
 		if err := createBazelOverlay(ctx, bazelOverlayDir); err != nil {
 			fmt.Fprintf(os.Stderr, "%s", err)
@@ -105,7 +131,7 @@
 	//  to affect the command line of the primary builder.
 	if shouldPrepareBuildActions() {
 		metricsFile := filepath.Join(bootstrap.BuildDir, "soong_build_metrics.pb")
-		err = android.WriteMetrics(configuration, metricsFile)
+		err := android.WriteMetrics(configuration, metricsFile)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err)
 			os.Exit(1)
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 69e4f69..774a872 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -119,9 +119,9 @@
 func main() {
 	buildStarted := time.Now()
 
-	c, args := getCommand(os.Args)
-	if c == nil {
-		fmt.Fprintf(os.Stderr, "The `soong` native UI is not yet available.\n")
+	c, args, err := getCommand(os.Args)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Error parsing `soong` args: %s.\n", err)
 		os.Exit(1)
 	}
 
@@ -173,6 +173,7 @@
 	rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
 	soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
 	defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile)
+	build.PrintOutDirWarning(buildCtx, config)
 
 	os.MkdirAll(logsDir, 0777)
 	log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
@@ -478,14 +479,14 @@
 
 // getCommand finds the appropriate command based on args[1] flag. args[0]
 // is the soong_ui filename.
-func getCommand(args []string) (*command, []string) {
+func getCommand(args []string) (*command, []string, error) {
 	if len(args) < 2 {
-		return nil, args
+		return nil, nil, fmt.Errorf("Too few arguments: %q", args)
 	}
 
 	for _, c := range commands {
 		if c.flag == args[1] {
-			return &c, args[2:]
+			return &c, args[2:], nil
 		}
 
 		// special case for --make-mode: if soong_ui was called from
@@ -494,11 +495,11 @@
 		// TODO: Remove this hack once it has been fixed.
 		if c.flag == makeModeFlagName {
 			if inList(makeModeFlagName, args) {
-				return &c, args[1:]
+				return &c, args[1:], nil
 			}
 		}
 	}
 
 	// command not found
-	return nil, args
+	return nil, nil, fmt.Errorf("Command not found: %q", args)
 }
diff --git a/cmd/zip2zip/zip2zip_test.go b/cmd/zip2zip/zip2zip_test.go
index e6ac0bf..2c4e005 100644
--- a/cmd/zip2zip/zip2zip_test.go
+++ b/cmd/zip2zip/zip2zip_test.go
@@ -416,7 +416,6 @@
 }
 
 func TestZip2Zip(t *testing.T) {
-	t.Parallel()
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {
 			inputBuf := &bytes.Buffer{}
@@ -473,7 +472,6 @@
 }
 
 func TestConstantPartOfPattern(t *testing.T) {
-	t.Parallel()
 	testCases := []struct{ in, out string }{
 		{
 			in:  "",
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 1fbd7f1..ec31549 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -61,7 +61,6 @@
 }
 
 func TestDexPreopt(t *testing.T) {
-	t.Parallel()
 	config := android.TestConfig("out", nil, "", nil)
 	ctx := android.PathContextForTesting(config)
 	globalSoong := GlobalSoongConfigForTests(config)
@@ -84,7 +83,6 @@
 }
 
 func TestDexPreoptSystemOther(t *testing.T) {
-	t.Parallel()
 	config := android.TestConfig("out", nil, "", nil)
 	ctx := android.PathContextForTesting(config)
 	globalSoong := GlobalSoongConfigForTests(config)
@@ -145,7 +143,6 @@
 }
 
 func TestDexPreoptProfile(t *testing.T) {
-	t.Parallel()
 	config := android.TestConfig("out", nil, "", nil)
 	ctx := android.PathContextForTesting(config)
 	globalSoong := GlobalSoongConfigForTests(config)
diff --git a/docs/OWNERS b/docs/OWNERS
new file mode 100644
index 0000000..d143317
--- /dev/null
+++ b/docs/OWNERS
@@ -0,0 +1 @@
+per-file map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 8e35679..664cb51 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -214,6 +214,13 @@
 		Output: p.outputFilePath,
 		Input:  p.sourceFilePath,
 	})
+
+	if p.Installable() {
+		installPath := ctx.InstallFile(p.installDirPath, p.outputFilePath.Base(), p.outputFilePath)
+		for _, sl := range p.properties.Symlinks {
+			ctx.InstallSymlink(p.installDirPath, sl, installPath)
+		}
+	}
 }
 
 func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index 528c484..8fc36c2 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -102,7 +102,6 @@
 	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
 }
 func TestPrebuiltEtcVariants(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testPrebuiltEtc(t, `
 		prebuilt_etc {
 			name: "foo.conf",
@@ -137,7 +136,6 @@
 }
 
 func TestPrebuiltEtcOutputPath(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testPrebuiltEtc(t, `
 		prebuilt_etc {
 			name: "foo.conf",
@@ -153,7 +151,6 @@
 }
 
 func TestPrebuiltEtcGlob(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testPrebuiltEtc(t, `
 		prebuilt_etc {
 			name: "my_foo",
@@ -178,7 +175,6 @@
 }
 
 func TestPrebuiltEtcAndroidMk(t *testing.T) {
-	t.Parallel()
 	ctx, config := testPrebuiltEtc(t, `
 		prebuilt_etc {
 			name: "foo",
@@ -215,7 +211,6 @@
 }
 
 func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testPrebuiltEtc(t, `
 		prebuilt_etc {
 			name: "foo.conf",
@@ -232,7 +227,6 @@
 }
 
 func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) {
-	t.Parallel()
 	testPrebuiltEtcError(t, "relative_install_path is set. Cannot set sub_dir", `
 		prebuilt_etc {
 			name: "foo.conf",
@@ -244,7 +238,6 @@
 }
 
 func TestPrebuiltEtcHost(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testPrebuiltEtc(t, `
 		prebuilt_etc_host {
 			name: "foo.conf",
@@ -260,7 +253,6 @@
 }
 
 func TestPrebuiltUserShareInstallDirPath(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testPrebuiltEtc(t, `
 		prebuilt_usr_share {
 			name: "foo.conf",
@@ -277,7 +269,6 @@
 }
 
 func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) {
-	t.Parallel()
 	ctx, config := testPrebuiltEtc(t, `
 		prebuilt_usr_share_host {
 			name: "foo.conf",
@@ -295,7 +286,6 @@
 }
 
 func TestPrebuiltFontInstallDirPath(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testPrebuiltEtc(t, `
 		prebuilt_font {
 			name: "foo.conf",
@@ -311,7 +301,6 @@
 }
 
 func TestPrebuiltFirmwareDirPath(t *testing.T) {
-	t.Parallel()
 	targetPath := buildDir + "/target/product/test_device"
 	tests := []struct {
 		description  string
@@ -348,7 +337,6 @@
 }
 
 func TestPrebuiltDSPDirPath(t *testing.T) {
-	t.Parallel()
 	targetPath := filepath.Join(buildDir, "/target/product/test_device")
 	tests := []struct {
 		description  string
diff --git a/finder/finder.go b/finder/finder.go
index 6513fa3..5413fa6 100644
--- a/finder/finder.go
+++ b/finder/finder.go
@@ -103,6 +103,9 @@
 
 	// IncludeFiles are file names to include as matches
 	IncludeFiles []string
+
+	// IncludeSuffixes are filename suffixes to include as matches.
+	IncludeSuffixes []string
 }
 
 // a cacheConfig stores the inputs that determine what should be included in the cache
@@ -1310,6 +1313,20 @@
 	return stats
 }
 
+func (f *Finder) shouldIncludeFile(fileName string) bool {
+	for _, includedName := range f.cacheMetadata.Config.IncludeFiles {
+		if fileName == includedName {
+			return true
+		}
+	}
+	for _, includeSuffix := range f.cacheMetadata.Config.IncludeSuffixes {
+		if strings.HasSuffix(fileName, includeSuffix) {
+			return true
+		}
+	}
+	return false
+}
+
 // pruneCacheCandidates removes the items that we don't want to include in our persistent cache
 func (f *Finder) pruneCacheCandidates(items *DirEntries) {
 
@@ -1326,13 +1343,9 @@
 	// remove any files that aren't the ones we want to include
 	writeIndex := 0
 	for _, fileName := range items.FileNames {
-		// include only these files
-		for _, includedName := range f.cacheMetadata.Config.IncludeFiles {
-			if fileName == includedName {
-				items.FileNames[writeIndex] = fileName
-				writeIndex++
-				break
-			}
+		if f.shouldIncludeFile(fileName) {
+			items.FileNames[writeIndex] = fileName
+			writeIndex++
 		}
 	}
 	// resize
diff --git a/finder/finder_test.go b/finder/finder_test.go
index 029c80f..788dbdd 100644
--- a/finder/finder_test.go
+++ b/finder/finder_test.go
@@ -21,6 +21,7 @@
 	"os"
 	"path/filepath"
 	"sort"
+	"strings"
 	"testing"
 
 	"android/soong/finder/fs"
@@ -92,6 +93,7 @@
 			nil,
 			nil,
 			[]string{"findme.txt", "skipme.txt"},
+			nil,
 		},
 	)
 	defer finder.Shutdown()
@@ -104,6 +106,46 @@
 	fs.AssertSameResponse(t, foundPaths, absoluteMatches)
 }
 
+// runTestWithSuffixes creates a few files, searches for findme.txt or any file
+// with suffix `.findme_ext` and checks for the expected matches
+func runTestWithSuffixes(t *testing.T, existentPaths []string, expectedMatches []string) {
+	filesystem := newFs()
+	root := "/tmp"
+	filesystem.MkDirs(root)
+	for _, path := range existentPaths {
+		fs.Create(t, filepath.Join(root, path), filesystem)
+	}
+
+	finder := newFinder(t,
+		filesystem,
+		CacheParams{
+			"/cwd",
+			[]string{root},
+			nil,
+			nil,
+			[]string{"findme.txt", "skipme.txt"},
+			[]string{".findme_ext"},
+		},
+	)
+	defer finder.Shutdown()
+
+	foundPaths := finder.FindMatching(root,
+		func(entries DirEntries) (dirs []string, files []string) {
+			matches := []string{}
+			for _, foundName := range entries.FileNames {
+				if foundName == "findme.txt" || strings.HasSuffix(foundName, ".findme_ext") {
+					matches = append(matches, foundName)
+				}
+			}
+			return entries.DirNames, matches
+		})
+	absoluteMatches := []string{}
+	for i := range expectedMatches {
+		absoluteMatches = append(absoluteMatches, filepath.Join(root, expectedMatches[i]))
+	}
+	fs.AssertSameResponse(t, foundPaths, absoluteMatches)
+}
+
 // testAgainstSeveralThreadcounts runs the given test for each threadcount that we care to test
 func testAgainstSeveralThreadcounts(t *testing.T, tester func(t *testing.T, numThreads int)) {
 	// test singlethreaded, multithreaded, and also using the same number of threads as
@@ -122,7 +164,6 @@
 // end of utils, start of individual tests
 
 func TestSingleFile(t *testing.T) {
-	t.Parallel()
 	runSimpleTest(t,
 		[]string{"findme.txt"},
 		[]string{"findme.txt"},
@@ -130,23 +171,34 @@
 }
 
 func TestIncludeFiles(t *testing.T) {
-	t.Parallel()
 	runSimpleTest(t,
 		[]string{"findme.txt", "skipme.txt"},
 		[]string{"findme.txt"},
 	)
 }
 
+func TestIncludeFilesAndSuffixes(t *testing.T) {
+	runTestWithSuffixes(t,
+		[]string{"findme.txt", "skipme.txt", "alsome.findme_ext"},
+		[]string{"findme.txt", "alsome.findme_ext"},
+	)
+}
+
 func TestNestedDirectories(t *testing.T) {
-	t.Parallel()
 	runSimpleTest(t,
 		[]string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt"},
 		[]string{"findme.txt", "subdir/findme.txt"},
 	)
 }
 
+func TestNestedDirectoriesWithSuffixes(t *testing.T) {
+	runTestWithSuffixes(t,
+		[]string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt", "subdir/alsome.findme_ext"},
+		[]string{"findme.txt", "subdir/findme.txt", "subdir/alsome.findme_ext"},
+	)
+}
+
 func TestEmptyDirectory(t *testing.T) {
-	t.Parallel()
 	runSimpleTest(t,
 		[]string{},
 		[]string{},
@@ -154,7 +206,6 @@
 }
 
 func TestEmptyPath(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 	root := "/tmp"
 	fs.Create(t, filepath.Join(root, "findme.txt"), filesystem)
@@ -175,7 +226,6 @@
 }
 
 func TestFilesystemRoot(t *testing.T) {
-	t.Parallel()
 
 	testWithNumThreads := func(t *testing.T, numThreads int) {
 		filesystem := newFs()
@@ -203,7 +253,6 @@
 }
 
 func TestNonexistentDir(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 	fs.Create(t, "/tmp/findme.txt", filesystem)
 
@@ -222,7 +271,6 @@
 }
 
 func TestExcludeDirs(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 	fs.Create(t, "/tmp/exclude/findme.txt", filesystem)
 	fs.Create(t, "/tmp/exclude/subdir/findme.txt", filesystem)
@@ -251,7 +299,6 @@
 }
 
 func TestPruneFiles(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 	fs.Create(t, "/tmp/out/findme.txt", filesystem)
 	fs.Create(t, "/tmp/out/.ignore-out-dir", filesystem)
@@ -284,7 +331,6 @@
 // TestRootDir tests that the value of RootDirs is used
 // tests of the filesystem root are in TestFilesystemRoot
 func TestRootDir(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 	fs.Create(t, "/tmp/a/findme.txt", filesystem)
 	fs.Create(t, "/tmp/a/subdir/findme.txt", filesystem)
@@ -309,7 +355,6 @@
 }
 
 func TestUncachedDir(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 	fs.Create(t, "/tmp/a/findme.txt", filesystem)
 	fs.Create(t, "/tmp/a/subdir/findme.txt", filesystem)
@@ -337,7 +382,6 @@
 }
 
 func TestSearchingForFilesExcludedFromCache(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -365,7 +409,6 @@
 }
 
 func TestRelativeFilePaths(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 
 	fs.Create(t, "/tmp/ignore/hi.txt", filesystem)
@@ -410,7 +453,6 @@
 // have to run this test with the race-detector (`go test -race src/android/soong/finder/*.go`)
 // for there to be much chance of the test actually detecting any error that may be present
 func TestRootDirsContainedInOtherRootDirs(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 
 	fs.Create(t, "/tmp/a/b/c/d/e/f/g/h/i/j/findme.txt", filesystem)
@@ -432,7 +474,6 @@
 }
 
 func TestFindFirst(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 	fs.Create(t, "/tmp/a/hi.txt", filesystem)
 	fs.Create(t, "/tmp/b/hi.txt", filesystem)
@@ -457,7 +498,6 @@
 }
 
 func TestConcurrentFindSameDirectory(t *testing.T) {
-	t.Parallel()
 
 	testWithNumThreads := func(t *testing.T, numThreads int) {
 		filesystem := newFs()
@@ -509,7 +549,6 @@
 }
 
 func TestConcurrentFindDifferentDirectories(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 
 	// create a bunch of files and directories
@@ -573,7 +612,6 @@
 }
 
 func TestStrangelyFormattedPaths(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -599,7 +637,6 @@
 }
 
 func TestCorruptedCacheHeader(t *testing.T) {
-	t.Parallel()
 	filesystem := newFs()
 
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -624,7 +661,6 @@
 }
 
 func TestCanUseCache(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -671,7 +707,6 @@
 }
 
 func TestCorruptedCacheBody(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -736,7 +771,6 @@
 }
 
 func TestStatCalls(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/a/findme.txt", filesystem)
@@ -760,7 +794,6 @@
 }
 
 func TestFileAdded(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/ignoreme.txt", filesystem)
@@ -803,7 +836,6 @@
 }
 
 func TestDirectoriesAdded(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/ignoreme.txt", filesystem)
@@ -848,7 +880,6 @@
 }
 
 func TestDirectoryAndSubdirectoryBothUpdated(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/hi1.txt", filesystem)
@@ -889,7 +920,6 @@
 }
 
 func TestFileDeleted(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/ignoreme.txt", filesystem)
@@ -930,7 +960,6 @@
 }
 
 func TestDirectoriesDeleted(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -986,7 +1015,6 @@
 }
 
 func TestDirectoriesMoved(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -1045,7 +1073,6 @@
 }
 
 func TestDirectoriesSwapped(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -1161,7 +1188,6 @@
 }
 
 func TestChangeOfDevice(t *testing.T) {
-	t.Parallel()
 	fs1 := newFs()
 	// not as fine-grained mounting controls as a real filesystem, but should be adequate
 	fs1.SetDeviceNumber(0)
@@ -1173,7 +1199,6 @@
 }
 
 func TestChangeOfUserOrHost(t *testing.T) {
-	t.Parallel()
 	fs1 := newFs()
 	fs1.SetViewId("me@here")
 
@@ -1184,7 +1209,6 @@
 }
 
 func TestConsistentCacheOrdering(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	for i := 0; i < 5; i++ {
@@ -1237,7 +1261,6 @@
 }
 
 func TestNumSyscallsOfSecondFind(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -1268,7 +1291,6 @@
 }
 
 func TestChangingParamsOfSecondFind(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/findme.txt", filesystem)
@@ -1299,7 +1321,6 @@
 }
 
 func TestSymlinkPointingToFile(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/a/hi.txt", filesystem)
@@ -1336,7 +1357,6 @@
 }
 
 func TestSymlinkPointingToDirectory(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/dir/hi.txt", filesystem)
@@ -1371,7 +1391,6 @@
 // TestAddPruneFile confirms that adding a prune-file (into a directory for which we
 // already had a cache) causes the directory to be ignored
 func TestAddPruneFile(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/out/hi.txt", filesystem)
@@ -1410,7 +1429,6 @@
 }
 
 func TestUpdatingDbIffChanged(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/a/hi.txt", filesystem)
@@ -1470,7 +1488,6 @@
 }
 
 func TestDirectoryNotPermitted(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/hi.txt", filesystem)
@@ -1519,7 +1536,6 @@
 }
 
 func TestFileNotPermitted(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/hi.txt", filesystem)
@@ -1542,7 +1558,6 @@
 }
 
 func TestCacheEntryPathUnexpectedError(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := newFs()
 	fs.Create(t, "/tmp/a/hi.txt", filesystem)
diff --git a/finder/fs/fs_test.go b/finder/fs/fs_test.go
index 5671bcf..22a4d7a 100644
--- a/finder/fs/fs_test.go
+++ b/finder/fs/fs_test.go
@@ -20,7 +20,6 @@
 )
 
 func TestMockFs_LstatStatSymlinks(t *testing.T) {
-	t.Parallel()
 	// setup filesystem
 	filesystem := NewMockFs(nil)
 	Create(t, "/tmp/realdir/hi.txt", filesystem)
diff --git a/finder/fs/readdir_test.go b/finder/fs/readdir_test.go
index d133bba..24a6d18 100644
--- a/finder/fs/readdir_test.go
+++ b/finder/fs/readdir_test.go
@@ -22,7 +22,6 @@
 )
 
 func TestParseDirent(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name string
 		in   []byte
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 4a2f810..99d6207 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -81,6 +81,12 @@
 	label string
 }
 
+// TODO(cparsons): Move to a common location when there is more than just
+// genrule with a bazel_module property.
+type bazelModuleProperties struct {
+	Label string
+}
+
 type generatorProperties struct {
 	// The command to run on one or more input files. Cmd supports substitution of a few variables
 	//
@@ -113,8 +119,10 @@
 
 	// input files to exclude
 	Exclude_srcs []string `android:"path,arch_variant"`
-}
 
+	// in bazel-enabled mode, the bazel label to evaluate instead of this module
+	Bazel_module bazelModuleProperties
+}
 type Module struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
@@ -186,6 +194,20 @@
 	}
 }
 
+// Returns true if information was available from Bazel, false if bazel invocation still needs to occur.
+func (c *Module) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+	bazelCtx := ctx.Config().BazelContext
+	filePaths, ok := bazelCtx.GetAllFiles(label)
+	if ok {
+		var bazelOutputFiles android.Paths
+		for _, bazelOutputFile := range filePaths {
+			bazelOutputFiles = append(bazelOutputFiles, android.PathForSource(ctx, bazelOutputFile))
+		}
+		c.outputFiles = bazelOutputFiles
+		c.outputDeps = bazelOutputFiles
+	}
+	return ok
+}
 func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	g.subName = ctx.ModuleSubDir()
 
@@ -456,26 +478,29 @@
 
 	g.outputFiles = outputFiles.Paths()
 
-	// For <= 6 outputs, just embed those directly in the users. Right now, that covers >90% of
-	// the genrules on AOSP. That will make things simpler to look at the graph in the common
-	// case. For larger sets of outputs, inject a phony target in between to limit ninja file
-	// growth.
-	if len(g.outputFiles) <= 6 {
-		g.outputDeps = g.outputFiles
-	} else {
-		phonyFile := android.PathForModuleGen(ctx, "genrule-phony")
-
-		ctx.Build(pctx, android.BuildParams{
-			Rule:   blueprint.Phony,
-			Output: phonyFile,
-			Inputs: g.outputFiles,
-		})
-
-		g.outputDeps = android.Paths{phonyFile}
+	bazelModuleLabel := g.properties.Bazel_module.Label
+	bazelActionsUsed := false
+	if ctx.Config().BazelContext.BazelEnabled() && len(bazelModuleLabel) > 0 {
+		bazelActionsUsed = g.generateBazelBuildActions(ctx, bazelModuleLabel)
 	}
-
+	if !bazelActionsUsed {
+		// For <= 6 outputs, just embed those directly in the users. Right now, that covers >90% of
+		// the genrules on AOSP. That will make things simpler to look at the graph in the common
+		// case. For larger sets of outputs, inject a phony target in between to limit ninja file
+		// growth.
+		if len(g.outputFiles) <= 6 {
+			g.outputDeps = g.outputFiles
+		} else {
+			phonyFile := android.PathForModuleGen(ctx, "genrule-phony")
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   blueprint.Phony,
+				Output: phonyFile,
+				Inputs: g.outputFiles,
+			})
+			g.outputDeps = android.Paths{phonyFile}
+		}
+	}
 }
-
 func hashSrcFiles(srcFiles android.Paths) string {
 	h := sha256.New()
 	for _, src := range srcFiles {
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 66bb221..fdbb9d9 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -125,7 +125,6 @@
 }
 
 func TestGenruleCmd(t *testing.T) {
-	t.Parallel()
 	testcases := []struct {
 		name string
 		prop string
@@ -504,7 +503,6 @@
 }
 
 func TestGenruleHashInputs(t *testing.T) {
-	t.Parallel()
 
 	// The basic idea here is to verify that the sbox command (which is
 	// in the Command field of the generate rule) contains a hash of the
@@ -592,7 +590,6 @@
 }
 
 func TestGenSrcs(t *testing.T) {
-	t.Parallel()
 	testcases := []struct {
 		name string
 		prop string
@@ -685,7 +682,6 @@
 }
 
 func TestGenruleDefaults(t *testing.T) {
-	t.Parallel()
 	bp := `
 				genrule_defaults {
 					name: "gen_defaults1",
@@ -725,6 +721,39 @@
 	}
 }
 
+func TestGenruleWithBazel(t *testing.T) {
+	bp := `
+		genrule {
+				name: "foo",
+				out: ["one.txt", "two.txt"],
+				bazel_module: { label: "//foo/bar:bar" },
+		}
+	`
+
+	config := testConfig(bp, nil)
+	config.BazelContext = android.MockBazelContext{
+		AllFiles: map[string][]string{
+			"//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
+
+	ctx := testContext(config)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	if errs == nil {
+		_, errs = ctx.PrepareBuildActions(config)
+	}
+	if errs != nil {
+		t.Fatal(errs)
+	}
+	gen := ctx.ModuleForTests("foo", "").Module().(*Module)
+
+	expectedOutputFiles := []string{"bazelone.txt", "bazeltwo.txt"}
+	if !reflect.DeepEqual(gen.outputFiles.Strings(), expectedOutputFiles) {
+		t.Errorf("Expected output files: %q, actual: %q", expectedOutputFiles, gen.outputFiles)
+	}
+	if !reflect.DeepEqual(gen.outputDeps.Strings(), expectedOutputFiles) {
+		t.Errorf("Expected output deps: %q, actual: %q", expectedOutputFiles, gen.outputDeps)
+	}
+}
+
 type testTool struct {
 	android.ModuleBase
 	outputFile android.Path
diff --git a/jar/jar_test.go b/jar/jar_test.go
index f1c799b..c92011e 100644
--- a/jar/jar_test.go
+++ b/jar/jar_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestGetJavaPackage(t *testing.T) {
-	t.Parallel()
 	type args struct {
 		r   io.Reader
 		src string
@@ -79,7 +78,6 @@
 }
 
 func Test_javaIdentRune(t *testing.T) {
-	t.Parallel()
 	// runes that should be valid anywhere in an identifier
 	validAnywhere := []rune{
 		// letters, $, _
diff --git a/java/aar.go b/java/aar.go
index 8d2a74a..f1f6848 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -34,10 +34,16 @@
 	ExportedStaticPackages() android.Paths
 	ExportedManifests() android.Paths
 	ExportedAssets() android.OptionalPath
+	SetRROEnforcedForDependent(enforce bool)
+	IsRROEnforced(ctx android.BaseModuleContext) bool
 }
 
 func init() {
 	RegisterAARBuildComponents(android.InitRegistrationContext)
+
+	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
+	})
 }
 
 func RegisterAARBuildComponents(ctx android.RegistrationContext) {
@@ -82,6 +88,9 @@
 
 	// do not include AndroidManifest from dependent libraries
 	Dont_merge_manifests *bool
+
+	// true if RRO is enforced for any of the dependent modules
+	RROEnforcedForDependent bool `blueprint:"mutated"`
 }
 
 type aapt struct {
@@ -117,6 +126,18 @@
 	path   android.Path
 }
 
+// Propagate RRO enforcement flag to static lib dependencies transitively.
+func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) {
+	m := ctx.Module()
+	if d, ok := m.(AndroidLibraryDependency); ok && d.IsRROEnforced(ctx) {
+		ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
+			if a, ok := d.(AndroidLibraryDependency); ok {
+				a.SetRROEnforcedForDependent(true)
+			}
+		})
+	}
+}
+
 func (a *aapt) ExportPackage() android.Path {
 	return a.exportPackage
 }
@@ -133,6 +154,17 @@
 	return a.assetPackage
 }
 
+func (a *aapt) SetRROEnforcedForDependent(enforce bool) {
+	a.aaptProperties.RROEnforcedForDependent = enforce
+}
+
+func (a *aapt) IsRROEnforced(ctx android.BaseModuleContext) bool {
+	// True if RRO is enforced for this module or...
+	return ctx.Config().EnforceRROForModule(ctx.ModuleName()) ||
+		// if RRO is enforced for any of its dependents, and this module is not exempted.
+		(a.aaptProperties.RROEnforcedForDependent && !ctx.Config().EnforceRROExemptedForModule(ctx.ModuleName()))
+}
+
 func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
 	manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
 	resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
@@ -156,7 +188,7 @@
 			dir:   dir,
 			files: androidResourceGlob(ctx, dir),
 		})
-		resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir)
+		resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, a, dir)
 		overlayDirs = append(overlayDirs, resOverlayDirs...)
 		rroDirs = append(rroDirs, resRRODirs...)
 	}
@@ -412,14 +444,16 @@
 					assets = append(assets, aarDep.ExportedAssets().Path())
 				}
 
-			outer:
-				for _, d := range aarDep.ExportedRRODirs() {
-					for _, e := range staticRRODirs {
-						if d.path == e.path {
-							continue outer
+				if !ctx.Config().EnforceRROExemptedForModule(ctx.ModuleName()) {
+				outer:
+					for _, d := range aarDep.ExportedRRODirs() {
+						for _, e := range staticRRODirs {
+							if d.path == e.path {
+								continue outer
+							}
 						}
+						staticRRODirs = append(staticRRODirs, d)
 					}
-					staticRRODirs = append(staticRRODirs, d)
 				}
 			}
 		}
@@ -573,6 +607,22 @@
 	exportedStaticPackages android.Paths
 
 	hideApexVariantFromMake bool
+
+	aarPath android.Path
+}
+
+var _ android.OutputFileProducer = (*AARImport)(nil)
+
+// For OutputFileProducer interface
+func (a *AARImport) OutputFiles(tag string) (android.Paths, error) {
+	switch tag {
+	case ".aar":
+		return []android.Path{a.aarPath}, nil
+	case "":
+		return []android.Path{a.classpathFile}, nil
+	default:
+		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+	}
 }
 
 func (a *AARImport) sdkVersion() sdkSpec {
@@ -625,6 +675,17 @@
 	return android.OptionalPath{}
 }
 
+// RRO enforcement is not available on aar_import since its RRO dirs are not
+// exported.
+func (a *AARImport) SetRROEnforcedForDependent(enforce bool) {
+}
+
+// RRO enforcement is not available on aar_import since its RRO dirs are not
+// exported.
+func (a *AARImport) IsRROEnforced(ctx android.BaseModuleContext) bool {
+	return false
+}
+
 func (a *AARImport) Prebuilt() *android.Prebuilt {
 	return &a.prebuilt
 }
@@ -669,12 +730,12 @@
 	a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
 
 	aarName := ctx.ModuleName() + ".aar"
-	var aar android.Path
-	aar = android.PathForModuleSrc(ctx, a.properties.Aars[0])
+	a.aarPath = android.PathForModuleSrc(ctx, a.properties.Aars[0])
+
 	if Bool(a.properties.Jetifier) {
-		inputFile := aar
-		aar = android.PathForModuleOut(ctx, "jetifier", aarName)
-		TransformJetifier(ctx, aar.(android.WritablePath), inputFile)
+		inputFile := a.aarPath
+		a.aarPath = android.PathForModuleOut(ctx, "jetifier", aarName)
+		TransformJetifier(ctx, a.aarPath.(android.WritablePath), inputFile)
 	}
 
 	extractedAARDir := android.PathForModuleOut(ctx, "aar")
@@ -684,7 +745,7 @@
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        unzipAAR,
-		Input:       aar,
+		Input:       a.aarPath,
 		Outputs:     android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest},
 		Description: "unzip AAR",
 		Args: map[string]string{
@@ -698,7 +759,7 @@
 	compileFlags := []string{"--pseudo-localize"}
 	compiledResDir := android.PathForModuleOut(ctx, "flat-res")
 	flata := compiledResDir.Join(ctx, "gen_res.flata")
-	aapt2CompileZip(ctx, flata, aar, "res", compileFlags)
+	aapt2CompileZip(ctx, flata, a.aarPath, "res", compileFlags)
 
 	a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
 	// the subdir "android" is required to be filtered by package names
diff --git a/java/android_resources.go b/java/android_resources.go
index c2bc746..97f7679 100644
--- a/java/android_resources.go
+++ b/java/android_resources.go
@@ -66,13 +66,13 @@
 	files android.Paths
 }
 
-func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) (res []globbedResourceDir,
+func overlayResourceGlob(ctx android.ModuleContext, a *aapt, dir android.Path) (res []globbedResourceDir,
 	rroDirs []rroDir) {
 
 	overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
 
 	// Runtime resource overlays (RRO) may be turned on by the product config for some modules
-	rroEnabled := ctx.Config().EnforceRROForModule(ctx.ModuleName())
+	rroEnabled := a.IsRROEnforced(ctx)
 
 	for _, data := range overlayData {
 		files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
diff --git a/java/androidmk.go b/java/androidmk.go
index f72ee37..c21c83a 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -549,9 +549,6 @@
 				if dstubs.annotationsZip != nil {
 					entries.SetPath("LOCAL_DROIDDOC_ANNOTATIONS_ZIP", dstubs.annotationsZip)
 				}
-				if dstubs.jdiffDocZip != nil {
-					entries.SetPath("LOCAL_DROIDDOC_JDIFF_DOC_ZIP", dstubs.jdiffDocZip)
-				}
 				if dstubs.metadataZip != nil {
 					entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.metadataZip)
 				}
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 359d8d7..075b7aa 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -23,7 +23,6 @@
 )
 
 func TestRequired(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_library {
 			name: "foo",
@@ -43,7 +42,6 @@
 }
 
 func TestHostdex(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_library {
 			name: "foo",
@@ -74,7 +72,6 @@
 }
 
 func TestHostdexRequired(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_library {
 			name: "foo",
@@ -106,7 +103,6 @@
 }
 
 func TestHostdexSpecificRequired(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_library {
 			name: "foo",
@@ -140,7 +136,6 @@
 }
 
 func TestDistWithTag(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_library {
 			name: "foo_without_tag",
@@ -177,7 +172,6 @@
 }
 
 func TestDistWithDest(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_library {
 			name: "foo",
@@ -214,7 +208,6 @@
 }
 
 func TestDistsWithAllProperties(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_library {
 			name: "foo",
@@ -272,7 +265,6 @@
 }
 
 func TestDistsWithTag(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_library {
 			name: "foo_without_tag",
@@ -320,7 +312,6 @@
 }
 
 func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_sdk_library {
 			name: "foo-shared_library",
diff --git a/java/app.go b/java/app.go
index c25835c..46ca969 100755
--- a/java/app.go
+++ b/java/app.go
@@ -379,7 +379,6 @@
 			"can only be set for modules that set sdk_version")
 	}
 
-	tag := &jniDependencyTag{}
 	for _, jniTarget := range ctx.MultiTargets() {
 		variation := append(jniTarget.Variations(),
 			blueprint.Variation{Mutator: "link", Variation: "shared"})
@@ -393,7 +392,7 @@
 			Bool(a.appProperties.Jni_uses_sdk_apis) {
 			variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
 		}
-		ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
+		ctx.AddFarVariationDependencies(variation, jniLibTag, a.appProperties.Jni_libs...)
 	}
 
 	a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
@@ -643,7 +642,7 @@
 					// Work with the team to come up with a new format that handles multilib modules properly
 					// and change this.
 					if len(ctx.Config().Targets[android.Android]) == 1 ||
-						ctx.Config().Targets[android.Android][0].Arch.ArchType == jni.target.Arch.ArchType {
+						ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType == jni.target.Arch.ArchType {
 						a.jniCoverageOutputs = append(a.jniCoverageOutputs, jni.coverageFile.Path())
 					}
 				}
@@ -1402,7 +1401,7 @@
 	}
 
 	archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName("Arch")
-	archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
+	archType := ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType
 	MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
 }
 
diff --git a/java/app_test.go b/java/app_test.go
index f894379..49ed3aa 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -67,7 +67,6 @@
 }
 
 func TestApp(t *testing.T) {
-	t.Parallel()
 	for _, moduleType := range []string{"android_app", "android_library"} {
 		t.Run(moduleType, func(t *testing.T) {
 			ctx := testApp(t, moduleType+` {
@@ -114,7 +113,6 @@
 }
 
 func TestAppSplits(t *testing.T) {
-	t.Parallel()
 	ctx := testApp(t, `
 				android_app {
 					name: "foo",
@@ -144,7 +142,6 @@
 }
 
 func TestAndroidAppSet(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		android_app_set {
 			name: "foo",
@@ -173,7 +170,6 @@
 }
 
 func TestAndroidAppSet_Variants(t *testing.T) {
-	t.Parallel()
 	bp := `
 		android_app_set {
 			name: "foo",
@@ -239,7 +235,6 @@
 }
 
 func TestPlatformAPIs(t *testing.T) {
-	t.Parallel()
 	testJava(t, `
 		android_app {
 			name: "foo",
@@ -274,7 +269,6 @@
 }
 
 func TestAndroidAppLinkType(t *testing.T) {
-	t.Parallel()
 	testJava(t, `
 		android_app {
 			name: "foo",
@@ -364,7 +358,6 @@
 }
 
 func TestUpdatableApps(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name          string
 		bp            string
@@ -486,7 +479,6 @@
 }
 
 func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) {
-	t.Parallel()
 	testJavaError(t, `module "bar".*: should support min_sdk_version\(29\)`, cc.GatherRequiredDepsForTest(android.Android)+`
 		android_app {
 			name: "foo",
@@ -505,7 +497,6 @@
 }
 
 func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) {
-	t.Parallel()
 	testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		android_app {
 			name: "foo",
@@ -526,7 +517,6 @@
 }
 
 func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) {
-	t.Parallel()
 	bp := cc.GatherRequiredDepsForTest(android.Android) + `
 		android_app {
 			name: "foo",
@@ -581,7 +571,6 @@
 }
 
 func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) {
-	t.Parallel()
 	bp := cc.GatherRequiredDepsForTest(android.Android) + `
 		android_app {
 			name: "foo",
@@ -602,7 +591,6 @@
 }
 
 func TestUpdatableApps_ErrorIfDepSdkVersionIsHigher(t *testing.T) {
-	t.Parallel()
 	bp := cc.GatherRequiredDepsForTest(android.Android) + `
 		android_app {
 			name: "foo",
@@ -632,7 +620,6 @@
 }
 
 func TestResourceDirs(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name      string
 		prop      string
@@ -692,7 +679,6 @@
 }
 
 func TestLibraryAssets(t *testing.T) {
-	t.Parallel()
 	bp := `
 			android_app {
 				name: "foo",
@@ -794,7 +780,6 @@
 }
 
 func TestAndroidResources(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name                       string
 		enforceRROTargets          []string
@@ -863,19 +848,17 @@
 				"lib": {
 					buildDir + "/.intermediates/lib2/android_common/package-res.apk",
 					"lib/res/res/values/strings.xml",
-					"device/vendor/blah/overlay/lib/res/values/strings.xml",
 				},
 			},
 
 			rroDirs: map[string][]string{
 				"foo": {
 					"device:device/vendor/blah/overlay/foo/res",
-					// Enforce RRO on "foo" could imply RRO on static dependencies, but for now it doesn't.
-					// "device/vendor/blah/overlay/lib/res",
 					"product:product/vendor/blah/overlay/foo/res",
+					"device:device/vendor/blah/overlay/lib/res",
 				},
 				"bar": nil,
-				"lib": nil,
+				"lib": {"device:device/vendor/blah/overlay/lib/res"},
 			},
 		},
 		{
@@ -1085,7 +1068,6 @@
 }
 
 func TestAppSdkVersion(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name                  string
 		sdkVersion            string
@@ -1168,7 +1150,6 @@
 }
 
 func TestVendorAppSdkVersion(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name                                  string
 		sdkVersion                            string
@@ -1232,7 +1213,6 @@
 }
 
 func TestJNIABI(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		cc_library {
 			name: "libjni",
@@ -1307,7 +1287,6 @@
 }
 
 func TestAppSdkVersionByPartition(t *testing.T) {
-	t.Parallel()
 	testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
 		android_app {
 			name: "foo",
@@ -1346,7 +1325,6 @@
 }
 
 func TestJNIPackaging(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		cc_library {
 			name: "libjni",
@@ -1438,7 +1416,6 @@
 }
 
 func TestJNISDK(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		cc_library {
 			name: "libjni",
@@ -1556,7 +1533,6 @@
 }
 
 func TestCertificates(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name                string
 		bp                  string
@@ -1677,7 +1653,6 @@
 }
 
 func TestRequestV4SigningFlag(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name     string
 		bp       string
@@ -1738,7 +1713,6 @@
 }
 
 func TestPackageNameOverride(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name                string
 		bp                  string
@@ -1804,7 +1778,6 @@
 }
 
 func TestInstrumentationTargetOverridden(t *testing.T) {
-	t.Parallel()
 	bp := `
 		android_app {
 			name: "foo",
@@ -1834,7 +1807,6 @@
 }
 
 func TestOverrideAndroidApp(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_app {
 			name: "foo",
@@ -2036,7 +2008,6 @@
 }
 
 func TestOverrideAndroidAppDependency(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_app {
 			name: "foo",
@@ -2079,7 +2050,6 @@
 }
 
 func TestOverrideAndroidTest(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_app {
 			name: "foo",
@@ -2176,7 +2146,6 @@
 }
 
 func TestAndroidTest_FixTestConfig(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_app {
 			name: "foo",
@@ -2258,7 +2227,6 @@
 }
 
 func TestAndroidAppImport(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_app_import {
 			name: "foo",
@@ -2288,7 +2256,6 @@
 }
 
 func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_app_import {
 			name: "foo",
@@ -2310,7 +2277,6 @@
 }
 
 func TestAndroidAppImport_Presigned(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_app_import {
 			name: "foo",
@@ -2339,7 +2305,6 @@
 }
 
 func TestAndroidAppImport_SigningLineage(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 	  android_app_import {
 			name: "foo",
@@ -2361,7 +2326,6 @@
 }
 
 func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_app_import {
 			name: "foo",
@@ -2391,7 +2355,6 @@
 }
 
 func TestAndroidAppImport_DpiVariants(t *testing.T) {
-	t.Parallel()
 	bp := `
 		android_app_import {
 			name: "foo",
@@ -2470,7 +2433,6 @@
 }
 
 func TestAndroidAppImport_Filename(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		android_app_import {
 			name: "foo",
@@ -2518,7 +2480,6 @@
 }
 
 func TestAndroidAppImport_ArchVariants(t *testing.T) {
-	t.Parallel()
 	// The test config's target arch is ARM64.
 	testCases := []struct {
 		name     string
@@ -2582,7 +2543,6 @@
 }
 
 func TestAndroidTestImport(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		android_test_import {
 			name: "foo",
@@ -2611,7 +2571,6 @@
 }
 
 func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_test_import {
 			name: "foo",
@@ -2649,7 +2608,6 @@
 }
 
 func TestAndroidTestImport_Preprocessed(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		android_test_import {
 			name: "foo",
@@ -2686,7 +2644,6 @@
 }
 
 func TestStl(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		cc_library {
 			name: "libjni",
@@ -2750,7 +2707,6 @@
 }
 
 func TestUsesLibraries(t *testing.T) {
-	t.Parallel()
 	bp := `
 		java_sdk_library {
 			name: "foo",
@@ -2875,7 +2831,6 @@
 }
 
 func TestCodelessApp(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name   string
 		bp     string
@@ -2952,7 +2907,6 @@
 }
 
 func TestEmbedNotice(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJavaWithFS(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		android_app {
 			name: "foo",
@@ -3062,7 +3016,6 @@
 }
 
 func TestUncompressDex(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name string
 		bp   string
@@ -3190,7 +3143,6 @@
 }
 
 func TestRuntimeResourceOverlay(t *testing.T) {
-	t.Parallel()
 	fs := map[string][]byte{
 		"baz/res/res/values/strings.xml": nil,
 		"bar/res/res/values/strings.xml": nil,
@@ -3295,7 +3247,6 @@
 }
 
 func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_defaults {
 			name: "rro_defaults",
@@ -3355,7 +3306,6 @@
 }
 
 func TestOverrideRuntimeResourceOverlay(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		runtime_resource_overlay {
 			name: "foo_overlay",
@@ -3430,3 +3380,114 @@
 		checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag)
 	}
 }
+
+func TestEnforceRRO_propagatesToDependencies(t *testing.T) {
+	testCases := []struct {
+		name                    string
+		enforceRROTargets       []string
+		enforceRROExemptTargets []string
+		rroDirs                 map[string][]string
+	}{
+		{
+			name:                    "no RRO",
+			enforceRROTargets:       nil,
+			enforceRROExemptTargets: nil,
+			rroDirs: map[string][]string{
+				"foo": nil,
+				"bar": nil,
+			},
+		},
+		{
+			name:                    "enforce RRO on all",
+			enforceRROTargets:       []string{"*"},
+			enforceRROExemptTargets: nil,
+			rroDirs: map[string][]string{
+				"foo": {"product/vendor/blah/overlay/lib2/res"},
+				"bar": {"product/vendor/blah/overlay/lib2/res"},
+			},
+		},
+		{
+			name:                    "enforce RRO on foo",
+			enforceRROTargets:       []string{"foo"},
+			enforceRROExemptTargets: nil,
+			rroDirs: map[string][]string{
+				"foo": {"product/vendor/blah/overlay/lib2/res"},
+				"bar": {"product/vendor/blah/overlay/lib2/res"},
+			},
+		},
+		{
+			name:                    "enforce RRO on foo, bar exempted",
+			enforceRROTargets:       []string{"foo"},
+			enforceRROExemptTargets: []string{"bar"},
+			rroDirs: map[string][]string{
+				"foo": {"product/vendor/blah/overlay/lib2/res"},
+				"bar": nil,
+			},
+		},
+	}
+
+	productResourceOverlays := []string{
+		"product/vendor/blah/overlay",
+	}
+
+	fs := map[string][]byte{
+		"lib2/res/values/strings.xml":                             nil,
+		"product/vendor/blah/overlay/lib2/res/values/strings.xml": nil,
+	}
+
+	bp := `
+			android_app {
+				name: "foo",
+				sdk_version: "current",
+				resource_dirs: [],
+				static_libs: ["lib"],
+			}
+
+			android_app {
+				name: "bar",
+				sdk_version: "current",
+				resource_dirs: [],
+				static_libs: ["lib"],
+			}
+
+			android_library {
+				name: "lib",
+				sdk_version: "current",
+				resource_dirs: [],
+				static_libs: ["lib2"],
+			}
+
+			android_library {
+				name: "lib2",
+				sdk_version: "current",
+				resource_dirs: ["lib2/res"],
+			}
+		`
+
+	for _, testCase := range testCases {
+		t.Run(testCase.name, func(t *testing.T) {
+			config := testAppConfig(nil, bp, fs)
+			config.TestProductVariables.ProductResourceOverlays = productResourceOverlays
+			if testCase.enforceRROTargets != nil {
+				config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
+			}
+			if testCase.enforceRROExemptTargets != nil {
+				config.TestProductVariables.EnforceRROExemptedTargets = testCase.enforceRROExemptTargets
+			}
+
+			ctx := testContext()
+			run(t, ctx, config)
+
+			modules := []string{"foo", "bar"}
+			for _, moduleName := range modules {
+				module := ctx.ModuleForTests(moduleName, "android_common")
+				mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
+				actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"]
+				if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) {
+					t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q",
+						moduleName, testCase.rroDirs[moduleName], actualRRODirs)
+				}
+			}
+		})
+	}
+}
diff --git a/java/device_host_converter_test.go b/java/device_host_converter_test.go
index 208ea57..3c9a0f3 100644
--- a/java/device_host_converter_test.go
+++ b/java/device_host_converter_test.go
@@ -22,7 +22,6 @@
 )
 
 func TestDeviceForHost(t *testing.T) {
-	t.Parallel()
 	bp := `
 		java_library {
 			name: "device_module",
@@ -103,7 +102,6 @@
 }
 
 func TestHostForDevice(t *testing.T) {
-	t.Parallel()
 	bp := `
 		java_library_host {
 			name: "host_module",
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 00bd80c..4a8d3cd 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -84,7 +84,6 @@
 }
 
 func TestDexpreoptBootJars(t *testing.T) {
-	t.Parallel()
 	ruleFile := "boot-foo.art"
 
 	expectedInputs := []string{
@@ -115,7 +114,6 @@
 
 // Changes to the boot.zip structure may break the ART APK scanner.
 func TestDexpreoptBootZip(t *testing.T) {
-	t.Parallel()
 	ruleFile := "boot.zip"
 
 	ctx := android.PathContextForTesting(testConfig(nil, "", nil))
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index 0bb3ac9..5550a4c 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -19,7 +19,6 @@
 )
 
 func TestDexpreoptEnabled(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name    string
 		bp      string
diff --git a/java/droiddoc.go b/java/droiddoc.go
index b3bb5ab..344b15e 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -274,10 +274,6 @@
 	// if set to true, collect the values used by the Dev tools and
 	// write them in files packaged with the SDK. Defaults to false.
 	Write_sdk_values *bool
-
-	// If set to true, .xml based public API file will be also generated, and
-	// JDiff tool will be invoked to genreate javadoc files. Defaults to false.
-	Jdiff_enabled *bool
 }
 
 //
@@ -586,9 +582,8 @@
 	srcFiles = filterByPackage(srcFiles, j.properties.Filter_packages)
 
 	// While metalava needs package html files, it does not need them to be explicit on the command
-	// line. More importantly, the metalava rsp file is also used by the subsequent jdiff action if
-	// jdiff_enabled=true. javadoc complains if it receives html files on the command line. The filter
-	// below excludes html files from the rsp file for both metalava and jdiff. Note that the html
+	// line. javadoc complains if it receives html files on the command line. The filter
+	// below excludes html files from the rsp file metalava. Note that the html
 	// files are still included as implicit inputs for successful remote execution and correct
 	// incremental builds.
 	filterHtml := func(srcs []android.Path) []android.Path {
@@ -1021,10 +1016,8 @@
 	annotationsZip android.WritablePath
 	apiVersionsXml android.WritablePath
 
-	apiFilePath android.Path
-
-	jdiffDocZip      android.WritablePath
-	jdiffStubsSrcJar android.WritablePath
+	apiFilePath        android.Path
+	removedApiFilePath android.Path
 
 	metadataZip android.WritablePath
 	metadataDir android.WritablePath
@@ -1067,7 +1060,7 @@
 	case ".api.txt":
 		return android.Paths{d.apiFilePath}, nil
 	case ".removed-api.txt":
-		return android.Paths{d.removedApiFile}, nil
+		return android.Paths{d.removedApiFilePath}, nil
 	case ".annotations.zip":
 		return android.Paths{d.annotationsZip}, nil
 	case ".api_versions.xml":
@@ -1082,7 +1075,7 @@
 }
 
 func (d *Droidstubs) RemovedApiFilePath() android.Path {
-	return d.removedApiFile
+	return d.removedApiFilePath
 }
 
 func (d *Droidstubs) StubsSrcJar() android.Path {
@@ -1133,6 +1126,9 @@
 		d.apiFile = android.PathForModuleOut(ctx, filename)
 		cmd.FlagWithOutput("--api ", d.apiFile)
 		d.apiFilePath = d.apiFile
+	} else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
+		// If check api is disabled then make the source file available for export.
+		d.apiFilePath = android.PathForModuleSrc(ctx, sourceApiFile)
 	}
 
 	if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
@@ -1141,6 +1137,10 @@
 		filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
 		d.removedApiFile = android.PathForModuleOut(ctx, filename)
 		cmd.FlagWithOutput("--removed-api ", d.removedApiFile)
+		d.removedApiFilePath = d.removedApiFile
+	} else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
+		// If check api is disabled then make the source removed api file available for export.
+		d.removedApiFilePath = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
 	}
 
 	if String(d.properties.Removed_dex_api_filename) != "" {
@@ -1258,26 +1258,6 @@
 	})
 }
 
-func (d *Droidstubs) apiToXmlFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
-	if Bool(d.properties.Jdiff_enabled) && d.apiFile != nil {
-		if d.apiFile.String() == "" {
-			ctx.ModuleErrorf("API signature file has to be specified in Metalava when jdiff is enabled.")
-		}
-
-		d.apiXmlFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.xml")
-		cmd.FlagWithOutput("--api-xml ", d.apiXmlFile)
-
-		if String(d.properties.Check_api.Last_released.Api_file) == "" {
-			ctx.PropertyErrorf("check_api.last_released.api_file",
-				"has to be non-empty if jdiff was enabled!")
-		}
-
-		lastReleasedApi := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
-		d.lastReleasedApiXmlFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_last_released_api.xml")
-		cmd.FlagWithInput("--convert-to-jdiff ", lastReleasedApi).Output(d.lastReleasedApiXmlFile)
-	}
-}
-
 func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
 	srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicitsRsp android.WritablePath, sandbox bool) *android.RuleBuilderCommand {
 	// Metalava uses lots of memory, restrict the number of metalava jobs that can run in parallel.
@@ -1386,7 +1366,6 @@
 	d.annotationsFlags(ctx, cmd)
 	d.inclusionAnnotationsFlags(ctx, cmd)
 	d.apiLevelsAnnotationsFlags(ctx, cmd)
-	d.apiToXmlFlags(ctx, cmd)
 
 	if android.InList("--generate-documentation", d.Javadoc.args) {
 		// Currently Metalava have the ability to invoke Javadoc in a seperate process.
@@ -1663,74 +1642,6 @@
 
 		rule.Build(pctx, ctx, "nullabilityWarningsCheck", "nullability warnings check")
 	}
-
-	if Bool(d.properties.Jdiff_enabled) {
-		if len(d.Javadoc.properties.Out) > 0 {
-			ctx.PropertyErrorf("out", "out property may not be combined with jdiff")
-		}
-
-		outDir := android.PathForModuleOut(ctx, "jdiff-out")
-		srcJarDir := android.PathForModuleOut(ctx, "jdiff-srcjars")
-		stubsDir := android.PathForModuleOut(ctx, "jdiff-stubsDir")
-
-		rule := android.NewRuleBuilder()
-
-		// Please sync with android-api-council@ before making any changes for the name of jdiffDocZip below
-		// since there's cron job downstream that fetch this .zip file periodically.
-		// See b/116221385 for reference.
-		d.jdiffDocZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"jdiff-docs.zip")
-		d.jdiffStubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"jdiff-stubs.srcjar")
-
-		jdiff := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jdiff.jar")
-
-		rule.Command().Text("rm -rf").Text(outDir.String()).Text(stubsDir.String())
-		rule.Command().Text("mkdir -p").Text(outDir.String()).Text(stubsDir.String())
-
-		srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
-
-		cmd := javadocBootclasspathCmd(ctx, rule, d.Javadoc.srcFiles, outDir, srcJarDir, srcJarList,
-			deps.bootClasspath, deps.classpath, d.sourcepaths)
-
-		cmd.Flag("-J-Xmx1600m").
-			Flag("-XDignore.symbol.file").
-			FlagWithArg("-doclet ", "jdiff.JDiff").
-			FlagWithInput("-docletpath ", jdiff).
-			Flag("-quiet")
-
-		if d.apiXmlFile != nil {
-			cmd.FlagWithArg("-newapi ", strings.TrimSuffix(d.apiXmlFile.Base(), d.apiXmlFile.Ext())).
-				FlagWithArg("-newapidir ", filepath.Dir(d.apiXmlFile.String())).
-				Implicit(d.apiXmlFile)
-		}
-
-		if d.lastReleasedApiXmlFile != nil {
-			cmd.FlagWithArg("-oldapi ", strings.TrimSuffix(d.lastReleasedApiXmlFile.Base(), d.lastReleasedApiXmlFile.Ext())).
-				FlagWithArg("-oldapidir ", filepath.Dir(d.lastReleasedApiXmlFile.String())).
-				Implicit(d.lastReleasedApiXmlFile)
-		}
-
-		rule.Command().
-			BuiltTool(ctx, "soong_zip").
-			Flag("-write_if_changed").
-			Flag("-d").
-			FlagWithOutput("-o ", d.jdiffDocZip).
-			FlagWithArg("-C ", outDir.String()).
-			FlagWithArg("-D ", outDir.String())
-
-		rule.Command().
-			BuiltTool(ctx, "soong_zip").
-			Flag("-write_if_changed").
-			Flag("-jar").
-			FlagWithOutput("-o ", d.jdiffStubsSrcJar).
-			FlagWithArg("-C ", stubsDir.String()).
-			FlagWithArg("-D ", stubsDir.String())
-
-		rule.Restat()
-
-		zipSyncCleanupCmd(rule, srcJarDir)
-
-		rule.Build(pctx, ctx, "jdiff", "jdiff")
-	}
 }
 
 //
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index b140b89..9d07e41 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -18,6 +18,7 @@
 	"fmt"
 
 	"android/soong/android"
+	"android/soong/genrule"
 )
 
 func init() {
@@ -223,30 +224,26 @@
 // the unsupported API.
 func flagsRule(ctx android.SingletonContext) android.Path {
 	var flagsCSV android.Paths
-	var greylistRemovedApis android.Paths
+	var combinedRemovedApis android.Path
 
 	ctx.VisitAllModules(func(module android.Module) {
 		if h, ok := module.(hiddenAPIIntf); ok {
 			if csv := h.flagsCSV(); csv != nil {
 				flagsCSV = append(flagsCSV, csv)
 			}
-		} else if ds, ok := module.(*Droidstubs); ok {
-			// Track @removed public and system APIs via corresponding droidstubs targets.
-			// These APIs are not present in the stubs, however, we have to keep allowing access
-			// to them at runtime.
-			if moduleForGreyListRemovedApis(ctx, module) {
-				greylistRemovedApis = append(greylistRemovedApis, ds.removedDexApiFile)
+		} else if g, ok := module.(*genrule.Module); ok {
+			if ctx.ModuleName(module) == "combined-removed-dex" {
+				if len(g.GeneratedSourceFiles()) != 1 || combinedRemovedApis != nil {
+					ctx.Errorf("Expected 1 combined-removed-dex module that generates 1 output file.")
+				}
+				combinedRemovedApis = g.GeneratedSourceFiles()[0]
 			}
 		}
 	})
 
-	combinedRemovedApis := android.PathForOutput(ctx, "hiddenapi", "combined-removed-dex.txt")
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        android.Cat,
-		Inputs:      greylistRemovedApis,
-		Output:      combinedRemovedApis,
-		Description: "Combine removed apis for " + combinedRemovedApis.String(),
-	})
+	if combinedRemovedApis == nil {
+		ctx.Errorf("Failed to find combined-removed-dex.")
+	}
 
 	rule := android.NewRuleBuilder()
 
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 97dd125..dbdab7a 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -58,7 +58,6 @@
 }
 
 func TestHiddenAPISingleton(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testHiddenAPIBootJars(t, `
 		java_library {
 			name: "foo",
@@ -76,7 +75,6 @@
 }
 
 func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testHiddenAPIBootJars(t, `
 		java_import {
 			name: "foo",
@@ -94,7 +92,6 @@
 }
 
 func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testHiddenAPIBootJars(t, `
 		java_library {
 			name: "foo",
@@ -124,7 +121,6 @@
 }
 
 func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testHiddenAPIBootJars(t, `
 		java_library {
 			name: "foo",
@@ -154,7 +150,6 @@
 }
 
 func TestHiddenAPISingletonSdks(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name             string
 		unbundledBuild   bool
diff --git a/java/jacoco_test.go b/java/jacoco_test.go
index d77c916..91f0553 100644
--- a/java/jacoco_test.go
+++ b/java/jacoco_test.go
@@ -17,7 +17,6 @@
 import "testing"
 
 func TestJacocoFilterToSpecs(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name, in, out string
 	}{
@@ -67,7 +66,6 @@
 }
 
 func TestJacocoFiltersToZipCommand(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name               string
 		includes, excludes []string
diff --git a/java/java.go b/java/java.go
index 2553a30..a973bab 100644
--- a/java/java.go
+++ b/java/java.go
@@ -547,13 +547,8 @@
 	name string
 }
 
-type jniDependencyTag struct {
-	blueprint.BaseDependencyTag
-}
-
 func IsJniDepTag(depTag blueprint.DependencyTag) bool {
-	_, ok := depTag.(*jniDependencyTag)
-	return ok
+	return depTag == jniLibTag
 }
 
 var (
@@ -573,6 +568,7 @@
 	instrumentationForTag = dependencyTag{name: "instrumentation_for"}
 	usesLibTag            = dependencyTag{name: "uses-library"}
 	extraLintCheckTag     = dependencyTag{name: "extra-lint-check"}
+	jniLibTag             = dependencyTag{name: "jnilib"}
 )
 
 func IsLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -1001,7 +997,7 @@
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
-		if _, ok := tag.(*jniDependencyTag); ok {
+		if IsJniDepTag(tag) {
 			// Handled by AndroidApp.collectAppDeps
 			return
 		}
@@ -2436,6 +2432,10 @@
 
 	// Name of the class containing main to be inserted into the manifest as Main-Class.
 	Main_class *string
+
+	// Names of modules containing JNI libraries that should be installed alongside the host
+	// variant of the binary.
+	Jni_libs []string
 }
 
 type Binary struct {
@@ -2476,18 +2476,21 @@
 			j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
 		}
 
-		// Depend on the installed jar so that the wrapper doesn't get executed by
-		// another build rule before the jar has been installed.
-		jarFile := ctx.PrimaryModule().(*Binary).installFile
-
+		// The host installation rules make the installed wrapper depend on all the dependencies
+		// of the wrapper variant, which will include the common variant's jar file and any JNI
+		// libraries.  This is verified by TestBinary.
 		j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
-			ctx.ModuleName(), j.wrapperFile, jarFile)
+			ctx.ModuleName(), j.wrapperFile)
 	}
 }
 
 func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
 	if ctx.Arch().ArchType == android.Common {
 		j.deps(ctx)
+	} else {
+		// This dependency ensures the host installation rules will install the jni libraries
+		// when the wrapper is installed.
+		ctx.AddVariationDependencies(nil, jniLibTag, j.binaryProperties.Jni_libs...)
 	}
 }
 
@@ -2728,7 +2731,7 @@
 
 func (j *Import) OutputFiles(tag string) (android.Paths, error) {
 	switch tag {
-	case ".jar":
+	case "", ".jar":
 		return android.Paths{j.combinedClasspathFile}, nil
 	default:
 		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
diff --git a/java/java_test.go b/java/java_test.go
index 245654d..c751ea4 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -102,6 +102,10 @@
 
 	dexpreopt.RegisterToolModulesForTest(ctx)
 
+	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
+	})
+
 	return ctx
 }
 
@@ -177,7 +181,6 @@
 }
 
 func TestJavaLinkType(t *testing.T) {
-	t.Parallel()
 	testJava(t, `
 		java_library {
 			name: "foo",
@@ -266,7 +269,6 @@
 }
 
 func TestSimple(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -311,7 +313,6 @@
 }
 
 func TestExportedPlugins(t *testing.T) {
-	t.Parallel()
 	type Result struct {
 		library    string
 		processors string
@@ -395,7 +396,6 @@
 }
 
 func TestSdkVersionByPartition(t *testing.T) {
-	t.Parallel()
 	testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
 		java_library {
 			name: "foo",
@@ -431,7 +431,6 @@
 }
 
 func TestArchSpecific(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -451,7 +450,6 @@
 }
 
 func TestBinary(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library_host {
 			name: "foo",
@@ -462,6 +460,14 @@
 			name: "bar",
 			srcs: ["b.java"],
 			static_libs: ["foo"],
+			jni_libs: ["libjni"],
+		}
+
+		cc_library_shared {
+			name: "libjni",
+			host_supported: true,
+			device_supported: false,
+			stl: "none",
 		}
 	`)
 
@@ -472,15 +478,21 @@
 	barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64")
 	barWrapperDeps := barWrapper.Output("bar").Implicits.Strings()
 
+	libjni := ctx.ModuleForTests("libjni", buildOS+"_x86_64_shared")
+	libjniSO := libjni.Rule("Cp").Output.String()
+
 	// Test that the install binary wrapper depends on the installed jar file
-	if len(barWrapperDeps) != 1 || barWrapperDeps[0] != barJar {
-		t.Errorf("expected binary wrapper implicits [%q], got %v",
-			barJar, barWrapperDeps)
+	if g, w := barWrapperDeps, barJar; !android.InList(w, g) {
+		t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g)
+	}
+
+	// Test that the install binary wrapper depends on the installed JNI libraries
+	if g, w := barWrapperDeps, libjniSO; !android.InList(w, g) {
+		t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g)
 	}
 }
 
 func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
-	t.Parallel()
 	bp := `
 		java_library {
 			name: "target_library",
@@ -516,7 +528,6 @@
 }
 
 func TestPrebuilts(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -612,7 +623,6 @@
 }
 
 func TestJavaSdkLibraryImport(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -669,7 +679,6 @@
 }
 
 func TestJavaSdkLibraryImport_WithSource(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_sdk_library {
 			name: "sdklib",
@@ -709,7 +718,6 @@
 }
 
 func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_sdk_library {
 			name: "sdklib",
@@ -747,7 +755,6 @@
 }
 
 func TestDefaults(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_defaults {
 			name: "defaults",
@@ -823,7 +830,6 @@
 }
 
 func TestResources(t *testing.T) {
-	t.Parallel()
 	var table = []struct {
 		name  string
 		prop  string
@@ -930,7 +936,6 @@
 }
 
 func TestIncludeSrcs(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJavaWithFS(t, `
 		java_library {
 			name: "foo",
@@ -998,7 +1003,6 @@
 }
 
 func TestGeneratedSources(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJavaWithFS(t, `
 		java_library {
 			name: "foo",
@@ -1035,7 +1039,6 @@
 }
 
 func TestTurbine(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -1085,7 +1088,6 @@
 }
 
 func TestSharding(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "bar",
@@ -1104,7 +1106,6 @@
 }
 
 func TestDroiddoc(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJavaWithFS(t, `
 		droiddoc_exported_dir {
 		    name: "droiddoc-templates-sdk",
@@ -1183,7 +1184,6 @@
 }
 
 func TestDroiddocArgsAndFlagsCausesError(t *testing.T) {
-	t.Parallel()
 	testJavaError(t, "flags is set. Cannot set args", `
 		droiddoc_exported_dir {
 		    name: "droiddoc-templates-sdk",
@@ -1230,7 +1230,6 @@
 }
 
 func TestDroidstubs(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJavaWithFS(t, `
 		droiddoc_exported_dir {
 		    name: "droiddoc-templates-sdk",
@@ -1287,7 +1286,6 @@
 }
 
 func TestDroidstubsWithSystemModules(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		droidstubs {
 		    name: "stubs-source-system-modules",
@@ -1347,7 +1345,6 @@
 }
 
 func TestJarGenrules(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -1402,7 +1399,6 @@
 }
 
 func TestExcludeFileGroupInSrcs(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -1429,7 +1425,6 @@
 }
 
 func TestJavaLibrary(t *testing.T) {
-	t.Parallel()
 	config := testConfig(nil, "", map[string][]byte{
 		"libcore/Android.bp": []byte(`
 				java_library {
@@ -1467,7 +1462,6 @@
 }
 
 func TestJavaSdkLibrary(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		droiddoc_exported_dir {
 			name: "droiddoc-templates-sdk",
@@ -1605,8 +1599,40 @@
 	}
 }
 
+func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_sdk_library {
+			name: "sdk_lib",
+			srcs: ["a.java"],
+			impl_only_libs: ["foo"],
+			stub_only_libs: ["bar"],
+		}
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			sdk_version: "current",
+		}
+		java_library {
+			name: "bar",
+			srcs: ["a.java"],
+			sdk_version: "current",
+		}
+		`)
+
+	for _, implName := range []string{"sdk_lib", "sdk_lib.impl"} {
+		implJavacCp := ctx.ModuleForTests(implName, "android_common").Rule("javac").Args["classpath"]
+		if !strings.Contains(implJavacCp, "/foo.jar") || strings.Contains(implJavacCp, "/bar.jar") {
+			t.Errorf("%v javac classpath %v does not contain foo and not bar", implName, implJavacCp)
+		}
+	}
+	stubName := apiScopePublic.stubsLibraryModuleName("sdk_lib")
+	stubsJavacCp := ctx.ModuleForTests(stubName, "android_common").Rule("javac").Args["classpath"]
+	if strings.Contains(stubsJavacCp, "/foo.jar") || !strings.Contains(stubsJavacCp, "/bar.jar") {
+		t.Errorf("stubs javac classpath %v does not contain bar and not foo", stubsJavacCp)
+	}
+}
+
 func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_sdk_library {
 			name: "foo",
@@ -1632,7 +1658,6 @@
 }
 
 func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) {
-	t.Parallel()
 	testJava(t, `
 		java_sdk_library {
 			name: "foo",
@@ -1651,7 +1676,6 @@
 }
 
 func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) {
-	t.Parallel()
 	testJavaError(t, `"foo" does not provide api scope system`, `
 		java_sdk_library {
 			name: "foo",
@@ -1670,7 +1694,6 @@
 }
 
 func TestJavaSdkLibrary_Deps(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_sdk_library {
 			name: "sdklib",
@@ -1693,7 +1716,6 @@
 }
 
 func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) {
-	t.Parallel()
 	testJava(t, `
 		java_sdk_library_import {
 			name: "foo",
@@ -1717,7 +1739,6 @@
 }
 
 func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
-	t.Parallel()
 	bp := `
 		java_sdk_library_import {
 			name: "foo",
@@ -1766,7 +1787,6 @@
 }
 
 func TestJavaSdkLibrary_InvalidScopes(t *testing.T) {
-	t.Parallel()
 	testJavaError(t, `module "foo": enabled api scope "system" depends on disabled scope "public"`, `
 		java_sdk_library {
 			name: "foo",
@@ -1785,7 +1805,6 @@
 }
 
 func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
-	t.Parallel()
 	testJava(t, `
 		java_sdk_library {
 			name: "foo",
@@ -1800,7 +1819,6 @@
 }
 
 func TestJavaSdkLibrary_ModuleLib(t *testing.T) {
-	t.Parallel()
 	testJava(t, `
 		java_sdk_library {
 			name: "foo",
@@ -1817,7 +1835,6 @@
 }
 
 func TestJavaSdkLibrary_SystemServer(t *testing.T) {
-	t.Parallel()
 	testJava(t, `
 		java_sdk_library {
 			name: "foo",
@@ -1834,7 +1851,6 @@
 }
 
 func TestJavaSdkLibrary_MissingScope(t *testing.T) {
-	t.Parallel()
 	testJavaError(t, `requires api scope module-lib from foo but it only has \[\] available`, `
 		java_sdk_library {
 			name: "foo",
@@ -1854,7 +1870,6 @@
 }
 
 func TestJavaSdkLibrary_FallbackScope(t *testing.T) {
-	t.Parallel()
 	testJava(t, `
 		java_sdk_library {
 			name: "foo",
@@ -1875,7 +1890,6 @@
 }
 
 func TestJavaSdkLibrary_DefaultToStubs(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_sdk_library {
 			name: "foo",
@@ -1951,7 +1965,6 @@
 }
 
 func TestCompilerFlags(t *testing.T) {
-	t.Parallel()
 	for _, testCase := range compilerFlagsTestCases {
 		ctx := &mockContext{result: true}
 		CheckKotlincFlags(ctx, []string{testCase.in})
@@ -1982,7 +1995,6 @@
 }
 
 func TestPatchModule(t *testing.T) {
-	t.Parallel()
 	t.Run("Java language level 8", func(t *testing.T) {
 		// Test with legacy javac -source 1.8 -target 1.8
 		bp := `
@@ -2048,7 +2060,6 @@
 }
 
 func TestJavaSystemModules(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_system_modules {
 			name: "system-modules",
@@ -2083,7 +2094,6 @@
 }
 
 func TestJavaSystemModulesImport(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_system_modules_import {
 			name: "system-modules",
@@ -2114,7 +2124,6 @@
 }
 
 func TestJavaLibraryWithSystemModules(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 		    name: "lib-with-source-system-modules",
@@ -2171,7 +2180,6 @@
 }
 
 func TestAidlExportIncludeDirsFromImports(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -2196,7 +2204,6 @@
 }
 
 func TestDataNativeBinaries(t *testing.T) {
-	t.Parallel()
 	ctx, config := testJava(t, `
 		java_test_host {
 			name: "foo",
diff --git a/java/jdeps_test.go b/java/jdeps_test.go
index 46e7296..874d1d7 100644
--- a/java/jdeps_test.go
+++ b/java/jdeps_test.go
@@ -22,7 +22,6 @@
 )
 
 func TestCollectJavaLibraryPropertiesAddLibsDeps(t *testing.T) {
-	t.Parallel()
 	expected := []string{"Foo", "Bar"}
 	module := LibraryFactory().(*Library)
 	module.properties.Libs = append(module.properties.Libs, expected...)
@@ -36,7 +35,6 @@
 }
 
 func TestCollectJavaLibraryPropertiesAddStaticLibsDeps(t *testing.T) {
-	t.Parallel()
 	expected := []string{"Foo", "Bar"}
 	module := LibraryFactory().(*Library)
 	module.properties.Static_libs = append(module.properties.Static_libs, expected...)
@@ -50,7 +48,6 @@
 }
 
 func TestCollectJavaLibraryPropertiesAddScrs(t *testing.T) {
-	t.Parallel()
 	expected := []string{"Foo", "Bar"}
 	module := LibraryFactory().(*Library)
 	module.expandIDEInfoCompiledSrcs = append(module.expandIDEInfoCompiledSrcs, expected...)
@@ -64,7 +61,6 @@
 }
 
 func TestCollectJavaLibraryPropertiesAddAidlIncludeDirs(t *testing.T) {
-	t.Parallel()
 	expected := []string{"Foo", "Bar"}
 	module := LibraryFactory().(*Library)
 	module.deviceProperties.Aidl.Include_dirs = append(module.deviceProperties.Aidl.Include_dirs, expected...)
@@ -78,7 +74,6 @@
 }
 
 func TestCollectJavaLibraryPropertiesAddJarjarRules(t *testing.T) {
-	t.Parallel()
 	expected := "Jarjar_rules.txt"
 	module := LibraryFactory().(*Library)
 	module.expandJarjarRules = android.PathForTesting(expected)
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 530f7fe..60ca1c4 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -22,7 +22,6 @@
 )
 
 func TestKotlin(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -85,7 +84,6 @@
 }
 
 func TestKapt(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -165,7 +163,6 @@
 }
 
 func TestKaptEncodeFlags(t *testing.T) {
-	t.Parallel()
 	// Compares the kaptEncodeFlags against the results of the example implementation at
 	// https://kotlinlang.org/docs/reference/kapt.html#apjavac-options-encoding
 	tests := []struct {
diff --git a/java/plugin_test.go b/java/plugin_test.go
index 3eb0215..c7913d3 100644
--- a/java/plugin_test.go
+++ b/java/plugin_test.go
@@ -20,7 +20,6 @@
 )
 
 func TestNoPlugin(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -45,7 +44,6 @@
 }
 
 func TestPlugin(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
@@ -85,7 +83,6 @@
 }
 
 func TestPluginGeneratesApi(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 119eb65..d6ef4e9 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -257,7 +257,7 @@
 	})
 	apiScopeTest = initApiScope(&apiScope{
 		name:                "test",
-		extends:             apiScopePublic,
+		extends:             apiScopeSystem,
 		legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
 		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
 			return &module.sdkLibraryProperties.Test
@@ -388,6 +388,9 @@
 	// visibility property.
 	Stubs_source_visibility []string
 
+	// List of Java libraries that will be in the classpath when building the implementation lib
+	Impl_only_libs []string `android:"arch_variant"`
+
 	// List of Java libraries that will be in the classpath when building stubs
 	Stub_only_libs []string `android:"arch_variant"`
 
@@ -1137,12 +1140,16 @@
 		Name              *string
 		Visibility        []string
 		Instrument        bool
+		Libs              []string
 		ConfigurationName *string
 	}{
 		Name:       proptools.StringPtr(module.implLibraryModuleName()),
 		Visibility: visibility,
 		// Set the instrument property to ensure it is instrumented when instrumentation is required.
 		Instrument: true,
+		// Set the impl_only libs. Note that the module's "Libs" get appended as well, via the
+		// addition of &module.properties below.
+		Libs: module.sdkLibraryProperties.Impl_only_libs,
 
 		// Make the created library behave as if it had the same name as this module.
 		ConfigurationName: moduleNamePtr,
@@ -1565,6 +1572,9 @@
 		defer javaSdkLibrariesLock.Unlock()
 		*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
 	}
+
+	// Add the impl_only_libs *after* we're done using the Libs prop in submodules.
+	module.properties.Libs = append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...)
 }
 
 func (module *SdkLibrary) InitSdkLibraryProperties() {
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 374da11..776069d 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -27,7 +27,6 @@
 )
 
 func TestClasspath(t *testing.T) {
-	t.Parallel()
 	var classpathTestcases = []struct {
 		name       string
 		unbundled  bool
diff --git a/linkerconfig/Android.bp b/linkerconfig/Android.bp
new file mode 100644
index 0000000..8807a2e
--- /dev/null
+++ b/linkerconfig/Android.bp
@@ -0,0 +1,17 @@
+bootstrap_go_package {
+    name: "soong-linkerconfig",
+    pkgPath: "android/soong/linkerconfig",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+        "soong-etc",
+    ],
+    srcs: [
+        "linkerconfig.go",
+    ],
+    testSrcs: [
+        "linkerconfig_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
new file mode 100644
index 0000000..1c44c74
--- /dev/null
+++ b/linkerconfig/linkerconfig.go
@@ -0,0 +1,108 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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 linkerconfig
+
+import (
+	"android/soong/android"
+	"android/soong/etc"
+
+	"github.com/google/blueprint/proptools"
+)
+
+var (
+	pctx = android.NewPackageContext("android/soong/linkerconfig")
+)
+
+func init() {
+	pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config")
+	android.RegisterModuleType("linker_config", linkerConfigFactory)
+}
+
+type linkerConfigProperties struct {
+	// source linker configuration property file
+	Src *string `android:"path"`
+
+	// If set to true, allow module to be installed to one of the partitions.
+	// Default value is true.
+	// Installable should be marked as false for APEX configuration to avoid
+	// conflicts of configuration on /system/etc directory.
+	Installable *bool
+}
+
+type linkerConfig struct {
+	android.ModuleBase
+	properties linkerConfigProperties
+
+	outputFilePath android.OutputPath
+	installDirPath android.InstallPath
+}
+
+// Implement PrebuiltEtcModule interface to fit in APEX prebuilt list.
+var _ etc.PrebuiltEtcModule = (*linkerConfig)(nil)
+
+func (l *linkerConfig) BaseDir() string {
+	return "etc"
+}
+
+func (l *linkerConfig) SubDir() string {
+	return ""
+}
+
+func (l *linkerConfig) OutputFile() android.OutputPath {
+	return l.outputFilePath
+}
+
+func (l *linkerConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	inputFile := android.PathForModuleSrc(ctx, android.String(l.properties.Src))
+	l.outputFilePath = android.PathForModuleOut(ctx, "linker.config.pb").OutputPath
+	l.installDirPath = android.PathForModuleInstall(ctx, "etc")
+	linkerConfigRule := android.NewRuleBuilder()
+	linkerConfigRule.Command().
+		BuiltTool(ctx, "conv_linker_config").
+		Flag("proto").
+		FlagWithInput("-s ", inputFile).
+		FlagWithOutput("-o ", l.outputFilePath)
+	linkerConfigRule.Build(pctx, ctx, "conv_linker_config",
+		"Generate linker config protobuf "+l.outputFilePath.String())
+
+	if proptools.BoolDefault(l.properties.Installable, true) {
+		ctx.InstallFile(l.installDirPath, l.outputFilePath.Base(), l.outputFilePath)
+	}
+}
+
+// linker_config generates protobuf file from json file. This protobuf file will be used from
+// linkerconfig while generating ld.config.txt. Format of this file can be found from
+// https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md
+func linkerConfigFactory() android.Module {
+	m := &linkerConfig{}
+	m.AddProperties(&m.properties)
+	android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibFirst)
+	return m
+}
+
+func (l *linkerConfig) AndroidMkEntries() []android.AndroidMkEntries {
+	installable := proptools.BoolDefault(l.properties.Installable, true)
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(l.outputFilePath),
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(entries *android.AndroidMkEntries) {
+				entries.SetString("LOCAL_MODULE_PATH", l.installDirPath.ToMakePath().String())
+				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", l.outputFilePath.Base())
+				entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !installable)
+			},
+		},
+	}}
+}
diff --git a/linkerconfig/linkerconfig_test.go b/linkerconfig/linkerconfig_test.go
new file mode 100644
index 0000000..13c276a
--- /dev/null
+++ b/linkerconfig/linkerconfig_test.go
@@ -0,0 +1,127 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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 linkerconfig
+
+import (
+	"android/soong/android"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"testing"
+)
+
+var buildDir string
+
+func setUp() {
+	var err error
+	buildDir, err = ioutil.TempDir("", "soong_etc_test")
+	if err != nil {
+		panic(err)
+	}
+}
+
+func tearDown() {
+	os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+	run := func() int {
+		setUp()
+		defer tearDown()
+
+		return m.Run()
+	}
+
+	os.Exit(run())
+}
+
+func testContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
+	t.Helper()
+
+	fs := map[string][]byte{
+		"linker.config.json": nil,
+	}
+
+	config := android.TestArchConfig(buildDir, nil, bp, fs)
+
+	ctx := android.NewTestArchContext()
+	ctx.RegisterModuleType("linker_config", linkerConfigFactory)
+	ctx.Register(config)
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+
+	return ctx, config
+}
+
+func TestBaseLinkerConfig(t *testing.T) {
+	ctx, config := testContext(t, `
+	linker_config {
+		name: "linker-config-base",
+		src: "linker.config.json",
+	}
+	`)
+
+	expected := map[string][]string{
+		"LOCAL_MODULE":                {"linker-config-base"},
+		"LOCAL_MODULE_CLASS":          {"ETC"},
+		"LOCAL_INSTALLED_MODULE_STEM": {"linker.config.pb"},
+	}
+
+	p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+
+	if p.outputFilePath.Base() != "linker.config.pb" {
+		t.Errorf("expected linker.config.pb, got %q", p.outputFilePath.Base())
+	}
+
+	entries := android.AndroidMkEntriesForTest(t, config, "", p)[0]
+	for k, expectedValue := range expected {
+		if value, ok := entries.EntryMap[k]; ok {
+			if !reflect.DeepEqual(value, expectedValue) {
+				t.Errorf("Value of %s is '%s', but expected as '%s'", k, value, expectedValue)
+			}
+		} else {
+			t.Errorf("%s is not defined", k)
+		}
+	}
+
+	if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok {
+		t.Errorf("Value of LOCAL_UNINSTALLABLE_MODULE is %s, but expected as empty", value)
+	}
+}
+
+func TestUninstallableLinkerConfig(t *testing.T) {
+	ctx, config := testContext(t, `
+	linker_config {
+		name: "linker-config-base",
+		src: "linker.config.json",
+		installable: false,
+	}
+	`)
+
+	expected := []string{"true"}
+
+	p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+	entries := android.AndroidMkEntriesForTest(t, config, "", p)[0]
+	if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok {
+		if !reflect.DeepEqual(value, expected) {
+			t.Errorf("LOCAL_UNINSTALLABLE_MODULE is expected to be true but %s", value)
+		}
+	} else {
+		t.Errorf("LOCAL_UNINSTALLABLE_MODULE is not defined")
+	}
+}
diff --git a/linkerconfig/proto/Android.bp b/linkerconfig/proto/Android.bp
new file mode 100644
index 0000000..c04887e
--- /dev/null
+++ b/linkerconfig/proto/Android.bp
@@ -0,0 +1,28 @@
+cc_library_static {
+    name: "lib_linker_config_proto_lite",
+    host_supported: true,
+    recovery_available: true,
+    proto: {
+        export_proto_headers: true,
+        type: "lite",
+    },
+    srcs: ["linker_config.proto"],
+}
+
+python_library_host {
+    name: "linker_config_proto",
+    version: {
+        py2: {
+            enabled: false,
+        },
+        py3: {
+            enabled: true,
+        },
+    },
+    srcs: [
+        "linker_config.proto",
+    ],
+    proto: {
+        canonical_path_from_root: false,
+    },
+}
diff --git a/linkerconfig/proto/OWNERS b/linkerconfig/proto/OWNERS
new file mode 100644
index 0000000..31f0460
--- /dev/null
+++ b/linkerconfig/proto/OWNERS
@@ -0,0 +1,3 @@
+kiyoungkim@google.com
+jiyong@google.com
+jooyung@google.com
diff --git a/linkerconfig/proto/linker_config.proto b/linkerconfig/proto/linker_config.proto
new file mode 100644
index 0000000..91a5968
--- /dev/null
+++ b/linkerconfig/proto/linker_config.proto
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// This format file defines configuration file for linkerconfig. Details on this
+// format can be found from
+// https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md
+
+syntax = "proto3";
+
+package android.linkerconfig.proto;
+
+message LinkerConfig {
+  // Extra permitted paths
+  repeated string permittedPaths = 1;
+
+  // Force APEX namespace visible
+  bool visible = 2;
+}
diff --git a/makedeps/deps_test.go b/makedeps/deps_test.go
index 17e77c4..ac2f699 100644
--- a/makedeps/deps_test.go
+++ b/makedeps/deps_test.go
@@ -23,7 +23,6 @@
 )
 
 func TestParse(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name   string
 		input  string
@@ -340,7 +339,6 @@
 }
 
 func TestDepPrint(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name   string
 		input  Deps
diff --git a/partner/androidmk/androidmk_test.go b/partner/androidmk/androidmk_test.go
index 2a0ddc8..6bae836 100644
--- a/partner/androidmk/androidmk_test.go
+++ b/partner/androidmk/androidmk_test.go
@@ -54,7 +54,6 @@
 }
 
 func TestEndToEnd(t *testing.T) {
-	t.Parallel()
 	for i, test := range testCases {
 		expected, err := bpfix.Reformat(test.expected)
 		if err != nil {
diff --git a/python/python_test.go b/python/python_test.go
index 455d84a..23db24e 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -326,7 +326,6 @@
 )
 
 func TestPythonModule(t *testing.T) {
-	t.Parallel()
 	for _, d := range data {
 		t.Run(d.desc, func(t *testing.T) {
 			config := android.TestConfig(buildDir, nil, "", d.mockFiles)
diff --git a/remoteexec/remoteexec_test.go b/remoteexec/remoteexec_test.go
index 2fd3687..56985d3 100644
--- a/remoteexec/remoteexec_test.go
+++ b/remoteexec/remoteexec_test.go
@@ -22,7 +22,6 @@
 )
 
 func TestTemplate(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name   string
 		params *REParams
@@ -68,7 +67,6 @@
 }
 
 func TestNoVarTemplate(t *testing.T) {
-	t.Parallel()
 	params := &REParams{
 		Labels:      map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
 		Inputs:      []string{"$in"},
@@ -85,7 +83,6 @@
 }
 
 func TestTemplateDeterminism(t *testing.T) {
-	t.Parallel()
 	r := &REParams{
 		Labels:      map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
 		Inputs:      []string{"$in"},
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 5a33f77..29e4bd7 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -156,7 +156,7 @@
 }
 
 func (sourceProvider *BaseSourceProvider) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
-	outFile := sourceProvider.OutputFile
+	outFile := sourceProvider.OutputFiles[0]
 	ret.Class = "ETC"
 	ret.OutputFile = android.OptionalPathForPath(outFile)
 	ret.SubName += sourceProvider.subName
diff --git a/rust/binary_test.go b/rust/binary_test.go
index 692a066..b44a5bc 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -23,7 +23,6 @@
 
 // Test that rustlibs default linkage is correct for binaries.
 func TestBinaryLinkage(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_binary {
 			name: "fizz-buzz",
@@ -87,7 +86,6 @@
 
 // Test that the path returned by HostToolPath is correct
 func TestHostToolPath(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_binary_host {
 			name: "fizz-buzz",
@@ -102,7 +100,6 @@
 
 // Test that the flags being passed to rust_binary modules are as expected
 func TestBinaryFlags(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_binary_host {
 			name: "fizz-buzz",
@@ -146,7 +143,6 @@
 }
 
 func TestLinkObjects(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_binary {
 			name: "fizz-buzz",
@@ -166,7 +162,6 @@
 
 // Test that stripped versions are correctly generated and used.
 func TestStrippedBinary(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_binary {
 			name: "foo",
diff --git a/rust/bindgen.go b/rust/bindgen.go
index ac33ff7..68f219e 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -202,7 +202,7 @@
 		},
 	})
 
-	b.BaseSourceProvider.OutputFile = outputFile
+	b.BaseSourceProvider.OutputFiles = android.Paths{outputFile}
 	return outputFile
 }
 
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index 7ff996d..9cccf13 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -20,7 +20,6 @@
 )
 
 func TestRustBindgen(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_bindgen {
 			name: "libbindgen",
@@ -67,7 +66,6 @@
 }
 
 func TestRustBindgenCustomBindgen(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_bindgen {
 			name: "libbindgen",
diff --git a/rust/builder_test.go b/rust/builder_test.go
index cda03a9..5c11cb7 100644
--- a/rust/builder_test.go
+++ b/rust/builder_test.go
@@ -17,7 +17,6 @@
 import "testing"
 
 func TestSourceProviderCollision(t *testing.T) {
-	t.Parallel()
 	testRustError(t, "multiple source providers generate the same filename output: bindings.rs", `
 		rust_binary {
 			name: "source_collider",
diff --git a/rust/clippy_test.go b/rust/clippy_test.go
index 786dc15..7815aab 100644
--- a/rust/clippy_test.go
+++ b/rust/clippy_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestClippy(t *testing.T) {
-	t.Parallel()
 
 	bp := `
 		// foo uses the default value of clippy_lints
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index 70f0dff..a25523c 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -23,7 +23,6 @@
 
 // Test that feature flags are being correctly generated.
 func TestFeaturesToFlags(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_library_host_dylib {
 			name: "libfoo",
@@ -45,7 +44,6 @@
 
 // Test that we reject multiple source files.
 func TestEnforceSingleSourceFile(t *testing.T) {
-	t.Parallel()
 
 	singleSrcError := "srcs can only contain one path for a rust file and source providers prefixed by \":\""
 
@@ -80,7 +78,6 @@
 }
 
 func TestInstallDir(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_library_dylib {
 			name: "libfoo",
@@ -111,7 +108,6 @@
 }
 
 func TestLints(t *testing.T) {
-	t.Parallel()
 
 	bp := `
 		// foo uses the default value of lints
@@ -184,7 +180,6 @@
 
 // Test that devices are linking the stdlib dynamically
 func TestStdDeviceLinkage(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_binary {
 			name: "fizz",
diff --git a/rust/config/OWNERS b/rust/config/OWNERS
new file mode 100644
index 0000000..dfff873
--- /dev/null
+++ b/rust/config/OWNERS
@@ -0,0 +1,2 @@
+per-file global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
+
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 678f822..b9a879a 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -2,7 +2,7 @@
 
 var (
 	// When adding a new path below, add a rustfmt.toml file at the root of
-	// the repository and enable the rustfmt repo hook. See aosp/1347562
+	// the repository and enable the rustfmt repo hook. See aosp/1458238
 	// for an example.
 	// TODO(b/160223496): enable rustfmt globally.
 	RustAllowedPaths = []string{
@@ -11,6 +11,7 @@
 		"external/crosvm",
 		"external/adhd",
 		"frameworks/native/libs/binder/rust",
+		"packages/modules/Virtualization",
 		"prebuilts/rust",
 		"system/extras/profcollectd",
 		"system/hardware/interfaces/keystore2",
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index ced548d..90155ca 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -23,7 +23,6 @@
 
 // Test that coverage flags are being correctly generated.
 func TestCoverageFlags(t *testing.T) {
-	t.Parallel()
 	ctx := testRustCov(t, `
 		rust_library {
 			name: "libfoo_cov",
@@ -99,7 +98,6 @@
 
 // Test coverage files are included correctly
 func TestCoverageZip(t *testing.T) {
-	t.Parallel()
 	ctx := testRustCov(t, `
 		rust_library {
 			name: "libfoo",
@@ -176,7 +174,6 @@
 }
 
 func TestCoverageDeps(t *testing.T) {
-	t.Parallel()
 	ctx := testRustCov(t, `
 		rust_binary {
 			name: "fizz",
diff --git a/rust/library.go b/rust/library.go
index 3bba089..ae33f0f 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -20,6 +20,7 @@
 	"strings"
 
 	"android/soong/android"
+	"android/soong/cc"
 )
 
 var (
@@ -484,11 +485,35 @@
 	library.coverageOutputZipFile = TransformCoverageFilesToZip(ctx, coverageFiles, library.getStem(ctx))
 
 	if library.rlib() || library.dylib() {
-		library.exportLinkDirs(deps.linkDirs...)
-		library.exportDepFlags(deps.depFlags...)
-		library.exportLinkObjects(deps.linkObjects...)
+		library.flagExporter.exportLinkDirs(deps.linkDirs...)
+		library.flagExporter.exportDepFlags(deps.depFlags...)
+		library.flagExporter.exportLinkObjects(deps.linkObjects...)
 	}
 
+	if library.static() || library.shared() {
+		ctx.SetProvider(cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
+			IncludeDirs: library.includeDirs,
+		})
+	}
+
+	if library.shared() {
+		ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{
+			SharedLibrary:           outputFile,
+			UnstrippedSharedLibrary: outputFile,
+		})
+	}
+
+	if library.static() {
+		depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build()
+		ctx.SetProvider(cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{
+			StaticLibrary: outputFile,
+
+			TransitiveStaticLibrariesForOrdering: depSet,
+		})
+	}
+
+	library.flagExporter.setProvider(ctx)
+
 	return outputFile
 }
 
diff --git a/rust/library_test.go b/rust/library_test.go
index fdab78d..fec3992 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -23,7 +23,6 @@
 
 // Test that variants are being generated correctly, and that crate-types are correct.
 func TestLibraryVariants(t *testing.T) {
-	t.Parallel()
 
 	ctx := testRust(t, `
 		rust_library_host {
@@ -72,7 +71,6 @@
 
 // Test that dylibs are not statically linking the standard library.
 func TestDylibPreferDynamic(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_library_host_dylib {
 			name: "libfoo",
@@ -88,7 +86,6 @@
 }
 
 func TestValidateLibraryStem(t *testing.T) {
-	t.Parallel()
 	testRustError(t, "crate_name must be defined.", `
 			rust_library_host {
 				name: "libfoo",
@@ -126,7 +123,6 @@
 }
 
 func TestSharedLibrary(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_ffi_shared {
 			name: "libfoo",
@@ -149,7 +145,6 @@
 }
 
 func TestStaticLibraryLinkage(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_ffi_static {
 			name: "libfoo",
@@ -167,7 +162,6 @@
 
 // Test that variants pull in the right type of rustlib autodep
 func TestAutoDeps(t *testing.T) {
-	t.Parallel()
 
 	ctx := testRust(t, `
                 rust_library_host {
@@ -215,7 +209,6 @@
 
 // Test that stripped versions are correctly generated and used.
 func TestStrippedLibrary(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_library_dylib {
 			name: "libfoo",
@@ -247,7 +240,6 @@
 }
 
 func TestLibstdLinkage(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_library {
 			name: "libfoo",
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index f9c8934..94fe1e5 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -93,7 +93,8 @@
 }
 
 func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
-	prebuilt.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
+	prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
+	prebuilt.flagExporter.setProvider(ctx)
 
 	srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
 	if len(paths) > 0 {
diff --git a/rust/project_json.go b/rust/project_json.go
index 8d161b2..5697408 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -93,7 +93,7 @@
 			return "", false
 		}
 	default:
-		if rModule.Target().String() != ctx.Config().Targets[android.Android][0].String() {
+		if rModule.Target().String() != ctx.Config().AndroidFirstDeviceTarget.String() {
 			return "", false
 		}
 	}
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 11964f3..69288fc 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -22,22 +22,15 @@
 	"testing"
 
 	"android/soong/android"
-	"android/soong/cc"
 )
 
 // testProjectJson run the generation of rust-project.json. It returns the raw
 // content of the generated file.
-func testProjectJson(t *testing.T, bp string, fs map[string][]byte) []byte {
-	cc.GatherRequiredFilesForTest(fs)
-
-	env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
-	config := android.TestArchConfig(buildDir, env, bp, fs)
-	ctx := CreateTestContext()
-	ctx.Register(config)
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	android.FailIfErrored(t, errs)
+func testProjectJson(t *testing.T, bp string) []byte {
+	tctx := newTestRustCtx(t, bp)
+	tctx.env = map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
+	tctx.generateConfig()
+	tctx.parse(t)
 
 	// The JSON file is generated via WriteFileToOutputDir. Therefore, it
 	// won't appear in the Output of the TestingSingleton. Manually verify
@@ -87,12 +80,8 @@
 		crate_name: "b",
 		rlibs: ["liba"],
 	}
-	` + GatherRequiredDepsForTest()
-	fs := map[string][]byte{
-		"a/src/lib.rs": nil,
-		"b/src/lib.rs": nil,
-	}
-	jsonContent := testProjectJson(t, bp, fs)
+	`
+	jsonContent := testProjectJson(t, bp)
 	validateJsonCrates(t, jsonContent)
 }
 
@@ -123,11 +112,8 @@
 		source_stem: "bindings2",
 		wrapper_src: "src/any.h",
 	}
-	` + GatherRequiredDepsForTest()
-	fs := map[string][]byte{
-		"src/lib.rs": nil,
-	}
-	jsonContent := testProjectJson(t, bp, fs)
+	`
+	jsonContent := testProjectJson(t, bp)
 	crates := validateJsonCrates(t, jsonContent)
 	for _, c := range crates {
 		crate, ok := c.(map[string]interface{})
@@ -166,13 +152,8 @@
 		crate_name: "b",
 		rustlibs: ["liba1", "liba2"],
 	}
-	` + GatherRequiredDepsForTest()
-	fs := map[string][]byte{
-		"a1/src/lib.rs": nil,
-		"a2/src/lib.rs": nil,
-		"b/src/lib.rs":  nil,
-	}
-	jsonContent := testProjectJson(t, bp, fs)
+	`
+	jsonContent := testProjectJson(t, bp)
 	crates := validateJsonCrates(t, jsonContent)
 	for _, crate := range crates {
 		c := crate.(map[string]interface{})
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 897300f..ebb1c3c 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -61,15 +61,22 @@
 	}
 
 	outDir := android.PathForModuleOut(ctx)
-	depFile := android.PathForModuleOut(ctx, proto.BaseSourceProvider.getStem(ctx)+".d")
-	outputs := android.WritablePaths{android.PathForModuleOut(ctx, proto.BaseSourceProvider.getStem(ctx)+".rs")}
+	stem := proto.BaseSourceProvider.getStem(ctx)
+	// rust protobuf-codegen output <stem>.rs
+	stemFile := android.PathForModuleOut(ctx, stem+".rs")
+	// add mod_<stem>.rs to import <stem>.rs
+	modFile := android.PathForModuleOut(ctx, "mod_"+stem+".rs")
+	// mod_<stem>.rs is the main/first output file to be included/compiled
+	outputs := android.WritablePaths{modFile, stemFile}
+	depFile := android.PathForModuleOut(ctx, "mod_"+stem+".d")
 
 	rule := android.NewRuleBuilder()
 	android.ProtoRule(ctx, rule, protoFile.Path(), protoFlags, protoFlags.Deps, outDir, depFile, outputs)
+	rule.Command().Text("printf '// @generated\\npub mod %s;\\n' '" + stem + "' >").Output(modFile)
 	rule.Build(pctx, ctx, "protoc_"+protoFile.Path().Rel(), "protoc "+protoFile.Path().Rel())
 
-	proto.BaseSourceProvider.OutputFile = outputs[0]
-	return outputs[0]
+	proto.BaseSourceProvider.OutputFiles = android.Paths{modFile, stemFile}
+	return modFile
 }
 
 func (proto *protobufDecorator) SourceProviderProps() []interface{} {
diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go
index cfe56a3..bd11a5a 100644
--- a/rust/protobuf_test.go
+++ b/rust/protobuf_test.go
@@ -20,7 +20,6 @@
 )
 
 func TestRustProtobuf(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_protobuf {
 			name: "librust_proto",
diff --git a/rust/rust.go b/rust/rust.go
index ba8673c..1b999d7 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -302,9 +302,6 @@
 }
 
 type exportedFlagsProducer interface {
-	exportedLinkDirs() []string
-	exportedDepFlags() []string
-	exportedLinkObjects() []string
 	exportLinkDirs(...string)
 	exportDepFlags(...string)
 	exportLinkObjects(...string)
@@ -316,18 +313,6 @@
 	linkObjects []string
 }
 
-func (flagExporter *flagExporter) exportedLinkDirs() []string {
-	return flagExporter.linkDirs
-}
-
-func (flagExporter *flagExporter) exportedDepFlags() []string {
-	return flagExporter.depFlags
-}
-
-func (flagExporter *flagExporter) exportedLinkObjects() []string {
-	return flagExporter.linkObjects
-}
-
 func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
 	flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
 }
@@ -340,16 +325,28 @@
 	flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
 }
 
+func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
+	ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
+		Flags:       flagExporter.depFlags,
+		LinkDirs:    flagExporter.linkDirs,
+		LinkObjects: flagExporter.linkObjects,
+	})
+}
+
 var _ exportedFlagsProducer = (*flagExporter)(nil)
 
 func NewFlagExporter() *flagExporter {
-	return &flagExporter{
-		depFlags:    []string{},
-		linkDirs:    []string{},
-		linkObjects: []string{},
-	}
+	return &flagExporter{}
 }
 
+type FlagExporterInfo struct {
+	Flags       []string
+	LinkDirs    []string // TODO: this should be android.Paths
+	LinkObjects []string // TODO: this should be android.Paths
+}
+
+var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{})
+
 func (mod *Module) isCoverageVariant() bool {
 	return mod.coverage.Properties.IsCoverageVariant
 }
@@ -499,22 +496,11 @@
 	panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", mod.BaseModuleName()))
 }
 
-// Rust module deps don't have a link order (?)
-func (mod *Module) SetDepsInLinkOrder([]android.Path) {}
-
-func (mod *Module) GetDepsInLinkOrder() []android.Path {
-	return []android.Path{}
-}
-
-func (mod *Module) GetStaticVariant() cc.LinkableInterface {
-	return nil
-}
-
 func (mod *Module) Module() android.Module {
 	return mod
 }
 
-func (mod *Module) StubsVersions() []string {
+func (mod *Module) StubsVersions(ctx android.BaseMutatorContext) []string {
 	// For now, Rust has no stubs versions.
 	if mod.compiler != nil {
 		if _, ok := mod.compiler.(libraryInterface); ok {
@@ -532,12 +518,6 @@
 	// For now, Rust has no notion of the recovery image
 	return false
 }
-func (mod *Module) HasStaticVariant() bool {
-	if mod.GetStaticVariant() != nil {
-		return true
-	}
-	return false
-}
 
 func (mod *Module) CoverageFiles() android.Paths {
 	if mod.compiler != nil {
@@ -701,15 +681,10 @@
 		if mod.compiler.(libraryInterface).source() {
 			mod.sourceProvider.GenerateSource(ctx, deps)
 			mod.sourceProvider.setSubName(ctx.ModuleSubDir())
-			if lib, ok := mod.compiler.(*libraryDecorator); ok {
-				lib.flagExporter.linkDirs = nil
-				lib.flagExporter.linkObjects = nil
-				lib.flagExporter.depFlags = nil
-			}
 		} else {
 			sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag)
 			sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
-			mod.sourceProvider.setOutputFile(sourceLib.sourceProvider.Srcs()[0])
+			mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs())
 		}
 	}
 
@@ -846,10 +821,11 @@
 			}
 
 			//Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
-			if lib, ok := rustDep.compiler.(exportedFlagsProducer); ok && depTag != procMacroDepTag {
-				depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedLinkDirs()...)
-				depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...)
-				depPaths.linkObjects = append(depPaths.linkObjects, lib.exportedLinkObjects()...)
+			if depTag != procMacroDepTag {
+				exportedInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
+				depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
+				depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
+				depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...)
 			}
 
 			if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
@@ -889,24 +865,22 @@
 			case cc.IsStaticDepTag(depTag):
 				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
 				depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
-				depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...)
-				if mod, ok := ccDep.(*cc.Module); ok {
-					depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...)
-					depPaths.depClangFlags = append(depPaths.depClangFlags, mod.ExportedFlags()...)
-					depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, mod.ExportedGeneratedHeaders()...)
-				}
+				exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
+				depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
+				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
+				depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
+				depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
 				depPaths.coverageFiles = append(depPaths.coverageFiles, ccDep.CoverageFiles()...)
 				directStaticLibDeps = append(directStaticLibDeps, ccDep)
 				mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName)
 			case cc.IsSharedDepTag(depTag):
 				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
 				depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
-				depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...)
-				if mod, ok := ccDep.(*cc.Module); ok {
-					depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...)
-					depPaths.depClangFlags = append(depPaths.depClangFlags, mod.ExportedFlags()...)
-					depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, mod.ExportedGeneratedHeaders()...)
-				}
+				exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
+				depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
+				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
+				depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
+				depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
 				directSharedLibDeps = append(directSharedLibDeps, ccDep)
 				mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
 				exportDep = true
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 26e943a..9b2f023 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -54,10 +54,58 @@
 	os.Exit(run())
 }
 
-func testConfig(bp string) android.Config {
-	bp = bp + GatherRequiredDepsForTest()
+// testRust returns a TestContext in which a basic environment has been setup.
+// This environment contains a few mocked files. See testRustCtx.useMockedFs
+// for the list of these files.
+func testRust(t *testing.T, bp string) *android.TestContext {
+	tctx := newTestRustCtx(t, bp)
+	tctx.useMockedFs()
+	tctx.generateConfig()
+	return tctx.parse(t)
+}
 
-	fs := map[string][]byte{
+// testRustCov returns a TestContext in which a basic environment has been
+// setup. This environment explicitly enables coverage.
+func testRustCov(t *testing.T, bp string) *android.TestContext {
+	tctx := newTestRustCtx(t, bp)
+	tctx.useMockedFs()
+	tctx.generateConfig()
+	tctx.enableCoverage(t)
+	return tctx.parse(t)
+}
+
+// testRustError ensures that at least one error was raised and its value
+// matches the pattern provided. The error can be either in the parsing of the
+// Blueprint or when generating the build actions.
+func testRustError(t *testing.T, pattern string, bp string) {
+	tctx := newTestRustCtx(t, bp)
+	tctx.useMockedFs()
+	tctx.generateConfig()
+	tctx.parseError(t, pattern)
+}
+
+// testRustCtx is used to build a particular test environment. Unless your
+// tests requires a specific setup, prefer the wrapping functions: testRust,
+// testRustCov or testRustError.
+type testRustCtx struct {
+	bp     string
+	fs     map[string][]byte
+	env    map[string]string
+	config *android.Config
+}
+
+// newTestRustCtx returns a new testRustCtx for the Blueprint definition argument.
+func newTestRustCtx(t *testing.T, bp string) *testRustCtx {
+	// TODO (b/140435149)
+	if runtime.GOOS != "linux" {
+		t.Skip("Rust Soong tests can only be run on Linux hosts currently")
+	}
+	return &testRustCtx{bp: bp}
+}
+
+// useMockedFs setup a default mocked filesystem for the test environment.
+func (tctx *testRustCtx) useMockedFs() {
+	tctx.fs = map[string][]byte{
 		"foo.rs":     nil,
 		"foo.c":      nil,
 		"src/bar.rs": nil,
@@ -66,57 +114,51 @@
 		"liby.so":    nil,
 		"libz.so":    nil,
 	}
-
-	cc.GatherRequiredFilesForTest(fs)
-
-	return android.TestArchConfig(buildDir, nil, bp, fs)
 }
 
-func testRust(t *testing.T, bp string) *android.TestContext {
-	return testRustContext(t, bp, false)
+// generateConfig creates the android.Config based on the bp, fs and env
+// attributes of the testRustCtx.
+func (tctx *testRustCtx) generateConfig() {
+	tctx.bp = tctx.bp + GatherRequiredDepsForTest()
+	cc.GatherRequiredFilesForTest(tctx.fs)
+	config := android.TestArchConfig(buildDir, tctx.env, tctx.bp, tctx.fs)
+	tctx.config = &config
 }
 
-func testRustCov(t *testing.T, bp string) *android.TestContext {
-	return testRustContext(t, bp, true)
-}
-
-func testRustContext(t *testing.T, bp string, coverage bool) *android.TestContext {
-	// TODO (b/140435149)
-	if runtime.GOOS != "linux" {
-		t.Skip("Only the Linux toolchain is supported for Rust")
+// enableCoverage configures the test to enable coverage.
+func (tctx *testRustCtx) enableCoverage(t *testing.T) {
+	if tctx.config == nil {
+		t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
 	}
+	tctx.config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
+	tctx.config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
+	tctx.config.TestProductVariables.NativeCoveragePaths = []string{"*"}
+}
 
-	t.Helper()
-	config := testConfig(bp)
-
-	if coverage {
-		config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
-		config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
-		config.TestProductVariables.NativeCoveragePaths = []string{"*"}
+// parse validates the configuration and parses the Blueprint file. It returns
+// a TestContext which can be used to retrieve the generated modules via
+// ModuleForTests.
+func (tctx testRustCtx) parse(t *testing.T) *android.TestContext {
+	if tctx.config == nil {
+		t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
 	}
-
 	ctx := CreateTestContext()
-	ctx.Register(config)
-
+	ctx.Register(*tctx.config)
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
 	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
+	_, errs = ctx.PrepareBuildActions(*tctx.config)
 	android.FailIfErrored(t, errs)
-
 	return ctx
 }
 
-func testRustError(t *testing.T, pattern string, bp string) {
-	// TODO (b/140435149)
-	if runtime.GOOS != "linux" {
-		t.Skip("Only the Linux toolchain is supported for Rust")
+// parseError parses the Blueprint file and ensure that at least one error
+// matching the provided pattern is observed.
+func (tctx testRustCtx) parseError(t *testing.T, pattern string) {
+	if tctx.config == nil {
+		t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
 	}
-
-	t.Helper()
-	config := testConfig(bp)
-
 	ctx := CreateTestContext()
-	ctx.Register(config)
+	ctx.Register(*tctx.config)
 
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
 	if len(errs) > 0 {
@@ -124,7 +166,7 @@
 		return
 	}
 
-	_, errs = ctx.PrepareBuildActions(config)
+	_, errs = ctx.PrepareBuildActions(*tctx.config)
 	if len(errs) > 0 {
 		android.FailIfNoMatchingErrors(t, pattern, errs)
 		return
@@ -135,7 +177,6 @@
 
 // Test that we can extract the link path from a lib path.
 func TestLinkPathFromFilePath(t *testing.T) {
-	t.Parallel()
 	barPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")
 	libName := linkPathFromFilePath(barPath)
 	expectedResult := "out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/"
@@ -147,7 +188,6 @@
 
 // Test to make sure dependencies are being picked up correctly.
 func TestDepsTracking(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_ffi_host_static {
 			name: "libstatic",
@@ -209,7 +249,6 @@
 }
 
 func TestSourceProviderDeps(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_binary {
 			name: "fizz-buzz-dep",
@@ -297,7 +336,6 @@
 }
 
 func TestSourceProviderTargetMismatch(t *testing.T) {
-	t.Parallel()
 	// This might error while building the dependency tree or when calling depsToPaths() depending on the lunched
 	// target, which results in two different errors. So don't check the error, just confirm there is one.
 	testRustError(t, ".*", `
@@ -320,7 +358,6 @@
 
 // Test to make sure proc_macros use host variants when building device modules.
 func TestProcMacroDeviceDeps(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_library_host_rlib {
 			name: "libbar",
@@ -348,7 +385,6 @@
 
 // Test that no_stdlibs suppresses dependencies on rust standard libraries
 func TestNoStdlibs(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_binary {
 			name: "fizz-buzz",
@@ -364,7 +400,6 @@
 
 // Test that libraries provide both 32-bit and 64-bit variants.
 func TestMultilib(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_library_rlib {
 			name: "libfoo",
diff --git a/rust/source_provider.go b/rust/source_provider.go
index 03adf9e..436518c 100644
--- a/rust/source_provider.go
+++ b/rust/source_provider.go
@@ -30,7 +30,7 @@
 type BaseSourceProvider struct {
 	Properties SourceProviderProperties
 
-	OutputFile       android.Path
+	OutputFiles      android.Paths
 	subAndroidMkOnce map[SubAndroidMkProvider]bool
 	subName          string
 }
@@ -43,11 +43,11 @@
 	SourceProviderProps() []interface{}
 	SourceProviderDeps(ctx DepsContext, deps Deps) Deps
 	setSubName(subName string)
-	setOutputFile(outputFile android.Path)
+	setOutputFiles(outputFiles android.Paths)
 }
 
 func (sp *BaseSourceProvider) Srcs() android.Paths {
-	return android.Paths{sp.OutputFile}
+	return sp.OutputFiles
 }
 
 func (sp *BaseSourceProvider) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
@@ -97,6 +97,6 @@
 	sp.subName = subName
 }
 
-func (sp *BaseSourceProvider) setOutputFile(outputFile android.Path) {
-	sp.OutputFile = outputFile
+func (sp *BaseSourceProvider) setOutputFiles(outputFiles android.Paths) {
+	sp.OutputFiles = outputFiles
 }
diff --git a/rust/source_provider_test.go b/rust/source_provider_test.go
index f16d694..6e68ae6 100644
--- a/rust/source_provider_test.go
+++ b/rust/source_provider_test.go
@@ -21,7 +21,6 @@
 var stemRequiredError = "source_stem property is undefined but required for rust_bindgen modules"
 
 func TestSourceProviderRequiredFields(t *testing.T) {
-	t.Parallel()
 	testRustError(t, stemRequiredError, `
 		rust_bindgen {
 			name: "libbindgen",
diff --git a/rust/test_test.go b/rust/test_test.go
index bb4695a..fea2ad0 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -22,7 +22,6 @@
 )
 
 func TestRustTest(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_test_host {
 			name: "my_test",
@@ -38,7 +37,6 @@
 }
 
 func TestRustTestLinkage(t *testing.T) {
-	t.Parallel()
 	ctx := testRust(t, `
 		rust_test {
 			name: "my_test",
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 7782c68..92f5c53 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -206,3 +206,22 @@
         "ninja_rsp.py",
     ],
 }
+
+python_binary_host {
+    name: "conv_linker_config",
+    srcs: [
+        "conv_linker_config.py",
+    ],
+    version: {
+        py2: {
+            enabled: false,
+        },
+        py3: {
+            enabled: true,
+            embedded_launcher: true,
+        },
+    },
+    libs: [
+        "linker_config_proto",
+    ],
+}
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 8c64424..8198083 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -2,3 +2,4 @@
 per-file build-mainline-modules.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
 per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
 per-file construct_context.py = ngeoffray@google.com,calin@google.com,mathieuc@google.com,skvadrik@google.com
+per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com
diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py
new file mode 100644
index 0000000..86f788d
--- /dev/null
+++ b/scripts/conv_linker_config.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# 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.
+""" A tool to convert json file into pb with linker config format."""
+
+import argparse
+import collections
+import json
+
+import linker_config_pb2
+from google.protobuf.json_format import ParseDict
+from google.protobuf.text_format import MessageToString
+
+
+def Proto(args):
+  with open(args.source) as f:
+    obj = json.load(f, object_pairs_hook=collections.OrderedDict)
+  pb = ParseDict(obj, linker_config_pb2.LinkerConfig())
+  with open(args.output, 'wb') as f:
+    f.write(pb.SerializeToString())
+
+
+def Print(args):
+  with open(args.source, 'rb') as f:
+    pb = linker_config_pb2.LinkerConfig()
+    pb.ParseFromString(f.read())
+  print(MessageToString(pb))
+
+
+def GetArgParser():
+  parser = argparse.ArgumentParser()
+  subparsers = parser.add_subparsers()
+
+  parser_proto = subparsers.add_parser(
+      'proto', help='Convert the input JSON configuration file into protobuf.')
+  parser_proto.add_argument(
+      '-s',
+      '--source',
+      required=True,
+      type=str,
+      help='Source linker configuration file in JSON.')
+  parser_proto.add_argument(
+      '-o',
+      '--output',
+      required=True,
+      type=str,
+      help='Target path to create protobuf file.')
+  parser_proto.set_defaults(func=Proto)
+
+  print_proto = subparsers.add_parser(
+      'print', help='Print configuration in human-readable text format.')
+  print_proto.add_argument(
+      '-s',
+      '--source',
+      required=True,
+      type=str,
+      help='Source linker configuration file in protobuf.')
+  print_proto.set_defaults(func=Print)
+
+  return parser
+
+
+def main():
+  args = GetArgParser().parse_args()
+  args.func(args)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
index 4cd54c7..e1edc51 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -180,7 +180,6 @@
 }
 
 func TestTransformRemoveProperty(t *testing.T) {
-	t.Parallel()
 
 	helper := &TestHelper{t}
 
@@ -196,7 +195,6 @@
 }
 
 func TestTransformRemovePropertySet(t *testing.T) {
-	t.Parallel()
 
 	helper := &TestHelper{t}
 
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index e0cba09..c214e75 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -40,7 +40,6 @@
 // Contains tests for SDK members provided by the cc package.
 
 func TestSingleDeviceOsAssumption(t *testing.T) {
-	t.Parallel()
 	// Mock a module with DeviceSupported() == true.
 	s := &sdk{}
 	android.InitAndroidArchModule(s, android.DeviceSupported, android.MultilibCommon)
@@ -55,7 +54,6 @@
 }
 
 func TestSdkIsCompileMultilibBoth(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -86,7 +84,6 @@
 }
 
 func TestSdkCompileMultilibOverride(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -178,7 +175,6 @@
 }
 
 func TestBasicSdkWithCc(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -285,7 +281,6 @@
 
 // Make sure the sdk can use host specific cc libraries static/shared and both.
 func TestHostSdkWithCc(t *testing.T) {
-	t.Parallel()
 	testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -309,7 +304,6 @@
 
 // Make sure the sdk can use cc libraries static/shared and both.
 func TestSdkWithCc(t *testing.T) {
-	t.Parallel()
 	testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -340,7 +334,6 @@
 }
 
 func TestSnapshotWithObject(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -412,7 +405,6 @@
 }
 
 func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -454,7 +446,6 @@
 // handling is tested with the sanitize clauses (but note there's a lot of
 // built-in logic in sanitize.go that can affect those flags).
 func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -568,7 +559,6 @@
 }
 
 func TestSnapshotWithCcBinary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "mymodule_exports",
@@ -633,7 +623,6 @@
 }
 
 func TestMultipleHostOsTypesSnapshotWithCcBinary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -760,7 +749,6 @@
 }
 
 func TestSnapshotWithSingleHostOsType(t *testing.T) {
-	t.Parallel()
 	ctx, config := testSdkContext(`
 		cc_defaults {
 			name: "mydefaults",
@@ -924,7 +912,6 @@
 // Test that we support the necessary flags for the linker binary, which is
 // special in several ways.
 func TestSnapshotWithCcStaticNocrtBinary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "mymodule_exports",
@@ -1027,7 +1014,6 @@
 }
 
 func TestSnapshotWithCcSharedLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -1121,7 +1107,6 @@
 }
 
 func TestSnapshotWithCcSharedLibrarySharedLibs(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -1316,7 +1301,6 @@
 }
 
 func TestHostSnapshotWithCcSharedLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -1434,7 +1418,6 @@
 }
 
 func TestMultipleHostOsTypesSnapshotWithCcSharedLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -1560,7 +1543,6 @@
 }
 
 func TestSnapshotWithCcStaticLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -1645,7 +1627,6 @@
 }
 
 func TestHostSnapshotWithCcStaticLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -1760,7 +1741,6 @@
 }
 
 func TestSnapshotWithCcLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -1858,7 +1838,6 @@
 }
 
 func TestHostSnapshotWithMultiLib64(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		module_exports {
 			name: "myexports",
@@ -1966,7 +1945,6 @@
 }
 
 func TestSnapshotWithCcHeadersLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2015,7 +1993,6 @@
 }
 
 func TestHostSnapshotWithCcHeadersLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2098,7 +2075,6 @@
 }
 
 func TestDeviceAndHostSnapshotWithCcHeadersLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2194,7 +2170,6 @@
 }
 
 func TestSystemSharedLibPropagation(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2432,7 +2407,6 @@
 }
 
 func TestStubsLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2511,7 +2485,6 @@
 }
 
 func TestDeviceAndHostSnapshotWithStubsLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -2628,7 +2601,6 @@
 }
 
 func TestUniqueHostSoname(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
index 173ccb9..aa1200f 100644
--- a/sdk/exports_test.go
+++ b/sdk/exports_test.go
@@ -20,7 +20,6 @@
 
 // Ensure that module_exports generates a module_exports_snapshot module.
 func TestModuleExportsSnapshot(t *testing.T) {
-	t.Parallel()
 	packageBp := `
 		module_exports {
 			name: "myexports",
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index f86ab57..d6828c9 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -92,7 +92,6 @@
 // Contains tests for SDK members provided by the java package.
 
 func TestSdkDependsOnSourceEvenWhenPrebuiltPreferred(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -142,7 +141,6 @@
 }
 
 func TestBasicSdkWithJavaLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -222,7 +220,6 @@
 }
 
 func TestSnapshotWithJavaHeaderLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -275,7 +272,6 @@
 }
 
 func TestHostSnapshotWithJavaHeaderLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -336,7 +332,6 @@
 }
 
 func TestDeviceAndHostSnapshotWithJavaHeaderLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -403,7 +398,6 @@
 }
 
 func TestSnapshotWithJavaImplLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		module_exports {
 			name: "myexports",
@@ -457,7 +451,6 @@
 }
 
 func TestHostSnapshotWithJavaImplLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		module_exports {
 			name: "myexports",
@@ -518,7 +511,6 @@
 }
 
 func TestSnapshotWithJavaTest(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		module_exports {
 			name: "myexports",
@@ -569,7 +561,6 @@
 }
 
 func TestHostSnapshotWithJavaTest(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		module_exports {
 			name: "myexports",
@@ -642,7 +633,6 @@
 // directly or indirectly from an APEX as droidstubs can never be a part of an
 // apex.
 func TestBasicSdkWithDroidstubs(t *testing.T) {
-	t.Parallel()
 	testSdkWithDroidstubs(t, `
 		sdk {
 				name: "mysdk",
@@ -673,7 +663,6 @@
 }
 
 func TestSnapshotWithDroidstubs(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithDroidstubs(t, `
 		module_exports {
 			name: "myexports",
@@ -719,7 +708,6 @@
 }
 
 func TestHostSnapshotWithDroidstubs(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithDroidstubs(t, `
 		module_exports {
 			name: "myexports",
@@ -774,7 +762,6 @@
 }
 
 func TestSnapshotWithJavaSystemModules(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -869,7 +856,6 @@
 }
 
 func TestHostSnapshotWithJavaSystemModules(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -948,7 +934,6 @@
 }
 
 func TestDeviceAndHostSnapshotWithOsSpecificMembers(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		module_exports {
 			name: "myexports",
@@ -1076,7 +1061,6 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -1181,7 +1165,6 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_SdkVersion_None(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -1246,7 +1229,6 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -1314,7 +1296,6 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_ApiScopes(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -1405,7 +1386,6 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_ModuleLib(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -1517,7 +1497,6 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_SystemServer(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -1608,7 +1587,6 @@
 }
 
 func TestSnapshotWithJavaSdkLibrary_NamingScheme(t *testing.T) {
-	t.Parallel()
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index a6afdc5..2e6c62a 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -35,7 +35,6 @@
 }
 
 func TestDepNotInRequiredSdks(t *testing.T) {
-	t.Parallel()
 	testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, `
 		sdk {
 			name: "mysdk",
@@ -96,7 +95,6 @@
 // Ensure that prebuilt modules have the same effective visibility as the source
 // modules.
 func TestSnapshotVisibility(t *testing.T) {
-	t.Parallel()
 	packageBp := `
 		package {
 			default_visibility: ["//other/foo"],
@@ -304,7 +302,6 @@
 }
 
 func TestSDkInstall(t *testing.T) {
-	t.Parallel()
 	sdk := `
 		sdk {
 			name: "mysdk",
@@ -349,7 +346,6 @@
 var _ propertiesContainer = (*testPropertiesStruct)(nil)
 
 func TestCommonValueOptimization(t *testing.T) {
-	t.Parallel()
 	common := &testPropertiesStruct{name: "common"}
 	structs := []propertiesContainer{
 		&testPropertiesStruct{
@@ -447,7 +443,6 @@
 }
 
 func TestCommonValueOptimization_InvalidArchSpecificVariants(t *testing.T) {
-	t.Parallel()
 	common := &testPropertiesStruct{name: "common"}
 	structs := []propertiesContainer{
 		&testPropertiesStruct{
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 7c3cdbd..e807877 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -261,7 +261,7 @@
 	ctx.AddFarVariationDependencies(append(ctx.Target().Variations(), sharedLibVariations...),
 		shTestDataLibsTag, s.testProperties.Data_libs...)
 	if ctx.Target().Os.Class == android.Host && len(ctx.Config().Targets[android.Android]) > 0 {
-		deviceVariations := ctx.Config().Targets[android.Android][0].Variations()
+		deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
 		ctx.AddFarVariationDependencies(deviceVariations, shTestDataDeviceBinsTag, s.testProperties.Data_device_bins...)
 		ctx.AddFarVariationDependencies(append(deviceVariations, sharedLibVariations...),
 			shTestDataDeviceLibsTag, s.testProperties.Data_device_libs...)
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index e9086be..0aa607b 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -61,7 +61,6 @@
 }
 
 func TestShTestSubDir(t *testing.T) {
-	t.Parallel()
 	ctx, config := testShBinary(t, `
 		sh_test {
 			name: "foo",
@@ -82,7 +81,6 @@
 }
 
 func TestShTest(t *testing.T) {
-	t.Parallel()
 	ctx, config := testShBinary(t, `
 		sh_test {
 			name: "foo",
@@ -113,7 +111,6 @@
 }
 
 func TestShTest_dataModules(t *testing.T) {
-	t.Parallel()
 	ctx, config := testShBinary(t, `
 		sh_test {
 			name: "foo",
@@ -173,7 +170,6 @@
 }
 
 func TestShTestHost(t *testing.T) {
-	t.Parallel()
 	ctx, _ := testShBinary(t, `
 		sh_test_host {
 			name: "foo",
@@ -194,7 +190,6 @@
 }
 
 func TestShTestHost_dataDeviceModules(t *testing.T) {
-	t.Parallel()
 	ctx, config := testShBinary(t, `
 		sh_test_host {
 			name: "foo",
diff --git a/symbol_inject/elf_test.go b/symbol_inject/elf_test.go
index 316c69a..aceee44 100644
--- a/symbol_inject/elf_test.go
+++ b/symbol_inject/elf_test.go
@@ -20,7 +20,6 @@
 )
 
 func TestElfSymbolTable(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		file         *mockElfFile
 		symbol       string
diff --git a/symbol_inject/macho_test.go b/symbol_inject/macho_test.go
index d5b962d..50df131 100644
--- a/symbol_inject/macho_test.go
+++ b/symbol_inject/macho_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestMachoSymbolTable(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		file         *macho.File
 		symbol       string
diff --git a/symbol_inject/pe_test.go b/symbol_inject/pe_test.go
index 16b2009..df7bac3 100644
--- a/symbol_inject/pe_test.go
+++ b/symbol_inject/pe_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestPESymbolTable(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		file         *pe.File
 		symbol       string
diff --git a/symbol_inject/symbol_inject_test.go b/symbol_inject/symbol_inject_test.go
index ab874b9..6607e65 100644
--- a/symbol_inject/symbol_inject_test.go
+++ b/symbol_inject/symbol_inject_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestCopyAndInject(t *testing.T) {
-	t.Parallel()
 	s := "abcdefghijklmnopqrstuvwxyz"
 	testCases := []struct {
 		offset   uint64
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 7df0f3d..711129c 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -158,7 +158,6 @@
 }
 
 func TestSyspropLibrary(t *testing.T) {
-	t.Parallel()
 	ctx := test(t, `
 		sysprop_library {
 			name: "sysprop-platform",
diff --git a/tradefed/Android.bp b/tradefed/Android.bp
index 6e5e533..4e4e6a7 100644
--- a/tradefed/Android.bp
+++ b/tradefed/Android.bp
@@ -12,3 +12,20 @@
     ],
     pluginFor: ["soong_build"],
 }
+
+bootstrap_go_package {
+    name: "soong-suite-harness",
+    pkgPath: "android/soong/tradefed/suite_harness",
+    deps: [
+        "blueprint",
+        "blueprint-pathtools",
+        "blueprint-proptools",
+        "soong",
+        "soong-android",
+        "soong-java",
+    ],
+    srcs: [
+        "suite_harness/tradefed_binary.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/tradefed/suite_harness/tradefed_binary.go b/tradefed/suite_harness/tradefed_binary.go
new file mode 100644
index 0000000..1bd4f93
--- /dev/null
+++ b/tradefed/suite_harness/tradefed_binary.go
@@ -0,0 +1,164 @@
+// Copyright 2018 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 suite_harness
+
+import (
+	"strings"
+
+	"github.com/google/blueprint"
+
+	"android/soong/android"
+	"android/soong/java"
+)
+
+var pctx = android.NewPackageContext("android/soong/tradefed/suite_harness")
+
+func init() {
+	android.RegisterModuleType("tradefed_binary_host", tradefedBinaryFactory)
+
+	pctx.Import("android/soong/android")
+}
+
+type TradefedBinaryProperties struct {
+	Short_name                    string
+	Full_name                     string
+	Version                       string
+	Prepend_platform_version_name bool
+}
+
+// tradefedBinaryFactory creates an empty module for the tradefed_binary module type,
+// which is a java_binary with some additional processing in tradefedBinaryLoadHook.
+func tradefedBinaryFactory() android.Module {
+	props := &TradefedBinaryProperties{}
+	module := java.BinaryHostFactory()
+	module.AddProperties(props)
+	android.AddLoadHook(module, tradefedBinaryLoadHook(props))
+
+	return module
+}
+
+const genSuffix = "-gen"
+
+// tradefedBinaryLoadHook adds extra resources and libraries to tradefed_binary modules.
+func tradefedBinaryLoadHook(tfb *TradefedBinaryProperties) func(ctx android.LoadHookContext) {
+	return func(ctx android.LoadHookContext) {
+		genName := ctx.ModuleName() + genSuffix
+		version := tfb.Version
+		if tfb.Prepend_platform_version_name {
+			version = ctx.Config().PlatformVersionName() + tfb.Version
+		}
+
+		// Create a submodule that generates the test-suite-info.properties file
+		// and copies DynamicConfig.xml if it is present.
+		ctx.CreateModule(tradefedBinaryGenFactory,
+			&TradefedBinaryGenProperties{
+				Name:       &genName,
+				Short_name: tfb.Short_name,
+				Full_name:  tfb.Full_name,
+				Version:    version,
+			})
+
+		props := struct {
+			Java_resources []string
+			Libs           []string
+		}{}
+
+		// Add dependencies required by all tradefed_binary modules.
+		props.Libs = []string{
+			"tradefed",
+			"tradefed-test-framework",
+			"loganalysis",
+			"hosttestlib",
+			"compatibility-host-util",
+		}
+
+		// Add the files generated by the submodule created above to the resources.
+		props.Java_resources = []string{":" + genName}
+
+		ctx.AppendProperties(&props)
+
+	}
+}
+
+type TradefedBinaryGenProperties struct {
+	Name       *string
+	Short_name string
+	Full_name  string
+	Version    string
+}
+
+type tradefedBinaryGen struct {
+	android.ModuleBase
+
+	properties TradefedBinaryGenProperties
+
+	gen android.Paths
+}
+
+func tradefedBinaryGenFactory() android.Module {
+	tfg := &tradefedBinaryGen{}
+	tfg.AddProperties(&tfg.properties)
+	android.InitAndroidModule(tfg)
+	return tfg
+}
+
+func (tfg *tradefedBinaryGen) DepsMutator(android.BottomUpMutatorContext) {}
+
+var tradefedBinaryGenRule = pctx.StaticRule("tradefedBinaryGenRule", blueprint.RuleParams{
+	Command: `rm -f $out && touch $out && ` +
+		`echo "# This file is auto generated by Android.mk. Do not modify." >> $out && ` +
+		`echo "build_number = $$(cat ${buildNumberFile})" >> $out && ` +
+		`echo "target_arch = ${arch}" >> $out && ` +
+		`echo "name = ${name}" >> $out && ` +
+		`echo "fullname = ${fullname}" >> $out && ` +
+		`echo "version = ${version}" >> $out`,
+}, "buildNumberFile", "arch", "name", "fullname", "version")
+
+func (tfg *tradefedBinaryGen) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	buildNumberFile := ctx.Config().BuildNumberFile(ctx)
+	outputFile := android.PathForModuleOut(ctx, "test-suite-info.properties")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:      tradefedBinaryGenRule,
+		Output:    outputFile,
+		OrderOnly: android.Paths{buildNumberFile},
+		Args: map[string]string{
+			"buildNumberFile": buildNumberFile.String(),
+			"arch":            ctx.Config().DevicePrimaryArchType().String(),
+			"name":            tfg.properties.Short_name,
+			"fullname":        tfg.properties.Full_name,
+			"version":         tfg.properties.Version,
+		},
+	})
+
+	tfg.gen = append(tfg.gen, outputFile)
+
+	dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+	if dynamicConfig.Valid() {
+		outputFile := android.PathForModuleOut(ctx, strings.TrimSuffix(ctx.ModuleName(), genSuffix)+".dynamic")
+		ctx.Build(pctx, android.BuildParams{
+			Rule:   android.Cp,
+			Input:  dynamicConfig.Path(),
+			Output: outputFile,
+		})
+
+		tfg.gen = append(tfg.gen, outputFile)
+	}
+}
+
+func (tfg *tradefedBinaryGen) Srcs() android.Paths {
+	return append(android.Paths(nil), tfg.gen...)
+}
+
+var _ android.SourceFileProducer = (*tradefedBinaryGen)(nil)
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index e1123e0..03e884a 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -80,6 +80,10 @@
 		return filepath.Join(hostOutPath, path)
 	}
 
+	hostCommonOut := func(path string) string {
+		return filepath.Join(config.hostOutRoot(), "common", path)
+	}
+
 	productOutPath := config.ProductOut()
 	productOut := func(path string) string {
 		return filepath.Join(productOutPath, path)
@@ -101,6 +105,7 @@
 		hostOut("vts"),
 		hostOut("vts10"),
 		hostOut("vts-core"),
+		hostCommonOut("obj/PACKAGING"),
 		productOut("*.img"),
 		productOut("*.zip"),
 		productOut("android-info.txt"),
@@ -122,6 +127,7 @@
 		productOut("system"),
 		productOut("system_other"),
 		productOut("vendor"),
+		productOut("vendor_dlkm"),
 		productOut("product"),
 		productOut("system_ext"),
 		productOut("oem"),
@@ -131,6 +137,7 @@
 		productOut("coverage"),
 		productOut("installer"),
 		productOut("odm"),
+		productOut("odm_dlkm"),
 		productOut("sysloader"),
 		productOut("testcases"))
 }
diff --git a/ui/build/cleanbuild_test.go b/ui/build/cleanbuild_test.go
index be60362..89f4ad9 100644
--- a/ui/build/cleanbuild_test.go
+++ b/ui/build/cleanbuild_test.go
@@ -27,7 +27,6 @@
 )
 
 func TestCleanOldFiles(t *testing.T) {
-	t.Parallel()
 	dir, err := ioutil.TempDir("", "testcleanoldfiles")
 	if err != nil {
 		t.Fatal(err)
diff --git a/ui/build/config.go b/ui/build/config.go
index 5445c78..82df8a0 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -297,6 +297,12 @@
 		UseRbe:       proto.Bool(config.UseRBE()),
 	}
 	ctx.Metrics.BuildConfig(b)
+
+	s := &smpb.SystemResourceInfo{
+		TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
+		AvailableCpus:       proto.Int32(int32(runtime.NumCPU())),
+	}
+	ctx.Metrics.SystemResourceInfo(s)
 }
 
 // getConfigArgs processes the command arguments based on the build action and creates a set of new
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 35c6ed4..7b14c47 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -39,7 +39,6 @@
 }
 
 func TestConfigParseArgsJK(t *testing.T) {
-	t.Parallel()
 	ctx := testContext()
 
 	testCases := []struct {
@@ -112,7 +111,6 @@
 }
 
 func TestConfigParseArgsVars(t *testing.T) {
-	t.Parallel()
 	ctx := testContext()
 
 	testCases := []struct {
@@ -640,7 +638,6 @@
 }
 
 func TestConfigSplitArgs(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		// ********* Setup *********
 		// Test description.
diff --git a/ui/build/environment_test.go b/ui/build/environment_test.go
index d8f83f4..37f500f 100644
--- a/ui/build/environment_test.go
+++ b/ui/build/environment_test.go
@@ -21,7 +21,6 @@
 )
 
 func TestEnvUnset(t *testing.T) {
-	t.Parallel()
 	initial := &Environment{"TEST=1", "TEST2=0"}
 	initial.Unset("TEST")
 	got := initial.Environ()
@@ -31,7 +30,6 @@
 }
 
 func TestEnvUnsetMissing(t *testing.T) {
-	t.Parallel()
 	initial := &Environment{"TEST2=0"}
 	initial.Unset("TEST")
 	got := initial.Environ()
@@ -41,7 +39,6 @@
 }
 
 func TestEnvSet(t *testing.T) {
-	t.Parallel()
 	initial := &Environment{}
 	initial.Set("TEST", "0")
 	got := initial.Environ()
@@ -51,7 +48,6 @@
 }
 
 func TestEnvSetDup(t *testing.T) {
-	t.Parallel()
 	initial := &Environment{"TEST=1"}
 	initial.Set("TEST", "0")
 	got := initial.Environ()
@@ -61,7 +57,6 @@
 }
 
 func TestEnvAllow(t *testing.T) {
-	t.Parallel()
 	initial := &Environment{"TEST=1", "TEST2=0", "TEST3=2"}
 	initial.Allow("TEST3", "TEST")
 	got := initial.Environ()
@@ -78,7 +73,6 @@
 `
 
 func TestEnvAppendFromKati(t *testing.T) {
-	t.Parallel()
 	initial := &Environment{"CLANG=/usr/bin/clang", "TEST=0"}
 	err := initial.appendFromKati(strings.NewReader(testKatiEnvFileContents))
 	if err != nil {
diff --git a/ui/build/finder.go b/ui/build/finder.go
index c019ea2..7a85657 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -63,10 +63,13 @@
 			"AndroidProducts.mk",
 			"Android.bp",
 			"Blueprints",
+			"BUILD.bazel",
 			"CleanSpec.mk",
 			"OWNERS",
 			"TEST_MAPPING",
+			"WORKSPACE",
 		},
+		IncludeSuffixes: []string{".bzl"},
 	}
 	dumpDir := config.FileListDir()
 	f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard),
@@ -77,6 +80,16 @@
 	return f
 }
 
+func findBazelFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
+	matches := []string{}
+	for _, foundName := range entries.FileNames {
+		if foundName == "BUILD.bazel" || foundName == "WORKSPACE" || strings.HasSuffix(foundName, ".bzl") {
+			matches = append(matches, foundName)
+		}
+	}
+	return entries.DirNames, matches
+}
+
 // FindSources searches for source files known to <f> and writes them to the filesystem for
 // use later.
 func FindSources(ctx Context, config Config, f *finder.Finder) {
@@ -99,6 +112,12 @@
 		ctx.Fatalf("Could not export product list: %v", err)
 	}
 
+	bazelFiles := f.FindMatching(".", findBazelFiles)
+	err = dumpListToFile(ctx, config, bazelFiles, filepath.Join(dumpDir, "bazel.list"))
+	if err != nil {
+		ctx.Fatalf("Could not export bazel BUILD list: %v", err)
+	}
+
 	cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
 	err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
 	if err != nil {
diff --git a/ui/build/paths/logs_test.go b/ui/build/paths/logs_test.go
index d5921a8..3b1005f 100644
--- a/ui/build/paths/logs_test.go
+++ b/ui/build/paths/logs_test.go
@@ -26,7 +26,6 @@
 )
 
 func TestSendLog(t *testing.T) {
-	t.Parallel()
 	t.Run("Short name", func(t *testing.T) {
 		d, err := ioutil.TempDir("", "s")
 		if err != nil {
@@ -106,7 +105,6 @@
 }
 
 func TestSendLogError(t *testing.T) {
-	t.Parallel()
 	d, err := ioutil.TempDir("", "log_socket")
 	if err != nil {
 		t.Fatal(err)
diff --git a/ui/build/proc_sync_test.go b/ui/build/proc_sync_test.go
index 1b52fce..857bea3 100644
--- a/ui/build/proc_sync_test.go
+++ b/ui/build/proc_sync_test.go
@@ -108,7 +108,6 @@
 
 // simple test
 func TestGetLock(t *testing.T) {
-	t.Parallel()
 	lockfile := lockOrFail(t)
 	defer removeTestLock(lockfile)
 }
@@ -120,7 +119,6 @@
 var busyStatus = 2
 
 func TestTrylock(t *testing.T) {
-	t.Parallel()
 	lockpath := os.Getenv(lockPathVariable)
 	if len(lockpath) < 1 {
 		checkTrylockMainProcess(t)
@@ -206,7 +204,6 @@
 }
 
 func TestLockFirstTrySucceeds(t *testing.T) {
-	t.Parallel()
 	noopLogger := logger.New(ioutil.Discard)
 	lock := testLockCountingTo(0)
 	waiter := newCountWaiter(0)
@@ -219,7 +216,6 @@
 	}
 }
 func TestLockThirdTrySucceeds(t *testing.T) {
-	t.Parallel()
 	noopLogger := logger.New(ioutil.Discard)
 	lock := testLockCountingTo(2)
 	waiter := newCountWaiter(2)
@@ -232,7 +228,6 @@
 	}
 }
 func TestLockTimedOut(t *testing.T) {
-	t.Parallel()
 	noopLogger := logger.New(ioutil.Discard)
 	lock := testLockCountingTo(3)
 	waiter := newCountWaiter(2)
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 182c544..64f3d4c 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -34,6 +34,8 @@
 
 	// RBE metrics proto buffer file
 	rbeMetricsPBFilename = "rbe_metrics.pb"
+
+	defaultOutDir = "out"
 )
 
 func rbeCommand(ctx Context, config Config, rbeCmd string) string {
@@ -151,3 +153,16 @@
 		ctx.Fatalf("failed to copy %q to %q: %v\n", metricsFile, filename, err)
 	}
 }
+
+// PrintOutDirWarning prints a warning to indicate to the user that
+// setting output directory to a path other than "out" in an RBE enabled
+// build can cause slow builds.
+func PrintOutDirWarning(ctx Context, config Config) {
+	if config.UseRBE() && config.OutDir() != defaultOutDir {
+		fmt.Fprintln(ctx.Writer, "")
+		fmt.Fprintln(ctx.Writer, "\033[33mWARNING:\033[0m")
+		fmt.Fprintln(ctx.Writer, fmt.Sprintf("Setting OUT_DIR to a path other than %v may result in slow RBE builds.", defaultOutDir))
+		fmt.Fprintln(ctx.Writer, "See http://go/android_rbe_out_dir for a workaround.")
+		fmt.Fprintln(ctx.Writer, "")
+	}
+}
diff --git a/ui/build/rbe_test.go b/ui/build/rbe_test.go
index fa371bb..8ff96bc 100644
--- a/ui/build/rbe_test.go
+++ b/ui/build/rbe_test.go
@@ -26,7 +26,6 @@
 )
 
 func TestDumpRBEMetrics(t *testing.T) {
-	t.Parallel()
 	ctx := testContext()
 	tests := []struct {
 		description string
@@ -82,7 +81,6 @@
 }
 
 func TestDumpRBEMetricsErrors(t *testing.T) {
-	t.Parallel()
 	ctx := testContext()
 	tests := []struct {
 		description      string
diff --git a/ui/build/util_test.go b/ui/build/util_test.go
index a06c3e9..b22e997 100644
--- a/ui/build/util_test.go
+++ b/ui/build/util_test.go
@@ -25,7 +25,6 @@
 )
 
 func TestEnsureEmptyDirs(t *testing.T) {
-	t.Parallel()
 	ctx := testContext()
 	defer logger.Recover(func(err error) {
 		t.Error(err)
@@ -53,7 +52,6 @@
 }
 
 func TestCopyFile(t *testing.T) {
-	t.Parallel()
 	tmpDir, err := ioutil.TempDir("", "test_copy_file")
 	if err != nil {
 		t.Fatalf("failed to create temporary directory to hold test text files: %v", err)
@@ -88,7 +86,6 @@
 }
 
 func TestCopyFileErrors(t *testing.T) {
-	t.Parallel()
 	tmpDir, err := ioutil.TempDir("", "test_copy_file_errors")
 	if err != nil {
 		t.Fatalf("failed to create temporary directory to hold test text files: %v", err)
diff --git a/ui/logger/logger_test.go b/ui/logger/logger_test.go
index 7b3791c..044e6f0 100644
--- a/ui/logger/logger_test.go
+++ b/ui/logger/logger_test.go
@@ -29,7 +29,6 @@
 )
 
 func TestCreateFileWithRotation(t *testing.T) {
-	t.Parallel()
 	dir, err := ioutil.TempDir("", "test-rotation")
 	if err != nil {
 		t.Fatalf("Failed to get TempDir: %v", err)
@@ -97,7 +96,6 @@
 }
 
 func TestPanic(t *testing.T) {
-	t.Parallel()
 	if os.Getenv("ACTUALLY_PANIC") == "1" {
 		panicValue := "foo"
 		log := New(&bytes.Buffer{})
@@ -130,7 +128,6 @@
 }
 
 func TestFatal(t *testing.T) {
-	t.Parallel()
 	if os.Getenv("ACTUALLY_FATAL") == "1" {
 		log := New(&bytes.Buffer{})
 		defer func() {
@@ -153,7 +150,6 @@
 }
 
 func TestNonFatal(t *testing.T) {
-	t.Parallel()
 	if os.Getenv("ACTUAL_TEST") == "1" {
 		log := New(&bytes.Buffer{})
 		defer log.Cleanup()
@@ -170,7 +166,6 @@
 }
 
 func TestRecoverFatal(t *testing.T) {
-	t.Parallel()
 	log := New(&bytes.Buffer{})
 	defer func() {
 		if p := recover(); p != nil {
@@ -187,7 +182,6 @@
 }
 
 func TestRecoverNonFatal(t *testing.T) {
-	t.Parallel()
 	log := New(&bytes.Buffer{})
 	defer func() {
 		if p := recover(); p == nil {
@@ -204,7 +198,6 @@
 }
 
 func TestRuntimePanic(t *testing.T) {
-	t.Parallel()
 	defer func() {
 		if p := recover(); p == nil {
 			t.Errorf("Panic not thrown")
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index f5552a3..35d1976 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -70,6 +70,10 @@
 	m.metrics.BuildConfig = b
 }
 
+func (m *Metrics) SystemResourceInfo(b *soong_metrics_proto.SystemResourceInfo) {
+	m.metrics.SystemResourceInfo = b
+}
+
 func (m *Metrics) SetMetadataMetrics(metadata map[string]string) {
 	for k, v := range metadata {
 		switch k {
@@ -139,7 +143,12 @@
 }
 
 // exports the output to the file at outputPath
-func (m *Metrics) Dump(outputPath string) (err error) {
+func (m *Metrics) Dump(outputPath string) error {
+	// ignore the error if the hostname could not be retrieved as it
+	// is not a critical metric to extract.
+	if hostname, err := os.Hostname(); err == nil {
+		m.metrics.Hostname = proto.String(hostname)
+	}
 	m.metrics.HostOs = proto.String(runtime.GOOS)
 	return writeMessageToFile(&m.metrics, outputPath)
 }
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 05efe13..e824f6b 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -152,7 +152,7 @@
 }
 
 func (ModuleTypeInfo_BuildSystem) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_6039342a2ba47b72, []int{3, 0}
+	return fileDescriptor_6039342a2ba47b72, []int{4, 0}
 }
 
 type MetricsBase struct {
@@ -197,12 +197,16 @@
 	// The metrics for calling Ninja.
 	NinjaRuns []*PerfInfo `protobuf:"bytes,20,rep,name=ninja_runs,json=ninjaRuns" json:"ninja_runs,omitempty"`
 	// The metrics for the whole build
-	Total                *PerfInfo          `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
-	SoongBuildMetrics    *SoongBuildMetrics `protobuf:"bytes,22,opt,name=soong_build_metrics,json=soongBuildMetrics" json:"soong_build_metrics,omitempty"`
-	BuildConfig          *BuildConfig       `protobuf:"bytes,23,opt,name=build_config,json=buildConfig" json:"build_config,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}           `json:"-"`
-	XXX_unrecognized     []byte             `json:"-"`
-	XXX_sizecache        int32              `json:"-"`
+	Total             *PerfInfo          `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
+	SoongBuildMetrics *SoongBuildMetrics `protobuf:"bytes,22,opt,name=soong_build_metrics,json=soongBuildMetrics" json:"soong_build_metrics,omitempty"`
+	BuildConfig       *BuildConfig       `protobuf:"bytes,23,opt,name=build_config,json=buildConfig" json:"build_config,omitempty"`
+	// The hostname of the machine.
+	Hostname *string `protobuf:"bytes,24,opt,name=hostname" json:"hostname,omitempty"`
+	// The system resource information such as total physical memory.
+	SystemResourceInfo   *SystemResourceInfo `protobuf:"bytes,25,opt,name=system_resource_info,json=systemResourceInfo" json:"system_resource_info,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}            `json:"-"`
+	XXX_unrecognized     []byte              `json:"-"`
+	XXX_sizecache        int32               `json:"-"`
 }
 
 func (m *MetricsBase) Reset()         { *m = MetricsBase{} }
@@ -396,6 +400,20 @@
 	return nil
 }
 
+func (m *MetricsBase) GetHostname() string {
+	if m != nil && m.Hostname != nil {
+		return *m.Hostname
+	}
+	return ""
+}
+
+func (m *MetricsBase) GetSystemResourceInfo() *SystemResourceInfo {
+	if m != nil {
+		return m.SystemResourceInfo
+	}
+	return nil
+}
+
 type BuildConfig struct {
 	UseGoma              *bool    `protobuf:"varint,1,opt,name=use_goma,json=useGoma" json:"use_goma,omitempty"`
 	UseRbe               *bool    `protobuf:"varint,2,opt,name=use_rbe,json=useRbe" json:"use_rbe,omitempty"`
@@ -451,6 +469,55 @@
 	return false
 }
 
+type SystemResourceInfo struct {
+	// The total physical memory in bytes.
+	TotalPhysicalMemory *uint64 `protobuf:"varint,1,opt,name=total_physical_memory,json=totalPhysicalMemory" json:"total_physical_memory,omitempty"`
+	// The total of available cores for building
+	AvailableCpus        *int32   `protobuf:"varint,2,opt,name=available_cpus,json=availableCpus" json:"available_cpus,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *SystemResourceInfo) Reset()         { *m = SystemResourceInfo{} }
+func (m *SystemResourceInfo) String() string { return proto.CompactTextString(m) }
+func (*SystemResourceInfo) ProtoMessage()    {}
+func (*SystemResourceInfo) Descriptor() ([]byte, []int) {
+	return fileDescriptor_6039342a2ba47b72, []int{2}
+}
+
+func (m *SystemResourceInfo) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_SystemResourceInfo.Unmarshal(m, b)
+}
+func (m *SystemResourceInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_SystemResourceInfo.Marshal(b, m, deterministic)
+}
+func (m *SystemResourceInfo) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SystemResourceInfo.Merge(m, src)
+}
+func (m *SystemResourceInfo) XXX_Size() int {
+	return xxx_messageInfo_SystemResourceInfo.Size(m)
+}
+func (m *SystemResourceInfo) XXX_DiscardUnknown() {
+	xxx_messageInfo_SystemResourceInfo.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SystemResourceInfo proto.InternalMessageInfo
+
+func (m *SystemResourceInfo) GetTotalPhysicalMemory() uint64 {
+	if m != nil && m.TotalPhysicalMemory != nil {
+		return *m.TotalPhysicalMemory
+	}
+	return 0
+}
+
+func (m *SystemResourceInfo) GetAvailableCpus() int32 {
+	if m != nil && m.AvailableCpus != nil {
+		return *m.AvailableCpus
+	}
+	return 0
+}
+
 type PerfInfo struct {
 	// The description for the phase/action/part while the tool running.
 	Desc *string `protobuf:"bytes,1,opt,name=desc" json:"desc,omitempty"`
@@ -473,7 +540,7 @@
 func (m *PerfInfo) String() string { return proto.CompactTextString(m) }
 func (*PerfInfo) ProtoMessage()    {}
 func (*PerfInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_6039342a2ba47b72, []int{2}
+	return fileDescriptor_6039342a2ba47b72, []int{3}
 }
 
 func (m *PerfInfo) XXX_Unmarshal(b []byte) error {
@@ -545,7 +612,7 @@
 func (m *ModuleTypeInfo) String() string { return proto.CompactTextString(m) }
 func (*ModuleTypeInfo) ProtoMessage()    {}
 func (*ModuleTypeInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_6039342a2ba47b72, []int{3}
+	return fileDescriptor_6039342a2ba47b72, []int{4}
 }
 
 func (m *ModuleTypeInfo) XXX_Unmarshal(b []byte) error {
@@ -603,7 +670,7 @@
 func (m *CriticalUserJourneyMetrics) String() string { return proto.CompactTextString(m) }
 func (*CriticalUserJourneyMetrics) ProtoMessage()    {}
 func (*CriticalUserJourneyMetrics) Descriptor() ([]byte, []int) {
-	return fileDescriptor_6039342a2ba47b72, []int{4}
+	return fileDescriptor_6039342a2ba47b72, []int{5}
 }
 
 func (m *CriticalUserJourneyMetrics) XXX_Unmarshal(b []byte) error {
@@ -650,7 +717,7 @@
 func (m *CriticalUserJourneysMetrics) String() string { return proto.CompactTextString(m) }
 func (*CriticalUserJourneysMetrics) ProtoMessage()    {}
 func (*CriticalUserJourneysMetrics) Descriptor() ([]byte, []int) {
-	return fileDescriptor_6039342a2ba47b72, []int{5}
+	return fileDescriptor_6039342a2ba47b72, []int{6}
 }
 
 func (m *CriticalUserJourneysMetrics) XXX_Unmarshal(b []byte) error {
@@ -698,7 +765,7 @@
 func (m *SoongBuildMetrics) String() string { return proto.CompactTextString(m) }
 func (*SoongBuildMetrics) ProtoMessage()    {}
 func (*SoongBuildMetrics) Descriptor() ([]byte, []int) {
-	return fileDescriptor_6039342a2ba47b72, []int{6}
+	return fileDescriptor_6039342a2ba47b72, []int{7}
 }
 
 func (m *SoongBuildMetrics) XXX_Unmarshal(b []byte) error {
@@ -760,6 +827,7 @@
 	proto.RegisterEnum("soong_build_metrics.ModuleTypeInfo_BuildSystem", ModuleTypeInfo_BuildSystem_name, ModuleTypeInfo_BuildSystem_value)
 	proto.RegisterType((*MetricsBase)(nil), "soong_build_metrics.MetricsBase")
 	proto.RegisterType((*BuildConfig)(nil), "soong_build_metrics.BuildConfig")
+	proto.RegisterType((*SystemResourceInfo)(nil), "soong_build_metrics.SystemResourceInfo")
 	proto.RegisterType((*PerfInfo)(nil), "soong_build_metrics.PerfInfo")
 	proto.RegisterType((*ModuleTypeInfo)(nil), "soong_build_metrics.ModuleTypeInfo")
 	proto.RegisterType((*CriticalUserJourneyMetrics)(nil), "soong_build_metrics.CriticalUserJourneyMetrics")
@@ -772,70 +840,76 @@
 }
 
 var fileDescriptor_6039342a2ba47b72 = []byte{
-	// 1036 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xef, 0x4e, 0x1b, 0x47,
-	0x10, 0xcf, 0x61, 0x83, 0x7d, 0x73, 0xd8, 0x1c, 0x0b, 0x29, 0x97, 0x44, 0xa8, 0x96, 0xd5, 0x44,
-	0xa8, 0x6a, 0x48, 0x44, 0x23, 0x14, 0xa1, 0xa8, 0x12, 0x18, 0x44, 0x53, 0x04, 0x8e, 0x16, 0x4c,
-	0xa3, 0xf6, 0xc3, 0x69, 0x7d, 0xb7, 0x86, 0x4b, 0x7d, 0xb7, 0xd6, 0xee, 0x5e, 0x04, 0x79, 0x87,
-	0x3e, 0x55, 0x9f, 0xa5, 0xaf, 0x51, 0x55, 0x3b, 0x7b, 0x67, 0x1f, 0xad, 0xdb, 0xa0, 0x7c, 0xf3,
-	0xce, 0xef, 0xcf, 0xce, 0xec, 0xce, 0xce, 0x19, 0x5a, 0x29, 0xd7, 0x32, 0x89, 0xd4, 0xf6, 0x44,
-	0x0a, 0x2d, 0xc8, 0x9a, 0x12, 0x22, 0xbb, 0x0a, 0x87, 0x79, 0x32, 0x8e, 0xc3, 0x02, 0xea, 0xfe,
-	0x05, 0xe0, 0x9d, 0xda, 0xdf, 0x07, 0x4c, 0x71, 0xf2, 0x12, 0xd6, 0x2d, 0x21, 0x66, 0x9a, 0x87,
-	0x3a, 0x49, 0xb9, 0xd2, 0x2c, 0x9d, 0x04, 0x4e, 0xc7, 0xd9, 0xaa, 0x51, 0x82, 0xd8, 0x21, 0xd3,
-	0xfc, 0xa2, 0x44, 0xc8, 0x23, 0x68, 0x5a, 0x45, 0x12, 0x07, 0x0b, 0x1d, 0x67, 0xcb, 0xa5, 0x0d,
-	0x5c, 0xbf, 0x8d, 0xc9, 0x1e, 0x3c, 0x9a, 0x8c, 0x99, 0x1e, 0x09, 0x99, 0x86, 0x1f, 0xb9, 0x54,
-	0x89, 0xc8, 0xc2, 0x48, 0xc4, 0x3c, 0x63, 0x29, 0x0f, 0x6a, 0xc8, 0xdd, 0x28, 0x09, 0x97, 0x16,
-	0xef, 0x15, 0x30, 0x79, 0x0a, 0x6d, 0xcd, 0xe4, 0x15, 0xd7, 0xe1, 0x44, 0x8a, 0x38, 0x8f, 0x74,
-	0x50, 0x47, 0x41, 0xcb, 0x46, 0xdf, 0xd9, 0x20, 0x89, 0x61, 0xbd, 0xa0, 0xd9, 0x24, 0x3e, 0x32,
-	0x99, 0xb0, 0x4c, 0x07, 0x8b, 0x1d, 0x67, 0xab, 0xbd, 0xf3, 0x7c, 0x7b, 0x4e, 0xcd, 0xdb, 0x95,
-	0x7a, 0xb7, 0x0f, 0x0c, 0x72, 0x69, 0x45, 0x7b, 0xb5, 0xa3, 0xb3, 0x63, 0x4a, 0xac, 0x5f, 0x15,
-	0x20, 0x7d, 0xf0, 0x8a, 0x5d, 0x98, 0x8c, 0xae, 0x83, 0x25, 0x34, 0x7f, 0xfa, 0x59, 0xf3, 0x7d,
-	0x19, 0x5d, 0xef, 0x35, 0x06, 0x67, 0x27, 0x67, 0xfd, 0x9f, 0xcf, 0x28, 0x58, 0x0b, 0x13, 0x24,
-	0xdb, 0xb0, 0x56, 0x31, 0x9c, 0x66, 0xdd, 0xc0, 0x12, 0x57, 0x67, 0xc4, 0x32, 0x81, 0xef, 0xa0,
-	0x48, 0x2b, 0x8c, 0x26, 0xf9, 0x94, 0xde, 0x44, 0xba, 0x6f, 0x91, 0xde, 0x24, 0x2f, 0xd9, 0x27,
-	0xe0, 0x5e, 0x0b, 0x55, 0x24, 0xeb, 0x7e, 0x51, 0xb2, 0x4d, 0x63, 0x80, 0xa9, 0x52, 0x68, 0xa1,
-	0xd9, 0x4e, 0x16, 0x5b, 0x43, 0xf8, 0x22, 0x43, 0xcf, 0x98, 0xec, 0x64, 0x31, 0x7a, 0x6e, 0x40,
-	0x03, 0x3d, 0x85, 0x0a, 0x3c, 0xac, 0x61, 0xc9, 0x2c, 0xfb, 0x8a, 0x74, 0x8b, 0xcd, 0x84, 0x0a,
-	0xf9, 0x8d, 0x96, 0x2c, 0x58, 0x46, 0xd8, 0xb3, 0xf0, 0x91, 0x09, 0x4d, 0x39, 0x91, 0x14, 0x4a,
-	0x19, 0x8b, 0xd6, 0x8c, 0xd3, 0x33, 0xb1, 0xbe, 0x22, 0xcf, 0x60, 0xa5, 0xc2, 0xc1, 0xb4, 0xdb,
-	0xb6, 0x7d, 0xa6, 0x2c, 0x4c, 0xe4, 0x39, 0xac, 0x55, 0x78, 0xd3, 0x12, 0x57, 0xec, 0xc1, 0x4e,
-	0xb9, 0x95, 0xbc, 0x45, 0xae, 0xc3, 0x38, 0x91, 0x81, 0x6f, 0xf3, 0x16, 0xb9, 0x3e, 0x4c, 0x24,
-	0xf9, 0x01, 0x3c, 0xc5, 0x75, 0x3e, 0x09, 0xb5, 0x10, 0x63, 0x15, 0xac, 0x76, 0x6a, 0x5b, 0xde,
-	0xce, 0xe6, 0xdc, 0x23, 0x7a, 0xc7, 0xe5, 0xe8, 0x6d, 0x36, 0x12, 0x14, 0x50, 0x71, 0x61, 0x04,
-	0x64, 0x0f, 0xdc, 0xdf, 0x98, 0x4e, 0x42, 0x99, 0x67, 0x2a, 0x20, 0xf7, 0x51, 0x37, 0x0d, 0x9f,
-	0xe6, 0x99, 0x22, 0x6f, 0x00, 0x2c, 0x13, 0xc5, 0x6b, 0xf7, 0x11, 0xbb, 0x88, 0x96, 0xea, 0x2c,
-	0xc9, 0x3e, 0x30, 0xab, 0x5e, 0xbf, 0x97, 0x1a, 0x05, 0xa8, 0xfe, 0x1e, 0x16, 0xb5, 0xd0, 0x6c,
-	0x1c, 0x3c, 0xec, 0x38, 0x9f, 0x17, 0x5a, 0x2e, 0xb9, 0x84, 0x79, 0xa3, 0x28, 0xf8, 0x0a, 0x2d,
-	0x9e, 0xcd, 0xb5, 0x38, 0x37, 0x31, 0x7c, 0x92, 0x45, 0x87, 0xd1, 0x55, 0xf5, 0xcf, 0x10, 0xe9,
-	0xc1, 0xb2, 0x55, 0x45, 0x22, 0x1b, 0x25, 0x57, 0xc1, 0x06, 0x1a, 0x76, 0xe6, 0x1a, 0xa2, 0xb0,
-	0x87, 0x3c, 0xea, 0x0d, 0x67, 0x8b, 0xee, 0x4b, 0x58, 0xbe, 0xf3, 0xf4, 0x9b, 0x50, 0x1f, 0x9c,
-	0x1f, 0x51, 0xff, 0x01, 0x69, 0x81, 0x6b, 0x7e, 0x1d, 0x1e, 0x1d, 0x0c, 0x8e, 0x7d, 0x87, 0x34,
-	0xc0, 0x8c, 0x0b, 0x7f, 0xa1, 0xfb, 0x06, 0xea, 0xd8, 0x1c, 0x1e, 0x94, 0xcd, 0xee, 0x3f, 0x30,
-	0xe8, 0x3e, 0x3d, 0xf5, 0x1d, 0xe2, 0xc2, 0xe2, 0x3e, 0x3d, 0xdd, 0x7d, 0xe5, 0x2f, 0x98, 0xd8,
-	0xfb, 0xd7, 0xbb, 0x7e, 0x8d, 0x00, 0x2c, 0xbd, 0x7f, 0xbd, 0x1b, 0xee, 0xbe, 0xf2, 0xeb, 0xdd,
-	0x2b, 0xf0, 0x2a, 0xb9, 0x98, 0x69, 0x9a, 0x2b, 0x1e, 0x5e, 0x89, 0x94, 0xe1, 0xcc, 0x6d, 0xd2,
-	0x46, 0xae, 0xf8, 0xb1, 0x48, 0x99, 0x69, 0x3e, 0x03, 0xc9, 0x21, 0xc7, 0x39, 0xdb, 0xa4, 0x4b,
-	0xb9, 0xe2, 0x74, 0xc8, 0xc9, 0x37, 0xd0, 0x1e, 0x09, 0x19, 0xf1, 0x70, 0xaa, 0xac, 0x21, 0xbe,
-	0x8c, 0xd1, 0x81, 0x95, 0x77, 0x7f, 0x77, 0xa0, 0x59, 0xde, 0x04, 0x21, 0x50, 0x8f, 0xb9, 0x8a,
-	0x70, 0x0b, 0x97, 0xe2, 0x6f, 0x13, 0xc3, 0xc1, 0x6c, 0x87, 0x38, 0xfe, 0x26, 0x9b, 0x00, 0x4a,
-	0x33, 0xa9, 0xf1, 0x4b, 0x80, 0xb6, 0x75, 0xea, 0x62, 0xc4, 0x7c, 0x00, 0xc8, 0x13, 0x70, 0x25,
-	0x67, 0x63, 0x8b, 0xd6, 0x11, 0x6d, 0x9a, 0x00, 0x82, 0x9b, 0x00, 0x29, 0x4f, 0x85, 0xbc, 0x35,
-	0x79, 0xe1, 0x40, 0xae, 0x53, 0xd7, 0x46, 0x06, 0x8a, 0x77, 0xff, 0x74, 0xa0, 0x7d, 0x2a, 0xe2,
-	0x7c, 0xcc, 0x2f, 0x6e, 0x27, 0x1c, 0xb3, 0xfa, 0xb5, 0xbc, 0x40, 0x75, 0xab, 0x34, 0x4f, 0x31,
-	0xbb, 0xf6, 0xce, 0x8b, 0xf9, 0x93, 0xe6, 0x8e, 0xd4, 0xde, 0xe7, 0x39, 0xca, 0x2a, 0x33, 0x67,
-	0x38, 0x8b, 0x92, 0xaf, 0xc1, 0x4b, 0x51, 0x13, 0xea, 0xdb, 0x49, 0x59, 0x25, 0xa4, 0x53, 0x1b,
-	0x73, 0x8c, 0x59, 0x9e, 0x86, 0x62, 0x14, 0xda, 0xa0, 0xc2, 0x7a, 0x5b, 0x74, 0x39, 0xcb, 0xd3,
-	0xfe, 0xc8, 0xee, 0xa7, 0xba, 0x2f, 0x8a, 0xfb, 0x2a, 0x5c, 0xef, 0x5c, 0xba, 0x0b, 0x8b, 0xe7,
-	0xfd, 0xfe, 0x99, 0xe9, 0x8e, 0x26, 0xd4, 0x4f, 0xf7, 0x4f, 0x8e, 0xfc, 0x85, 0xee, 0x18, 0x1e,
-	0xf7, 0x64, 0xa2, 0x93, 0x88, 0x8d, 0x07, 0x8a, 0xcb, 0x9f, 0x44, 0x2e, 0x33, 0x7e, 0x5b, 0xf6,
-	0x6c, 0x79, 0xe8, 0x4e, 0xe5, 0xd0, 0xf7, 0xa0, 0x51, 0xbe, 0x89, 0x85, 0xff, 0x69, 0xe1, 0xca,
-	0xac, 0xa5, 0xa5, 0xa0, 0x3b, 0x84, 0x27, 0x73, 0x76, 0x53, 0xb3, 0x27, 0x52, 0x8f, 0xf2, 0x0f,
-	0x2a, 0x70, 0xf0, 0x9d, 0xcf, 0x3f, 0xd9, 0xff, 0xce, 0x96, 0xa2, 0xb8, 0xfb, 0x87, 0x03, 0xab,
-	0xff, 0x7a, 0x90, 0x24, 0x80, 0x46, 0x79, 0x6e, 0x0e, 0x9e, 0x5b, 0xb9, 0x24, 0x8f, 0xa1, 0x59,
-	0x7c, 0xb1, 0x6c, 0x41, 0x2d, 0x3a, 0x5d, 0x93, 0x6f, 0x61, 0x15, 0x87, 0x42, 0xc8, 0xc6, 0x63,
-	0x11, 0x85, 0x91, 0xc8, 0x33, 0x5d, 0xf4, 0xd9, 0x0a, 0x02, 0xfb, 0x26, 0xde, 0x33, 0x61, 0xb2,
-	0x05, 0x7e, 0x95, 0xab, 0x92, 0x4f, 0x65, 0xd3, 0xb5, 0x67, 0xd4, 0xf3, 0xe4, 0x13, 0x37, 0x9f,
-	0x88, 0x94, 0xdd, 0x84, 0xd7, 0x9c, 0x4d, 0x2c, 0xcd, 0x76, 0x9f, 0x97, 0xb2, 0x9b, 0x1f, 0x39,
-	0x9b, 0x18, 0xce, 0xc1, 0xc3, 0x5f, 0x8a, 0x29, 0x54, 0xd4, 0x1d, 0xe2, 0xbf, 0xa4, 0xbf, 0x03,
-	0x00, 0x00, 0xff, 0xff, 0x85, 0xc5, 0xe0, 0x4b, 0x35, 0x09, 0x00, 0x00,
+	// 1130 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x6f, 0x6f, 0xd4, 0x46,
+	0x13, 0xc7, 0xc9, 0x25, 0x77, 0x1e, 0xe7, 0x0e, 0x67, 0x13, 0x1e, 0x0c, 0x08, 0x3d, 0x91, 0x55,
+	0x68, 0x54, 0x95, 0x80, 0xae, 0x28, 0x42, 0x11, 0xaa, 0x94, 0x1c, 0x11, 0xa5, 0xe8, 0x72, 0x68,
+	0xc3, 0x51, 0xda, 0xbe, 0xb0, 0xf6, 0xec, 0xbd, 0xc4, 0xd4, 0xf6, 0x5a, 0xbb, 0x6b, 0xc4, 0xf1,
+	0x1d, 0xfa, 0xa9, 0xfa, 0x59, 0xfa, 0x11, 0xfa, 0xbe, 0xda, 0x59, 0xfb, 0xee, 0x28, 0xd7, 0x82,
+	0x78, 0x77, 0x9e, 0xdf, 0x9f, 0x9d, 0x19, 0x8f, 0x67, 0x0f, 0xba, 0x39, 0xd7, 0x32, 0x8d, 0xd5,
+	0x41, 0x29, 0x85, 0x16, 0x64, 0x47, 0x09, 0x51, 0x5c, 0x44, 0x93, 0x2a, 0xcd, 0x92, 0xa8, 0x86,
+	0xc2, 0xbf, 0x3c, 0xf0, 0x86, 0xf6, 0xf7, 0x09, 0x53, 0x9c, 0x3c, 0x80, 0x5d, 0x4b, 0x48, 0x98,
+	0xe6, 0x91, 0x4e, 0x73, 0xae, 0x34, 0xcb, 0xcb, 0xc0, 0xd9, 0x73, 0xf6, 0xd7, 0x29, 0x41, 0xec,
+	0x09, 0xd3, 0xfc, 0x65, 0x83, 0x90, 0x1b, 0xd0, 0xb1, 0x8a, 0x34, 0x09, 0xd6, 0xf6, 0x9c, 0x7d,
+	0x97, 0xb6, 0xf1, 0xf9, 0x59, 0x42, 0x8e, 0xe0, 0x46, 0x99, 0x31, 0x3d, 0x15, 0x32, 0x8f, 0xde,
+	0x72, 0xa9, 0x52, 0x51, 0x44, 0xb1, 0x48, 0x78, 0xc1, 0x72, 0x1e, 0xac, 0x23, 0xf7, 0x7a, 0x43,
+	0x78, 0x65, 0xf1, 0x41, 0x0d, 0x93, 0x3b, 0xd0, 0xd3, 0x4c, 0x5e, 0x70, 0x1d, 0x95, 0x52, 0x24,
+	0x55, 0xac, 0x83, 0x16, 0x0a, 0xba, 0x36, 0xfa, 0xc2, 0x06, 0x49, 0x02, 0xbb, 0x35, 0xcd, 0x26,
+	0xf1, 0x96, 0xc9, 0x94, 0x15, 0x3a, 0xd8, 0xd8, 0x73, 0xf6, 0x7b, 0xfd, 0x7b, 0x07, 0x2b, 0x6a,
+	0x3e, 0x58, 0xaa, 0xf7, 0xe0, 0xc4, 0x20, 0xaf, 0xac, 0xe8, 0x68, 0xfd, 0xf4, 0xec, 0x29, 0x25,
+	0xd6, 0x6f, 0x19, 0x20, 0x23, 0xf0, 0xea, 0x53, 0x98, 0x8c, 0x2f, 0x83, 0x4d, 0x34, 0xbf, 0xf3,
+	0x49, 0xf3, 0x63, 0x19, 0x5f, 0x1e, 0xb5, 0xc7, 0x67, 0xcf, 0xcf, 0x46, 0x3f, 0x9d, 0x51, 0xb0,
+	0x16, 0x26, 0x48, 0x0e, 0x60, 0x67, 0xc9, 0x70, 0x9e, 0x75, 0x1b, 0x4b, 0xdc, 0x5e, 0x10, 0x9b,
+	0x04, 0xbe, 0x85, 0x3a, 0xad, 0x28, 0x2e, 0xab, 0x39, 0xbd, 0x83, 0x74, 0xdf, 0x22, 0x83, 0xb2,
+	0x6a, 0xd8, 0xcf, 0xc1, 0xbd, 0x14, 0xaa, 0x4e, 0xd6, 0xfd, 0xa2, 0x64, 0x3b, 0xc6, 0x00, 0x53,
+	0xa5, 0xd0, 0x45, 0xb3, 0x7e, 0x91, 0x58, 0x43, 0xf8, 0x22, 0x43, 0xcf, 0x98, 0xf4, 0x8b, 0x04,
+	0x3d, 0xaf, 0x43, 0x1b, 0x3d, 0x85, 0x0a, 0x3c, 0xac, 0x61, 0xd3, 0x3c, 0x8e, 0x14, 0x09, 0xeb,
+	0xc3, 0x84, 0x8a, 0xf8, 0x3b, 0x2d, 0x59, 0xb0, 0x85, 0xb0, 0x67, 0xe1, 0x53, 0x13, 0x9a, 0x73,
+	0x62, 0x29, 0x94, 0x32, 0x16, 0xdd, 0x05, 0x67, 0x60, 0x62, 0x23, 0x45, 0xee, 0xc2, 0xd5, 0x25,
+	0x0e, 0xa6, 0xdd, 0xb3, 0xe3, 0x33, 0x67, 0x61, 0x22, 0xf7, 0x60, 0x67, 0x89, 0x37, 0x2f, 0xf1,
+	0xaa, 0x6d, 0xec, 0x9c, 0xbb, 0x94, 0xb7, 0xa8, 0x74, 0x94, 0xa4, 0x32, 0xf0, 0x6d, 0xde, 0xa2,
+	0xd2, 0x4f, 0x52, 0x49, 0xbe, 0x07, 0x4f, 0x71, 0x5d, 0x95, 0x91, 0x16, 0x22, 0x53, 0xc1, 0xf6,
+	0xde, 0xfa, 0xbe, 0xd7, 0xbf, 0xbd, 0xb2, 0x45, 0x2f, 0xb8, 0x9c, 0x3e, 0x2b, 0xa6, 0x82, 0x02,
+	0x2a, 0x5e, 0x1a, 0x01, 0x39, 0x02, 0xf7, 0x37, 0xa6, 0xd3, 0x48, 0x56, 0x85, 0x0a, 0xc8, 0xe7,
+	0xa8, 0x3b, 0x86, 0x4f, 0xab, 0x42, 0x91, 0xc7, 0x00, 0x96, 0x89, 0xe2, 0x9d, 0xcf, 0x11, 0xbb,
+	0x88, 0x36, 0xea, 0x22, 0x2d, 0xde, 0x30, 0xab, 0xde, 0xfd, 0x2c, 0x35, 0x0a, 0x50, 0xfd, 0x1d,
+	0x6c, 0x68, 0xa1, 0x59, 0x16, 0x5c, 0xdb, 0x73, 0x3e, 0x2d, 0xb4, 0x5c, 0xf2, 0x0a, 0x56, 0xad,
+	0xa2, 0xe0, 0x7f, 0x68, 0x71, 0x77, 0xa5, 0xc5, 0xb9, 0x89, 0xe1, 0x27, 0x59, 0x4f, 0x18, 0xdd,
+	0x56, 0xff, 0x0c, 0x91, 0x01, 0x6c, 0x59, 0x55, 0x2c, 0x8a, 0x69, 0x7a, 0x11, 0x5c, 0x47, 0xc3,
+	0xbd, 0x95, 0x86, 0x28, 0x1c, 0x20, 0x8f, 0x7a, 0x93, 0xc5, 0x03, 0xb9, 0x09, 0x38, 0xfa, 0xb8,
+	0xa2, 0x02, 0x7c, 0xc7, 0xf3, 0x67, 0xf2, 0x33, 0xec, 0xaa, 0x99, 0xd2, 0x3c, 0x8f, 0x24, 0x57,
+	0xa2, 0x92, 0x31, 0x8f, 0xd2, 0x62, 0x2a, 0x82, 0x1b, 0x78, 0xd0, 0xd7, 0xab, 0x33, 0x47, 0x01,
+	0xad, 0xf9, 0xd8, 0x06, 0xa2, 0x3e, 0x8a, 0x85, 0x0f, 0x60, 0xeb, 0x83, 0x8d, 0xd3, 0x81, 0xd6,
+	0xf8, 0xfc, 0x94, 0xfa, 0x57, 0x48, 0x17, 0x5c, 0xf3, 0xeb, 0xc9, 0xe9, 0xc9, 0xf8, 0xa9, 0xef,
+	0x90, 0x36, 0x98, 0x2d, 0xe5, 0xaf, 0x85, 0x8f, 0xa1, 0x85, 0x33, 0xe9, 0x41, 0xf3, 0x8d, 0xf9,
+	0x57, 0x0c, 0x7a, 0x4c, 0x87, 0xbe, 0x43, 0x5c, 0xd8, 0x38, 0xa6, 0xc3, 0xc3, 0x87, 0xfe, 0x9a,
+	0x89, 0xbd, 0x7e, 0x74, 0xe8, 0xaf, 0x13, 0x80, 0xcd, 0xd7, 0x8f, 0x0e, 0xa3, 0xc3, 0x87, 0x7e,
+	0x2b, 0xbc, 0x00, 0x6f, 0xa9, 0x05, 0x66, 0x89, 0x57, 0x8a, 0x47, 0x17, 0x22, 0x67, 0xb8, 0xea,
+	0x3b, 0xb4, 0x5d, 0x29, 0xfe, 0x54, 0xe4, 0xcc, 0xcc, 0xbc, 0x81, 0xe4, 0x84, 0xe3, 0x7a, 0xef,
+	0xd0, 0xcd, 0x4a, 0x71, 0x3a, 0xe1, 0xe4, 0x2b, 0xe8, 0x4d, 0x85, 0xe9, 0xc1, 0x5c, 0xb9, 0x8e,
+	0xf8, 0x16, 0x46, 0xc7, 0x56, 0x1e, 0x0a, 0x20, 0x1f, 0xb7, 0x80, 0xf4, 0xe1, 0x1a, 0xce, 0x42,
+	0x54, 0x5e, 0xce, 0x54, 0x1a, 0xb3, 0x2c, 0xca, 0x79, 0x2e, 0xe4, 0x0c, 0x0f, 0x6f, 0xd1, 0x1d,
+	0x04, 0x5f, 0xd4, 0xd8, 0x10, 0x21, 0x73, 0x23, 0xb0, 0xb7, 0x2c, 0xcd, 0xd8, 0x24, 0xe3, 0x66,
+	0x0d, 0x2a, 0xcc, 0x67, 0x83, 0x76, 0xe7, 0xd1, 0x41, 0x59, 0xa9, 0xf0, 0x77, 0x07, 0x3a, 0xcd,
+	0xc4, 0x11, 0x02, 0xad, 0x84, 0xab, 0x18, 0x6d, 0x5d, 0x8a, 0xbf, 0x4d, 0x0c, 0xdf, 0xae, 0xbd,
+	0xac, 0xf0, 0x37, 0xb9, 0x0d, 0xa0, 0x34, 0x93, 0x1a, 0x6f, 0x3c, 0xac, 0xa3, 0x45, 0x5d, 0x8c,
+	0x98, 0x8b, 0x8e, 0xdc, 0x02, 0x57, 0x72, 0x96, 0x59, 0xb4, 0x85, 0x68, 0xc7, 0x04, 0x10, 0xbc,
+	0x0d, 0x60, 0x93, 0x37, 0x8d, 0xc0, 0x8b, 0xa7, 0x45, 0x5d, 0x1b, 0x19, 0x2b, 0x1e, 0xfe, 0xe9,
+	0x40, 0x6f, 0x28, 0x92, 0x2a, 0xe3, 0x2f, 0x67, 0xa5, 0xad, 0xfe, 0xd7, 0x66, 0x50, 0xed, 0x20,
+	0x60, 0x76, 0xbd, 0xfe, 0xfd, 0xd5, 0x1b, 0xf5, 0x03, 0xa9, 0x9d, 0x5b, 0xdb, 0xd0, 0xa5, 0xdd,
+	0x3a, 0x59, 0x44, 0xc9, 0xff, 0xc1, 0xcb, 0x51, 0x13, 0xe9, 0x59, 0xd9, 0x54, 0x09, 0xf9, 0xdc,
+	0xc6, 0xbc, 0xb7, 0xa2, 0xca, 0x23, 0x31, 0x8d, 0x6c, 0x50, 0x61, 0xbd, 0x5d, 0xba, 0x55, 0x54,
+	0xf9, 0x68, 0x6a, 0xcf, 0x53, 0xe1, 0xfd, 0x7a, 0x40, 0x6a, 0xd7, 0x0f, 0xa6, 0xcc, 0x85, 0x8d,
+	0xf3, 0xd1, 0xe8, 0xcc, 0x8c, 0x63, 0x07, 0x5a, 0xc3, 0xe3, 0xe7, 0xa7, 0xfe, 0x5a, 0x98, 0xc1,
+	0xcd, 0x81, 0x4c, 0xb5, 0x79, 0x61, 0x63, 0xc5, 0xe5, 0x8f, 0xa2, 0x92, 0x05, 0x9f, 0x35, 0xdf,
+	0x66, 0xd3, 0x74, 0x67, 0xa9, 0xe9, 0x47, 0xd0, 0x6e, 0xbe, 0xfd, 0xb5, 0xff, 0xf8, 0x54, 0x97,
+	0xee, 0x14, 0xda, 0x08, 0xc2, 0x09, 0xdc, 0x5a, 0x71, 0x9a, 0x5a, 0xac, 0x82, 0x56, 0x5c, 0xbd,
+	0x51, 0x81, 0x83, 0xfb, 0x6c, 0x75, 0x67, 0xff, 0x3d, 0x5b, 0x8a, 0xe2, 0xf0, 0x0f, 0x07, 0xb6,
+	0x3f, 0x5a, 0x3c, 0x24, 0x80, 0x76, 0xd3, 0x37, 0x07, 0xfb, 0xd6, 0x3c, 0x9a, 0xd5, 0x51, 0xdf,
+	0xcc, 0xb6, 0xa0, 0x2e, 0x9d, 0x3f, 0x93, 0x6f, 0x60, 0xdb, 0x0e, 0x3c, 0xcb, 0x32, 0x11, 0x47,
+	0xb1, 0xa8, 0x0a, 0x5d, 0xcf, 0xd9, 0x55, 0x04, 0x8e, 0x4d, 0x7c, 0x60, 0xc2, 0x64, 0x1f, 0xfc,
+	0x65, 0xae, 0x4a, 0xdf, 0x37, 0x43, 0xd7, 0x5b, 0x50, 0xcf, 0xd3, 0xf7, 0xdc, 0x5c, 0x85, 0x39,
+	0x7b, 0x17, 0x5d, 0x72, 0x56, 0x5a, 0x9a, 0x9d, 0x3e, 0x2f, 0x67, 0xef, 0x7e, 0xe0, 0xac, 0x34,
+	0x9c, 0x93, 0x6b, 0xbf, 0xd4, 0xdb, 0xb6, 0xae, 0x3b, 0xc2, 0x7f, 0x83, 0x7f, 0x07, 0x00, 0x00,
+	0xff, 0xff, 0xa3, 0xdd, 0xbb, 0xb3, 0x1d, 0x0a, 0x00, 0x00,
 }
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 4d6118b..3586be0 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -96,6 +96,12 @@
   optional SoongBuildMetrics soong_build_metrics = 22;
 
   optional BuildConfig build_config = 23;
+
+  // The hostname of the machine.
+  optional string hostname = 24;
+
+  // The system resource information such as total physical memory.
+  optional SystemResourceInfo system_resource_info = 25;
 }
 
 message BuildConfig {
@@ -106,6 +112,14 @@
   optional bool force_use_goma = 3;
 }
 
+message SystemResourceInfo {
+  // The total physical memory in bytes.
+  optional uint64 total_physical_memory = 1;
+
+  // The total of available cores for building
+  optional int32 available_cpus = 2;
+}
+
 message PerfInfo {
   // The description for the phase/action/part while the tool running.
   optional string desc = 1;
diff --git a/ui/metrics/metrics_proto/regen.sh b/ui/metrics/metrics_proto/regen.sh
index 343c638..8eb2d74 100755
--- a/ui/metrics/metrics_proto/regen.sh
+++ b/ui/metrics/metrics_proto/regen.sh
@@ -1,3 +1,17 @@
 #!/bin/bash
 
-aprotoc --go_out=paths=source_relative:. metrics.proto
+# Generates the golang source file of metrics.proto protobuf file.
+
+set -e
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+  die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. metrics.proto; then
+  die "build failed. ${error_msg}"
+fi
diff --git a/ui/metrics/time_test.go b/ui/metrics/time_test.go
index 16d6a20..d73080a 100644
--- a/ui/metrics/time_test.go
+++ b/ui/metrics/time_test.go
@@ -22,7 +22,6 @@
 )
 
 func TestEnd(t *testing.T) {
-	t.Parallel()
 	startTime := time.Date(2020, time.July, 13, 13, 0, 0, 0, time.UTC)
 	dur := time.Nanosecond * 10
 	initialNow := _now
diff --git a/ui/status/critical_path_test.go b/ui/status/critical_path_test.go
index e44298b..965e0ad 100644
--- a/ui/status/critical_path_test.go
+++ b/ui/status/critical_path_test.go
@@ -51,7 +51,6 @@
 }
 
 func TestCriticalPath(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name     string
 		msgs     func(*testCriticalPath)
diff --git a/ui/status/kati_test.go b/ui/status/kati_test.go
index 24a38b3..f2cb813 100644
--- a/ui/status/kati_test.go
+++ b/ui/status/kati_test.go
@@ -43,7 +43,6 @@
 func (l *lastOutput) Flush() {}
 
 func TestKatiNormalCase(t *testing.T) {
-	t.Parallel()
 	status := &Status{}
 	output := &lastOutput{}
 	status.AddOutput(output)
@@ -111,7 +110,6 @@
 }
 
 func TestKatiExtraIncludes(t *testing.T) {
-	t.Parallel()
 	status := &Status{}
 	output := &lastOutput{}
 	status.AddOutput(output)
@@ -158,7 +156,6 @@
 }
 
 func TestKatiFailOnError(t *testing.T) {
-	t.Parallel()
 	status := &Status{}
 	output := &lastOutput{}
 	status.AddOutput(output)
diff --git a/ui/status/ninja_test.go b/ui/status/ninja_test.go
index 232be55..c400c97 100644
--- a/ui/status/ninja_test.go
+++ b/ui/status/ninja_test.go
@@ -26,7 +26,6 @@
 
 // Tests that closing the ninja reader when nothing has opened the other end of the fifo is fast.
 func TestNinjaReader_Close(t *testing.T) {
-	t.Parallel()
 	tempDir, err := ioutil.TempDir("", "ninja_test")
 	if err != nil {
 		t.Fatal(err)
diff --git a/ui/status/status_test.go b/ui/status/status_test.go
index 2a90c7b..9494582 100644
--- a/ui/status/status_test.go
+++ b/ui/status/status_test.go
@@ -53,7 +53,6 @@
 }
 
 func TestBasicUse(t *testing.T) {
-	t.Parallel()
 	status := &Status{}
 	counts := &counterOutput{}
 	status.AddOutput(counts)
@@ -102,7 +101,6 @@
 
 // For when a tool claims to have 2 actions, but finishes after one.
 func TestFinishEarly(t *testing.T) {
-	t.Parallel()
 	status := &Status{}
 	counts := &counterOutput{}
 	status.AddOutput(counts)
@@ -131,7 +129,6 @@
 
 // For when a tool claims to have 1 action, but starts two.
 func TestExtraActions(t *testing.T) {
-	t.Parallel()
 	status := &Status{}
 	counts := &counterOutput{}
 	status.AddOutput(counts)
@@ -152,7 +149,6 @@
 
 // When a tool calls Finish() with a running Action
 func TestRunningWhenFinished(t *testing.T) {
-	t.Parallel()
 	status := &Status{}
 	counts := &counterOutput{}
 	status.AddOutput(counts)
diff --git a/ui/terminal/status_test.go b/ui/terminal/status_test.go
index da10912..aa69dff 100644
--- a/ui/terminal/status_test.go
+++ b/ui/terminal/status_test.go
@@ -25,7 +25,6 @@
 )
 
 func TestStatusOutput(t *testing.T) {
-	t.Parallel()
 	tests := []struct {
 		name   string
 		calls  func(stat status.StatusOutput)
@@ -267,7 +266,6 @@
 }
 
 func TestSmartStatusOutputWidthChange(t *testing.T) {
-	t.Parallel()
 	os.Setenv(tableHeightEnVar, "")
 
 	smart := &fakeSmartTerminal{termWidth: 40}
diff --git a/ui/terminal/util_test.go b/ui/terminal/util_test.go
index b01b133..82bde7c 100644
--- a/ui/terminal/util_test.go
+++ b/ui/terminal/util_test.go
@@ -19,7 +19,6 @@
 )
 
 func TestStripAnsiEscapes(t *testing.T) {
-	t.Parallel()
 	testcases := []struct {
 		input  string
 		output string
diff --git a/xml/xml_test.go b/xml/xml_test.go
index d9a6cee..abcb108 100644
--- a/xml/xml_test.go
+++ b/xml/xml_test.go
@@ -78,7 +78,6 @@
 
 // Minimal test
 func TestPrebuiltEtcXml(t *testing.T) {
-	t.Parallel()
 	ctx := testXml(t, `
 		prebuilt_etc_xml {
 			name: "foo.xml",
diff --git a/zip/zip_test.go b/zip/zip_test.go
index 9e1ef90..302a749 100644
--- a/zip/zip_test.go
+++ b/zip/zip_test.go
@@ -102,7 +102,6 @@
 }
 
 func TestZip(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name               string
 		args               *FileArgsBuilder
@@ -531,7 +530,6 @@
 }
 
 func TestReadRespFile(t *testing.T) {
-	t.Parallel()
 	testCases := []struct {
 		name, in string
 		out      []string
@@ -604,7 +602,6 @@
 }
 
 func TestSrcJar(t *testing.T) {
-	t.Parallel()
 	mockFs := pathtools.MockFs(map[string][]byte{
 		"wrong_package.java":       []byte("package foo;"),
 		"foo/correct_package.java": []byte("package foo;"),