Merge "Fix nested properties in soong config structs"
diff --git a/android/apex.go b/android/apex.go
index 81f8c86..a014592 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -849,8 +849,12 @@
 		if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
 			toName := ctx.OtherModuleName(to)
 			if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) {
-				ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v. Dependency path: %s",
-					minSdkVersion, ctx.ModuleName(), err.Error(), ctx.GetPathString(false))
+				ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v."+
+					"\n\nDependency path: %s\n\n"+
+					"Consider adding 'min_sdk_version: %q' to %q",
+					minSdkVersion, ctx.ModuleName(), err.Error(),
+					ctx.GetPathString(false),
+					minSdkVersion, ctx.ModuleName())
 				return false
 			}
 		}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 415f00e..9cd9fad 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -441,7 +441,7 @@
 		case "arm":
 			deps_arm = append(deps_arm, labelString)
 		default:
-			panic(fmt.Sprintf("unhandled architecture %s for %s", getArchString(val), val))
+			panic(fmt.Sprintf("unhandled architecture %s for %v", getArchString(val), val))
 		}
 	}
 
diff --git a/android/config.go b/android/config.go
index ef5eadf..c10ad09 100644
--- a/android/config.go
+++ b/android/config.go
@@ -232,7 +232,7 @@
 
 	// Copy the real PATH value to the test environment, it's needed by
 	// NonHermeticHostSystemTool() used in x86_darwin_host.go
-	envCopy["PATH"] = originalEnv["PATH"]
+	envCopy["PATH"] = os.Getenv("PATH")
 
 	config := &config{
 		productVariables: productVariables{
diff --git a/android/defs.go b/android/defs.go
index 38ecb05..1a76721 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -57,6 +57,15 @@
 		},
 		"cpFlags")
 
+	// A copy rule that only updates the output if it changed.
+	CpIfChanged = pctx.AndroidStaticRule("CpIfChanged",
+		blueprint.RuleParams{
+			Command:     "if ! cmp -s $in $out; then cp $in $out; fi",
+			Description: "cp if changed $out",
+			Restat:      true,
+		},
+		"cpFlags")
+
 	CpExecutable = pctx.AndroidStaticRule("CpExecutable",
 		blueprint.RuleParams{
 			Command:     "rm -f $out && cp $cpPreserveSymlinks $cpFlags $in $out && chmod +x $out",
diff --git a/android/env.go b/android/env.go
index a8c7777..289d803 100644
--- a/android/env.go
+++ b/android/env.go
@@ -15,12 +15,6 @@
 package android
 
 import (
-	"fmt"
-	"os"
-	"os/exec"
-	"strings"
-	"syscall"
-
 	"android/soong/shared"
 )
 
@@ -32,70 +26,12 @@
 // a manifest regeneration.
 
 var originalEnv map[string]string
-var soongDelveListen string
-var soongDelvePath string
-var soongDelveEnv []string
 
-func init() {
-	// Delve support needs to read this environment variable very early, before NewConfig has created a way to
-	// access originalEnv with dependencies.  Store the value where soong_build can find it, it will manually
-	// ensure the dependencies are created.
-	soongDelveListen = os.Getenv("SOONG_DELVE")
-	soongDelvePath = os.Getenv("SOONG_DELVE_PATH")
-	if soongDelvePath == "" {
-		soongDelvePath, _ = exec.LookPath("dlv")
-	}
-
-	originalEnv = make(map[string]string)
-	soongDelveEnv = []string{}
-	for _, env := range os.Environ() {
-		idx := strings.IndexRune(env, '=')
-		if idx != -1 {
-			originalEnv[env[:idx]] = env[idx+1:]
-			if env[:idx] != "SOONG_DELVE" && env[:idx] != "SOONG_DELVE_PATH" {
-				soongDelveEnv = append(soongDelveEnv, env)
-			}
-		}
-	}
-
-	// Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment
-	// variable values.  The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc.
-	os.Clearenv()
-}
-
-func ReexecWithDelveMaybe() {
-	if soongDelveListen == "" {
-		return
-	}
-
-	if soongDelvePath == "" {
-		fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv")
-		os.Exit(1)
-	}
-	dlvArgv := []string{
-		soongDelvePath,
-		"--listen=:" + soongDelveListen,
-		"--headless=true",
-		"--api-version=2",
-		"exec",
-		os.Args[0],
-		"--",
-	}
-	dlvArgv = append(dlvArgv, os.Args[1:]...)
-	os.Chdir(absSrcDir)
-	syscall.Exec(soongDelvePath, dlvArgv, soongDelveEnv)
-	fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
-	os.Exit(1)
-}
-
-// getenv checks either os.Getenv or originalEnv so that it works before or after the init()
-// function above.  It doesn't add any dependencies on the environment variable, so it should
-// only be used for values that won't change.  For values that might change use ctx.Config().Getenv.
-func getenv(key string) string {
-	if originalEnv == nil {
-		return os.Getenv(key)
-	} else {
-		return originalEnv[key]
+func InitEnvironment(envFile string) {
+	var err error
+	originalEnv, err = shared.EnvFromFile(envFile)
+	if err != nil {
+		panic(err)
 	}
 }
 
@@ -108,7 +44,7 @@
 func (c *envSingleton) GenerateBuildActions(ctx SingletonContext) {
 	envDeps := ctx.Config().EnvDeps()
 
-	envFile := PathForOutput(ctx, ".soong.environment")
+	envFile := PathForOutput(ctx, "soong.environment.used")
 	if ctx.Failed() {
 		return
 	}
diff --git a/android/fixture.go b/android/fixture.go
index ae24b91..2c8997b 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -61,15 +61,15 @@
 // register module bar twice:
 //   var Preparer1 = FixtureRegisterWithContext(RegisterModuleFooAndBar)
 //   var Preparer2 = FixtureRegisterWithContext(RegisterModuleBarAndBaz)
-//   var AllPreparers = FixturePreparers(Preparer1, Preparer2)
+//   var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
 //
 // However, when restructured like this it would work fine:
 //   var PreparerFoo = FixtureRegisterWithContext(RegisterModuleFoo)
 //   var PreparerBar = FixtureRegisterWithContext(RegisterModuleBar)
 //   var PreparerBaz = FixtureRegisterWithContext(RegisterModuleBaz)
-//   var Preparer1 = FixturePreparers(RegisterModuleFoo, RegisterModuleBar)
-//   var Preparer2 = FixturePreparers(RegisterModuleBar, RegisterModuleBaz)
-//   var AllPreparers = FixturePreparers(Preparer1, Preparer2)
+//   var Preparer1 = GroupFixturePreparers(RegisterModuleFoo, RegisterModuleBar)
+//   var Preparer2 = GroupFixturePreparers(RegisterModuleBar, RegisterModuleBaz)
+//   var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
 //
 // As after deduping and flattening AllPreparers would result in the following preparers being
 // applied:
@@ -109,7 +109,7 @@
 // An exported preparer for use by other packages that need to use java modules.
 //
 // package java
-// var PrepareForIntegrationTestWithJava = FixturePreparers(
+// var PrepareForIntegrationTestWithJava = GroupFixturePreparers(
 //    android.PrepareForIntegrationTestWithAndroid,
 //    FixtureRegisterWithContext(RegisterAGroupOfRelatedModulesMutatorsAndSingletons),
 //    FixtureRegisterWithContext(RegisterAnotherGroupOfRelatedModulesMutatorsAndSingletons),
@@ -144,7 +144,7 @@
 // }
 //
 // package cc
-// var PrepareForTestWithCC = FixturePreparers(
+// var PrepareForTestWithCC = GroupFixturePreparers(
 //    android.PrepareForArchMutator,
 //	  android.prepareForPrebuilts,
 //    FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
@@ -153,7 +153,7 @@
 //
 // package apex
 //
-// var PrepareForApex = FixturePreparers(
+// var PrepareForApex = GroupFixturePreparers(
 //    ...
 // )
 //
@@ -182,7 +182,8 @@
 	// Create a Fixture.
 	Fixture(t *testing.T, preparers ...FixturePreparer) Fixture
 
-	// Set the error handler that will be used to check any errors reported by the test.
+	// SetErrorHandler creates a new FixtureFactory that will use the supplied error handler to check
+	// the errors (may be 0) reported by the test.
 	//
 	// The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any
 	// errors are reported.
@@ -285,9 +286,12 @@
 	return FixtureAddTextFile("Android.bp", contents)
 }
 
-// Create a composite FixturePreparer that is equivalent to applying each of the supplied
-// FixturePreparer instances in order.
-func FixturePreparers(preparers ...FixturePreparer) FixturePreparer {
+// GroupFixturePreparers creates a composite FixturePreparer that is equivalent to applying each of
+// the supplied FixturePreparer instances in order.
+//
+// Before preparing the fixture the list of preparers is flattened by replacing each
+// instance of GroupFixturePreparers with its contents.
+func GroupFixturePreparers(preparers ...FixturePreparer) FixturePreparer {
 	return &compositeFixturePreparer{dedupAndFlattenPreparers(nil, preparers)}
 }
 
@@ -378,23 +382,28 @@
 	// The supplied result can be used to access the state of the code under test just as the main
 	// body of the test would but if any errors other than ones expected are reported the state may
 	// be indeterminate.
-	CheckErrors(result *TestResult, errs []error)
+	CheckErrors(result *TestResult)
 }
 
 type simpleErrorHandler struct {
-	function func(result *TestResult, errs []error)
+	function func(result *TestResult)
 }
 
-func (h simpleErrorHandler) CheckErrors(result *TestResult, errs []error) {
-	h.function(result, errs)
+func (h simpleErrorHandler) CheckErrors(result *TestResult) {
+	result.Helper()
+	h.function(result)
 }
 
 // The default fixture error handler.
 //
 // Will fail the test immediately if any errors are reported.
+//
+// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
+// which the test is being run which means that the RunTest() method will not return.
 var FixtureExpectsNoErrors = FixtureCustomErrorHandler(
-	func(result *TestResult, errs []error) {
-		FailIfErrored(result.T, errs)
+	func(result *TestResult) {
+		result.Helper()
+		FailIfErrored(result.T, result.Errs)
 	},
 )
 
@@ -407,9 +416,15 @@
 //
 // The test will not fail if:
 // * Multiple errors are reported that do not match the pattern as long as one does match.
+//
+// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
+// which the test is being run which means that the RunTest() method will not return.
 func FixtureExpectsAtLeastOneErrorMatchingPattern(pattern string) FixtureErrorHandler {
-	return FixtureCustomErrorHandler(func(result *TestResult, errs []error) {
-		FailIfNoMatchingErrors(result.T, pattern, errs)
+	return FixtureCustomErrorHandler(func(result *TestResult) {
+		result.Helper()
+		if !FailIfNoMatchingErrors(result.T, pattern, result.Errs) {
+			result.FailNow()
+		}
 	})
 }
 
@@ -423,14 +438,18 @@
 //
 // The test will not fail if:
 // * One or more of the patterns does not match an error.
+//
+// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
+// which the test is being run which means that the RunTest() method will not return.
 func FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandler {
-	return FixtureCustomErrorHandler(func(result *TestResult, errs []error) {
-		CheckErrorsAgainstExpectations(result.T, errs, patterns)
+	return FixtureCustomErrorHandler(func(result *TestResult) {
+		result.Helper()
+		CheckErrorsAgainstExpectations(result.T, result.Errs, patterns)
 	})
 }
 
 // FixtureCustomErrorHandler creates a custom error handler
-func FixtureCustomErrorHandler(function func(result *TestResult, errs []error)) FixtureErrorHandler {
+func FixtureCustomErrorHandler(function func(result *TestResult)) FixtureErrorHandler {
 	return simpleErrorHandler{
 		function: function,
 	}
@@ -531,6 +550,9 @@
 
 	fixture *fixture
 	Config  Config
+
+	// The errors that were reported during the test.
+	Errs []error
 }
 
 var _ FixtureFactory = (*fixtureFactory)(nil)
@@ -575,8 +597,10 @@
 }
 
 func (f *fixtureFactory) SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory {
-	f.errorHandler = errorHandler
-	return f
+	newFactory := &fixtureFactory{}
+	*newFactory = *f
+	newFactory.errorHandler = errorHandler
+	return newFactory
 }
 
 func (f *fixtureFactory) RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult {
@@ -639,9 +663,10 @@
 		testContext: testContext{ctx},
 		fixture:     f,
 		Config:      f.config,
+		Errs:        errs,
 	}
 
-	f.errorHandler.CheckErrors(result, errs)
+	f.errorHandler.CheckErrors(result)
 
 	return result
 }
diff --git a/android/fixture_test.go b/android/fixture_test.go
index 7bc033b..5a7bf3b 100644
--- a/android/fixture_test.go
+++ b/android/fixture_test.go
@@ -32,9 +32,9 @@
 	preparer3 := appendToList("preparer3")
 	preparer4 := appendToList("preparer4")
 
-	preparer1Then2 := FixturePreparers(preparer1, preparer2)
+	preparer1Then2 := GroupFixturePreparers(preparer1, preparer2)
 
-	preparer2Then1 := FixturePreparers(preparer2, preparer1)
+	preparer2Then1 := GroupFixturePreparers(preparer2, preparer1)
 
 	buildDir := "build"
 	factory := NewFixtureFactory(&buildDir, preparer1, preparer2, preparer1, preparer1Then2)
diff --git a/android/license.go b/android/license.go
index b140b55..3bc6199 100644
--- a/android/license.go
+++ b/android/license.go
@@ -19,7 +19,7 @@
 )
 
 type licenseKindDependencyTag struct {
-        blueprint.BaseDependencyTag
+	blueprint.BaseDependencyTag
 }
 
 var (
diff --git a/android/license_test.go b/android/license_test.go
index 552bbae..9f68713 100644
--- a/android/license_test.go
+++ b/android/license_test.go
@@ -49,9 +49,9 @@
 				}`),
 		},
 		expectedErrors: []string{
-			`other/Blueprints:2:5: module "arule": depends on //top:top_allowed_as_notice `+
+			`other/Blueprints:2:5: module "arule": depends on //top:top_allowed_as_notice ` +
 				`which is not visible to this module`,
-			`yetmore/Blueprints:2:5: module "//yetmore": depends on //top:top_allowed_as_notice `+
+			`yetmore/Blueprints:2:5: module "//yetmore": depends on //top:top_allowed_as_notice ` +
 				`which is not visible to this module`,
 		},
 	},
@@ -70,7 +70,7 @@
 				}`),
 		},
 		expectedErrors: []string{
-			`top/Blueprints:6:5: module "top_proprietary": license_kinds property `+
+			`top/Blueprints:6:5: module "top_proprietary": license_kinds property ` +
 				`"top_by_exception_only" is not a license_kind module`,
 		},
 	},
diff --git a/android/licenses.go b/android/licenses.go
index 1000429..2838f5d 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -51,7 +51,7 @@
 
 func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
 	return applicableLicensesPropertyImpl{
-		name: name,
+		name:             name,
 		licensesProperty: licensesProperty,
 	}
 }
diff --git a/android/licenses_test.go b/android/licenses_test.go
index b94add7..c043791 100644
--- a/android/licenses_test.go
+++ b/android/licenses_test.go
@@ -7,15 +7,15 @@
 )
 
 var licensesTests = []struct {
-	name                         string
-	fs                           map[string][]byte
-	expectedErrors               []string
-	effectiveLicenses            map[string][]string
-	effectiveInheritedLicenses   map[string][]string
-	effectivePackage             map[string]string
-	effectiveNotices             map[string][]string
-	effectiveKinds               map[string][]string
-	effectiveConditions          map[string][]string
+	name                       string
+	fs                         map[string][]byte
+	expectedErrors             []string
+	effectiveLicenses          map[string][]string
+	effectiveInheritedLicenses map[string][]string
+	effectivePackage           map[string]string
+	effectiveNotices           map[string][]string
+	effectiveKinds             map[string][]string
+	effectiveConditions        map[string][]string
 }{
 	{
 		name: "invalid module type without licenses property",
@@ -71,28 +71,28 @@
 		},
 		effectiveLicenses: map[string][]string{
 			"libexample1": []string{"top_Apache2"},
-			"libnested": []string{"top_Apache2"},
-			"libother": []string{"top_Apache2"},
+			"libnested":   []string{"top_Apache2"},
+			"libother":    []string{"top_Apache2"},
 		},
 		effectiveKinds: map[string][]string{
 			"libexample1": []string{"notice"},
-			"libnested": []string{"notice"},
-			"libother": []string{"notice"},
+			"libnested":   []string{"notice"},
+			"libother":    []string{"notice"},
 		},
 		effectivePackage: map[string]string{
 			"libexample1": "topDog",
-			"libnested": "topDog",
-			"libother": "topDog",
+			"libnested":   "topDog",
+			"libother":    "topDog",
 		},
 		effectiveConditions: map[string][]string{
 			"libexample1": []string{"shownotice"},
-			"libnested": []string{"shownotice"},
-			"libother": []string{"shownotice"},
+			"libnested":   []string{"shownotice"},
+			"libother":    []string{"shownotice"},
 		},
 		effectiveNotices: map[string][]string{
 			"libexample1": []string{"top/LICENSE", "top/NOTICE"},
-			"libnested": []string{"top/LICENSE", "top/NOTICE"},
-			"libother": []string{"top/LICENSE", "top/NOTICE"},
+			"libnested":   []string{"top/LICENSE", "top/NOTICE"},
+			"libother":    []string{"top/LICENSE", "top/NOTICE"},
 		},
 	},
 
@@ -147,28 +147,28 @@
 				}`),
 		},
 		effectiveLicenses: map[string][]string{
-			"libexample": []string{"nested_other", "top_other"},
+			"libexample":     []string{"nested_other", "top_other"},
 			"libsamepackage": []string{},
-			"libnested": []string{},
-			"libother": []string{},
+			"libnested":      []string{},
+			"libother":       []string{},
 		},
 		effectiveInheritedLicenses: map[string][]string{
-			"libexample": []string{"nested_other", "top_other"},
+			"libexample":     []string{"nested_other", "top_other"},
 			"libsamepackage": []string{"nested_other", "top_other"},
-			"libnested": []string{"nested_other", "top_other"},
-			"libother": []string{"nested_other", "top_other"},
+			"libnested":      []string{"nested_other", "top_other"},
+			"libother":       []string{"nested_other", "top_other"},
 		},
 		effectiveKinds: map[string][]string{
-			"libexample": []string{"nested_notice", "top_notice"},
+			"libexample":     []string{"nested_notice", "top_notice"},
 			"libsamepackage": []string{},
-			"libnested": []string{},
-			"libother": []string{},
+			"libnested":      []string{},
+			"libother":       []string{},
 		},
 		effectiveConditions: map[string][]string{
-			"libexample": []string{"notice"},
+			"libexample":     []string{"notice"},
 			"libsamepackage": []string{},
-			"libnested": []string{},
-			"libother": []string{},
+			"libnested":      []string{},
+			"libother":       []string{},
 		},
 	},
 	{
@@ -218,32 +218,32 @@
 				}`),
 		},
 		effectiveLicenses: map[string][]string{
-			"libexample": []string{"other", "top_nested"},
+			"libexample":     []string{"other", "top_nested"},
 			"libsamepackage": []string{},
-			"libnested": []string{},
-			"libother": []string{},
-			"liboutsider": []string{},
+			"libnested":      []string{},
+			"libother":       []string{},
+			"liboutsider":    []string{},
 		},
 		effectiveInheritedLicenses: map[string][]string{
-			"libexample": []string{"other", "top_nested"},
+			"libexample":     []string{"other", "top_nested"},
 			"libsamepackage": []string{"other", "top_nested"},
-			"libnested": []string{"other", "top_nested"},
-			"libother": []string{"other", "top_nested"},
-			"liboutsider": []string{"other", "top_nested"},
+			"libnested":      []string{"other", "top_nested"},
+			"libother":       []string{"other", "top_nested"},
+			"liboutsider":    []string{"other", "top_nested"},
 		},
 		effectiveKinds: map[string][]string{
-			"libexample": []string{},
+			"libexample":     []string{},
 			"libsamepackage": []string{},
-			"libnested": []string{},
-			"libother": []string{},
-			"liboutsider": []string{},
+			"libnested":      []string{},
+			"libother":       []string{},
+			"liboutsider":    []string{},
 		},
 		effectiveNotices: map[string][]string{
-			"libexample": []string{"top/nested/LICENSE.txt"},
+			"libexample":     []string{"top/nested/LICENSE.txt"},
 			"libsamepackage": []string{},
-			"libnested": []string{},
-			"libother": []string{},
-			"liboutsider": []string{},
+			"libnested":      []string{},
+			"libother":       []string{},
+			"liboutsider":    []string{},
 		},
 	},
 
@@ -285,11 +285,11 @@
 				}`),
 		},
 		effectiveLicenses: map[string][]string{
-			"libexample": []string{"by_exception_only"},
+			"libexample":  []string{"by_exception_only"},
 			"libdefaults": []string{"notice"},
 		},
 		effectiveInheritedLicenses: map[string][]string{
-			"libexample": []string{"by_exception_only"},
+			"libexample":  []string{"by_exception_only"},
 			"libdefaults": []string{"notice"},
 		},
 	},
@@ -327,11 +327,11 @@
 				}`),
 		},
 		effectiveLicenses: map[string][]string{
-			"libexample": []string{"top_notice"},
+			"libexample":  []string{"top_notice"},
 			"liboutsider": []string{},
 		},
 		effectiveInheritedLicenses: map[string][]string{
-			"libexample": []string{"top_notice"},
+			"libexample":  []string{"top_notice"},
 			"liboutsider": []string{"top_notice"},
 		},
 	},
@@ -370,15 +370,15 @@
 				}`),
 		},
 		effectiveLicenses: map[string][]string{
-			"libexample": []string{"top_notice"},
-			"libnested": []string{"outsider"},
-			"libother": []string{},
+			"libexample":  []string{"top_notice"},
+			"libnested":   []string{"outsider"},
+			"libother":    []string{},
 			"liboutsider": []string{},
 		},
 		effectiveInheritedLicenses: map[string][]string{
-			"libexample": []string{"top_notice"},
-			"libnested": []string{"outsider"},
-			"libother": []string{},
+			"libexample":  []string{"top_notice"},
+			"libnested":   []string{"outsider"},
+			"libother":    []string{},
 			"liboutsider": []string{"top_notice", "outsider"},
 		},
 	},
@@ -449,7 +449,7 @@
 		},
 		effectiveInheritedLicenses: map[string][]string{
 			"module": []string{"prebuilt", "top_sources"},
-			"other": []string{"prebuilt", "top_sources"},
+			"other":  []string{"prebuilt", "top_sources"},
 		},
 	},
 }
diff --git a/android/module.go b/android/module.go
index e8fb749..9f923e2 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1832,6 +1832,18 @@
 			return
 		}
 
+		m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
+		rcDir := PathForModuleInstall(ctx, "etc", "init")
+		for _, src := range m.initRcPaths {
+			ctx.PackageFile(rcDir, filepath.Base(src.String()), src)
+		}
+
+		m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
+		vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
+		for _, src := range m.vintfFragmentsPaths {
+			ctx.PackageFile(vintfDir, filepath.Base(src.String()), src)
+		}
+
 		// Create the set of tagged dist files after calling GenerateAndroidBuildActions
 		// as GenerateTaggedDistFiles() calls OutputFiles(tag) and so relies on the
 		// output paths being set which must be done before or during
@@ -1844,8 +1856,6 @@
 		m.installFiles = append(m.installFiles, ctx.installFiles...)
 		m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
 		m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
-		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...)
 		}
diff --git a/android/mutator.go b/android/mutator.go
index b023001..9552aa1 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -33,22 +33,8 @@
 //   run FinalDeps mutators (CreateVariations disallowed in this phase)
 //   continue on to GenerateAndroidBuildActions
 
-func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) {
-	for _, t := range mutators {
-		var handle blueprint.MutatorHandle
-		if t.bottomUpMutator != nil {
-			handle = ctx.RegisterBottomUpMutator(t.name, t.bottomUpMutator)
-		} else if t.topDownMutator != nil {
-			handle = ctx.RegisterTopDownMutator(t.name, t.topDownMutator)
-		}
-		if t.parallel {
-			handle.Parallel()
-		}
-	}
-}
-
 // RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
-func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) {
+func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) {
 	mctx := &registerMutatorsContext{
 		bazelConversionMode: true,
 	}
@@ -80,10 +66,17 @@
 		f(mctx)
 	}
 
-	registerMutatorsToContext(ctx, mctx.mutators)
+	mctx.mutators.registerAll(ctx)
 }
 
-func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) {
+// collateGloballyRegisteredMutators constructs the list of mutators that have been registered
+// with the InitRegistrationContext and will be used at runtime.
+func collateGloballyRegisteredMutators() sortableComponents {
+	return collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps)
+}
+
+// collateRegisteredMutators constructs a single list of mutators from the separate lists.
+func collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) sortableComponents {
 	mctx := &registerMutatorsContext{}
 
 	register := func(funcs []RegisterMutatorFunc) {
@@ -103,11 +96,11 @@
 	mctx.finalPhase = true
 	register(finalDeps)
 
-	registerMutatorsToContext(ctx, mctx.mutators)
+	return mctx.mutators
 }
 
 type registerMutatorsContext struct {
-	mutators            []*mutator
+	mutators            sortableComponents
 	finalPhase          bool
 	bazelConversionMode bool
 }
@@ -473,6 +466,23 @@
 	return mutator
 }
 
+func (mutator *mutator) componentName() string {
+	return mutator.name
+}
+
+func (mutator *mutator) register(ctx *Context) {
+	blueprintCtx := ctx.Context
+	var handle blueprint.MutatorHandle
+	if mutator.bottomUpMutator != nil {
+		handle = blueprintCtx.RegisterBottomUpMutator(mutator.name, mutator.bottomUpMutator)
+	} else if mutator.topDownMutator != nil {
+		handle = blueprintCtx.RegisterTopDownMutator(mutator.name, mutator.topDownMutator)
+	}
+	if mutator.parallel {
+		handle.Parallel()
+	}
+}
+
 type MutatorHandle interface {
 	Parallel() MutatorHandle
 }
diff --git a/android/paths.go b/android/paths.go
index ada4da6..3f4d3f2 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1662,9 +1662,9 @@
 			// on a device without a dedicated recovery partition, install the
 			// recovery variant.
 			if ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() {
-				partition = "vendor-ramdisk/first_stage_ramdisk"
+				partition = "vendor_ramdisk/first_stage_ramdisk"
 			} else {
-				partition = "vendor-ramdisk"
+				partition = "vendor_ramdisk"
 			}
 			if !ctx.InstallInRoot() {
 				partition += "/system"
diff --git a/android/queryview.go b/android/queryview.go
index 9e3e45a..b940202 100644
--- a/android/queryview.go
+++ b/android/queryview.go
@@ -67,10 +67,14 @@
 		blueprint.RuleParams{
 			Command: fmt.Sprintf(
 				"rm -rf ${outDir}/* && "+
-					"%s --bazel_queryview_dir ${outDir} %s && "+
+					"BUILDER=\"%s\" && "+
+					"cd $$(dirname \"$$BUILDER\") && "+
+					"ABSBUILDER=\"$$PWD/$$(basename \"$$BUILDER\")\" && "+
+					"cd / && "+
+					"env -i \"$$ABSBUILDER\" --bazel_queryview_dir ${outDir} \"%s\" && "+
 					"echo WORKSPACE: `cat %s` > ${outDir}/.queryview-depfile.d",
 				primaryBuilder.String(),
-				strings.Join(os.Args[1:], " "),
+				strings.Join(os.Args[1:], "\" \""),
 				moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
 			),
 			CommandDeps: []string{primaryBuilder.String()},
diff --git a/android/register.go b/android/register.go
index 47df972..278a04f 100644
--- a/android/register.go
+++ b/android/register.go
@@ -21,21 +21,78 @@
 	"github.com/google/blueprint"
 )
 
+// A sortable component is one whose registration order affects the order in which it is executed
+// and so affects the behavior of the build system. As a result it is important for the order in
+// which they are registered during tests to match the order used at runtime and so the test
+// infrastructure will sort them to match.
+//
+// The sortable components are mutators, singletons and pre-singletons. Module types are not
+// sortable because their order of registration does not affect the runtime behavior.
+type sortableComponent interface {
+	// componentName returns the name of the component.
+	//
+	// Uniquely identifies the components within the set of components used at runtimr and during
+	// tests.
+	componentName() string
+
+	// register registers this component in the supplied context.
+	register(ctx *Context)
+}
+
+type sortableComponents []sortableComponent
+
+// registerAll registers all components in this slice with the supplied context.
+func (r sortableComponents) registerAll(ctx *Context) {
+	for _, c := range r {
+		c.register(ctx)
+	}
+}
+
 type moduleType struct {
 	name    string
 	factory ModuleFactory
 }
 
+func (t moduleType) register(ctx *Context) {
+	ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+}
+
 var moduleTypes []moduleType
 var moduleTypesForDocs = map[string]reflect.Value{}
 
 type singleton struct {
+	// True if this should be registered as a pre-singleton, false otherwise.
+	pre bool
+
 	name    string
 	factory SingletonFactory
 }
 
-var singletons []singleton
-var preSingletons []singleton
+func newSingleton(name string, factory SingletonFactory) singleton {
+	return singleton{false, name, factory}
+}
+
+func newPreSingleton(name string, factory SingletonFactory) singleton {
+	return singleton{true, name, factory}
+}
+
+func (s singleton) componentName() string {
+	return s.name
+}
+
+func (s singleton) register(ctx *Context) {
+	adaptor := SingletonFactoryAdaptor(ctx, s.factory)
+	if s.pre {
+		ctx.RegisterPreSingletonType(s.name, adaptor)
+	} else {
+		ctx.RegisterSingletonType(s.name, adaptor)
+	}
+}
+
+var _ sortableComponent = singleton{}
+
+var singletons sortableComponents
+var preSingletons sortableComponents
 
 type mutator struct {
 	name            string
@@ -44,6 +101,8 @@
 	parallel        bool
 }
 
+var _ sortableComponent = &mutator{}
+
 type ModuleFactory func() Module
 
 // ModuleFactoryAdaptor wraps a ModuleFactory into a blueprint.ModuleFactory by converting a Module
@@ -84,11 +143,11 @@
 }
 
 func RegisterSingletonType(name string, factory SingletonFactory) {
-	singletons = append(singletons, singleton{name, factory})
+	singletons = append(singletons, newSingleton(name, factory))
 }
 
 func RegisterPreSingletonType(name string, factory SingletonFactory) {
-	preSingletons = append(preSingletons, singleton{name, factory})
+	preSingletons = append(preSingletons, newPreSingleton(name, factory))
 }
 
 type Context struct {
@@ -107,33 +166,30 @@
 // files to semantically equivalent BUILD files.
 func (ctx *Context) RegisterForBazelConversion() {
 	for _, t := range moduleTypes {
-		ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+		t.register(ctx)
 	}
 
 	// Required for SingletonModule types, even though we are not using them.
 	for _, t := range singletons {
-		ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
+		t.register(ctx)
 	}
 
-	RegisterMutatorsForBazelConversion(ctx.Context, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
+	RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
 }
 
 // Register the pipeline of singletons, module types, and mutators for
 // generating build.ninja and other files for Kati, from Android.bp files.
 func (ctx *Context) Register() {
-	for _, t := range preSingletons {
-		ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
-	}
+	preSingletons.registerAll(ctx)
 
 	for _, t := range moduleTypes {
-		ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+		t.register(ctx)
 	}
 
-	for _, t := range singletons {
-		ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
-	}
+	singletons.registerAll(ctx)
 
-	registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
+	mutators := collateGloballyRegisteredMutators()
+	mutators.registerAll(ctx)
 
 	ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(ctx, BazelSingleton))
 
diff --git a/android/sandbox.go b/android/sandbox.go
index ed022fb..28e903a 100644
--- a/android/sandbox.go
+++ b/android/sandbox.go
@@ -14,29 +14,8 @@
 
 package android
 
-import (
-	"fmt"
-	"os"
-)
-
-func init() {
-	// Stash the working directory in a private variable and then change the working directory
-	// to "/", which will prevent untracked accesses to files by Go Soong plugins. The
-	// SOONG_SANDBOX_SOONG_BUILD environment variable is set by soong_ui, and is not
-	// overrideable on the command line.
-
-	orig, err := os.Getwd()
-	if err != nil {
-		panic(fmt.Errorf("failed to get working directory: %s", err))
-	}
-	absSrcDir = orig
-
-	if getenv("SOONG_SANDBOX_SOONG_BUILD") == "true" {
-		err = os.Chdir("/")
-		if err != nil {
-			panic(fmt.Errorf("failed to change working directory to '/': %s", err))
-		}
-	}
+func InitSandbox(topDir string) {
+	absSrcDir = topDir
 }
 
 // DO NOT USE THIS FUNCTION IN NEW CODE.
diff --git a/android/testing.go b/android/testing.go
index 5832796..b134eae 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -48,7 +48,7 @@
 	return ctx
 }
 
-var PrepareForTestWithArchMutator = FixturePreparers(
+var PrepareForTestWithArchMutator = GroupFixturePreparers(
 	// Configure architecture targets in the fixture config.
 	FixtureModifyConfig(modifyTestConfigToSupportArchMutator),
 
@@ -73,7 +73,7 @@
 })
 
 // Prepares an integration test with build components from the android package.
-var PrepareForIntegrationTestWithAndroid = FixturePreparers(
+var PrepareForIntegrationTestWithAndroid = GroupFixturePreparers(
 	// Mutators. Must match order in mutator.go.
 	PrepareForTestWithArchMutator,
 	PrepareForTestWithDefaults,
@@ -141,14 +141,15 @@
 }
 
 func (ctx *TestContext) Register() {
-	registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
+	mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
+	mutators.registerAll(ctx.Context)
 
 	ctx.RegisterSingletonType("env", EnvSingleton)
 }
 
 // RegisterForBazelConversion prepares a test context for bp2build conversion.
 func (ctx *TestContext) RegisterForBazelConversion() {
-	RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
+	RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
 }
 
 func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
@@ -456,12 +457,15 @@
 	}
 }
 
-func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) {
+// Fail if no errors that matched the regular expression were found.
+//
+// Returns true if a matching error was found, false otherwise.
+func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) bool {
 	t.Helper()
 
 	matcher, err := regexp.Compile(pattern)
 	if err != nil {
-		t.Errorf("failed to compile regular expression %q because %s", pattern, err)
+		t.Fatalf("failed to compile regular expression %q because %s", pattern, err)
 	}
 
 	found := false
@@ -477,6 +481,8 @@
 			t.Errorf("errs[%d] = %q", i, err)
 		}
 	}
+
+	return found
 }
 
 func CheckErrorsAgainstExpectations(t *testing.T, errs []error, expectedErrorPatterns []string) {
@@ -497,9 +503,9 @@
 			for i, err := range errs {
 				t.Errorf("errs[%d] = %s", i, err)
 			}
+			t.FailNow()
 		}
 	}
-
 }
 
 func SetKatiEnabledForTests(config Config) {
diff --git a/android/writedocs.go b/android/writedocs.go
index 91c2318..6cb2f10 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -34,7 +34,8 @@
 type docsSingleton struct{}
 
 func primaryBuilderPath(ctx SingletonContext) Path {
-	primaryBuilder, err := filepath.Rel(ctx.Config().BuildDir(), os.Args[0])
+	buildDir := absolutePath(ctx.Config().BuildDir())
+	primaryBuilder, err := filepath.Rel(buildDir, os.Args[0])
 	if err != nil {
 		ctx.Errorf("path to primary builder %q is not in build dir %q",
 			os.Args[0], ctx.Config().BuildDir())
@@ -65,7 +66,9 @@
 	soongDocs := ctx.Rule(pctx, "soongDocs",
 		blueprint.RuleParams{
 			Command: fmt.Sprintf("rm -f ${outDir}/* && %s --soong_docs %s %s",
-				primaryBuilder.String(), docsFile.String(), strings.Join(os.Args[1:], " ")),
+				primaryBuilder.String(),
+				docsFile.String(),
+				"\""+strings.Join(os.Args[1:], "\" \"")+"\""),
 			CommandDeps: []string{primaryBuilder.String()},
 			Description: fmt.Sprintf("%s docs $out", primaryBuilder.Base()),
 		},
diff --git a/apex/OWNERS b/apex/OWNERS
index 793f3ed..fee739b 100644
--- a/apex/OWNERS
+++ b/apex/OWNERS
@@ -1,4 +1,4 @@
 per-file * = jiyong@google.com
 
 per-file allowed_deps.txt = set noparent
-per-file allowed_deps.txt = dariofreni@google.com,hansson@google.com,harpin@google.com,jiyong@google.com,narayan@google.com,omakoto@google.com,jham@google.com
+per-file allowed_deps.txt = dariofreni@google.com,hansson@google.com,harpin@google.com,jiyong@google.com,narayan@google.com,jham@google.com
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 78b84f0..047a0f3 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -192,7 +192,7 @@
 GoogleCellBroadcastApp(minSdkVersion:29)
 GoogleCellBroadcastServiceModule(minSdkVersion:29)
 GoogleExtServices(minSdkVersion:current)
-GooglePermissionController(minSdkVersion:28)
+GooglePermissionController(minSdkVersion:30)
 guava(minSdkVersion:current)
 gwp_asan_headers(minSdkVersion:(no version))
 i18n.module.public.api.stubs(minSdkVersion:(no version))
@@ -361,6 +361,7 @@
 libmedia_headers(minSdkVersion:29)
 libmedia_helper_headers(minSdkVersion:29)
 libmedia_midiiowrapper(minSdkVersion:29)
+libmediaparser-jni(minSdkVersion:29)
 libmidiextractor(minSdkVersion:29)
 libminijail(minSdkVersion:29)
 libminijail_gen_constants(minSdkVersion:(no version))
@@ -526,7 +527,7 @@
 no_op(minSdkVersion:current)
 note_memtag_heap_async(minSdkVersion:16)
 note_memtag_heap_sync(minSdkVersion:16)
-PermissionController(minSdkVersion:28)
+PermissionController(minSdkVersion:30)
 permissioncontroller-statsd(minSdkVersion:current)
 philox_random(minSdkVersion:(no version))
 philox_random_headers(minSdkVersion:(no version))
@@ -635,6 +636,7 @@
 Tethering(minSdkVersion:current)
 TetheringApiCurrentLib(minSdkVersion:30)
 TetheringApiCurrentLib(minSdkVersion:current)
+TetheringGoogle(minSdkVersion:30)
 TetheringGoogle(minSdkVersion:current)
 textclassifier-statsd(minSdkVersion:current)
 TextClassifierNotificationLibNoManifest(minSdkVersion:29)
diff --git a/apex/apex.go b/apex/apex.go
index 8f388c4..efd1736 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2244,8 +2244,10 @@
 		if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
 			return true
 		}
-		ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'. Dependency path:%s",
-			fromName, toName, ctx.GetPathString(true))
+		ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+
+			"\n\nDependency path:%s\n\n"+
+			"Consider adding %q to 'apex_available' property of %q",
+			fromName, toName, ctx.GetPathString(true), apexName, toName)
 		// Visit this module's dependencies to check and report any issues with their availability.
 		return true
 	})
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 8ae6634..991f5c9 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -67,14 +67,14 @@
 	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
 }
 
-func testApex(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
+func testApex(t *testing.T, bp string, handlers ...testCustomizer) *android.TestContext {
 	t.Helper()
 	ctx, config := testApexContext(t, bp, handlers...)
 	_, errs := ctx.ParseBlueprintsFiles(".")
 	android.FailIfErrored(t, errs)
 	_, errs = ctx.PrepareBuildActions(config)
 	android.FailIfErrored(t, errs)
-	return ctx, config
+	return ctx
 }
 
 type testCustomizer func(fs map[string][]byte, config android.Config)
@@ -240,7 +240,6 @@
 
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterComponentsMutator)
-	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
 
 	android.RegisterPrebuiltMutators(ctx)
 
@@ -249,6 +248,10 @@
 	ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
 	ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
 
+	// These must come after prebuilts and visibility rules to match runtime.
+	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
+
+	// These must come after override rules to match the runtime.
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
 	rust.RegisterRequiredBuildComponentsForTest(ctx)
 	java.RegisterRequiredBuildComponentsForTest(ctx)
@@ -357,7 +360,7 @@
 
 // Minimal test
 func TestBasicApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_defaults {
 			name: "myapex-defaults",
 			manifest: ":myapex.manifest",
@@ -663,7 +666,7 @@
 }
 
 func TestDefaults(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_defaults {
 			name: "myapex-defaults",
 			key: "myapex.key",
@@ -738,7 +741,7 @@
 }
 
 func TestApexManifest(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -760,7 +763,7 @@
 }
 
 func TestBasicZipApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -811,7 +814,7 @@
 }
 
 func TestApexWithStubs(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -906,7 +909,7 @@
 
 func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
 	t.Parallel()
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1013,7 +1016,7 @@
 	//                                  |
 	//   <platform>                     |
 	//      libplatform ----------------'
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1078,7 +1081,7 @@
 }
 
 func TestApexWithExplicitStubsDependency(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex2",
 			key: "myapex2.key",
@@ -1174,7 +1177,7 @@
 			    |
 			    `------> libbar
 	*/
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1236,7 +1239,7 @@
 }
 
 func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
-	ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+	ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
 		bp := `
 		apex {
 			name: "com.android.runtime",
@@ -1300,7 +1303,7 @@
 }
 
 func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
-	ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+	ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
 		bp := `
 		apex {
 			name: "com.android.runtime",
@@ -1386,7 +1389,7 @@
 	}
 	for _, tc := range testcases {
 		t.Run(tc.name, func(t *testing.T) {
-			ctx, _ := testApex(t, `
+			ctx := testApex(t, `
 			apex {
 				name: "myapex",
 				key: "myapex.key",
@@ -1453,7 +1456,7 @@
 }
 
 func TestApexWithSystemLibsStubs(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1549,7 +1552,7 @@
 	// 1) myapex -> libx -> liba -> libz    : this should be #30 link
 	// 2) otherapex -> liby -> liba -> libz : this should be #30 link
 	// 3) (platform) -> liba -> libz        : this should be non-stub link
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1631,7 +1634,7 @@
 }
 
 func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1680,7 +1683,7 @@
 }
 
 func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1726,7 +1729,7 @@
 }
 
 func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1774,7 +1777,7 @@
 }
 
 func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1813,7 +1816,7 @@
 }
 
 func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2140,7 +2143,7 @@
 }
 
 func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2227,7 +2230,7 @@
 		config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("S")
 		config.TestProductVariables.Platform_version_active_codenames = []string{"S", "T"}
 	}
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2261,7 +2264,7 @@
 }
 
 func TestFilesInSubDir(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2324,7 +2327,7 @@
 }
 
 func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2383,7 +2386,7 @@
 }
 
 func TestUseVendor(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2496,7 +2499,7 @@
 }
 
 func TestVendorApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2534,7 +2537,8 @@
 	var builder strings.Builder
 	data.Custom(&builder, name, prefix, "", data)
 	androidMk := builder.String()
-	ensureContains(t, androidMk, `LOCAL_MODULE_PATH := /tmp/target/product/test_device/vendor/apex`)
+	installPath := path.Join(buildDir, "../target/product/test_device/vendor/apex")
+	ensureContains(t, androidMk, "LOCAL_MODULE_PATH := "+installPath)
 
 	apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
 	requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
@@ -2542,7 +2546,7 @@
 }
 
 func TestVendorApex_use_vndk_as_stable(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2606,7 +2610,7 @@
 	}
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
-			ctx, _ := testApex(t, `
+			ctx := testApex(t, `
 				apex {
 					name: "myapex",
 					key: "myapex.key",
@@ -2634,7 +2638,7 @@
 }
 
 func TestAndroidMk_UseVendorRequired(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2669,7 +2673,7 @@
 }
 
 func TestAndroidMk_VendorApexRequired(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2701,7 +2705,7 @@
 }
 
 func TestAndroidMkWritesCommonProperties(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2731,7 +2735,7 @@
 }
 
 func TestStaticLinking(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2776,7 +2780,7 @@
 }
 
 func TestKeys(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex_keytest",
 			key: "myapex.key",
@@ -2834,7 +2838,7 @@
 
 func TestCertificate(t *testing.T) {
 	t.Run("if unspecified, it defaults to DefaultAppCertificate", func(t *testing.T) {
-		ctx, _ := testApex(t, `
+		ctx := testApex(t, `
 			apex {
 				name: "myapex",
 				key: "myapex.key",
@@ -2852,7 +2856,7 @@
 		}
 	})
 	t.Run("override when unspecified", func(t *testing.T) {
-		ctx, _ := testApex(t, `
+		ctx := testApex(t, `
 			apex {
 				name: "myapex_keytest",
 				key: "myapex.key",
@@ -2875,7 +2879,7 @@
 		}
 	})
 	t.Run("if specified as :module, it respects the prop", func(t *testing.T) {
-		ctx, _ := testApex(t, `
+		ctx := testApex(t, `
 			apex {
 				name: "myapex",
 				key: "myapex.key",
@@ -2898,7 +2902,7 @@
 		}
 	})
 	t.Run("override when specifiec as <:module>", func(t *testing.T) {
-		ctx, _ := testApex(t, `
+		ctx := testApex(t, `
 			apex {
 				name: "myapex_keytest",
 				key: "myapex.key",
@@ -2922,7 +2926,7 @@
 		}
 	})
 	t.Run("if specified as name, finds it from DefaultDevKeyDir", func(t *testing.T) {
-		ctx, _ := testApex(t, `
+		ctx := testApex(t, `
 			apex {
 				name: "myapex",
 				key: "myapex.key",
@@ -2941,7 +2945,7 @@
 		}
 	})
 	t.Run("override when specified as <name>", func(t *testing.T) {
-		ctx, _ := testApex(t, `
+		ctx := testApex(t, `
 			apex {
 				name: "myapex_keytest",
 				key: "myapex.key",
@@ -2967,7 +2971,7 @@
 }
 
 func TestMacro(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -3095,7 +3099,7 @@
 }
 
 func TestHeaderLibsDependency(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -3239,7 +3243,7 @@
 }
 
 func TestVndkApexCurrent(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.current",
 			key: "com.android.vndk.current.key",
@@ -3296,7 +3300,7 @@
 }
 
 func TestVndkApexWithPrebuilt(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.current",
 			key: "com.android.vndk.current.key",
@@ -3380,7 +3384,7 @@
 }
 
 func TestVndkApexVersion(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.v27",
 			key: "myapex.key",
@@ -3449,7 +3453,7 @@
 }
 
 func TestVndkApexNameRule(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.current",
 			key: "myapex.key",
@@ -3482,7 +3486,7 @@
 }
 
 func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.current",
 			key: "com.android.vndk.current.key",
@@ -3554,7 +3558,7 @@
 }
 
 func TestVndkApexWithBinder32(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.v27",
 			key: "myapex.key",
@@ -3623,7 +3627,7 @@
 }
 
 func TestVndkApexShouldNotProvideNativeLibs(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.current",
 			key: "com.android.vndk.current.key",
@@ -3659,7 +3663,7 @@
 }
 
 func TestDependenciesInApexManifest(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex_nodep",
 			key: "myapex.key",
@@ -3767,7 +3771,7 @@
 }
 
 func TestApexName(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -3812,7 +3816,7 @@
 }
 
 func TestNonTestApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -3865,7 +3869,7 @@
 }
 
 func TestTestApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_test {
 			name: "myapex",
 			key: "myapex.key",
@@ -3914,7 +3918,7 @@
 }
 
 func TestApexWithTarget(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4005,7 +4009,7 @@
 }
 
 func TestApexWithArch(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4064,7 +4068,7 @@
 }
 
 func TestApexWithShBinary(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4105,7 +4109,7 @@
 	}
 	for _, tc := range testcases {
 		t.Run(tc.propName+":"+tc.parition, func(t *testing.T) {
-			ctx, _ := testApex(t, `
+			ctx := testApex(t, `
 				apex {
 					name: "myapex",
 					key: "myapex.key",
@@ -4138,7 +4142,7 @@
 }
 
 func TestFileContexts_FindInDefaultLocationIfNotSet(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4192,7 +4196,7 @@
 		}
 	`)
 
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4215,7 +4219,7 @@
 }
 
 func TestFileContexts_SetViaFileGroup(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4243,7 +4247,7 @@
 }
 
 func TestApexKeyFromOtherModule(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_key {
 			name: "myapex.key",
 			public_key: ":my.avbpubkey",
@@ -4276,7 +4280,7 @@
 }
 
 func TestPrebuilt(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		prebuilt_apex {
 			name: "myapex",
 			arch: {
@@ -4299,7 +4303,7 @@
 }
 
 func TestPrebuiltFilenameOverride(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		prebuilt_apex {
 			name: "myapex",
 			src: "myapex-arm.apex",
@@ -4316,7 +4320,7 @@
 }
 
 func TestPrebuiltOverrides(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		prebuilt_apex {
 			name: "myapex.prebuilt",
 			src: "myapex-arm.apex",
@@ -4827,7 +4831,7 @@
 }
 
 func TestApexWithTests(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_test {
 			name: "myapex",
 			key: "myapex.key",
@@ -4939,7 +4943,7 @@
 }
 
 func TestInstallExtraFlattenedApexes(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5009,7 +5013,7 @@
 }
 
 func TestApexWithJavaImport(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5038,7 +5042,7 @@
 }
 
 func TestApexWithApps(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5117,7 +5121,7 @@
 }
 
 func TestApexWithAppImports(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5166,7 +5170,7 @@
 }
 
 func TestApexWithAppImportsPrefer(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5203,12 +5207,13 @@
 	}))
 
 	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
-		"app/AppFoo/AppFooPrebuilt.apk",
+		// TODO(b/181974714) - this is wrong it should be "app/AppFoo/AppFooPrebuilt.apk"
+		"app/AppFoo/AppFoo.apk",
 	})
 }
 
 func TestApexWithTestHelperApp(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5314,7 +5319,7 @@
 
 func TestApexAvailable_IndirectDep(t *testing.T) {
 	// libbbaz is an indirect dep
-	testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'. Dependency path:
+	testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.\n\nDependency path:
 .*via tag apex\.dependencyTag.*name:sharedLib.*
 .*-> libfoo.*link:shared.*
 .*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
@@ -5419,7 +5424,7 @@
 }
 
 func TestApexAvailable_CheckForPlatform(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 	apex {
 		name: "myapex",
 		key: "myapex.key",
@@ -5482,7 +5487,7 @@
 }
 
 func TestApexAvailable_CreatedForApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 	apex {
 		name: "myapex",
 		key: "myapex.key",
@@ -5517,7 +5522,7 @@
 }
 
 func TestOverrideApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5601,7 +5606,7 @@
 }
 
 func TestLegacyAndroid10Support(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5661,7 +5666,7 @@
 }
 
 func TestJavaSDKLibrary(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5699,7 +5704,7 @@
 }
 
 func TestJavaSDKLibrary_WithinApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5752,7 +5757,7 @@
 }
 
 func TestJavaSDKLibrary_CrossBoundary(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5803,7 +5808,7 @@
 }
 
 func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		prebuilt_apis {
 			name: "sdk",
 			api_dirs: ["100"],
@@ -5920,7 +5925,7 @@
 }
 
 func TestCompatConfig(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5981,7 +5986,7 @@
 }
 
 func TestCarryRequiredModuleNames(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6125,7 +6130,7 @@
 
 	// For unbundled build, symlink shouldn't exist regardless of whether an APEX
 	// is updatable or not
-	ctx, _ := testApex(t, bp, withUnbundledBuild)
+	ctx := testApex(t, bp, withUnbundledBuild)
 	files := getFiles(t, ctx, "myapex", "android_common_myapex_image")
 	ensureRealfileExists(t, files, "javalib/myjar.jar")
 	ensureRealfileExists(t, files, "lib64/mylib.so")
@@ -6137,7 +6142,7 @@
 	ensureRealfileExists(t, files, "lib64/myotherlib.so")
 
 	// For bundled build, symlink to the system for the non-updatable APEXes only
-	ctx, _ = testApex(t, bp)
+	ctx = testApex(t, bp)
 	files = getFiles(t, ctx, "myapex", "android_common_myapex_image")
 	ensureRealfileExists(t, files, "javalib/myjar.jar")
 	ensureRealfileExists(t, files, "lib64/mylib.so")
@@ -6150,7 +6155,7 @@
 }
 
 func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6202,7 +6207,7 @@
 }
 
 func TestApexWithJniLibs(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6244,7 +6249,7 @@
 }
 
 func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6266,7 +6271,7 @@
 }
 
 func TestAppBundle(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6297,7 +6302,7 @@
 }
 
 func TestAppSetBundle(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6330,7 +6335,7 @@
 }
 
 func TestAppSetBundlePrebuilt(t *testing.T) {
-	ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+	ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
 		bp := `
 		apex_set {
 			name: "myapex",
@@ -6815,7 +6820,7 @@
 }
 
 func TestTestFor(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6901,7 +6906,7 @@
 }
 
 func TestApexSet(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_set {
 			name: "myapex",
 			set: "myapex.apks",
@@ -6977,7 +6982,7 @@
 }
 
 func TestApexKeysTxt(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7018,7 +7023,7 @@
 }
 
 func TestAllowedFiles(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7074,7 +7079,7 @@
 }
 
 func TestNonPreferredPrebuiltDependency(t *testing.T) {
-	_, _ = testApex(t, `
+	testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7110,7 +7115,7 @@
 }
 
 func TestCompressedApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7145,7 +7150,7 @@
 }
 
 func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7197,7 +7202,7 @@
 }
 
 func TestExcludeDependency(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7341,7 +7346,7 @@
 		t.Run(test.name, func(t *testing.T) {
 			for _, otherApexEnabled := range test.otherApexEnabled {
 				t.Run("otherapex_enabled_"+otherApexEnabled, func(t *testing.T) {
-					ctx, _ := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
+					ctx := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
 
 					type modAndMkEntries struct {
 						mod       *cc.Module
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index ff779e1..2e6ed82 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -28,7 +28,7 @@
 // modules from the ART apex.
 
 func TestBootImages(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		java_sdk_library {
 			name: "foo",
 			srcs: ["b.java"],
@@ -181,7 +181,7 @@
 }
 
 func TestBootImageInApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index 5e9a11f..34b9408 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -9,7 +9,7 @@
 )
 
 func TestVndkApexForVndkLite(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.current",
 			key: "com.android.vndk.current.key",
@@ -100,7 +100,7 @@
 	}
 
 	t.Run("VNDK lib doesn't have an apex variant", func(t *testing.T) {
-		ctx, _ := testApex(t, bp)
+		ctx := testApex(t, bp)
 
 		// libfoo doesn't have apex variants
 		for _, variant := range ctx.ModuleVariantsForTests("libfoo") {
@@ -113,7 +113,7 @@
 	})
 
 	t.Run("VNDK APEX gathers only vendor variants even if product variants are available", func(t *testing.T) {
-		ctx, _ := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
+		ctx := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
 			// Now product variant is available
 			config.TestProductVariables.ProductVndkVersion = proptools.StringPtr("current")
 		})
@@ -123,7 +123,7 @@
 	})
 
 	t.Run("VNDK APEX supports coverage variants", func(t *testing.T) {
-		ctx, _ := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
+		ctx := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
 			config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
 			config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
 		})
diff --git a/cc/testing.go b/cc/testing.go
index 45e5312..f62c5f1 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -25,7 +25,6 @@
 	RegisterBinaryBuildComponents(ctx)
 	RegisterLibraryBuildComponents(ctx)
 	RegisterLibraryHeadersBuildComponents(ctx)
-	genrule.RegisterGenruleBuildComponents(ctx)
 
 	ctx.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
 	ctx.RegisterModuleType("llndk_library", LlndkLibraryFactory)
@@ -591,6 +590,7 @@
 
 func CreateTestContext(config android.Config) *android.TestContext {
 	ctx := android.NewTestArchContext(config)
+	genrule.RegisterGenruleBuildComponents(ctx)
 	ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
 	ctx.RegisterModuleType("cc_test", TestFactory)
 	ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 3a6feca..d022f49 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -21,6 +21,7 @@
 	"path/filepath"
 	"strings"
 
+	"android/soong/shared"
 	"github.com/google/blueprint/bootstrap"
 
 	"android/soong/android"
@@ -28,11 +29,19 @@
 )
 
 var (
+	topDir            string
+	outDir            string
 	docFile           string
 	bazelQueryViewDir string
+	delveListen       string
+	delvePath         string
 )
 
 func init() {
+	flag.StringVar(&topDir, "top", "", "Top directory of the Android source tree")
+	flag.StringVar(&outDir, "out", "", "Soong output directory (usually $TOP/out/soong)")
+	flag.StringVar(&delveListen, "delve_listen", "", "Delve port to listen on for debugging")
+	flag.StringVar(&delvePath, "delve_path", "", "Path to Delve. Only used if --delve_listen is set")
 	flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
 	flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory")
 }
@@ -80,18 +89,23 @@
 }
 
 func main() {
-	android.ReexecWithDelveMaybe()
 	flag.Parse()
 
+	shared.ReexecWithDelveMaybe(delveListen, delvePath)
+	android.InitSandbox(topDir)
+	android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available"))
+
 	// The top-level Blueprints file is passed as the first argument.
 	srcDir := filepath.Dir(flag.Arg(0))
 	var ctx *android.Context
 	configuration := newConfig(srcDir)
 	extraNinjaDeps := []string{configuration.ProductVariablesFileName}
 
-	// Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
-	// and soong_build will rerun when it is set for the first time.
-	if listen := configuration.Getenv("SOONG_DELVE"); listen != "" {
+	// These two are here so that we restart a non-debugged soong_build when the
+	// user sets SOONG_DELVE the first time.
+	configuration.Getenv("SOONG_DELVE")
+	configuration.Getenv("SOONG_DELVE_PATH")
+	if shared.IsDebugging() {
 		// Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
 		// enabled even if it completed successfully.
 		extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 74ede68..1c5e78a 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -25,6 +25,7 @@
 	"strings"
 	"time"
 
+	"android/soong/shared"
 	"android/soong/ui/build"
 	"android/soong/ui/logger"
 	"android/soong/ui/metrics"
@@ -118,6 +119,8 @@
 // Command is the type of soong_ui execution. Only one type of
 // execution is specified. The args are specific to the command.
 func main() {
+	shared.ReexecWithDelveMaybe(os.Getenv("SOONG_UI_DELVE"), shared.ResolveDelveBinary())
+
 	buildStarted := time.Now()
 
 	c, args, err := getCommand(os.Args)
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 737773f..fdb00bd 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -288,12 +288,9 @@
 
 	} else {
 		// Other libraries or APKs for which the exact <uses-library> list is unknown.
-		// Pass special class loader context to skip the classpath and collision check.
-		// This will get removed once LOCAL_USES_LIBRARIES is enforced.
-		// Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
-		// to the &.
+		// We assume the class loader context is empty.
 		rule.Command().
-			Text(`class_loader_context_arg=--class-loader-context=\&`).
+			Text(`class_loader_context_arg=--class-loader-context=PCL[]`).
 			Text(`stored_class_loader_context_arg=""`)
 	}
 
diff --git a/java/aar.go b/java/aar.go
index 602d2c4..554ea67 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -805,14 +805,6 @@
 	return android.Paths{a.classpathFile}
 }
 
-func (a *AARImport) ImplementationJars() android.Paths {
-	return android.Paths{a.classpathFile}
-}
-
-func (a *AARImport) ResourceJars() android.Paths {
-	return nil
-}
-
 func (a *AARImport) ImplementationAndResourcesJars() android.Paths {
 	return android.Paths{a.classpathFile}
 }
@@ -825,22 +817,10 @@
 	return nil
 }
 
-func (a *AARImport) AidlIncludeDirs() android.Paths {
-	return nil
-}
-
 func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
 	return nil
 }
 
-func (d *AARImport) ExportedPlugins() (android.Paths, []string, bool) {
-	return nil, nil, false
-}
-
-func (a *AARImport) SrcJarArgs() ([]string, android.Paths) {
-	return nil, nil
-}
-
 var _ android.ApexModule = (*AARImport)(nil)
 
 // Implements android.ApexModule
diff --git a/java/android_manifest.go b/java/android_manifest.go
index c76bb2f..b30f3d2 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -91,7 +91,7 @@
 	if err != nil {
 		ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
 	}
-	if UseApiFingerprint(ctx) {
+	if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
 		targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
 		deps = append(deps, ApiFingerprintPath(ctx))
 	}
@@ -100,7 +100,7 @@
 	if err != nil {
 		ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
 	}
-	if UseApiFingerprint(ctx) {
+	if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
 		minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
 		deps = append(deps, ApiFingerprintPath(ctx))
 	}
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index ee7d018..39fb04a 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -146,14 +146,6 @@
 	return d.headerJars
 }
 
-func (d *DeviceHostConverter) ImplementationJars() android.Paths {
-	return d.implementationJars
-}
-
-func (d *DeviceHostConverter) ResourceJars() android.Paths {
-	return d.resourceJars
-}
-
 func (d *DeviceHostConverter) ImplementationAndResourcesJars() android.Paths {
 	return d.implementationAndResourceJars
 }
@@ -174,14 +166,6 @@
 	return nil
 }
 
-func (d *DeviceHostConverter) ExportedPlugins() (android.Paths, []string, bool) {
-	return nil, nil, false
-}
-
-func (d *DeviceHostConverter) SrcJarArgs() ([]string, android.Paths) {
-	return d.srcJarArgs, d.srcJarDeps
-}
-
 func (d *DeviceHostConverter) JacocoReportClassesFile() android.Path {
 	return nil
 }
diff --git a/java/java.go b/java/java.go
index e471f0d..9e35835 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2046,13 +2046,6 @@
 	return j.installFile
 }
 
-func (j *Module) ResourceJars() android.Paths {
-	if j.resourceJar == nil {
-		return nil
-	}
-	return android.Paths{j.resourceJar}
-}
-
 func (j *Module) ImplementationAndResourcesJars() android.Paths {
 	if j.implementationAndResourcesJar == nil {
 		return nil
@@ -2069,17 +2062,6 @@
 	return j.classLoaderContexts
 }
 
-// ExportedPlugins returns the list of jars needed to run the exported plugins, the list of
-// classes for the plugins, and a boolean for whether turbine needs to be disabled due to plugins
-// that generate APIs.
-func (j *Module) ExportedPlugins() (android.Paths, []string, bool) {
-	return j.exportedPluginJars, j.exportedPluginClasses, j.exportedDisableTurbine
-}
-
-func (j *Module) SrcJarArgs() ([]string, android.Paths) {
-	return j.srcJarArgs, j.srcJarDeps
-}
-
 var _ logtagsProducer = (*Module)(nil)
 
 func (j *Module) logtags() android.Paths {
@@ -2515,6 +2497,11 @@
 }
 
 func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if j.testProperties.Test_options.Unit_test == nil && ctx.Host() {
+		// TODO(b/): Clean temporary heuristic to avoid unexpected onboarding.
+		defaultUnitTest := !inList("tradefed", j.properties.Static_libs) && !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites) && !inList("robolectric-host-android_all", j.properties.Static_libs) && !inList("robolectric-host-android_all", j.properties.Libs)
+		j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest)
+	}
 	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
 		j.testProperties.Test_suites, j.testProperties.Auto_gen_config, j.testProperties.Test_options.Unit_test)
 
@@ -2675,6 +2662,7 @@
 	module.Module.properties.Installable = proptools.BoolPtr(true)
 
 	InitJavaModuleMultiTargets(module, android.HostSupported)
+
 	return module
 }
 
@@ -3046,17 +3034,6 @@
 	return android.Paths{j.combinedClasspathFile}
 }
 
-func (j *Import) ImplementationJars() android.Paths {
-	if j.combinedClasspathFile == nil {
-		return nil
-	}
-	return android.Paths{j.combinedClasspathFile}
-}
-
-func (j *Import) ResourceJars() android.Paths {
-	return nil
-}
-
 func (j *Import) ImplementationAndResourcesJars() android.Paths {
 	if j.combinedClasspathFile == nil {
 		return nil
@@ -3072,22 +3049,10 @@
 	return nil
 }
 
-func (j *Import) AidlIncludeDirs() android.Paths {
-	return j.exportAidlIncludeDirs
-}
-
 func (j *Import) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
 	return j.classLoaderContexts
 }
 
-func (j *Import) ExportedPlugins() (android.Paths, []string, bool) {
-	return nil, nil, false
-}
-
-func (j *Import) SrcJarArgs() ([]string, android.Paths) {
-	return nil, nil
-}
-
 var _ android.ApexModule = (*Import)(nil)
 
 // Implements android.ApexModule
diff --git a/java/java_test.go b/java/java_test.go
index bb51ebc..9112655 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -25,6 +25,7 @@
 	"strings"
 	"testing"
 
+	"android/soong/genrule"
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
@@ -79,6 +80,8 @@
 
 	android.RegisterPrebuiltMutators(ctx)
 
+	genrule.RegisterGenruleBuildComponents(ctx)
+
 	// Register module types and mutators from cc needed for JNI testing
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
 
diff --git a/java/lint.go b/java/lint.go
index 8272595..50b84dc 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -313,6 +313,7 @@
 
 	rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
 	rule.Command().Text("mkdir -p").Flag(cacheDir.String()).Flag(homeDir.String())
+	rule.Command().Text("rm -f").Output(html).Output(text).Output(xml)
 
 	var annotationsZipPath, apiVersionsXMLPath android.Path
 	if ctx.Config().AlwaysUsePrebuiltSdks() {
@@ -329,8 +330,7 @@
 		FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()).
 		FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
 		FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath).
-		Tool(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/bin/lint")).
-		Implicit(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/lib/lint-classpath.jar")).
+		BuiltTool("lint").
 		Flag("--quiet").
 		FlagWithInput("--project ", projectXML).
 		FlagWithInput("--config ", lintXML).
@@ -362,7 +362,7 @@
 		}
 	}
 
-	cmd.Text("|| (").Text("cat").Input(text).Text("; exit 7)").Text(")")
+	cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)").Text(")")
 
 	rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
 
@@ -438,13 +438,13 @@
 	}
 
 	ctx.Build(pctx, android.BuildParams{
-		Rule:   android.Cp,
+		Rule:   android.CpIfChanged,
 		Input:  android.OutputFileForModule(ctx, frameworkDocStubs, ".annotations.zip"),
 		Output: copiedAnnotationsZipPath(ctx),
 	})
 
 	ctx.Build(pctx, android.BuildParams{
-		Rule:   android.Cp,
+		Rule:   android.CpIfChanged,
 		Input:  android.OutputFileForModule(ctx, frameworkDocStubs, ".api_versions.xml"),
 		Output: copiedAPIVersionsXmlPath(ctx),
 	})
diff --git a/java/robolectric.go b/java/robolectric.go
index 98bb710..00f233e 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -31,13 +31,15 @@
 }
 
 var robolectricDefaultLibs = []string{
-	"Robolectric_all-target",
 	"mockito-robolectric-prebuilt",
 	"truth-prebuilt",
 	// TODO(ccross): this is not needed at link time
 	"junitxml",
 }
 
+const robolectricCurrentLib = "Robolectric_all-target"
+const robolectricPrebuiltLibPattern = "platform-robolectric-%s-prebuilt"
+
 var (
 	roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
 	roboRuntimesTag     = dependencyTag{name: "roboRuntimes"}
@@ -57,6 +59,10 @@
 		// Number of shards to use when running the tests.
 		Shards *int64
 	}
+
+	// The version number of a robolectric prebuilt to use from prebuilts/misc/common/robolectric
+	// instead of the one built from source in external/robolectric-shadows.
+	Robolectric_prebuilt_version *string
 }
 
 type robolectricTest struct {
@@ -94,6 +100,12 @@
 		ctx.PropertyErrorf("instrumentation_for", "missing required instrumented module")
 	}
 
+	if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
+		ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
+	} else {
+		ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib)
+	}
+
 	ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
 
 	ctx.AddVariationDependencies(nil, roboCoverageLibsTag, r.robolectricProperties.Coverage_libs...)
@@ -298,7 +310,11 @@
 	if t := r.robolectricProperties.Test_options.Timeout; t != nil {
 		fmt.Fprintln(w, "LOCAL_ROBOTEST_TIMEOUT :=", *t)
 	}
-	fmt.Fprintln(w, "-include external/robolectric-shadows/run_robotests.mk")
+	if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
+		fmt.Fprintf(w, "-include prebuilts/misc/common/robolectric/%s/run_robotests.mk\n", v)
+	} else {
+		fmt.Fprintln(w, "-include external/robolectric-shadows/run_robotests.mk")
+	}
 }
 
 // An android_robolectric_test module compiles tests against the Robolectric framework that can run on the local host
diff --git a/java/rro_test.go b/java/rro_test.go
index edbf170..061d9d3 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -20,6 +20,7 @@
 	"testing"
 
 	"android/soong/android"
+	"android/soong/shared"
 )
 
 func TestRuntimeResourceOverlay(t *testing.T) {
@@ -105,7 +106,7 @@
 
 	// Check device location.
 	path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
-	expectedPath = []string{"/tmp/target/product/test_device/product/overlay"}
+	expectedPath = []string{shared.JoinPath(buildDir, "../target/product/test_device/product/overlay")}
 	if !reflect.DeepEqual(path, expectedPath) {
 		t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
 	}
@@ -114,7 +115,7 @@
 	m = ctx.ModuleForTests("foo_themed", "android_common")
 	androidMkEntries = android.AndroidMkEntriesForTest(t, ctx, m.Module())[0]
 	path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
-	expectedPath = []string{"/tmp/target/product/test_device/product/overlay/faza"}
+	expectedPath = []string{shared.JoinPath(buildDir, "../target/product/test_device/product/overlay/faza")}
 	if !reflect.DeepEqual(path, expectedPath) {
 		t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
 	}
@@ -160,7 +161,7 @@
 
 	// Check device location.
 	path := android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
-	expectedPath := []string{"/tmp/target/product/test_device/product/overlay/default_theme"}
+	expectedPath := []string{shared.JoinPath(buildDir, "../target/product/test_device/product/overlay/default_theme")}
 	if !reflect.DeepEqual(path, expectedPath) {
 		t.Errorf("Unexpected LOCAL_MODULE_PATH value: %q, expected: %q", path, expectedPath)
 	}
@@ -179,7 +180,7 @@
 
 	// Check device location.
 	path = android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
-	expectedPath = []string{"/tmp/target/product/test_device/system/overlay"}
+	expectedPath = []string{shared.JoinPath(buildDir, "../target/product/test_device/system/overlay")}
 	if !reflect.DeepEqual(path, expectedPath) {
 		t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
 	}
diff --git a/rust/testing.go b/rust/testing.go
index 1afe27e..9534ab5 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -17,6 +17,7 @@
 import (
 	"android/soong/android"
 	"android/soong/cc"
+	"android/soong/genrule"
 )
 
 func GatherRequiredDepsForTest() string {
@@ -211,6 +212,7 @@
 	ctx := android.NewTestArchContext(config)
 	android.RegisterPrebuiltMutators(ctx)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	genrule.RegisterGenruleBuildComponents(ctx)
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
 	RegisterRequiredBuildComponentsForTest(ctx)
 
diff --git a/sdk/testing.go b/sdk/testing.go
index 0bbf7f4..7a2540a 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -26,6 +26,7 @@
 	"android/soong/android"
 	"android/soong/apex"
 	"android/soong/cc"
+	"android/soong/genrule"
 	"android/soong/java"
 )
 
@@ -109,6 +110,9 @@
 	// from java package
 	java.RegisterRequiredBuildComponentsForTest(ctx)
 
+	// from genrule package
+	genrule.RegisterGenruleBuildComponents(ctx)
+
 	// from cc package
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
 
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index fb7ab13..f48f7fb 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -3,6 +3,7 @@
 import (
 	"io/ioutil"
 	"os"
+	"path"
 	"path/filepath"
 	"reflect"
 	"testing"
@@ -73,7 +74,8 @@
 
 	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 
-	expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo_test"
+	expectedPath := path.Join(buildDir,
+		"../target/product/test_device/data/nativetest64/foo_test")
 	actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
 	if expectedPath != actualPath {
 		t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath)
@@ -97,7 +99,8 @@
 
 	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 
-	expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo"
+	expectedPath := path.Join(buildDir,
+		"../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)
diff --git a/shared/Android.bp b/shared/Android.bp
index c79bc2b..deb17f8 100644
--- a/shared/Android.bp
+++ b/shared/Android.bp
@@ -8,6 +8,10 @@
     srcs: [
         "env.go",
         "paths.go",
+        "debug.go",
+    ],
+    testSrcs: [
+        "paths_test.go",
     ],
     deps: [
         "soong-bazel",
diff --git a/shared/debug.go b/shared/debug.go
new file mode 100644
index 0000000..5392f2b
--- /dev/null
+++ b/shared/debug.go
@@ -0,0 +1,69 @@
+package shared
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+	"strings"
+	"syscall"
+)
+
+var (
+	isDebugging bool
+)
+
+// Finds the Delve binary to use. Either uses the SOONG_DELVE_PATH environment
+// variable or if that is unset, looks at $PATH.
+func ResolveDelveBinary() string {
+	result := os.Getenv("SOONG_DELVE_PATH")
+	if result == "" {
+		result, _ = exec.LookPath("dlv")
+	}
+
+	return result
+}
+
+// Returns whether the current process is running under Delve due to
+// ReexecWithDelveMaybe().
+func IsDebugging() bool {
+	return isDebugging
+}
+
+// Re-executes the binary in question under the control of Delve when
+// delveListen is not the empty string. delvePath gives the path to the Delve.
+func ReexecWithDelveMaybe(delveListen, delvePath string) {
+	isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
+	if isDebugging || delveListen == "" {
+		return
+	}
+
+	if delvePath == "" {
+		fmt.Fprintln(os.Stderr, "Delve debugging requested but failed to find dlv")
+		os.Exit(1)
+	}
+
+	soongDelveEnv := []string{}
+	for _, env := range os.Environ() {
+		idx := strings.IndexRune(env, '=')
+		if idx != -1 {
+			soongDelveEnv = append(soongDelveEnv, env)
+		}
+	}
+
+	soongDelveEnv = append(soongDelveEnv, "SOONG_DELVE_REEXECUTED=true")
+
+	dlvArgv := []string{
+		delvePath,
+		"--listen=:" + delveListen,
+		"--headless=true",
+		"--api-version=2",
+		"exec",
+		os.Args[0],
+		"--",
+	}
+
+	dlvArgv = append(dlvArgv, os.Args[1:]...)
+	syscall.Exec(delvePath, dlvArgv, soongDelveEnv)
+	fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
+	os.Exit(1)
+}
diff --git a/shared/env.go b/shared/env.go
index 7900daa..152729b 100644
--- a/shared/env.go
+++ b/shared/env.go
@@ -91,6 +91,28 @@
 	return false, nil
 }
 
+// Deserializes and environment serialized by EnvFileContents() and returns it
+// as a map[string]string.
+func EnvFromFile(envFile string) (map[string]string, error) {
+	result := make(map[string]string)
+	data, err := ioutil.ReadFile(envFile)
+	if err != nil {
+		return result, err
+	}
+
+	var contents envFileData
+	err = json.Unmarshal(data, &contents)
+	if err != nil {
+		return result, err
+	}
+
+	for _, entry := range contents {
+		result[entry.Key] = entry.Value
+	}
+
+	return result, nil
+}
+
 // Implements sort.Interface so that we can use sort.Sort on envFileData arrays.
 func (e envFileData) Len() int {
 	return len(e)
diff --git a/shared/paths.go b/shared/paths.go
index 1b9ff60..fca8b4c 100644
--- a/shared/paths.go
+++ b/shared/paths.go
@@ -30,6 +30,21 @@
 	BazelMetricsDir() string
 }
 
+// Joins the path strings in the argument list, taking absolute paths into
+// account. That is, if one of the strings is an absolute path, the ones before
+// are ignored.
+func JoinPath(base string, rest ...string) string {
+	result := base
+	for _, next := range rest {
+		if filepath.IsAbs(next) {
+			result = next
+		} else {
+			result = filepath.Join(result, next)
+		}
+	}
+	return result
+}
+
 // Given the out directory, returns the root of the temp directory (to be cleared at the start of each execution of Soong)
 func TempDirForOutDir(outDir string) (tempPath string) {
 	return filepath.Join(outDir, ".temp")
diff --git a/shared/paths_test.go b/shared/paths_test.go
new file mode 100644
index 0000000..018d55f
--- /dev/null
+++ b/shared/paths_test.go
@@ -0,0 +1,32 @@
+// Copyright 2021 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 shared
+
+import (
+	"testing"
+)
+
+func assertEqual(t *testing.T, expected, actual string) {
+	t.Helper()
+	if expected != actual {
+		t.Errorf("expected %q != got %q", expected, actual)
+	}
+}
+
+func TestJoinPath(t *testing.T) {
+	assertEqual(t, "/a/b", JoinPath("c/d", "/a/b"))
+	assertEqual(t, "a/b", JoinPath("a", "b"))
+	assertEqual(t, "/a/b", JoinPath("x", "/a", "b"))
+}
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index b1f8551..6ba497c 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -124,7 +124,7 @@
 		productOut("obj/PACKAGING"),
 		productOut("ramdisk"),
 		productOut("debug_ramdisk"),
-		productOut("vendor-ramdisk"),
+		productOut("vendor_ramdisk"),
 		productOut("vendor_debug_ramdisk"),
 		productOut("test_harness_ramdisk"),
 		productOut("recovery"),
diff --git a/ui/build/environment.go b/ui/build/environment.go
index 6d8a28f..50d059f 100644
--- a/ui/build/environment.go
+++ b/ui/build/environment.go
@@ -33,6 +33,19 @@
 	return &env
 }
 
+// Returns a copy of the environment as a map[string]string.
+func (e *Environment) AsMap() map[string]string {
+	result := make(map[string]string)
+
+	for _, envVar := range *e {
+		if k, v, ok := decodeKeyValue(envVar); ok {
+			result[k] = v
+		}
+	}
+
+	return result
+}
+
 // Get returns the value associated with the key, and whether it exists.
 // It's equivalent to the os.LookupEnv function, but with this copy of the
 // Environment.
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 125dbcc..c2fa427 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -21,6 +21,7 @@
 	"strconv"
 
 	"android/soong/shared"
+
 	soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
 
 	"github.com/golang/protobuf/proto"
@@ -30,6 +31,15 @@
 	"android/soong/ui/status"
 )
 
+func writeEnvironmentFile(ctx Context, envFile string, envDeps map[string]string) error {
+	data, err := shared.EnvFileContents(envDeps)
+	if err != nil {
+		return err
+	}
+
+	return ioutil.WriteFile(envFile, data, 0644)
+}
+
 // This uses Android.bp files and various tools to generate <builddir>/build.ninja.
 //
 // However, the execution of <builddir>/build.ninja happens later in build/soong/ui/build/build.go#Build()
@@ -47,6 +57,12 @@
 	ctx.BeginTrace(metrics.RunSoong, "soong")
 	defer ctx.EndTrace()
 
+	// We have two environment files: .available is the one with every variable,
+	// .used with the ones that were actually used. The latter is used to
+	// determine whether Soong needs to be re-run since why re-run it if only
+	// unused variables were changed?
+	envFile := filepath.Join(config.SoongOutDir(), "soong.environment.available")
+
 	// Use an anonymous inline function for tracing purposes (this pattern is used several times below).
 	func() {
 		ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
@@ -61,6 +77,7 @@
 		}
 
 		cmd := Command(ctx, config, "blueprint bootstrap", "build/blueprint/bootstrap.bash", args...)
+
 		cmd.Environment.Set("BLUEPRINTDIR", "./build/blueprint")
 		cmd.Environment.Set("BOOTSTRAP", "./build/blueprint/bootstrap.bash")
 		cmd.Environment.Set("BUILDDIR", config.SoongOutDir())
@@ -74,11 +91,30 @@
 		cmd.RunAndPrintOrFatal()
 	}()
 
+	soongBuildEnv := config.Environment().Copy()
+	soongBuildEnv.Set("TOP", os.Getenv("TOP"))
+	// These two dependencies are read from bootstrap.go, but also need to be here
+	// so that soong_build can declare a dependency on them
+	soongBuildEnv.Set("SOONG_DELVE", os.Getenv("SOONG_DELVE"))
+	soongBuildEnv.Set("SOONG_DELVE_PATH", os.Getenv("SOONG_DELVE_PATH"))
+	soongBuildEnv.Set("SOONG_OUTDIR", config.SoongOutDir())
+	// For Bazel mixed builds.
+	soongBuildEnv.Set("BAZEL_PATH", "./tools/bazel")
+	soongBuildEnv.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
+	soongBuildEnv.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
+	soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
+	soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
+
+	err := writeEnvironmentFile(ctx, envFile, soongBuildEnv.AsMap())
+	if err != nil {
+		ctx.Fatalf("failed to write environment file %s: %s", envFile, err)
+	}
+
 	func() {
 		ctx.BeginTrace(metrics.RunSoong, "environment check")
 		defer ctx.EndTrace()
 
-		envFile := filepath.Join(config.SoongOutDir(), ".soong.environment")
+		envFile := filepath.Join(config.SoongOutDir(), "soong.environment.used")
 		getenv := func(k string) string {
 			v, _ := config.Environment().Get(k)
 			return v
@@ -134,14 +170,12 @@
 			"--frontend_file", fifo,
 			"-f", filepath.Join(config.SoongOutDir(), file))
 
-		// For Bazel mixed builds.
-		cmd.Environment.Set("BAZEL_PATH", "./tools/bazel")
-		cmd.Environment.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
-		cmd.Environment.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
-		cmd.Environment.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
-		cmd.Environment.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
+		cmd.Environment.Set("SOONG_OUTDIR", config.SoongOutDir())
+		if os.Getenv("SOONG_DELVE") != "" {
+			// SOONG_DELVE is already in cmd.Environment
+			cmd.Environment.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
+		}
 
-		cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
 		cmd.Sandbox = soongSandbox
 		cmd.RunAndStreamOrFatal()
 	}
diff --git a/vnames.go.json b/vnames.go.json
index 7ce2d4b..f8c6b7f 100644
--- a/vnames.go.json
+++ b/vnames.go.json
@@ -2,7 +2,6 @@
     {
         "pattern": "(.*)",
         "vname": {
-            "corpus": "android.googlesource.com/platform/superproject",
             "path": "@1@"
         }
     }
diff --git a/vnames.json b/vnames.json
index f9d3adc..096260f 100644
--- a/vnames.json
+++ b/vnames.json
@@ -2,7 +2,6 @@
   {
     "pattern": "out/(.*)",
     "vname": {
-      "corpus": "android.googlesource.com/platform/superproject",
       "root": "out",
       "path": "@1@"
     }
@@ -10,9 +9,7 @@
   {
     "pattern": "(.*)",
     "vname": {
-      "corpus": "android.googlesource.com/platform/superproject",
       "path": "@1@"
     }
   }
 ]
-