Merge "Fix module name when autogenerating test config"
diff --git a/android/Android.bp b/android/Android.bp
index 47dbc5d..487372b 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -36,6 +36,7 @@
         "package_ctx.go",
         "path_properties.go",
         "paths.go",
+        "phony.go",
         "prebuilt.go",
         "proto.go",
         "register.go",
diff --git a/android/config.go b/android/config.go
index 675660e..0fe4a0c 100644
--- a/android/config.go
+++ b/android/config.go
@@ -111,6 +111,10 @@
 	fs         pathtools.FileSystem
 	mockBpList string
 
+	// If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error
+	// in tests when a path doesn't exist.
+	testAllowNonExistentPaths bool
+
 	OncePer
 }
 
@@ -230,6 +234,10 @@
 		buildDir:     buildDir,
 		captureBuild: true,
 		env:          envCopy,
+
+		// Set testAllowNonExistentPaths so that test contexts don't need to specify every path
+		// passed to PathForSource or PathForModuleSrc.
+		testAllowNonExistentPaths: true,
 	}
 	config.deviceConfig = &deviceConfig{
 		config: config,
@@ -1155,8 +1163,8 @@
 	return Bool(c.productVariables.EnforceSystemCertificate)
 }
 
-func (c *config) EnforceSystemCertificateWhitelist() []string {
-	return c.productVariables.EnforceSystemCertificateWhitelist
+func (c *config) EnforceSystemCertificateAllowList() []string {
+	return c.productVariables.EnforceSystemCertificateAllowList
 }
 
 func (c *config) EnforceProductPartitionInterface() bool {
diff --git a/android/makevars.go b/android/makevars.go
index aba4cce..ff7c8e4 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -17,12 +17,11 @@
 import (
 	"bytes"
 	"fmt"
-	"io/ioutil"
-	"os"
 	"strconv"
 	"strings"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/pathtools"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -84,6 +83,29 @@
 	// builder whenever a file matching the pattern as added or removed, without rerunning if a
 	// file that does not match the pattern is added to a searched directory.
 	GlobWithDeps(pattern string, excludes []string) ([]string, error)
+
+	// Phony creates a phony rule in Make, which will allow additional DistForGoal
+	// dependencies to be added to it.  Phony can be called on the same name multiple
+	// times to add additional dependencies.
+	Phony(names string, deps ...Path)
+
+	// DistForGoal creates a rule to copy one or more Paths to the artifacts
+	// directory on the build server when the specified goal is built.
+	DistForGoal(goal string, paths ...Path)
+
+	// DistForGoalWithFilename creates a rule to copy a Path to the artifacts
+	// directory on the build server with the given filename when the specified
+	// goal is built.
+	DistForGoalWithFilename(goal string, path Path, filename string)
+
+	// DistForGoals creates a rule to copy one or more Paths to the artifacts
+	// directory on the build server when any of the specified goals are built.
+	DistForGoals(goals []string, paths ...Path)
+
+	// DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
+	// directory on the build server with the given filename when any of the
+	// specified goals are built.
+	DistForGoalsWithFilename(goals []string, path Path, filename string)
 }
 
 var _ PathContext = MakeVarsContext(nil)
@@ -130,9 +152,11 @@
 
 type makeVarsContext struct {
 	SingletonContext
-	config Config
-	pctx   PackageContext
-	vars   []makeVarsVariable
+	config  Config
+	pctx    PackageContext
+	vars    []makeVarsVariable
+	phonies []phony
+	dists   []dist
 }
 
 var _ MakeVarsContext = &makeVarsContext{}
@@ -144,6 +168,16 @@
 	strict bool
 }
 
+type phony struct {
+	name string
+	deps []string
+}
+
+type dist struct {
+	goals []string
+	paths []string
+}
+
 func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
 	if !ctx.Config().EmbeddedInMake() {
 		return
@@ -152,11 +186,16 @@
 	outFile := absolutePath(PathForOutput(ctx,
 		"make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
 
+	lateOutFile := absolutePath(PathForOutput(ctx,
+		"late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
+
 	if ctx.Failed() {
 		return
 	}
 
-	vars := []makeVarsVariable{}
+	var vars []makeVarsVariable
+	var dists []dist
+	var phonies []phony
 	for _, provider := range makeVarsProviders {
 		mctx := &makeVarsContext{
 			SingletonContext: ctx,
@@ -166,6 +205,8 @@
 		provider.call(mctx)
 
 		vars = append(vars, mctx.vars...)
+		phonies = append(phonies, mctx.phonies...)
+		dists = append(dists, mctx.dists...)
 	}
 
 	if ctx.Failed() {
@@ -174,17 +215,16 @@
 
 	outBytes := s.writeVars(vars)
 
-	if _, err := os.Stat(absolutePath(outFile)); err == nil {
-		if data, err := ioutil.ReadFile(absolutePath(outFile)); err == nil {
-			if bytes.Equal(data, outBytes) {
-				return
-			}
-		}
-	}
-
-	if err := ioutil.WriteFile(absolutePath(outFile), outBytes, 0666); err != nil {
+	if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil {
 		ctx.Errorf(err.Error())
 	}
+
+	lateOutBytes := s.writeLate(phonies, dists)
+
+	if err := pathtools.WriteFileIfChanged(lateOutFile, lateOutBytes, 0666); err != nil {
+		ctx.Errorf(err.Error())
+	}
+
 }
 
 func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
@@ -263,6 +303,33 @@
 
 	fmt.Fprintln(buf, "\nsoong-compare-var :=")
 
+	fmt.Fprintln(buf)
+
+	return buf.Bytes()
+}
+
+func (s *makeVarsSingleton) writeLate(phonies []phony, dists []dist) []byte {
+	buf := &bytes.Buffer{}
+
+	fmt.Fprint(buf, `# Autogenerated file
+
+# Values written by Soong read after parsing all Android.mk files.
+
+
+`)
+
+	for _, phony := range phonies {
+		fmt.Fprintf(buf, ".PHONY: %s\n", phony.name)
+		fmt.Fprintf(buf, "%s: %s\n", phony.name, strings.Join(phony.deps, "\\\n  "))
+	}
+
+	fmt.Fprintln(buf)
+
+	for _, dist := range dists {
+		fmt.Fprintf(buf, "$(call dist-for-goals,%s,%s)\n",
+			strings.Join(dist.goals, " "), strings.Join(dist.paths, " "))
+	}
+
 	return buf.Bytes()
 }
 
@@ -299,6 +366,17 @@
 	c.addVariableRaw(name, value, strict, sort)
 }
 
+func (c *makeVarsContext) addPhony(name string, deps []string) {
+	c.phonies = append(c.phonies, phony{name, deps})
+}
+
+func (c *makeVarsContext) addDist(goals []string, paths []string) {
+	c.dists = append(c.dists, dist{
+		goals: goals,
+		paths: paths,
+	})
+}
+
 func (c *makeVarsContext) Strict(name, ninjaStr string) {
 	c.addVariable(name, ninjaStr, true, false)
 }
@@ -318,3 +396,23 @@
 func (c *makeVarsContext) CheckRaw(name, value string) {
 	c.addVariableRaw(name, value, false, false)
 }
+
+func (c *makeVarsContext) Phony(name string, deps ...Path) {
+	c.addPhony(name, Paths(deps).Strings())
+}
+
+func (c *makeVarsContext) DistForGoal(goal string, paths ...Path) {
+	c.DistForGoals([]string{goal}, paths...)
+}
+
+func (c *makeVarsContext) DistForGoalWithFilename(goal string, path Path, filename string) {
+	c.DistForGoalsWithFilename([]string{goal}, path, filename)
+}
+
+func (c *makeVarsContext) DistForGoals(goals []string, paths ...Path) {
+	c.addDist(goals, Paths(paths).Strings())
+}
+
+func (c *makeVarsContext) DistForGoalsWithFilename(goals []string, path Path, filename string) {
+	c.addDist(goals, []string{path.String() + ":" + filename})
+}
diff --git a/android/module.go b/android/module.go
index 82321f4..a488c0d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -207,6 +207,10 @@
 	// Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
 	// and performs more verification.
 	Build(pctx PackageContext, params BuildParams)
+	// Phony creates a Make-style phony rule, a rule with no commands that can depend on other
+	// phony rules or real files.  Phony can be called on the same name multiple times to add
+	// additional dependencies.
+	Phony(phony string, deps ...Path)
 
 	PrimaryModule() Module
 	FinalModule() Module
@@ -722,6 +726,7 @@
 	installFiles       InstallPaths
 	checkbuildFiles    Paths
 	noticeFiles        Paths
+	phonies            map[string]Paths
 
 	// Used by buildTargetSingleton to create checkbuild and per-directory build targets
 	// Only set on the final variant of each module
@@ -1093,26 +1098,17 @@
 	}
 
 	if len(allInstalledFiles) > 0 {
-		name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-install")
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    name,
-			Implicits: allInstalledFiles.Paths(),
-			Default:   !ctx.Config().EmbeddedInMake(),
-		})
-		deps = append(deps, name)
-		m.installTarget = name
+		name := namespacePrefix + ctx.ModuleName() + "-install"
+		ctx.Phony(name, allInstalledFiles.Paths()...)
+		m.installTarget = PathForPhony(ctx, name)
+		deps = append(deps, m.installTarget)
 	}
 
 	if len(allCheckbuildFiles) > 0 {
-		name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-checkbuild")
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    name,
-			Implicits: allCheckbuildFiles,
-		})
-		deps = append(deps, name)
-		m.checkbuildTarget = name
+		name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
+		ctx.Phony(name, allCheckbuildFiles...)
+		m.checkbuildTarget = PathForPhony(ctx, name)
+		deps = append(deps, m.checkbuildTarget)
 	}
 
 	if len(deps) > 0 {
@@ -1121,12 +1117,7 @@
 			suffix = "-soong"
 		}
 
-		name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+suffix)
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Outputs:   []WritablePath{name},
-			Implicits: deps,
-		})
+		ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...)
 
 		m.blueprintDir = ctx.ModuleDir()
 	}
@@ -1313,6 +1304,9 @@
 		m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
 		m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
 		m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
+		for k, v := range ctx.phonies {
+			m.phonies[k] = append(m.phonies[k], v...)
+		}
 	} else if ctx.Config().AllowMissingDependencies() {
 		// If the module is not enabled it will not create any build rules, nothing will call
 		// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -1460,6 +1454,7 @@
 	installFiles    InstallPaths
 	checkbuildFiles Paths
 	module          Module
+	phonies         map[string]Paths
 
 	// For tests
 	buildParams []BuildParams
@@ -1574,6 +1569,11 @@
 
 	m.bp.Build(pctx.PackageContext, convertBuildParams(params))
 }
+
+func (m *moduleContext) Phony(name string, deps ...Path) {
+	addPhony(m.config, name, deps...)
+}
+
 func (m *moduleContext) GetMissingDependencies() []string {
 	var missingDeps []string
 	missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
@@ -2233,9 +2233,8 @@
 func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
 	var checkbuildDeps Paths
 
-	mmTarget := func(dir string) WritablePath {
-		return PathForPhony(ctx,
-			"MODULES-IN-"+strings.Replace(filepath.Clean(dir), "/", "-", -1))
+	mmTarget := func(dir string) string {
+		return "MODULES-IN-" + strings.Replace(filepath.Clean(dir), "/", "-", -1)
 	}
 
 	modulesInDir := make(map[string]Paths)
@@ -2261,11 +2260,7 @@
 	}
 
 	// Create a top-level checkbuild target that depends on all modules
-	ctx.Build(pctx, BuildParams{
-		Rule:      blueprint.Phony,
-		Output:    PathForPhony(ctx, "checkbuild"+suffix),
-		Implicits: checkbuildDeps,
-	})
+	ctx.Phony("checkbuild"+suffix, checkbuildDeps...)
 
 	// Make will generate the MODULES-IN-* targets
 	if ctx.Config().EmbeddedInMake() {
@@ -2289,7 +2284,7 @@
 	for _, dir := range dirs {
 		p := parentDir(dir)
 		if p != "." && p != "/" {
-			modulesInDir[p] = append(modulesInDir[p], mmTarget(dir))
+			modulesInDir[p] = append(modulesInDir[p], PathForPhony(ctx, mmTarget(dir)))
 		}
 	}
 
@@ -2297,14 +2292,7 @@
 	// depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp
 	// files.
 	for _, dir := range dirs {
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    mmTarget(dir),
-			Implicits: modulesInDir[dir],
-			// HACK: checkbuild should be an optional build, but force it
-			// enabled for now in standalone builds
-			Default: !ctx.Config().EmbeddedInMake(),
-		})
+		ctx.Phony(mmTarget(dir), modulesInDir[dir]...)
 	}
 
 	// Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild.
@@ -2331,23 +2319,15 @@
 			continue
 		}
 
-		name := PathForPhony(ctx, className+"-"+os.Name)
-		osClass[className] = append(osClass[className], name)
+		name := className + "-" + os.Name
+		osClass[className] = append(osClass[className], PathForPhony(ctx, name))
 
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    name,
-			Implicits: deps,
-		})
+		ctx.Phony(name, deps...)
 	}
 
 	// Wrap those into host|host-cross|target phony rules
 	for _, class := range SortedStringKeys(osClass) {
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    PathForPhony(ctx, class),
-			Implicits: osClass[class],
-		})
+		ctx.Phony(class, osClass[class]...)
 	}
 }
 
diff --git a/android/neverallow.go b/android/neverallow.go
index be3f712..26e42e6 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -166,7 +166,7 @@
 }
 
 func createJavaDeviceForHostRules() []Rule {
-	javaDeviceForHostProjectsWhitelist := []string{
+	javaDeviceForHostProjectsAllowedList := []string{
 		"external/guava",
 		"external/robolectric-shadows",
 		"framework/layoutlib",
@@ -174,14 +174,14 @@
 
 	return []Rule{
 		NeverAllow().
-			NotIn(javaDeviceForHostProjectsWhitelist...).
+			NotIn(javaDeviceForHostProjectsAllowedList...).
 			ModuleType("java_device_for_host", "java_host_for_device").
-			Because("java_device_for_host can only be used in whitelisted projects"),
+			Because("java_device_for_host can only be used in allowed projects"),
 	}
 }
 
 func createCcSdkVariantRules() []Rule {
-	sdkVersionOnlyWhitelist := []string{
+	sdkVersionOnlyAllowedList := []string{
 		// derive_sdk_prefer32 has stem: "derive_sdk" which conflicts with the derive_sdk.
 		// This sometimes works because the APEX modules that contain derive_sdk and
 		// derive_sdk_prefer32 suppress the platform installation rules, but fails when
@@ -193,7 +193,7 @@
 		"tools/test/graphicsbenchmark/functional_tests/java",
 	}
 
-	platformVariantPropertiesWhitelist := []string{
+	platformVariantPropertiesAllowedList := []string{
 		// android_native_app_glue and libRSSupport use native_window.h but target old
 		// sdk versions (minimum and 9 respectively) where libnativewindow didn't exist,
 		// so they can't add libnativewindow to shared_libs to get the header directory
@@ -205,13 +205,13 @@
 
 	return []Rule{
 		NeverAllow().
-			NotIn(sdkVersionOnlyWhitelist...).
+			NotIn(sdkVersionOnlyAllowedList...).
 			WithMatcher("sdk_variant_only", isSetMatcherInstance).
-			Because("sdk_variant_only can only be used in whitelisted projects"),
+			Because("sdk_variant_only can only be used in allowed projects"),
 		NeverAllow().
-			NotIn(platformVariantPropertiesWhitelist...).
+			NotIn(platformVariantPropertiesAllowedList...).
 			WithMatcher("platform.shared_libs", isSetMatcherInstance).
-			Because("platform variant properties can only be used in whitelisted projects"),
+			Because("platform variant properties can only be used in allowed projects"),
 	}
 }
 
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 85c8c59..45d36a6 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -212,7 +212,7 @@
 				}`),
 		},
 		expectedErrors: []string{
-			"java_device_for_host can only be used in whitelisted projects",
+			"java_device_for_host can only be used in allowed projects",
 		},
 	},
 	// Libcore rule tests
@@ -261,46 +261,46 @@
 	},
 	// CC sdk rule tests
 	{
-		name: `"sdk_variant_only" outside whitelist`,
+		name: `"sdk_variant_only" outside allowed list`,
 		fs: map[string][]byte{
 			"Android.bp": []byte(`
 				cc_library {
-					name: "outside_whitelist",
+					name: "outside_allowed_list",
 					sdk_version: "current",
 					sdk_variant_only: true,
 				}`),
 		},
 		expectedErrors: []string{
-			`module "outside_whitelist": violates neverallow`,
+			`module "outside_allowed_list": violates neverallow`,
 		},
 	},
 	{
-		name: `"sdk_variant_only: false" outside whitelist`,
+		name: `"sdk_variant_only: false" outside allowed list`,
 		fs: map[string][]byte{
 			"Android.bp": []byte(`
 				cc_library {
-					name: "outside_whitelist",
+					name: "outside_allowed_list",
 					sdk_version: "current",
 					sdk_variant_only: false,
 				}`),
 		},
 		expectedErrors: []string{
-			`module "outside_whitelist": violates neverallow`,
+			`module "outside_allowed_list": violates neverallow`,
 		},
 	},
 	{
-		name: `"platform" outside whitelist`,
+		name: `"platform" outside allowed list`,
 		fs: map[string][]byte{
 			"Android.bp": []byte(`
 				cc_library {
-					name: "outside_whitelist",
+					name: "outside_allowed_list",
 					platform: {
 						shared_libs: ["libfoo"],
 					},
 				}`),
 		},
 		expectedErrors: []string{
-			`module "outside_whitelist": violates neverallow`,
+			`module "outside_allowed_list": violates neverallow`,
 		},
 	},
 	{
diff --git a/android/override_module.go b/android/override_module.go
index 9f5127d..7e58890 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -208,7 +208,21 @@
 // next phase.
 func overrideModuleDepsMutator(ctx BottomUpMutatorContext) {
 	if module, ok := ctx.Module().(OverrideModule); ok {
-		ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)
+		// Skip this overriding module if there's a prebuilt module that overrides it with prefer flag.
+		overriddenByPrebuilt := false
+		ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(dep Module) {
+			prebuilt, ok := dep.(PrebuiltInterface)
+			if !ok {
+				panic("PrebuiltDepTag leads to a non-prebuilt module " + dep.Name())
+			}
+			if prebuilt.Prebuilt().UsePrebuilt() {
+				overriddenByPrebuilt = true
+				return
+			}
+		})
+		if !overriddenByPrebuilt {
+			ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)
+		}
 	}
 }
 
diff --git a/android/paths.go b/android/paths.go
index 3ad27ac..bed6f3f 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -405,7 +405,7 @@
 		p := pathForModuleSrc(ctx, s)
 		if exists, _, err := ctx.Config().fs.Exists(p.String()); err != nil {
 			reportPathErrorf(ctx, "%s: %s", p, err.Error())
-		} else if !exists {
+		} else if !exists && !ctx.Config().testAllowNonExistentPaths {
 			reportPathErrorf(ctx, "module source path %q does not exist", p)
 		}
 
@@ -798,7 +798,7 @@
 		}
 	} else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil {
 		reportPathErrorf(ctx, "%s: %s", path, err.Error())
-	} else if !exists {
+	} else if !exists && !ctx.Config().testAllowNonExistentPaths {
 		reportPathErrorf(ctx, "source path %q does not exist", path)
 	}
 	return path
diff --git a/android/phony.go b/android/phony.go
new file mode 100644
index 0000000..f8e5a44
--- /dev/null
+++ b/android/phony.go
@@ -0,0 +1,75 @@
+// 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 (
+	"sync"
+
+	"github.com/google/blueprint"
+)
+
+var phonyMapOnceKey = NewOnceKey("phony")
+
+type phonyMap map[string]Paths
+
+var phonyMapLock sync.Mutex
+
+func getPhonyMap(config Config) phonyMap {
+	return config.Once(phonyMapOnceKey, func() interface{} {
+		return make(phonyMap)
+	}).(phonyMap)
+}
+
+func addPhony(config Config, name string, deps ...Path) {
+	phonyMap := getPhonyMap(config)
+	phonyMapLock.Lock()
+	defer phonyMapLock.Unlock()
+	phonyMap[name] = append(phonyMap[name], deps...)
+}
+
+type phonySingleton struct {
+	phonyMap  phonyMap
+	phonyList []string
+}
+
+var _ SingletonMakeVarsProvider = (*phonySingleton)(nil)
+
+func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
+	p.phonyMap = getPhonyMap(ctx.Config())
+	p.phonyList = SortedStringKeys(p.phonyMap)
+	for _, phony := range p.phonyList {
+		p.phonyMap[phony] = SortedUniquePaths(p.phonyMap[phony])
+	}
+
+	if !ctx.Config().EmbeddedInMake() {
+		for _, phony := range p.phonyList {
+			ctx.Build(pctx, BuildParams{
+				Rule:      blueprint.Phony,
+				Outputs:   []WritablePath{PathForPhony(ctx, phony)},
+				Implicits: p.phonyMap[phony],
+			})
+		}
+	}
+}
+
+func (p phonySingleton) MakeVars(ctx MakeVarsContext) {
+	for _, phony := range p.phonyList {
+		ctx.Phony(phony, p.phonyMap[phony]...)
+	}
+}
+
+func phonySingletonFactory() Singleton {
+	return &phonySingleton{}
+}
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index b568f78..8029b85 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -155,6 +155,44 @@
 			}`,
 		prebuilt: []OsClass{Host},
 	},
+	{
+		name: "prebuilt override not preferred",
+		modules: `
+			source {
+				name: "baz",
+			}
+
+			override_source {
+				name: "bar",
+				base: "baz",
+			}
+
+			prebuilt {
+				name: "bar",
+				prefer: false,
+				srcs: ["prebuilt_file"],
+			}`,
+		prebuilt: nil,
+	},
+	{
+		name: "prebuilt override preferred",
+		modules: `
+			source {
+				name: "baz",
+			}
+
+			override_source {
+				name: "bar",
+				base: "baz",
+			}
+
+			prebuilt {
+				name: "bar",
+				prefer: true,
+				srcs: ["prebuilt_file"],
+			}`,
+		prebuilt: []OsClass{Device, Host},
+	},
 }
 
 func TestPrebuilts(t *testing.T) {
@@ -256,8 +294,10 @@
 func registerTestPrebuiltBuildComponents(ctx RegistrationContext) {
 	ctx.RegisterModuleType("prebuilt", newPrebuiltModule)
 	ctx.RegisterModuleType("source", newSourceModule)
+	ctx.RegisterModuleType("override_source", newOverrideSourceModule)
 
 	RegisterPrebuiltMutators(ctx)
+	ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
 }
 
 type prebuiltModule struct {
@@ -300,11 +340,15 @@
 	}
 }
 
+type sourceModuleProperties struct {
+	Deps []string `android:"path,arch_variant"`
+}
+
 type sourceModule struct {
 	ModuleBase
-	properties struct {
-		Deps []string `android:"path,arch_variant"`
-	}
+	OverridableModuleBase
+
+	properties                                     sourceModuleProperties
 	dependsOnSourceModule, dependsOnPrebuiltModule bool
 	deps                                           Paths
 	src                                            Path
@@ -314,10 +358,11 @@
 	m := &sourceModule{}
 	m.AddProperties(&m.properties)
 	InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
+	InitOverridableModule(m, nil)
 	return m
 }
 
-func (s *sourceModule) DepsMutator(ctx BottomUpMutatorContext) {
+func (s *sourceModule) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) {
 	// s.properties.Deps are annotated with android:path, so they are
 	// automatically added to the dependency by pathDeps mutator
 }
@@ -330,3 +375,20 @@
 func (s *sourceModule) Srcs() Paths {
 	return Paths{s.src}
 }
+
+type overrideSourceModule struct {
+	ModuleBase
+	OverrideModuleBase
+}
+
+func (o *overrideSourceModule) GenerateAndroidBuildActions(_ ModuleContext) {
+}
+
+func newOverrideSourceModule() Module {
+	m := &overrideSourceModule{}
+	m.AddProperties(&sourceModuleProperties{})
+
+	InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
+	InitOverrideModule(m)
+	return m
+}
diff --git a/android/register.go b/android/register.go
index ccfe01e..036a811 100644
--- a/android/register.go
+++ b/android/register.go
@@ -104,6 +104,9 @@
 
 	registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
 
+	// Register phony just before makevars so it can write out its phony rules as Make rules
+	ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory))
+
 	// Register makevars after other singletons so they can export values through makevars
 	ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc))
 
diff --git a/android/singleton.go b/android/singleton.go
index 568398c..2c51c6c 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -36,6 +36,12 @@
 	Variable(pctx PackageContext, name, value string)
 	Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
 	Build(pctx PackageContext, params BuildParams)
+
+	// Phony creates a Make-style phony rule, a rule with no commands that can depend on other
+	// phony rules or real files.  Phony can be called on the same name multiple times to add
+	// additional dependencies.
+	Phony(name string, deps ...Path)
+
 	RequireNinjaVersion(major, minor, micro int)
 
 	// SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable
@@ -156,6 +162,10 @@
 
 }
 
+func (s *singletonContextAdaptor) Phony(name string, deps ...Path) {
+	addPhony(s.Config(), name, deps...)
+}
+
 func (s *singletonContextAdaptor) SetNinjaBuildDir(pctx PackageContext, value string) {
 	s.SingletonContext.SetNinjaBuildDir(pctx.PackageContext, value)
 }
diff --git a/android/variable.go b/android/variable.go
index e025ae0..b69d425 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -319,7 +319,7 @@
 	PackageNameOverrides         []string `json:",omitempty"`
 
 	EnforceSystemCertificate          *bool    `json:",omitempty"`
-	EnforceSystemCertificateWhitelist []string `json:",omitempty"`
+	EnforceSystemCertificateAllowList []string `json:",omitempty"`
 
 	ProductHiddenAPIStubs       []string `json:",omitempty"`
 	ProductHiddenAPIStubsSystem []string `json:",omitempty"`
diff --git a/android/writedocs.go b/android/writedocs.go
index 7262ad8..9e43e80 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -69,9 +69,5 @@
 	})
 
 	// Add a phony target for building the documentation
-	ctx.Build(pctx, BuildParams{
-		Rule:   blueprint.Phony,
-		Output: PathForPhony(ctx, "soong_docs"),
-		Input:  docsFile,
-	})
+	ctx.Phony("soong_docs", docsFile)
 }
diff --git a/apex/apex.go b/apex/apex.go
index d45dd6f..3fef1ee 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -64,13 +64,14 @@
 	usesTag        = dependencyTag{name: "uses"}
 	androidAppTag  = dependencyTag{name: "androidApp", payload: true}
 	rroTag         = dependencyTag{name: "rro", payload: true}
-	apexAvailWl    = makeApexAvailableWhitelist()
 
-	inverseApexAvailWl = invertApexWhiteList(apexAvailWl)
+	apexAvailBaseline = makeApexAvailableBaseline()
+
+	inverseApexAvailBaseline = invertApexBaseline(apexAvailBaseline)
 )
 
 // Transform the map of apex -> modules to module -> apexes.
-func invertApexWhiteList(m map[string][]string) map[string][]string {
+func invertApexBaseline(m map[string][]string) map[string][]string {
 	r := make(map[string][]string)
 	for apex, modules := range m {
 		for _, module := range modules {
@@ -80,16 +81,16 @@
 	return r
 }
 
-// Retrieve the while list of apexes to which the supplied module belongs.
-func WhitelistedApexAvailable(moduleName string) []string {
-	return inverseApexAvailWl[normalizeModuleName(moduleName)]
+// Retrieve the baseline of apexes to which the supplied module belongs.
+func BaselineApexAvailable(moduleName string) []string {
+	return inverseApexAvailBaseline[normalizeModuleName(moduleName)]
 }
 
 // This is a map from apex to modules, which overrides the
 // apex_available setting for that particular module to make
 // it available for the apex regardless of its setting.
 // TODO(b/147364041): remove this
-func makeApexAvailableWhitelist() map[string][]string {
+func makeApexAvailableBaseline() map[string][]string {
 	// The "Module separator"s below are employed to minimize merge conflicts.
 	m := make(map[string][]string)
 	//
@@ -871,17 +872,17 @@
 }
 
 var (
-	useVendorWhitelistKey = android.NewOnceKey("useVendorWhitelist")
+	useVendorAllowListKey = android.NewOnceKey("useVendorAllowList")
 )
 
-// useVendorWhitelist returns the list of APEXes which are allowed to use_vendor.
+// useVendorAllowList returns the list of APEXes which are allowed to use_vendor.
 // When use_vendor is used, native modules are built with __ANDROID_VNDK__ and __ANDROID_APEX__,
 // which may cause compatibility issues. (e.g. libbinder)
 // Even though libbinder restricts its availability via 'apex_available' property and relies on
 // yet another macro __ANDROID_APEX_<NAME>__, we restrict usage of "use_vendor:" from other APEX modules
 // to avoid similar problems.
-func useVendorWhitelist(config android.Config) []string {
-	return config.Once(useVendorWhitelistKey, func() interface{} {
+func useVendorAllowList(config android.Config) []string {
+	return config.Once(useVendorAllowListKey, func() interface{} {
 		return []string{
 			// swcodec uses "vendor" variants for smaller size
 			"com.android.media.swcodec",
@@ -890,11 +891,11 @@
 	}).([]string)
 }
 
-// setUseVendorWhitelistForTest overrides useVendorWhitelist and must be
-// called before the first call to useVendorWhitelist()
-func setUseVendorWhitelistForTest(config android.Config, whitelist []string) {
-	config.Once(useVendorWhitelistKey, func() interface{} {
-		return whitelist
+// setUseVendorAllowListForTest overrides useVendorAllowList and must be
+// called before the first call to useVendorAllowList()
+func setUseVendorAllowListForTest(config android.Config, allowList []string) {
+	config.Once(useVendorAllowListKey, func() interface{} {
+		return allowList
 	})
 }
 
@@ -992,7 +993,7 @@
 	// List of providing APEXes' names so that this APEX can depend on provided shared libraries.
 	Uses []string
 
-	// A txt file containing list of files that are whitelisted to be included in this APEX.
+	// A txt file containing list of files that are allowed to be included in this APEX.
 	Whitelisted_files *string
 
 	// package format of this apex variant; could be non-flattened, flattened, or zip.
@@ -1332,7 +1333,7 @@
 }
 
 func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
-	if proptools.Bool(a.properties.Use_vendor) && !android.InList(a.Name(), useVendorWhitelist(ctx.Config())) {
+	if proptools.Bool(a.properties.Use_vendor) && !android.InList(a.Name(), useVendorAllowList(ctx.Config())) {
 		ctx.PropertyErrorf("use_vendor", "not allowed to set use_vendor: true")
 	}
 
@@ -1804,7 +1805,7 @@
 			return false
 		}
 
-		if to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) {
+		if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
 			return true
 		}
 		ctx.ModuleErrorf("%q requires %q that is not available for the APEX. Dependency path:%s", fromName, toName, ctx.GetPathString(true))
@@ -2243,16 +2244,16 @@
 	})
 }
 
-func whitelistedApexAvailable(apex, moduleName string) bool {
+func baselineApexAvailable(apex, moduleName string) bool {
 	key := apex
 	moduleName = normalizeModuleName(moduleName)
 
-	if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
+	if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) {
 		return true
 	}
 
 	key = android.AvailableToAnyApex
-	if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
+	if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) {
 		return true
 	}
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 7bd0374..7159a45 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -241,6 +241,7 @@
 	java.RegisterSystemModulesBuildComponents(ctx)
 	java.RegisterAppBuildComponents(ctx)
 	ctx.RegisterModuleType("java_sdk_library", java.SdkLibraryFactory)
+	ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
 
 	ctx.PreDepsMutators(RegisterPreDepsMutators)
 	ctx.PostDepsMutators(RegisterPostDepsMutators)
@@ -1143,7 +1144,7 @@
 				symbol_file: "",
 			}
 			`, func(fs map[string][]byte, config android.Config) {
-				setUseVendorWhitelistForTest(config, []string{"myapex"})
+				setUseVendorAllowListForTest(config, []string{"myapex"})
 			}, withUnbundledBuild)
 
 			// Ensure that LLNDK dep is not included
@@ -1870,7 +1871,7 @@
 			apex_available: [ "myapex" ],
 		}
 	`, func(fs map[string][]byte, config android.Config) {
-		setUseVendorWhitelistForTest(config, []string{"myapex"})
+		setUseVendorAllowListForTest(config, []string{"myapex"})
 	})
 
 	inputsList := []string{}
@@ -1903,9 +1904,9 @@
 			private_key: "testkey.pem",
 		}
 	`, func(fs map[string][]byte, config android.Config) {
-		setUseVendorWhitelistForTest(config, []string{""})
+		setUseVendorAllowListForTest(config, []string{""})
 	})
-	// no error with whitelist
+	// no error with allow list
 	testApex(t, `
 		apex {
 			name: "myapex",
@@ -1918,7 +1919,7 @@
 			private_key: "testkey.pem",
 		}
 	`, func(fs map[string][]byte, config android.Config) {
-		setUseVendorWhitelistForTest(config, []string{"myapex"})
+		setUseVendorAllowListForTest(config, []string{"myapex"})
 	})
 }
 
@@ -3683,7 +3684,7 @@
 			private_key: "testkey.pem",
 		}
 	`, func(fs map[string][]byte, config android.Config) {
-		setUseVendorWhitelistForTest(config, []string{"myapex"})
+		setUseVendorAllowListForTest(config, []string{"myapex"})
 	})
 }
 
@@ -5196,6 +5197,46 @@
 	`)
 }
 
+func TestApexKeysTxt(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		prebuilt_apex {
+			name: "myapex",
+			prefer: true,
+			arch: {
+				arm64: {
+					src: "myapex-arm64.apex",
+				},
+				arm: {
+					src: "myapex-arm.apex",
+				},
+			},
+		}
+
+		apex_set {
+			name: "myapex_set",
+			set: "myapex.apks",
+			filename: "myapex_set.apex",
+			overrides: ["myapex"],
+		}
+	`)
+
+	apexKeysText := ctx.SingletonForTests("apex_keys_text")
+	content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
+	ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
+	ensureNotContains(t, content, "myapex.apex")
+}
+
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
diff --git a/apex/builder.go b/apex/builder.go
index 17eac1a..1293588 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -165,13 +165,13 @@
 	diffApexContentRule = pctx.StaticRule("diffApexContentRule", blueprint.RuleParams{
 		Command: `diff --unchanged-group-format='' \` +
 			`--changed-group-format='%<' \` +
-			`${image_content_file} ${whitelisted_files_file} || (` +
+			`${image_content_file} ${allowed_files_file} || (` +
 			`echo -e "New unexpected files were added to ${apex_module_name}." ` +
 			` "To fix the build run following command:" && ` +
-			`echo "system/apex/tools/update_whitelist.sh ${whitelisted_files_file} ${image_content_file}" && ` +
+			`echo "system/apex/tools/update_allowed_list.sh ${allowed_files_file} ${image_content_file}" && ` +
 			`exit 1); touch ${out}`,
-		Description: "Diff ${image_content_file} and ${whitelisted_files_file}",
-	}, "image_content_file", "whitelisted_files_file", "apex_module_name")
+		Description: "Diff ${image_content_file} and ${allowed_files_file}",
+	}, "image_content_file", "allowed_files_file", "apex_module_name")
 )
 
 func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs, requireNativeLibs []string) {
@@ -402,7 +402,7 @@
 			},
 		})
 		implicitInputs = append(implicitInputs, imageContentFile)
-		whitelistedFilesFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.Whitelisted_files))
+		allowedFilesFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.Whitelisted_files))
 
 		phonyOutput := android.PathForModuleOut(ctx, a.Name()+"-diff-phony-output")
 		ctx.Build(pctx, android.BuildParams{
@@ -411,9 +411,9 @@
 			Output:      phonyOutput,
 			Description: "diff apex image content",
 			Args: map[string]string{
-				"whitelisted_files_file": whitelistedFilesFile.String(),
-				"image_content_file":     imageContentFile.String(),
-				"apex_module_name":       a.Name(),
+				"allowed_files_file": allowedFilesFile.String(),
+				"image_content_file": imageContentFile.String(),
+				"apex_module_name":   a.Name(),
 			},
 		})
 
diff --git a/apex/key.go b/apex/key.go
index 607cac5..a68f6e1 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -106,10 +106,36 @@
 
 func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
 	s.output = android.PathForOutput(ctx, "apexkeys.txt")
-	apexModulesMap := make(map[string]android.Module)
+	type apexKeyEntry struct {
+		name                  string
+		presigned             bool
+		public_key            string
+		private_key           string
+		container_certificate string
+		container_private_key string
+		partition             string
+	}
+	toString := func(e apexKeyEntry) string {
+		format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n"
+		if e.presigned {
+			return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition)
+		} else {
+			return fmt.Sprintf(format, e.name, e.public_key, e.private_key, e.container_certificate, e.container_private_key, e.partition)
+		}
+	}
+
+	apexKeyMap := make(map[string]apexKeyEntry)
 	ctx.VisitAllModules(func(module android.Module) {
 		if m, ok := module.(*apexBundle); ok && m.Enabled() && m.installable() {
-			apexModulesMap[m.Name()] = m
+			apexKeyMap[m.Name()] = apexKeyEntry{
+				name:                  m.Name() + ".apex",
+				presigned:             false,
+				public_key:            m.public_key_file.String(),
+				private_key:           m.private_key_file.String(),
+				container_certificate: m.container_certificate_file.String(),
+				container_private_key: m.container_private_key_file.String(),
+				partition:             m.PartitionTag(ctx.DeviceConfig()),
+			}
 		}
 	})
 
@@ -117,35 +143,43 @@
 	ctx.VisitAllModules(func(module android.Module) {
 		if m, ok := module.(*Prebuilt); ok && m.Enabled() && m.installable() &&
 			m.Prebuilt().UsePrebuilt() {
-			apexModulesMap[m.BaseModuleName()] = m
+			apexKeyMap[m.BaseModuleName()] = apexKeyEntry{
+				name:      m.InstallFilename(),
+				presigned: true,
+				partition: m.PartitionTag(ctx.DeviceConfig()),
+			}
+		}
+	})
+
+	// Find apex_set and let them override apexBundle or prebuilts. This is done in a separate pass
+	// so that apex_set are not overridden by prebuilts.
+	ctx.VisitAllModules(func(module android.Module) {
+		if m, ok := module.(*ApexSet); ok && m.Enabled() {
+			entry := apexKeyEntry{
+				name:      m.InstallFilename(),
+				presigned: true,
+				partition: m.PartitionTag(ctx.DeviceConfig()),
+			}
+
+			for _, om := range m.Overrides() {
+				if _, ok := apexKeyMap[om]; ok {
+					delete(apexKeyMap, om)
+				}
+			}
+			apexKeyMap[m.BaseModuleName()] = entry
 		}
 	})
 
 	// iterating over map does not give consistent ordering in golang
 	var moduleNames []string
-	for key, _ := range apexModulesMap {
+	for key, _ := range apexKeyMap {
 		moduleNames = append(moduleNames, key)
 	}
 	sort.Strings(moduleNames)
 
 	var filecontent strings.Builder
-	for _, key := range moduleNames {
-		module := apexModulesMap[key]
-		if m, ok := module.(*apexBundle); ok {
-			fmt.Fprintf(&filecontent,
-				"name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n",
-				m.Name()+".apex",
-				m.public_key_file.String(),
-				m.private_key_file.String(),
-				m.container_certificate_file.String(),
-				m.container_private_key_file.String(),
-				m.PartitionTag(ctx.DeviceConfig()))
-		} else if m, ok := module.(*Prebuilt); ok {
-			fmt.Fprintf(&filecontent,
-				"name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n",
-				m.InstallFilename(),
-				"PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", m.PartitionTag(ctx.DeviceConfig()))
-		}
+	for _, name := range moduleNames {
+		fmt.Fprintf(&filecontent, "%s", toString(apexKeyMap[name]))
 	}
 
 	ctx.Build(pctx, android.BuildParams{
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 03266c5..bf574dc 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -278,6 +278,10 @@
 	return a.prebuilt.Name(a.ModuleBase.Name())
 }
 
+func (a *ApexSet) Overrides() []string {
+	return a.properties.Overrides
+}
+
 // prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
 func apexSetFactory() android.Module {
 	module := &ApexSet{}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 52480ea..b3ad610 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -457,6 +457,9 @@
 		entries.SetString("LOCAL_MODULE_PATH", path)
 		entries.SetString("LOCAL_MODULE_STEM", stem)
 		entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
+		if c.parsedCoverageXmlPath.String() != "" {
+			entries.SetString("SOONG_NDK_API_XML", "$(SOONG_NDK_API_XML) "+c.parsedCoverageXmlPath.String())
+		}
 	})
 }
 
diff --git a/cc/builder.go b/cc/builder.go
index e571e5a..b4f9947 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -283,16 +283,19 @@
 		"cFlags")
 )
 
+func PwdPrefix() string {
+	// Darwin doesn't have /proc
+	if runtime.GOOS != "darwin" {
+		return "PWD=/proc/self/cwd"
+	}
+	return ""
+}
+
 func init() {
 	// We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the
 	// debug output. That way two builds in two different directories will
 	// create the same output.
-	if runtime.GOOS != "darwin" {
-		pctx.StaticVariable("relPwd", "PWD=/proc/self/cwd")
-	} else {
-		// Darwin doesn't have /proc
-		pctx.StaticVariable("relPwd", "")
-	}
+	pctx.StaticVariable("relPwd", PwdPrefix())
 
 	pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
 	pctx.Import("android/soong/remoteexec")
diff --git a/cc/cc.go b/cc/cc.go
index 770391a..f80c229 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3223,12 +3223,7 @@
 	})
 	// TODO(asmundak): Perhaps emit a rule to output a warning if there were no xrefTargets
 	if len(xrefTargets) > 0 {
-		ctx.Build(pctx, android.BuildParams{
-			Rule:   blueprint.Phony,
-			Output: android.PathForPhony(ctx, "xref_cxx"),
-			Inputs: xrefTargets,
-			//Default: true,
-		})
+		ctx.Phony("xref_cxx", xrefTargets...)
 	}
 }
 
diff --git a/cc/compiler.go b/cc/compiler.go
index e7495da..b5f297c 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -514,7 +514,7 @@
 		flags.Local.CFlags = append(flags.Local.CFlags, "-fopenmp")
 	}
 
-	// Exclude directories from manual binder interface whitelisting.
+	// Exclude directories from manual binder interface allowed list.
 	//TODO(b/145621474): Move this check into IInterface.h when clang-tidy no longer uses absolute paths.
 	if android.HasAnyPrefix(ctx.ModuleDir(), allowedManualInterfacePaths) {
 		flags.Local.CFlags = append(flags.Local.CFlags, "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES")
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 3759329..d79badb 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -25,6 +25,10 @@
 	"android/soong/android"
 )
 
+func init() {
+	pctx.HostBinToolVariable("ndk_api_coverage_parser", "ndk_api_coverage_parser")
+}
+
 var (
 	toolPath = pctx.SourcePathVariable("toolPath", "build/soong/cc/scriptlib/gen_stub_libs.py")
 
@@ -35,6 +39,12 @@
 			CommandDeps: []string{"$toolPath"},
 		}, "arch", "apiLevel", "apiMap", "flags")
 
+	parseNdkApiRule = pctx.AndroidStaticRule("parseNdkApiRule",
+		blueprint.RuleParams{
+			Command:     "$ndk_api_coverage_parser $in $out --api-map $apiMap",
+			CommandDeps: []string{"$ndk_api_coverage_parser"},
+		}, "apiMap")
+
 	ndkLibrarySuffix = ".ndk"
 
 	ndkPrebuiltSharedLibs = []string{
@@ -111,8 +121,9 @@
 
 	properties libraryProperties
 
-	versionScriptPath android.ModuleGenPath
-	installPath       android.Path
+	versionScriptPath     android.ModuleGenPath
+	parsedCoverageXmlPath android.ModuleOutPath
+	installPath           android.Path
 }
 
 // OMG GO
@@ -308,14 +319,35 @@
 	return compileObjs(ctx, flagsToBuilderFlags(flags), subdir, srcs, nil, nil), versionScriptPath
 }
 
+func parseSymbolFileForCoverage(ctx ModuleContext, symbolFile string) android.ModuleOutPath {
+	apiLevelsJson := android.GetApiLevelsJson(ctx)
+	symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
+	outputFileName := strings.Split(symbolFilePath.Base(), ".")[0]
+	parsedApiCoveragePath := android.PathForModuleOut(ctx, outputFileName+".xml")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        parseNdkApiRule,
+		Description: "parse ndk api symbol file for api coverage: " + symbolFilePath.Rel(),
+		Outputs:     []android.WritablePath{parsedApiCoveragePath},
+		Input:       symbolFilePath,
+		Args: map[string]string{
+			"apiMap": apiLevelsJson.String(),
+		},
+	})
+	return parsedApiCoveragePath
+}
+
 func (c *stubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
 	if !strings.HasSuffix(String(c.properties.Symbol_file), ".map.txt") {
 		ctx.PropertyErrorf("symbol_file", "must end with .map.txt")
 	}
 
-	objs, versionScript := compileStubLibrary(ctx, flags, String(c.properties.Symbol_file),
+	symbolFile := String(c.properties.Symbol_file)
+	objs, versionScript := compileStubLibrary(ctx, flags, symbolFile,
 		c.properties.ApiLevel, "")
 	c.versionScriptPath = versionScript
+	if c.properties.ApiLevel == "current" && ctx.PrimaryArch() {
+		c.parsedCoverageXmlPath = parseSymbolFileForCoverage(ctx, symbolFile)
+	}
 	return objs
 }
 
diff --git a/cc/scriptlib/Android.bp b/cc/scriptlib/Android.bp
index daebfe1..ff9a2f0 100644
--- a/cc/scriptlib/Android.bp
+++ b/cc/scriptlib/Android.bp
@@ -21,3 +21,12 @@
         "test_ndk_api_coverage_parser.py",
     ],
 }
+
+python_binary_host {
+    name: "ndk_api_coverage_parser",
+    main: "ndk_api_coverage_parser.py",
+    srcs: [
+        "gen_stub_libs.py",
+        "ndk_api_coverage_parser.py",
+    ],
+}
diff --git a/cc/testing.go b/cc/testing.go
index edbb24d..479b424 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -467,15 +467,6 @@
 }
 
 func GatherRequiredFilesForTest(fs map[string][]byte) {
-	fs["prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-arm/usr/lib/crtbegin_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-arm/usr/lib/crtend_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/crtbegin_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/crtend_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-x86/usr/lib/crtbegin_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-x86/usr/lib/crtend_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-x86_64/usr/lib64/crtbegin_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-x86_64/usr/lib64/crtend_so.o"] = nil
 }
 
 func TestConfig(buildDir string, os android.OsType, env map[string]string,
@@ -484,20 +475,7 @@
 	// add some modules that are required by the compiler and/or linker
 	bp = bp + GatherRequiredDepsForTest(os)
 
-	mockFS := map[string][]byte{
-		"foo.c":       nil,
-		"foo.lds":     nil,
-		"bar.c":       nil,
-		"baz.c":       nil,
-		"baz.o":       nil,
-		"a.proto":     nil,
-		"b.aidl":      nil,
-		"sub/c.aidl":  nil,
-		"my_include":  nil,
-		"foo.map.txt": nil,
-		"liba.so":     nil,
-		"libb.a":      nil,
-	}
+	mockFS := map[string][]byte{}
 
 	GatherRequiredFilesForTest(mockFS)
 
diff --git a/java/app.go b/java/app.go
index 7a109be..0fdede1 100755
--- a/java/app.go
+++ b/java/app.go
@@ -691,9 +691,9 @@
 		systemCertPath := ctx.Config().DefaultAppCertificateDir(ctx).String()
 		if strings.HasPrefix(certPath, systemCertPath) {
 			enforceSystemCert := ctx.Config().EnforceSystemCertificate()
-			whitelist := ctx.Config().EnforceSystemCertificateWhitelist()
+			allowed := ctx.Config().EnforceSystemCertificateAllowList()
 
-			if enforceSystemCert && !inList(m.Name(), whitelist) {
+			if enforceSystemCert && !inList(m.Name(), allowed) {
 				ctx.PropertyErrorf("certificate", "The module in product partition cannot be signed with certificate in system.")
 			}
 		}
diff --git a/java/app_test.go b/java/app_test.go
index eeba161..e45ba70 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2657,7 +2657,7 @@
 }
 
 func TestEmbedNotice(t *testing.T) {
-	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
+	ctx, _ := testJavaWithFS(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		android_app {
 			name: "foo",
 			srcs: ["a.java"],
@@ -2713,7 +2713,12 @@
 			srcs: ["b.java"],
 			notice: "TOOL_NOTICE",
 		}
-	`)
+	`, map[string][]byte{
+		"APP_NOTICE":     nil,
+		"GENRULE_NOTICE": nil,
+		"LIB_NOTICE":     nil,
+		"TOOL_NOTICE":    nil,
+	})
 
 	// foo has NOTICE files to process, and embed_notices is true.
 	foo := ctx.ModuleForTests("foo", "android_common")
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 877fd8a..9191a83 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -51,7 +51,7 @@
 // java_device_for_host makes the classes.jar output of a device java_library module available to host
 // java_library modules.
 //
-// It is rarely necessary, and its usage is restricted to a few whitelisted projects.
+// It is rarely necessary, and its usage is restricted to a few allowed projects.
 func DeviceForHostFactory() android.Module {
 	module := &DeviceForHost{}
 
@@ -68,7 +68,7 @@
 // java_host_for_device makes the classes.jar output of a host java_library module available to device
 // java_library modules.
 //
-// It is rarely necessary, and its usage is restricted to a few whitelisted projects.
+// It is rarely necessary, and its usage is restricted to a few allowed projects.
 func HostForDeviceFactory() android.Module {
 	module := &HostForDevice{}
 
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 4c3e112..68cfe9f 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1470,7 +1470,7 @@
 		FlagWithInput("@", srcJarList).
 		FlagWithOutput("--strict-input-files:warn ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))
 
-	if implicitsRsp.String() != "" {
+	if implicitsRsp != nil {
 		cmd.FlagWithArg("--strict-input-files-exempt ", "@"+implicitsRsp.String())
 	}
 
diff --git a/java/java.go b/java/java.go
index 5f8ad03..1cdfbf1 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2874,11 +2874,7 @@
 	})
 	// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
 	if len(xrefTargets) > 0 {
-		ctx.Build(pctx, android.BuildParams{
-			Rule:   blueprint.Phony,
-			Output: android.PathForPhony(ctx, "xref_java"),
-			Inputs: xrefTargets,
-		})
+		ctx.Phony("xref_java", xrefTargets...)
 	}
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index 8ea34d9..215070e 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -142,9 +142,14 @@
 	return ctx, config
 }
 
+func testJavaWithFS(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) {
+	t.Helper()
+	return testJavaWithConfig(t, testConfig(nil, bp, fs))
+}
+
 func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) {
 	t.Helper()
-	return testJavaWithConfig(t, testConfig(nil, bp, nil))
+	return testJavaWithFS(t, bp, nil)
 }
 
 func testJavaWithConfig(t *testing.T, config android.Config) (*android.TestContext, android.Config) {
@@ -740,7 +745,7 @@
 
 	for _, test := range table {
 		t.Run(test.name, func(t *testing.T) {
-			ctx, _ := testJava(t, `
+			ctx, _ := testJavaWithFS(t, `
 				java_library {
 					name: "foo",
 					srcs: [
@@ -750,7 +755,13 @@
 					],
 					`+test.prop+`,
 				}
-			`+test.extra)
+			`+test.extra,
+				map[string][]byte{
+					"java-res/a/a": nil,
+					"java-res/b/b": nil,
+					"java-res2/a":  nil,
+				},
+			)
 
 			foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
 			fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar")
@@ -769,7 +780,7 @@
 }
 
 func TestIncludeSrcs(t *testing.T) {
-	ctx, _ := testJava(t, `
+	ctx, _ := testJavaWithFS(t, `
 		java_library {
 			name: "foo",
 			srcs: [
@@ -790,7 +801,11 @@
 			java_resource_dirs: ["java-res"],
 			include_srcs: true,
 		}
-	`)
+	`, map[string][]byte{
+		"java-res/a/a": nil,
+		"java-res/b/b": nil,
+		"java-res2/a":  nil,
+	})
 
 	// Test a library with include_srcs: true
 	foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
@@ -832,7 +847,7 @@
 }
 
 func TestGeneratedSources(t *testing.T) {
-	ctx, _ := testJava(t, `
+	ctx, _ := testJavaWithFS(t, `
 		java_library {
 			name: "foo",
 			srcs: [
@@ -847,7 +862,10 @@
 			tool_files: ["java-res/a"],
 			out: ["gen.java"],
 		}
-	`)
+	`, map[string][]byte{
+		"a.java": nil,
+		"b.java": nil,
+	})
 
 	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
 	genrule := ctx.ModuleForTests("gen", "").Rule("generator")
@@ -932,7 +950,7 @@
 }
 
 func TestDroiddoc(t *testing.T) {
-	ctx, _ := testJava(t, `
+	ctx, _ := testJavaWithFS(t, `
 		droiddoc_exported_dir {
 		    name: "droiddoc-templates-sdk",
 		    path: ".",
@@ -945,7 +963,7 @@
 		droiddoc {
 		    name: "bar-doc",
 		    srcs: [
-		        "bar-doc/*.java",
+		        "bar-doc/a.java",
 		        "bar-doc/IFoo.aidl",
 		        ":bar-doc-aidl-srcs",
 		    ],
@@ -963,7 +981,11 @@
 		    todo_file: "libcore-docs-todo.html",
 		    args: "-offlinemode -title \"libcore\"",
 		}
-		`)
+		`,
+		map[string][]byte{
+			"bar-doc/a.java": nil,
+			"bar-doc/b.java": nil,
+		})
 
 	barDoc := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc")
 	var javaSrcs []string
@@ -989,7 +1011,7 @@
 		droidstubs {
 		    name: "stubs-source-system-modules",
 		    srcs: [
-		        "bar-doc/*.java",
+		        "bar-doc/a.java",
 		    ],
 				sdk_version: "none",
 				system_modules: "source-system-modules",
@@ -1010,7 +1032,7 @@
 		droidstubs {
 		    name: "stubs-prebuilt-system-modules",
 		    srcs: [
-		        "bar-doc/*.java",
+		        "bar-doc/a.java",
 		    ],
 				sdk_version: "none",
 				system_modules: "prebuilt-system-modules",
diff --git a/java/testing.go b/java/testing.go
index f993f56..f34c64a 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -25,35 +25,12 @@
 	bp += GatherRequiredDepsForTest()
 
 	mockFS := map[string][]byte{
-		"a.java":                 nil,
-		"b.java":                 nil,
-		"c.java":                 nil,
-		"b.kt":                   nil,
-		"a.jar":                  nil,
-		"b.jar":                  nil,
-		"c.jar":                  nil,
-		"APP_NOTICE":             nil,
-		"GENRULE_NOTICE":         nil,
-		"LIB_NOTICE":             nil,
-		"TOOL_NOTICE":            nil,
-		"AndroidTest.xml":        nil,
-		"java-res/a/a":           nil,
-		"java-res/b/b":           nil,
-		"java-res2/a":            nil,
-		"java-fg/a.java":         nil,
-		"java-fg/b.java":         nil,
-		"java-fg/c.java":         nil,
 		"api/current.txt":        nil,
 		"api/removed.txt":        nil,
 		"api/system-current.txt": nil,
 		"api/system-removed.txt": nil,
 		"api/test-current.txt":   nil,
 		"api/test-removed.txt":   nil,
-		"framework/aidl/a.aidl":  nil,
-		"aidl/foo/IFoo.aidl":     nil,
-		"aidl/bar/IBar.aidl":     nil,
-		"assets_a/a":             nil,
-		"assets_b/b":             nil,
 
 		"prebuilts/sdk/14/public/android.jar":                      nil,
 		"prebuilts/sdk/14/public/framework.aidl":                   nil,
@@ -103,45 +80,6 @@
 		"prebuilts/sdk/30/test/api/bar-removed.txt":                nil,
 		"prebuilts/sdk/tools/core-lambda-stubs.jar":                nil,
 		"prebuilts/sdk/Android.bp":                                 []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`),
-
-		"prebuilts/apk/app.apk":        nil,
-		"prebuilts/apk/app_arm.apk":    nil,
-		"prebuilts/apk/app_arm64.apk":  nil,
-		"prebuilts/apk/app_xhdpi.apk":  nil,
-		"prebuilts/apk/app_xxhdpi.apk": nil,
-
-		"prebuilts/apks/app.apks": nil,
-
-		// For framework-res, which is an implicit dependency for framework
-		"AndroidManifest.xml":                        nil,
-		"build/make/target/product/security/testkey": nil,
-
-		"build/soong/scripts/jar-wrapper.sh": nil,
-
-		"build/make/core/verify_uses_libraries.sh": nil,
-
-		"build/make/core/proguard.flags":             nil,
-		"build/make/core/proguard_basic_keeps.flags": nil,
-
-		"jdk8/jre/lib/jce.jar": nil,
-		"jdk8/jre/lib/rt.jar":  nil,
-		"jdk8/lib/tools.jar":   nil,
-
-		"bar-doc/a.java":                 nil,
-		"bar-doc/b.java":                 nil,
-		"bar-doc/IFoo.aidl":              nil,
-		"bar-doc/IBar.aidl":              nil,
-		"bar-doc/known_oj_tags.txt":      nil,
-		"external/doclava/templates-sdk": nil,
-
-		"cert/new_cert.x509.pem": nil,
-		"cert/new_cert.pk8":      nil,
-		"lineage.bin":            nil,
-
-		"testdata/data": nil,
-
-		"stubs-sources/foo/Foo.java": nil,
-		"stubs/sources/foo/Foo.java": nil,
 	}
 
 	cc.GatherRequiredFilesForTest(mockFS)
diff --git a/rust/OWNERS b/rust/OWNERS
index 82713f9..afd06e4 100644
--- a/rust/OWNERS
+++ b/rust/OWNERS
@@ -1,5 +1,5 @@
 # Additional owner/reviewers for rust rules, including parent directory owners.
 per-file * = chh@google.com, ivanlozano@google.com, jeffv@google.com, srhines@google.com
 
-# Limited owners/reviewers of the whitelist.
-per-file whitelist.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
+# Limited owners/reviewers of the allowed list.
+per-file allowed_list.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 0e2bea3..69d0df5 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -99,7 +99,6 @@
 func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	test.binaryDecorator.AndroidMk(ctx, ret)
 	ret.Class = "NATIVE_TESTS"
-	ret.SubName = test.getMutatedModuleSubName(ctx.Name())
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		if len(test.Properties.Test_suites) > 0 {
 			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
diff --git a/rust/builder.go b/rust/builder.go
index fbe0e53..5069b07 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -21,6 +21,7 @@
 	"github.com/google/blueprint/pathtools"
 
 	"android/soong/android"
+	"android/soong/cc"
 )
 
 var (
@@ -161,11 +162,17 @@
 
 	if flags.Coverage {
 		var gcnoFile android.WritablePath
+		// Provide consistency with cc gcda output, see cc/builder.go init()
+		profileEmitArg := strings.TrimPrefix("PWD=", cc.PwdPrefix()) + "/"
 
 		if outputFile.Ext() != "" {
 			gcnoFile = android.PathForModuleOut(ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcno"))
+			rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
+				ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcda")).String())
 		} else {
 			gcnoFile = android.PathForModuleOut(ctx, outputFile.Base()+".gcno")
+			rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
+				ctx, outputFile.Base()+".gcda").String())
 		}
 
 		implicitOutputs = append(implicitOutputs, gcnoFile)
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index 1a10312..5026da3 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -10,7 +10,7 @@
         "arm64_device.go",
         "global.go",
         "toolchain.go",
-        "whitelist.go",
+        "allowed_list.go",
         "x86_darwin_host.go",
         "x86_linux_host.go",
         "x86_device.go",
diff --git a/rust/config/whitelist.go b/rust/config/allowed_list.go
similarity index 100%
rename from rust/config/whitelist.go
rename to rust/config/allowed_list.go
diff --git a/rust/rust.go b/rust/rust.go
index 8cf2e6d..6671dd3 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -39,7 +39,6 @@
 	android.RegisterModuleType("rust_defaults", defaultsFactory)
 	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
-		ctx.BottomUp("rust_unit_tests", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("rust_begin", BeginMutator).Parallel()
 	})
 	pctx.Import("android/soong/rust/config")
diff --git a/rust/test.go b/rust/test.go
index 10c2785..f616c06 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -15,14 +15,16 @@
 package rust
 
 import (
-	"path/filepath"
-	"strings"
-
 	"android/soong/android"
 	"android/soong/tradefed"
 )
 
 type TestProperties struct {
+	// Disables the creation of a test-specific directory when used with
+	// relative_install_path. Useful if several tests need to be in the same
+	// directory, but test_per_src doesn't work.
+	No_named_install_directory *bool
+
 	// the name of the test configuration (for example "AndroidTest.xml") that should be
 	// installed with the module.
 	Test_config *string `android:"path,arch_variant"`
@@ -64,7 +66,7 @@
 	}
 
 	module.compiler = test
-
+	module.AddProperties(&test.Properties)
 	return module, test
 }
 
@@ -72,36 +74,21 @@
 	return append(test.binaryDecorator.compilerProps(), &test.Properties)
 }
 
-func (test *testDecorator) getMutatedModuleSubName(moduleName string) string {
-	stem := String(test.baseCompiler.Properties.Stem)
-	if stem != "" && !strings.HasSuffix(moduleName, "_"+stem) {
-		// Avoid repeated suffix in the module name.
-		return "_" + stem
-	}
-	return ""
-}
-
 func (test *testDecorator) install(ctx ModuleContext, file android.Path) {
-	name := ctx.ModuleName()
-	path := test.baseCompiler.relativeInstallPath()
-	// on device, use mutated module name
-	name = name + test.getMutatedModuleSubName(name)
-	if !ctx.Device() { // on host, use mutated module name + arch type + stem name
-		stem := String(test.baseCompiler.Properties.Stem)
-		if stem == "" {
-			stem = name
-		}
-		name = filepath.Join(name, ctx.Arch().ArchType.String(), stem)
-	}
-	test.testConfig = tradefed.AutoGenRustTestConfig(ctx, name,
+	test.testConfig = tradefed.AutoGenRustTestConfig(ctx,
 		test.Properties.Test_config,
 		test.Properties.Test_config_template,
 		test.Properties.Test_suites,
+		nil,
 		test.Properties.Auto_gen_config)
+
 	// default relative install path is module name
-	if path == "" {
+	if !Bool(test.Properties.No_named_install_directory) {
 		test.baseCompiler.relative = ctx.ModuleName()
+	} else if String(test.baseCompiler.Properties.Relative_install_path) == "" {
+		ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set")
 	}
+
 	test.binaryDecorator.install(ctx, file)
 }
 
@@ -126,64 +113,3 @@
 	module, _ := NewRustTest(android.HostSupported)
 	return module.Init()
 }
-
-func (test *testDecorator) testPerSrc() bool {
-	return true
-}
-
-func (test *testDecorator) srcs() []string {
-	return test.binaryDecorator.Properties.Srcs
-}
-
-func (test *testDecorator) setSrc(name, src string) {
-	test.binaryDecorator.Properties.Srcs = []string{src}
-	test.baseCompiler.Properties.Stem = StringPtr(name)
-}
-
-func (test *testDecorator) unsetSrc() {
-	test.binaryDecorator.Properties.Srcs = nil
-	test.baseCompiler.Properties.Stem = StringPtr("")
-}
-
-type testPerSrc interface {
-	testPerSrc() bool
-	srcs() []string
-	setSrc(string, string)
-	unsetSrc()
-}
-
-var _ testPerSrc = (*testDecorator)(nil)
-
-func TestPerSrcMutator(mctx android.BottomUpMutatorContext) {
-	if m, ok := mctx.Module().(*Module); ok {
-		if test, ok := m.compiler.(testPerSrc); ok {
-			numTests := len(test.srcs())
-			if test.testPerSrc() && numTests > 0 {
-				if duplicate, found := android.CheckDuplicate(test.srcs()); found {
-					mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
-					return
-				}
-				// Rust compiler always compiles one source file at a time and
-				// uses the crate name as output file name.
-				// Cargo uses the test source file name as default crate name,
-				// but that can be redefined.
-				// So when there are multiple source files, the source file names will
-				// be the output file names, but when there is only one test file,
-				// use the crate name.
-				testNames := make([]string, numTests)
-				for i, src := range test.srcs() {
-					testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
-				}
-				crateName := m.compiler.crateName()
-				if numTests == 1 && crateName != "" {
-					testNames[0] = crateName
-				}
-				// TODO(chh): Add an "all tests" variation like cc/test.go?
-				tests := mctx.CreateLocalVariations(testNames...)
-				for i, src := range test.srcs() {
-					tests[i].(*Module).compiler.(testPerSrc).setSrc(testNames[i], src)
-				}
-			}
-		}
-	}
-}
diff --git a/rust/test_test.go b/rust/test_test.go
index f131c6e..2382b18 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -19,45 +19,17 @@
 	"testing"
 )
 
-// Check if rust_test_host accepts multiple source files and applies --test flag.
 func TestRustTest(t *testing.T) {
 	ctx := testRust(t, `
 		rust_test_host {
 			name: "my_test",
-			srcs: ["foo.rs", "src/bar.rs"],
-			crate_name: "new_test", // not used for multiple source files
-			relative_install_path: "rust/my-test",
-		}`)
-
-	for _, name := range []string{"foo", "bar"} {
-		testingModule := ctx.ModuleForTests("my_test", "linux_glibc_x86_64_"+name)
-		testingBuildParams := testingModule.Output(name)
-		rustcFlags := testingBuildParams.Args["rustcFlags"]
-		if !strings.Contains(rustcFlags, "--test") {
-			t.Errorf("%v missing --test flag, rustcFlags: %#v", name, rustcFlags)
-		}
-		outPath := "/my_test/linux_glibc_x86_64_" + name + "/" + name
-		if !strings.Contains(testingBuildParams.Output.String(), outPath) {
-			t.Errorf("wrong output: %v  expect: %v", testingBuildParams.Output, outPath)
-		}
-	}
-}
-
-// crate_name is output file name, when there is only one source file.
-func TestRustTestSingleFile(t *testing.T) {
-	ctx := testRust(t, `
-		rust_test_host {
-			name: "my-test",
 			srcs: ["foo.rs"],
-			crate_name: "new_test",
-			relative_install_path: "my-pkg",
 		}`)
 
-	name := "new_test"
-	testingModule := ctx.ModuleForTests("my-test", "linux_glibc_x86_64_"+name)
-	outPath := "/my-test/linux_glibc_x86_64_" + name + "/" + name
-	testingBuildParams := testingModule.Output(name)
-	if !strings.Contains(testingBuildParams.Output.String(), outPath) {
-		t.Errorf("wrong output: %v  expect: %v", testingBuildParams.Output, outPath)
+	testingModule := ctx.ModuleForTests("my_test", "linux_glibc_x86_64")
+	expectedOut := "my_test/linux_glibc_x86_64/my_test"
+	outPath := testingModule.Output("my_test").Output.String()
+	if !strings.Contains(outPath, expectedOut) {
+		t.Errorf("wrong output path: %v;  expected: %v", outPath, expectedOut)
 	}
 }
diff --git a/rust/testing.go b/rust/testing.go
index f94af71..4e186d3 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -97,7 +97,6 @@
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		// rust mutators
 		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
-		ctx.BottomUp("rust_unit_tests", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("rust_begin", BeginMutator).Parallel()
 	})
 	ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index f836ea9..df763c8 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -20,6 +20,7 @@
   conscrypt-module-test-exports
   conscrypt-module-host-exports
   runtime-module-sdk
+  runtime-module-host-exports
 )
 
 # We want to create apex modules for all supported architectures.
diff --git a/sdk/update.go b/sdk/update.go
index 1ba5806..8241151 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -22,6 +22,7 @@
 
 	"android/soong/apex"
 	"android/soong/cc"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
@@ -700,8 +701,8 @@
 	if apexAware, ok := variant.(interface{ ApexAvailable() []string }); ok {
 		apexAvailable := apexAware.ApexAvailable()
 
-		// Add in any white listed apex available settings.
-		apexAvailable = append(apexAvailable, apex.WhitelistedApexAvailable(member.Name())...)
+		// Add in any baseline apex available settings.
+		apexAvailable = append(apexAvailable, apex.BaselineApexAvailable(member.Name())...)
 
 		if len(apexAvailable) > 0 {
 			// Remove duplicates and sort.
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index ae653fd..7bb267d 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -107,8 +107,6 @@
 
 	testProperties TestProperties
 
-	installDir android.InstallPath
-
 	data       android.Paths
 	testConfig android.Path
 }
@@ -203,8 +201,8 @@
 	} else if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
 		testDir = filepath.Join(testDir, ctx.Arch().ArchType.String())
 	}
-	s.installDir = android.PathForModuleInstall(ctx, testDir, proptools.String(s.properties.Sub_dir), s.Name())
-	s.installedFile = ctx.InstallExecutable(s.installDir, s.outputFilePath.Base(), s.outputFilePath)
+	installDir := android.PathForModuleInstall(ctx, testDir, proptools.String(s.properties.Sub_dir))
+	s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
 
 	s.data = android.PathsForModuleSrc(ctx, s.testProperties.Data)
 
@@ -232,7 +230,6 @@
 			func(entries *android.AndroidMkEntries) {
 				s.customAndroidMkEntries(entries)
 
-				entries.SetPath("LOCAL_MODULE_PATH", s.installDir.ToMakePath())
 				entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...)
 				if s.testConfig != nil {
 					entries.SetPath("LOCAL_FULL_TEST_CONFIG", s.testConfig)
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index 6ab22c5..6c0d96a 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -55,7 +55,7 @@
 	return ctx, config
 }
 
-func TestShTest(t *testing.T) {
+func TestShTestTestData(t *testing.T) {
 	ctx, config := testShBinary(t, `
 		sh_test {
 			name: "foo",
@@ -71,17 +71,10 @@
 	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
 
 	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
-
-	expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo"
-	actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
-	if expectedPath != actualPath {
-		t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath)
-	}
-
-	expectedData := []string{":testdata/data1", ":testdata/sub/data2"}
-	actualData := entries.EntryMap["LOCAL_TEST_DATA"]
-	if !reflect.DeepEqual(expectedData, actualData) {
-		t.Errorf("Unexpected test data expected: %q, actual: %q", expectedData, actualData)
+	expected := []string{":testdata/data1", ":testdata/sub/data2"}
+	actual := entries.EntryMap["LOCAL_TEST_DATA"]
+	if !reflect.DeepEqual(expected, actual) {
+		t.Errorf("Unexpected test data expected: %q, actual: %q", expected, actual)
 	}
 }
 
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index b225edd..1cb874d 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -220,19 +220,20 @@
 	return path
 }
 
-func AutoGenRustTestConfig(ctx android.ModuleContext, name string, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, autoGenConfig *bool) android.Path {
+func AutoGenRustTestConfig(ctx android.ModuleContext, testConfigProp *string,
+	testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool) android.Path {
 	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
 	if autogenPath != nil {
-		templatePathString := "${RustHostTestConfigTemplate}"
-		if ctx.Device() {
-			templatePathString = "${RustDeviceTestConfigTemplate}"
-		}
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			templatePathString = templatePath.String()
+			autogenTemplate(ctx, autogenPath, templatePath.String(), config)
+		} else {
+			if ctx.Device() {
+				autogenTemplate(ctx, autogenPath, "${RustDeviceTestConfigTemplate}", config)
+			} else {
+				autogenTemplate(ctx, autogenPath, "${RustHostTestConfigTemplate}", config)
+			}
 		}
-		autogenTemplateWithName(ctx, name, autogenPath, templatePathString, nil)
 		return autogenPath
 	}
 	return path