Merge "AIDEGen: Add "-fprofile-sample-use" parameter into category."
diff --git a/android/env.go b/android/env.go
index 58ad0b6..289d803 100644
--- a/android/env.go
+++ b/android/env.go
@@ -15,11 +15,6 @@
 package android
 
 import (
-	"fmt"
-	"os"
-	"strings"
-	"syscall"
-
 	"android/soong/shared"
 )
 
@@ -31,9 +26,6 @@
 // a manifest regeneration.
 
 var originalEnv map[string]string
-var soongDelveListen string
-var soongDelvePath string
-var isDebugging bool
 
 func InitEnvironment(envFile string) {
 	var err error
@@ -41,51 +33,6 @@
 	if err != nil {
 		panic(err)
 	}
-
-	soongDelveListen = originalEnv["SOONG_DELVE"]
-	soongDelvePath = originalEnv["SOONG_DELVE_PATH"]
-}
-
-// Returns whether the current process is running under Delve due to
-// ReexecWithDelveMaybe().
-func IsDebugging() bool {
-	return isDebugging
-}
-func ReexecWithDelveMaybe() {
-	isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
-	if isDebugging || soongDelveListen == "" {
-		return
-	}
-
-	if soongDelvePath == "" {
-		fmt.Fprintln(os.Stderr, "SOONG_DELVE is set 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{
-		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)
 }
 
 func EnvSingleton() Singleton {
diff --git a/android/fixture.go b/android/fixture.go
index 2c8997b..1def9c0 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -15,6 +15,7 @@
 package android
 
 import (
+	"fmt"
 	"reflect"
 	"strings"
 	"testing"
@@ -182,12 +183,12 @@
 	// Create a Fixture.
 	Fixture(t *testing.T, preparers ...FixturePreparer) Fixture
 
-	// SetErrorHandler creates a new FixtureFactory that will use the supplied error handler to check
-	// the errors (may be 0) reported by the test.
+	// ExtendWithErrorHandler 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.
-	SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory
+	ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory
 
 	// Run the test, checking any errors reported and returning a TestResult instance.
 	//
@@ -198,6 +199,24 @@
 	//
 	// Shorthand for RunTest(t, android.FixtureWithRootAndroidBp(bp))
 	RunTestWithBp(t *testing.T, bp string) *TestResult
+
+	// RunTestWithConfig is a temporary method added to help ease the migration of existing tests to
+	// the test fixture.
+	//
+	// In order to allow the Config object to be customized separately to the TestContext a lot of
+	// existing test code has `test...WithConfig` funcs that allow the Config object to be supplied
+	// from the test and then have the TestContext created and configured automatically. e.g.
+	// testCcWithConfig, testCcErrorWithConfig, testJavaWithConfig, etc.
+	//
+	// This method allows those methods to be migrated to use the test fixture pattern without
+	// requiring that every test that uses those methods be migrated at the same time. That allows
+	// those tests to benefit from correctness in the order of registration quickly.
+	//
+	// This method discards the config (along with its mock file system, product variables,
+	// environment, etc.) that may have been set up by FixturePreparers.
+	//
+	// deprecated
+	RunTestWithConfig(t *testing.T, config Config) *TestResult
 }
 
 // Create a new FixtureFactory that will apply the supplied preparers.
@@ -286,6 +305,45 @@
 	return FixtureAddTextFile("Android.bp", contents)
 }
 
+// Merge some environment variables into the fixture.
+func FixtureMergeEnv(env map[string]string) FixturePreparer {
+	return FixtureModifyConfig(func(config Config) {
+		for k, v := range env {
+			if k == "PATH" {
+				panic("Cannot set PATH environment variable")
+			}
+			config.env[k] = v
+		}
+	})
+}
+
+// Modify the env.
+//
+// Will panic if the mutator changes the PATH environment variable.
+func FixtureModifyEnv(mutator func(env map[string]string)) FixturePreparer {
+	return FixtureModifyConfig(func(config Config) {
+		oldPath := config.env["PATH"]
+		mutator(config.env)
+		newPath := config.env["PATH"]
+		if newPath != oldPath {
+			panic(fmt.Errorf("Cannot change PATH environment variable from %q to %q", oldPath, newPath))
+		}
+	})
+}
+
+// Allow access to the product variables when preparing the fixture.
+type FixtureProductVariables struct {
+	*productVariables
+}
+
+// Modify product variables.
+func FixtureModifyProductVariables(mutator func(variables FixtureProductVariables)) FixturePreparer {
+	return FixtureModifyConfig(func(config Config) {
+		productVariables := FixtureProductVariables{&config.productVariables}
+		mutator(productVariables)
+	})
+}
+
 // GroupFixturePreparers creates a composite FixturePreparer that is equivalent to applying each of
 // the supplied FixturePreparer instances in order.
 //
@@ -484,6 +542,18 @@
 	}
 }
 
+// AssertErrorMessageEquals checks if the error is not nil and has the expected message. If it does
+// not then this reports an error prefixed with the supplied message and including a reason for why
+// it failed.
+func (h *TestHelper) AssertErrorMessageEquals(message string, expected string, actual error) {
+	h.Helper()
+	if actual == nil {
+		h.Errorf("Expected error but was nil")
+	} else if actual.Error() != expected {
+		h.Errorf("%s: expected %s, actual %s", message, expected, actual.Error())
+	}
+}
+
 // AssertTrimmedStringEquals checks if the expected and actual values are the same after trimming
 // leading and trailing spaces from them both. If they are not then it reports an error prefixed
 // with the supplied message and including a reason for why it failed.
@@ -538,6 +608,23 @@
 	}
 }
 
+// AssertPanic checks that the supplied function panics as expected.
+func (h *TestHelper) AssertPanic(message string, funcThatShouldPanic func()) {
+	h.Helper()
+	panicked := false
+	func() {
+		defer func() {
+			if x := recover(); x != nil {
+				panicked = true
+			}
+		}()
+		funcThatShouldPanic()
+	}()
+	if !panicked {
+		h.Error(message)
+	}
+}
+
 // Struct to allow TestResult to embed a *TestContext and allow call forwarding to its methods.
 type testContext struct {
 	*TestContext
@@ -564,7 +651,11 @@
 }
 
 func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixtureFactory {
-	all := append(f.preparers, dedupAndFlattenPreparers(f.preparers, preparers)...)
+	// Create a new slice to avoid accidentally sharing the preparers slice from this factory with
+	// the extending factories.
+	var all []*simpleFixturePreparer
+	all = append(all, f.preparers...)
+	all = append(all, dedupAndFlattenPreparers(f.preparers, preparers)...)
 	// Copy the existing factory.
 	extendedFactory := &fixtureFactory{}
 	*extendedFactory = *f
@@ -596,7 +687,7 @@
 	return fixture
 }
 
-func (f *fixtureFactory) SetErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory {
+func (f *fixtureFactory) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory {
 	newFactory := &fixtureFactory{}
 	*newFactory = *f
 	newFactory.errorHandler = errorHandler
@@ -614,6 +705,28 @@
 	return f.RunTest(t, FixtureWithRootAndroidBp(bp))
 }
 
+func (f *fixtureFactory) RunTestWithConfig(t *testing.T, config Config) *TestResult {
+	t.Helper()
+	// Create the fixture as normal.
+	fixture := f.Fixture(t).(*fixture)
+
+	// Discard the mock filesystem as otherwise that will override the one in the config.
+	fixture.mockFS = nil
+
+	// Replace the config with the supplied one in the fixture.
+	fixture.config = config
+
+	// Ditto with config derived information in the TestContext.
+	ctx := fixture.ctx
+	ctx.config = config
+	ctx.SetFs(ctx.config.fs)
+	if ctx.config.mockBpList != "" {
+		ctx.SetModuleListFile(ctx.config.mockBpList)
+	}
+
+	return fixture.RunTest()
+}
+
 type fixture struct {
 	// The factory used to create this fixture.
 	factory *fixtureFactory
@@ -639,17 +752,22 @@
 
 	ctx := f.ctx
 
-	// The TestConfig() method assumes that the mock filesystem is available when creating so creates
-	// the mock file system immediately. Similarly, the NewTestContext(Config) method assumes that the
-	// supplied Config's FileSystem has been properly initialized before it is called and so it takes
-	// its own reference to the filesystem. However, fixtures create the Config and TestContext early
-	// so they can be modified by preparers at which time the mockFS has not been populated (because
-	// it too is modified by preparers). So, this reinitializes the Config and TestContext's
-	// FileSystem using the now populated mockFS.
-	f.config.mockFileSystem("", f.mockFS)
-	ctx.SetFs(ctx.config.fs)
-	if ctx.config.mockBpList != "" {
-		ctx.SetModuleListFile(ctx.config.mockBpList)
+	// Do not use the fixture's mockFS to initialize the config's mock file system if it has been
+	// cleared by RunTestWithConfig.
+	if f.mockFS != nil {
+		// The TestConfig() method assumes that the mock filesystem is available when creating so
+		// creates the mock file system immediately. Similarly, the NewTestContext(Config) method
+		// assumes that the supplied Config's FileSystem has been properly initialized before it is
+		// called and so it takes its own reference to the filesystem. However, fixtures create the
+		// Config and TestContext early so they can be modified by preparers at which time the mockFS
+		// has not been populated (because it too is modified by preparers). So, this reinitializes the
+		// Config and TestContext's FileSystem using the now populated mockFS.
+		f.config.mockFileSystem("", f.mockFS)
+
+		ctx.SetFs(ctx.config.fs)
+		if ctx.config.mockBpList != "" {
+			ctx.SetModuleListFile(ctx.config.mockBpList)
+		}
 	}
 
 	ctx.Register()
diff --git a/android/license_kind_test.go b/android/license_kind_test.go
index 767b64e..83e83ce 100644
--- a/android/license_kind_test.go
+++ b/android/license_kind_test.go
@@ -8,7 +8,7 @@
 
 var licenseKindTests = []struct {
 	name           string
-	fs             map[string][]byte
+	fs             MockFS
 	expectedErrors []string
 }{
 	{
@@ -97,48 +97,18 @@
 func TestLicenseKind(t *testing.T) {
 	for _, test := range licenseKindTests {
 		t.Run(test.name, func(t *testing.T) {
-			_, errs := testLicenseKind(test.fs)
-
-			expectedErrors := test.expectedErrors
-			if expectedErrors == nil {
-				FailIfErrored(t, errs)
-			} else {
-				for _, expectedError := range expectedErrors {
-					FailIfNoMatchingErrors(t, expectedError, errs)
-				}
-				if len(errs) > len(expectedErrors) {
-					t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
-					for i, expectedError := range expectedErrors {
-						t.Errorf("expectedErrors[%d] = %s", i, expectedError)
-					}
-					for i, err := range errs {
-						t.Errorf("errs[%d] = %s", i, err)
-					}
-				}
-			}
+			licenseTestFixtureFactory.
+				Extend(
+					FixtureRegisterWithContext(func(ctx RegistrationContext) {
+						ctx.RegisterModuleType("mock_license", newMockLicenseModule)
+					}),
+					test.fs.AddToFixture(),
+				).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+				RunTest(t)
 		})
 	}
 }
 
-func testLicenseKind(fs map[string][]byte) (*TestContext, []error) {
-
-	// Create a new config per test as license_kind information is stored in the config.
-	config := TestArchConfig(buildDir, nil, "", fs)
-
-	ctx := NewTestArchContext(config)
-	RegisterLicenseKindBuildComponents(ctx)
-	ctx.RegisterModuleType("mock_license", newMockLicenseModule)
-	ctx.Register()
-
-	_, errs := ctx.ParseBlueprintsFiles(".")
-	if len(errs) > 0 {
-		return ctx, errs
-	}
-
-	_, errs = ctx.PrepareBuildActions(config)
-	return ctx, errs
-}
-
 type mockLicenseProperties struct {
 	License_kinds []string
 }
diff --git a/android/license_test.go b/android/license_test.go
index 9f68713..a564827 100644
--- a/android/license_test.go
+++ b/android/license_test.go
@@ -4,9 +4,24 @@
 	"testing"
 )
 
+// Common test set up for license tests.
+var licenseTestFixtureFactory = emptyTestFixtureFactory.Extend(
+	// General preparers in alphabetical order.
+	PrepareForTestWithDefaults,
+	prepareForTestWithLicenses,
+	PrepareForTestWithOverrides,
+	PrepareForTestWithPackageModule,
+	PrepareForTestWithPrebuilts,
+	PrepareForTestWithVisibility,
+
+	// Additional test specific stuff
+	prepareForTestWithFakePrebuiltModules,
+	FixtureMergeEnv(map[string]string{"ANDROID_REQUIRE_LICENSES": "1"}),
+)
+
 var licenseTests = []struct {
 	name           string
-	fs             map[string][]byte
+	fs             MockFS
 	expectedErrors []string
 }{
 	{
@@ -163,58 +178,20 @@
 func TestLicense(t *testing.T) {
 	for _, test := range licenseTests {
 		t.Run(test.name, func(t *testing.T) {
-			_, errs := testLicense(test.fs)
-
-			expectedErrors := test.expectedErrors
-			if expectedErrors == nil {
-				FailIfErrored(t, errs)
-			} else {
-				for _, expectedError := range expectedErrors {
-					FailIfNoMatchingErrors(t, expectedError, errs)
-				}
-				if len(errs) > len(expectedErrors) {
-					t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
-					for i, expectedError := range expectedErrors {
-						t.Errorf("expectedErrors[%d] = %s", i, expectedError)
-					}
-					for i, err := range errs {
-						t.Errorf("errs[%d] = %s", i, err)
-					}
-				}
-			}
+			// Customize the common license text fixture factory.
+			licenseTestFixtureFactory.Extend(
+				FixtureRegisterWithContext(func(ctx RegistrationContext) {
+					ctx.RegisterModuleType("rule", newMockRuleModule)
+				}),
+				test.fs.AddToFixture(),
+			).
+				ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+				RunTest(t)
 		})
 	}
 }
 
-func testLicense(fs map[string][]byte) (*TestContext, []error) {
-
-	// Create a new config per test as visibility information is stored in the config.
-	env := make(map[string]string)
-	env["ANDROID_REQUIRE_LICENSES"] = "1"
-	config := TestArchConfig(buildDir, env, "", fs)
-
-	ctx := NewTestArchContext(config)
-	RegisterPackageBuildComponents(ctx)
-	registerTestPrebuiltBuildComponents(ctx)
-	RegisterLicenseKindBuildComponents(ctx)
-	RegisterLicenseBuildComponents(ctx)
-	ctx.RegisterModuleType("rule", newMockRuleModule)
-	ctx.PreArchMutators(RegisterVisibilityRuleChecker)
-	ctx.PreArchMutators(RegisterLicensesPackageMapper)
-	ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
-	ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
-	ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
-	ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
-	ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
-	ctx.Register()
-
-	_, errs := ctx.ParseBlueprintsFiles(".")
-	if len(errs) > 0 {
-		return ctx, errs
-	}
-
-	_, errs = ctx.PrepareBuildActions(config)
-	return ctx, errs
+func testLicense(t *testing.T, fs MockFS, expectedErrors []string) {
 }
 
 type mockRuleModule struct {
diff --git a/android/licenses_test.go b/android/licenses_test.go
index c043791..d0e3533 100644
--- a/android/licenses_test.go
+++ b/android/licenses_test.go
@@ -6,9 +6,21 @@
 	"github.com/google/blueprint"
 )
 
+var prepareForTestWithLicenses = GroupFixturePreparers(
+	FixtureRegisterWithContext(RegisterLicenseKindBuildComponents),
+	FixtureRegisterWithContext(RegisterLicenseBuildComponents),
+	FixtureRegisterWithContext(registerLicenseMutators),
+)
+
+func registerLicenseMutators(ctx RegistrationContext) {
+	ctx.PreArchMutators(RegisterLicensesPackageMapper)
+	ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
+	ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
+}
+
 var licensesTests = []struct {
 	name                       string
-	fs                         map[string][]byte
+	fs                         MockFS
 	expectedErrors             []string
 	effectiveLicenses          map[string][]string
 	effectiveInheritedLicenses map[string][]string
@@ -457,40 +469,48 @@
 func TestLicenses(t *testing.T) {
 	for _, test := range licensesTests {
 		t.Run(test.name, func(t *testing.T) {
-			ctx, errs := testLicenses(buildDir, test.fs)
-
-			CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
+			// Customize the common license text fixture factory.
+			result := licenseTestFixtureFactory.Extend(
+				FixtureRegisterWithContext(func(ctx RegistrationContext) {
+					ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule)
+					ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule)
+					ctx.RegisterModuleType("mock_defaults", defaultsLicensesFactory)
+				}),
+				test.fs.AddToFixture(),
+			).
+				ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+				RunTest(t)
 
 			if test.effectiveLicenses != nil {
-				checkEffectiveLicenses(t, ctx, test.effectiveLicenses)
+				checkEffectiveLicenses(result, test.effectiveLicenses)
 			}
 
 			if test.effectivePackage != nil {
-				checkEffectivePackage(t, ctx, test.effectivePackage)
+				checkEffectivePackage(result, test.effectivePackage)
 			}
 
 			if test.effectiveNotices != nil {
-				checkEffectiveNotices(t, ctx, test.effectiveNotices)
+				checkEffectiveNotices(result, test.effectiveNotices)
 			}
 
 			if test.effectiveKinds != nil {
-				checkEffectiveKinds(t, ctx, test.effectiveKinds)
+				checkEffectiveKinds(result, test.effectiveKinds)
 			}
 
 			if test.effectiveConditions != nil {
-				checkEffectiveConditions(t, ctx, test.effectiveConditions)
+				checkEffectiveConditions(result, test.effectiveConditions)
 			}
 
 			if test.effectiveInheritedLicenses != nil {
-				checkEffectiveInheritedLicenses(t, ctx, test.effectiveInheritedLicenses)
+				checkEffectiveInheritedLicenses(result, test.effectiveInheritedLicenses)
 			}
 		})
 	}
 }
 
-func checkEffectiveLicenses(t *testing.T, ctx *TestContext, effectiveLicenses map[string][]string) {
+func checkEffectiveLicenses(result *TestResult, effectiveLicenses map[string][]string) {
 	actualLicenses := make(map[string][]string)
-	ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+	result.Context.Context.VisitAllModules(func(m blueprint.Module) {
 		if _, ok := m.(*licenseModule); ok {
 			return
 		}
@@ -502,7 +522,7 @@
 		}
 		module, ok := m.(Module)
 		if !ok {
-			t.Errorf("%q not a module", m.Name())
+			result.Errorf("%q not a module", m.Name())
 			return
 		}
 		base := module.base()
@@ -518,14 +538,14 @@
 			licenses = []string{}
 		}
 		if !compareUnorderedStringArrays(expectedLicenses, licenses) {
-			t.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses)
+			result.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses)
 		}
 	}
 }
 
-func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveInheritedLicenses map[string][]string) {
+func checkEffectiveInheritedLicenses(result *TestResult, effectiveInheritedLicenses map[string][]string) {
 	actualLicenses := make(map[string][]string)
-	ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+	result.Context.Context.VisitAllModules(func(m blueprint.Module) {
 		if _, ok := m.(*licenseModule); ok {
 			return
 		}
@@ -537,7 +557,7 @@
 		}
 		module, ok := m.(Module)
 		if !ok {
-			t.Errorf("%q not a module", m.Name())
+			result.Errorf("%q not a module", m.Name())
 			return
 		}
 		base := module.base()
@@ -548,7 +568,7 @@
 		for _, l := range base.commonProperties.Effective_licenses {
 			inherited[l] = true
 		}
-		ctx.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) {
+		result.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) {
 			if _, ok := c.(*licenseModule); ok {
 				return
 			}
@@ -560,7 +580,7 @@
 			}
 			cmodule, ok := c.(Module)
 			if !ok {
-				t.Errorf("%q not a module", c.Name())
+				result.Errorf("%q not a module", c.Name())
 				return
 			}
 			cbase := cmodule.base()
@@ -583,14 +603,14 @@
 			licenses = []string{}
 		}
 		if !compareUnorderedStringArrays(expectedInheritedLicenses, licenses) {
-			t.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses)
+			result.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses)
 		}
 	}
 }
 
-func checkEffectivePackage(t *testing.T, ctx *TestContext, effectivePackage map[string]string) {
+func checkEffectivePackage(result *TestResult, effectivePackage map[string]string) {
 	actualPackage := make(map[string]string)
-	ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+	result.Context.Context.VisitAllModules(func(m blueprint.Module) {
 		if _, ok := m.(*licenseModule); ok {
 			return
 		}
@@ -602,7 +622,7 @@
 		}
 		module, ok := m.(Module)
 		if !ok {
-			t.Errorf("%q not a module", m.Name())
+			result.Errorf("%q not a module", m.Name())
 			return
 		}
 		base := module.base()
@@ -623,14 +643,14 @@
 			packageName = ""
 		}
 		if expectedPackage != packageName {
-			t.Errorf("effective package mismatch for module %q: expected %q, found %q", moduleName, expectedPackage, packageName)
+			result.Errorf("effective package mismatch for module %q: expected %q, found %q", moduleName, expectedPackage, packageName)
 		}
 	}
 }
 
-func checkEffectiveNotices(t *testing.T, ctx *TestContext, effectiveNotices map[string][]string) {
+func checkEffectiveNotices(result *TestResult, effectiveNotices map[string][]string) {
 	actualNotices := make(map[string][]string)
-	ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+	result.Context.Context.VisitAllModules(func(m blueprint.Module) {
 		if _, ok := m.(*licenseModule); ok {
 			return
 		}
@@ -642,7 +662,7 @@
 		}
 		module, ok := m.(Module)
 		if !ok {
-			t.Errorf("%q not a module", m.Name())
+			result.Errorf("%q not a module", m.Name())
 			return
 		}
 		base := module.base()
@@ -658,14 +678,14 @@
 			notices = []string{}
 		}
 		if !compareUnorderedStringArrays(expectedNotices, notices) {
-			t.Errorf("effective notice files mismatch for module %q: expected %q, found %q", moduleName, expectedNotices, notices)
+			result.Errorf("effective notice files mismatch for module %q: expected %q, found %q", moduleName, expectedNotices, notices)
 		}
 	}
 }
 
-func checkEffectiveKinds(t *testing.T, ctx *TestContext, effectiveKinds map[string][]string) {
+func checkEffectiveKinds(result *TestResult, effectiveKinds map[string][]string) {
 	actualKinds := make(map[string][]string)
-	ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+	result.Context.Context.VisitAllModules(func(m blueprint.Module) {
 		if _, ok := m.(*licenseModule); ok {
 			return
 		}
@@ -677,7 +697,7 @@
 		}
 		module, ok := m.(Module)
 		if !ok {
-			t.Errorf("%q not a module", m.Name())
+			result.Errorf("%q not a module", m.Name())
 			return
 		}
 		base := module.base()
@@ -693,14 +713,14 @@
 			kinds = []string{}
 		}
 		if !compareUnorderedStringArrays(expectedKinds, kinds) {
-			t.Errorf("effective license kinds mismatch for module %q: expected %q, found %q", moduleName, expectedKinds, kinds)
+			result.Errorf("effective license kinds mismatch for module %q: expected %q, found %q", moduleName, expectedKinds, kinds)
 		}
 	}
 }
 
-func checkEffectiveConditions(t *testing.T, ctx *TestContext, effectiveConditions map[string][]string) {
+func checkEffectiveConditions(result *TestResult, effectiveConditions map[string][]string) {
 	actualConditions := make(map[string][]string)
-	ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+	result.Context.Context.VisitAllModules(func(m blueprint.Module) {
 		if _, ok := m.(*licenseModule); ok {
 			return
 		}
@@ -712,7 +732,7 @@
 		}
 		module, ok := m.(Module)
 		if !ok {
-			t.Errorf("%q not a module", m.Name())
+			result.Errorf("%q not a module", m.Name())
 			return
 		}
 		base := module.base()
@@ -728,7 +748,7 @@
 			conditions = []string{}
 		}
 		if !compareUnorderedStringArrays(expectedConditions, conditions) {
-			t.Errorf("effective license conditions mismatch for module %q: expected %q, found %q", moduleName, expectedConditions, conditions)
+			result.Errorf("effective license conditions mismatch for module %q: expected %q, found %q", moduleName, expectedConditions, conditions)
 		}
 	}
 }
@@ -754,41 +774,6 @@
 	return true
 }
 
-func testLicenses(buildDir string, fs map[string][]byte) (*TestContext, []error) {
-
-	// Create a new config per test as licenses information is stored in the config.
-	env := make(map[string]string)
-	env["ANDROID_REQUIRE_LICENSES"] = "1"
-	config := TestArchConfig(buildDir, env, "", fs)
-
-	ctx := NewTestArchContext(config)
-	ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule)
-	ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule)
-	ctx.RegisterModuleType("mock_defaults", defaultsLicensesFactory)
-
-	// Order of the following method calls is significant.
-	RegisterPackageBuildComponents(ctx)
-	registerTestPrebuiltBuildComponents(ctx)
-	RegisterLicenseKindBuildComponents(ctx)
-	RegisterLicenseBuildComponents(ctx)
-	ctx.PreArchMutators(RegisterVisibilityRuleChecker)
-	ctx.PreArchMutators(RegisterLicensesPackageMapper)
-	ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
-	ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
-	ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
-	ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
-	ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
-	ctx.Register()
-
-	_, errs := ctx.ParseBlueprintsFiles(".")
-	if len(errs) > 0 {
-		return ctx, errs
-	}
-
-	_, errs = ctx.PrepareBuildActions(config)
-	return ctx, errs
-}
-
 type mockLicensesBadProperties struct {
 	Visibility []string
 }
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/override_module.go b/android/override_module.go
index fa08566..97acc5c 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -215,7 +215,14 @@
 	ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel()
 	ctx.TopDown("register_override", registerOverrideMutator).Parallel()
 	ctx.BottomUp("perform_override", performOverrideMutator).Parallel()
+	// overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can
+	// add deps from overridable properties.
 	ctx.BottomUp("overridable_deps", overridableModuleDepsMutator).Parallel()
+	// Because overridableModuleDepsMutator is run after PrebuiltPostDepsMutator,
+	// prebuilt's ReplaceDependencies doesn't affect to those deps added by overridable properties.
+	// By running PrebuiltPostDepsMutator again after overridableModuleDepsMutator, deps via overridable properties
+	// can be replaced with prebuilts.
+	ctx.BottomUp("replace_deps_on_prebuilts_for_overridable_deps_again", PrebuiltPostDepsMutator).Parallel()
 	ctx.BottomUp("replace_deps_on_override", replaceDepsOnOverridingModuleMutator).Parallel()
 }
 
diff --git a/android/path_properties.go b/android/path_properties.go
index 853e5a9..2c8d27c 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -118,6 +118,13 @@
 				*values = append(*values, v.Index(i).Field(index[0]))
 			}
 		} else {
+			// Dereference it if it's a pointer.
+			if v.Kind() == reflect.Ptr {
+				if v.IsNil() {
+					return
+				}
+				v = v.Elem()
+			}
 			*values = append(*values, v.Field(index[0]))
 		}
 		return
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index 2aab748..85c96ee 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -26,6 +26,9 @@
 		Bar []string `android:"path,arch_variant"`
 		Baz *string  `android:"path"`
 		Qux string
+		V   *struct {
+			W string `android:"path"`
+		}
 	}
 
 	// A second property struct with a duplicate property name
@@ -94,8 +97,11 @@
 						],
 					},
 				],
+				v: {
+					w: ":w",
+				},
 			}`,
-			deps: []string{"a", "b", "c", "x", "y", "z"},
+			deps: []string{"a", "b", "c", "w", "x", "y", "z"},
 		},
 		{
 			name: "arch variant",
@@ -136,6 +142,10 @@
 				}
 
 				filegroup {
+					name: "w",
+				}
+
+				filegroup {
 					name: "x",
 				}
 
diff --git a/android/queryview.go b/android/queryview.go
index 9e3e45a..12d14df 100644
--- a/android/queryview.go
+++ b/android/queryview.go
@@ -66,12 +66,20 @@
 	bazelQueryView := ctx.Rule(pctx, "bazelQueryView",
 		blueprint.RuleParams{
 			Command: fmt.Sprintf(
-				"rm -rf ${outDir}/* && "+
-					"%s --bazel_queryview_dir ${outDir} %s && "+
-					"echo WORKSPACE: `cat %s` > ${outDir}/.queryview-depfile.d",
-				primaryBuilder.String(),
-				strings.Join(os.Args[1:], " "),
+				`rm -rf "${outDir}/"* && `+
+					`mkdir -p "${outDir}" && `+
+					`echo WORKSPACE: cat "%s" > "${outDir}/.queryview-depfile.d" && `+
+					`BUILDER="%s" && `+
+					`echo BUILDER=$$BUILDER && `+
+					`cd "$$(dirname "$$BUILDER")" && `+
+					`echo PWD=$$PWD && `+
+					`ABSBUILDER="$$PWD/$$(basename "$$BUILDER")" && `+
+					`echo ABSBUILDER=$$ABSBUILDER && `+
+					`cd / && `+
+					`env -i "$$ABSBUILDER" --bazel_queryview_dir "${outDir}" "%s"`,
 				moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
+				primaryBuilder.String(),
+				strings.Join(os.Args[1:], "\" \""),
 			),
 			CommandDeps: []string{primaryBuilder.String()},
 			Description: fmt.Sprintf(
diff --git a/android/register.go b/android/register.go
index 47df972..c9e66e9 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,46 +166,51 @@
 // 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))
-	}
+	mutators := collateGloballyRegisteredMutators()
+	mutators.registerAll(ctx)
 
-	registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
+	singletons := collateGloballyRegisteredSingletons()
+	singletons.registerAll(ctx)
+}
 
-	ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(ctx, BazelSingleton))
+func collateGloballyRegisteredSingletons() sortableComponents {
+	allSingletons := append(sortableComponents(nil), singletons...)
+	allSingletons = append(allSingletons,
+		singleton{false, "bazeldeps", BazelSingleton},
 
-	// Register phony just before makevars so it can write out its phony rules as Make rules
-	ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(ctx, phonySingletonFactory))
+		// Register phony just before makevars so it can write out its phony rules as Make rules
+		singleton{false, "phony", phonySingletonFactory},
 
-	// Register makevars after other singletons so they can export values through makevars
-	ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(ctx, makeVarsSingletonFunc))
+		// Register makevars after other singletons so they can export values through makevars
+		singleton{false, "makevars", makeVarsSingletonFunc},
 
-	// Register env and ninjadeps last so that they can track all used environment variables and
-	// Ninja file dependencies stored in the config.
-	ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(ctx, EnvSingleton))
-	ctx.RegisterSingletonType("ninjadeps", SingletonFactoryAdaptor(ctx, ninjaDepsSingletonFactory))
+		// Register env and ninjadeps last so that they can track all used environment variables and
+		// Ninja file dependencies stored in the config.
+		singleton{false, "env", EnvSingleton},
+		singleton{false, "ninjadeps", ninjaDepsSingletonFactory},
+	)
+
+	return allSingletons
 }
 
 func ModuleTypeFactories() map[string]ModuleFactory {
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index c62e76d..34b180d 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -295,18 +295,25 @@
 	recurse = func(prefix string, aps []string) ([]string, reflect.Type) {
 		var fields []reflect.StructField
 
+		// Iterate while the list is non-empty so it can be modified in the loop.
 		for len(affectableProperties) > 0 {
 			p := affectableProperties[0]
 			if !strings.HasPrefix(affectableProperties[0], prefix) {
+				// The properties are sorted and recurse is always called with a prefix that matches
+				// the first property in the list, so if we've reached one that doesn't match the
+				// prefix we are done with this prefix.
 				break
 			}
-			affectableProperties = affectableProperties[1:]
 
 			nestedProperty := strings.TrimPrefix(p, prefix)
 			if i := strings.IndexRune(nestedProperty, '.'); i >= 0 {
 				var nestedType reflect.Type
 				nestedPrefix := nestedProperty[:i+1]
 
+				// Recurse to handle the properties with the found prefix.  This will return
+				// an updated affectableProperties with the handled entries removed from the front
+				// of the list, and the type that contains the handled entries.  The type may be
+				// nil if none of the entries matched factoryProps.
 				affectableProperties, nestedType = recurse(prefix+nestedPrefix, affectableProperties)
 
 				if nestedType != nil {
@@ -325,6 +332,8 @@
 						Type: typ,
 					})
 				}
+				// The first element in the list has been handled, remove it from the list.
+				affectableProperties = affectableProperties[1:]
 			}
 		}
 
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index b824c78..48cdfe7 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -235,6 +235,44 @@
 			}{},
 			want: "",
 		},
+		{
+			name:                 "nested",
+			affectableProperties: []string{"multilib.lib32.cflags"},
+			factoryProps: struct {
+				Multilib struct {
+					Lib32 struct {
+						Cflags string
+					}
+				}
+			}{},
+			want: "*struct { Multilib struct { Lib32 struct { Cflags string } } }",
+		},
+		{
+			name: "complex",
+			affectableProperties: []string{
+				"cflags",
+				"multilib.lib32.cflags",
+				"multilib.lib32.ldflags",
+				"multilib.lib64.cflags",
+				"multilib.lib64.ldflags",
+				"zflags",
+			},
+			factoryProps: struct {
+				Cflags   string
+				Multilib struct {
+					Lib32 struct {
+						Cflags  string
+						Ldflags string
+					}
+					Lib64 struct {
+						Cflags  string
+						Ldflags string
+					}
+				}
+				Zflags string
+			}{},
+			want: "*struct { Cflags string; Multilib struct { Lib32 struct { Cflags string; Ldflags string }; Lib64 struct { Cflags string; Ldflags string } }; Zflags string }",
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/android/testing.go b/android/testing.go
index d8c123b..03d7bd5 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -20,6 +20,7 @@
 	"regexp"
 	"sort"
 	"strings"
+	"sync"
 	"testing"
 
 	"github.com/google/blueprint"
@@ -72,17 +73,36 @@
 	ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
 })
 
-// Prepares an integration test with build components from the android package.
-var PrepareForIntegrationTestWithAndroid = GroupFixturePreparers(
-	// Mutators. Must match order in mutator.go.
+// Test fixture preparer that will register most java build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of java
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+//
+// The mutators in this group were chosen because they are needed by the vast majority of tests.
+var PrepareForTestWithAndroidBuildComponents = GroupFixturePreparers(
+	// Sorted alphabetically as the actual order does not matter as tests automatically enforce the
+	// correct order.
 	PrepareForTestWithArchMutator,
-	PrepareForTestWithDefaults,
 	PrepareForTestWithComponentsMutator,
-	PrepareForTestWithPrebuilts,
-	PrepareForTestWithOverrides,
-
-	// Modules
+	PrepareForTestWithDefaults,
 	PrepareForTestWithFilegroup,
+	PrepareForTestWithOverrides,
+	PrepareForTestWithPackageModule,
+	PrepareForTestWithPrebuilts,
+	PrepareForTestWithVisibility,
+)
+
+// Prepares an integration test with all build components from the android package.
+//
+// This should only be used by tests that want to run with as much of the build enabled as possible.
+var PrepareForIntegrationTestWithAndroid = GroupFixturePreparers(
+	PrepareForTestWithAndroidBuildComponents,
 )
 
 func NewTestArchContext(config Config) *TestContext {
@@ -96,6 +116,13 @@
 	preArch, preDeps, postDeps, finalDeps           []RegisterMutatorFunc
 	bp2buildPreArch, bp2buildDeps, bp2buildMutators []RegisterMutatorFunc
 	NameResolver                                    *NameResolver
+
+	// The list of pre-singletons and singletons registered for the test.
+	preSingletons, singletons sortableComponents
+
+	// The order in which the pre-singletons, mutators and singletons will be run in this test
+	// context; for debugging.
+	preSingletonOrder, mutatorOrder, singletonOrder []string
 }
 
 func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@@ -140,15 +167,244 @@
 	ctx.bp2buildDeps = append(ctx.bp2buildDeps, f)
 }
 
-func (ctx *TestContext) Register() {
-	registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
+// registeredComponentOrder defines the order in which a sortableComponent type is registered at
+// runtime and provides support for reordering the components registered for a test in the same
+// way.
+type registeredComponentOrder struct {
+	// The name of the component type, used for error messages.
+	componentType string
 
+	// The names of the registered components in the order in which they were registered.
+	namesInOrder []string
+
+	// Maps from the component name to its position in the runtime ordering.
+	namesToIndex map[string]int
+
+	// A function that defines the order between two named components that can be used to sort a slice
+	// of component names into the same order as they appear in namesInOrder.
+	less func(string, string) bool
+}
+
+// registeredComponentOrderFromExistingOrder takes an existing slice of sortableComponents and
+// creates a registeredComponentOrder that contains a less function that can be used to sort a
+// subset of that list of names so it is in the same order as the original sortableComponents.
+func registeredComponentOrderFromExistingOrder(componentType string, existingOrder sortableComponents) registeredComponentOrder {
+	// Only the names from the existing order are needed for this so create a list of component names
+	// in the correct order.
+	namesInOrder := componentsToNames(existingOrder)
+
+	// Populate the map from name to position in the list.
+	nameToIndex := make(map[string]int)
+	for i, n := range namesInOrder {
+		nameToIndex[n] = i
+	}
+
+	// A function to use to map from a name to an index in the original order.
+	indexOf := func(name string) int {
+		index, ok := nameToIndex[name]
+		if !ok {
+			// Should never happen as tests that use components that are not known at runtime do not sort
+			// so should never use this function.
+			panic(fmt.Errorf("internal error: unknown %s %q should be one of %s", componentType, name, strings.Join(namesInOrder, ", ")))
+		}
+		return index
+	}
+
+	// The less function.
+	less := func(n1, n2 string) bool {
+		i1 := indexOf(n1)
+		i2 := indexOf(n2)
+		return i1 < i2
+	}
+
+	return registeredComponentOrder{
+		componentType: componentType,
+		namesInOrder:  namesInOrder,
+		namesToIndex:  nameToIndex,
+		less:          less,
+	}
+}
+
+// componentsToNames maps from the slice of components to a slice of their names.
+func componentsToNames(components sortableComponents) []string {
+	names := make([]string, len(components))
+	for i, c := range components {
+		names[i] = c.componentName()
+	}
+	return names
+}
+
+// enforceOrdering enforces the supplied components are in the same order as is defined in this
+// object.
+//
+// If the supplied components contains any components that are not registered at runtime, i.e. test
+// specific components, then it is impossible to sort them into an order that both matches the
+// runtime and also preserves the implicit ordering defined in the test. In that case it will not
+// sort the components, instead it will just check that the components are in the correct order.
+//
+// Otherwise, this will sort the supplied components in place.
+func (o *registeredComponentOrder) enforceOrdering(components sortableComponents) {
+	// Check to see if the list of components contains any components that are
+	// not registered at runtime.
+	var unknownComponents []string
+	testOrder := componentsToNames(components)
+	for _, name := range testOrder {
+		if _, ok := o.namesToIndex[name]; !ok {
+			unknownComponents = append(unknownComponents, name)
+			break
+		}
+	}
+
+	// If the slice contains some unknown components then it is not possible to
+	// sort them into an order that matches the runtime while also preserving the
+	// order expected from the test, so in that case don't sort just check that
+	// the order of the known mutators does match.
+	if len(unknownComponents) > 0 {
+		// Check order.
+		o.checkTestOrder(testOrder, unknownComponents)
+	} else {
+		// Sort the components.
+		sort.Slice(components, func(i, j int) bool {
+			n1 := components[i].componentName()
+			n2 := components[j].componentName()
+			return o.less(n1, n2)
+		})
+	}
+}
+
+// checkTestOrder checks that the supplied testOrder matches the one defined by this object,
+// panicking if it does not.
+func (o *registeredComponentOrder) checkTestOrder(testOrder []string, unknownComponents []string) {
+	lastMatchingTest := -1
+	matchCount := 0
+	// Take a copy of the runtime order as it is modified during the comparison.
+	runtimeOrder := append([]string(nil), o.namesInOrder...)
+	componentType := o.componentType
+	for i, j := 0, 0; i < len(testOrder) && j < len(runtimeOrder); {
+		test := testOrder[i]
+		runtime := runtimeOrder[j]
+
+		if test == runtime {
+			testOrder[i] = test + fmt.Sprintf(" <-- matched with runtime %s %d", componentType, j)
+			runtimeOrder[j] = runtime + fmt.Sprintf(" <-- matched with test %s %d", componentType, i)
+			lastMatchingTest = i
+			i += 1
+			j += 1
+			matchCount += 1
+		} else if _, ok := o.namesToIndex[test]; !ok {
+			// The test component is not registered globally so assume it is the correct place, treat it
+			// as having matched and skip it.
+			i += 1
+			matchCount += 1
+		} else {
+			// Assume that the test list is in the same order as the runtime list but the runtime list
+			// contains some components that are not present in the tests. So, skip the runtime component
+			// to try and find the next one that matches the current test component.
+			j += 1
+		}
+	}
+
+	// If every item in the test order was either test specific or matched one in the runtime then
+	// it is in the correct order. Otherwise, it was not so fail.
+	if matchCount != len(testOrder) {
+		// The test component names were not all matched with a runtime component name so there must
+		// either be a component present in the test that is not present in the runtime or they must be
+		// in the wrong order.
+		testOrder[lastMatchingTest+1] = testOrder[lastMatchingTest+1] + " <--- unmatched"
+		panic(fmt.Errorf("the tests uses test specific components %q and so cannot be automatically sorted."+
+			" Unfortunately it uses %s components in the wrong order.\n"+
+			"test order:\n    %s\n"+
+			"runtime order\n    %s\n",
+			SortedUniqueStrings(unknownComponents),
+			componentType,
+			strings.Join(testOrder, "\n    "),
+			strings.Join(runtimeOrder, "\n    ")))
+	}
+}
+
+// registrationSorter encapsulates the information needed to ensure that the test mutators are
+// registered, and thereby executed, in the same order as they are at runtime.
+//
+// It MUST be populated lazily AFTER all package initialization has been done otherwise it will
+// only define the order for a subset of all the registered build components that are available for
+// the packages being tested.
+//
+// e.g if this is initialized during say the cc package initialization then any tests run in the
+// java package will not sort build components registered by the java package's init() functions.
+type registrationSorter struct {
+	// Used to ensure that this is only created once.
+	once sync.Once
+
+	// The order of pre-singletons
+	preSingletonOrder registeredComponentOrder
+
+	// The order of mutators
+	mutatorOrder registeredComponentOrder
+
+	// The order of singletons
+	singletonOrder registeredComponentOrder
+}
+
+// populate initializes this structure from globally registered build components.
+//
+// Only the first call has any effect.
+func (s *registrationSorter) populate() {
+	s.once.Do(func() {
+		// Create an ordering from the globally registered pre-singletons.
+		s.preSingletonOrder = registeredComponentOrderFromExistingOrder("pre-singleton", preSingletons)
+
+		// Created an ordering from the globally registered mutators.
+		globallyRegisteredMutators := collateGloballyRegisteredMutators()
+		s.mutatorOrder = registeredComponentOrderFromExistingOrder("mutator", globallyRegisteredMutators)
+
+		// Create an ordering from the globally registered singletons.
+		globallyRegisteredSingletons := collateGloballyRegisteredSingletons()
+		s.singletonOrder = registeredComponentOrderFromExistingOrder("singleton", globallyRegisteredSingletons)
+	})
+}
+
+// Provides support for enforcing the same order in which build components are registered globally
+// to the order in which they are registered during tests.
+//
+// MUST only be accessed via the globallyRegisteredComponentsOrder func.
+var globalRegistrationSorter registrationSorter
+
+// globallyRegisteredComponentsOrder returns the globalRegistrationSorter after ensuring it is
+// correctly populated.
+func globallyRegisteredComponentsOrder() *registrationSorter {
+	globalRegistrationSorter.populate()
+	return &globalRegistrationSorter
+}
+
+func (ctx *TestContext) Register() {
+	globalOrder := globallyRegisteredComponentsOrder()
+
+	// Ensure that the pre-singletons used in the test are in the same order as they are used at
+	// runtime.
+	globalOrder.preSingletonOrder.enforceOrdering(ctx.preSingletons)
+	ctx.preSingletons.registerAll(ctx.Context)
+
+	mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
+	// Ensure that the mutators used in the test are in the same order as they are used at runtime.
+	globalOrder.mutatorOrder.enforceOrdering(mutators)
+	mutators.registerAll(ctx.Context)
+
+	// Register the env singleton with this context before sorting.
 	ctx.RegisterSingletonType("env", EnvSingleton)
+
+	// Ensure that the singletons used in the test are in the same order as they are used at runtime.
+	globalOrder.singletonOrder.enforceOrdering(ctx.singletons)
+	ctx.singletons.registerAll(ctx.Context)
+
+	// Save the sorted components order away to make them easy to access while debugging.
+	ctx.preSingletonOrder = componentsToNames(preSingletons)
+	ctx.mutatorOrder = componentsToNames(mutators)
+	ctx.singletonOrder = componentsToNames(singletons)
 }
 
 // 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) {
@@ -174,11 +430,11 @@
 }
 
 func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
-	ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
+	ctx.singletons = append(ctx.singletons, newSingleton(name, factory))
 }
 
 func (ctx *TestContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
-	ctx.Context.RegisterPreSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
+	ctx.preSingletons = append(ctx.preSingletons, newPreSingleton(name, factory))
 }
 
 func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
@@ -550,10 +806,6 @@
 		return "<nil path>"
 	}
 	p := path.String()
-	// Allow absolute paths to /dev/
-	if strings.HasPrefix(p, "/dev/") {
-		return p
-	}
 	if w, ok := path.(WritablePath); ok {
 		rel, err := filepath.Rel(w.buildDir(), p)
 		if err != nil {
diff --git a/android/visibility.go b/android/visibility.go
index 631e88f..5d1be6b 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -202,17 +202,14 @@
 	ExcludeFromVisibilityEnforcement()
 }
 
-var PrepareForTestWithVisibilityRuleChecker = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+// The visibility mutators.
+var PrepareForTestWithVisibility = FixtureRegisterWithContext(registerVisibilityMutators)
+
+func registerVisibilityMutators(ctx RegistrationContext) {
 	ctx.PreArchMutators(RegisterVisibilityRuleChecker)
-})
-
-var PrepareForTestWithVisibilityRuleGatherer = FixtureRegisterWithContext(func(ctx RegistrationContext) {
 	ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
-})
-
-var PrepareForTestWithVisibilityRuleEnforcer = FixtureRegisterWithContext(func(ctx RegistrationContext) {
 	ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
-})
+}
 
 // The rule checker needs to be registered before defaults expansion to correctly check that
 // //visibility:xxx isn't combined with other packages in the same list in any one module.
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 30cdcbf..eb4071e 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1143,25 +1143,26 @@
 	for _, test := range visibilityTests {
 		t.Run(test.name, func(t *testing.T) {
 			result := emptyTestFixtureFactory.Extend(
+				// General preparers in alphabetical order as test infrastructure will enforce correct
+				// registration order.
+				PrepareForTestWithArchMutator,
+				PrepareForTestWithDefaults,
+				PrepareForTestWithOverrides,
+				PrepareForTestWithPackageModule,
+				PrepareForTestWithPrebuilts,
+				PrepareForTestWithVisibility,
+
+				// Additional test specific preparers.
 				FixtureRegisterWithContext(func(ctx RegistrationContext) {
 					ctx.RegisterModuleType("mock_library", newMockLibraryModule)
 					ctx.RegisterModuleType("mock_parent", newMockParentFactory)
 					ctx.RegisterModuleType("mock_defaults", defaultsFactory)
 				}),
 				prepareForTestWithFakePrebuiltModules,
-				PrepareForTestWithPackageModule,
-				// Order of the following method calls is significant as they register mutators.
-				PrepareForTestWithArchMutator,
-				PrepareForTestWithPrebuilts,
-				PrepareForTestWithOverrides,
-				PrepareForTestWithVisibilityRuleChecker,
-				PrepareForTestWithDefaults,
-				PrepareForTestWithVisibilityRuleGatherer,
-				PrepareForTestWithVisibilityRuleEnforcer,
 				// Add additional files to the mock filesystem
 				test.fs.AddToFixture(),
 			).
-				SetErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+				ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
 				RunTest(t)
 
 			if test.effectiveVisibility != nil {
diff --git a/android/writedocs.go b/android/writedocs.go
index 6417690..6cb2f10 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -66,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/allowed_deps.txt b/apex/allowed_deps.txt
index 476ac4a..170302c 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -163,11 +163,14 @@
 crtend_so(minSdkVersion:16)
 crtend_so(minSdkVersion:apex_inherit)
 datastallprotosnano(minSdkVersion:29)
+derive_classpath(minSdkVersion:30)
 derive_sdk(minSdkVersion:30)
 derive_sdk(minSdkVersion:current)
 derive_sdk_prefer32(minSdkVersion:30)
 derive_sdk_prefer32(minSdkVersion:current)
+dnsresolver_aidl_interface-lateststable-ndk_platform(minSdkVersion:29)
 dnsresolver_aidl_interface-unstable-ndk_platform(minSdkVersion:29)
+dnsresolver_aidl_interface-V7-ndk_platform(minSdkVersion:29)
 dnsresolver_aidl_interface-V8-ndk_platform(minSdkVersion:29)
 DocumentsUI-res-lib(minSdkVersion:29)
 exoplayer2-extractor(minSdkVersion:16)
@@ -192,7 +195,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))
@@ -306,6 +309,7 @@
 libcutils(minSdkVersion:29)
 libcutils_headers(minSdkVersion:29)
 libcutils_sockets(minSdkVersion:29)
+libderive_classpath(minSdkVersion:30)
 libderive_sdk(minSdkVersion:30)
 libdiagnose_usb(minSdkVersion:(no version))
 libdl(minSdkVersion:(no version))
@@ -502,8 +506,10 @@
 netd_aidl_interface-V5-java(minSdkVersion:29)
 netd_aidl_interface-V6-java(minSdkVersion:29)
 netd_event_listener_interface-java(minSdkVersion:29)
+netd_event_listener_interface-lateststable-ndk_platform(minSdkVersion:29)
 netd_event_listener_interface-ndk_platform(minSdkVersion:29)
 netd_event_listener_interface-unstable-ndk_platform(minSdkVersion:29)
+netd_event_listener_interface-V1-ndk_platform(minSdkVersion:29)
 netd_event_listener_interface-V2-ndk_platform(minSdkVersion:29)
 netlink-client(minSdkVersion:29)
 networkstack-aidl-interfaces-unstable-java(minSdkVersion:29)
@@ -527,7 +533,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))
diff --git a/apex/apex.go b/apex/apex.go
index efd1736..e5b5c92 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -39,16 +39,20 @@
 )
 
 func init() {
-	android.RegisterModuleType("apex", BundleFactory)
-	android.RegisterModuleType("apex_test", testApexBundleFactory)
-	android.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
-	android.RegisterModuleType("apex_defaults", defaultsFactory)
-	android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
-	android.RegisterModuleType("override_apex", overrideApexFactory)
-	android.RegisterModuleType("apex_set", apexSetFactory)
+	registerApexBuildComponents(android.InitRegistrationContext)
+}
 
-	android.PreDepsMutators(RegisterPreDepsMutators)
-	android.PostDepsMutators(RegisterPostDepsMutators)
+func registerApexBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("apex", BundleFactory)
+	ctx.RegisterModuleType("apex_test", testApexBundleFactory)
+	ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
+	ctx.RegisterModuleType("apex_defaults", defaultsFactory)
+	ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
+	ctx.RegisterModuleType("override_apex", overrideApexFactory)
+	ctx.RegisterModuleType("apex_set", apexSetFactory)
+
+	ctx.PreDepsMutators(RegisterPreDepsMutators)
+	ctx.PostDepsMutators(RegisterPostDepsMutators)
 }
 
 func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -970,6 +974,10 @@
 	// If any of the dep is not available to platform, this module is also considered as being
 	// not available to platform even if it has "//apex_available:platform"
 	mctx.VisitDirectDeps(func(child android.Module) {
+		depTag := mctx.OtherModuleDependencyTag(child)
+		if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
+			return
+		}
 		if !am.DepIsInSameApex(mctx, child) {
 			// if the dependency crosses apex boundary, don't consider it
 			return
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e3b7f95..08f54f7 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)
@@ -229,14 +229,8 @@
 	android.RegisterPackageBuildComponents(ctx)
 	ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
 
-	ctx.RegisterModuleType("apex", BundleFactory)
-	ctx.RegisterModuleType("apex_test", testApexBundleFactory)
-	ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
-	ctx.RegisterModuleType("apex_key", ApexKeyFactory)
-	ctx.RegisterModuleType("apex_defaults", defaultsFactory)
-	ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
-	ctx.RegisterModuleType("override_apex", overrideApexFactory)
-	ctx.RegisterModuleType("apex_set", apexSetFactory)
+	registerApexBuildComponents(ctx)
+	registerApexKeyBuildComponents(ctx)
 
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterComponentsMutator)
@@ -263,12 +257,8 @@
 	ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
 	ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
-	ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
 	ctx.RegisterModuleType("bpf", bpf.BpfFactory)
 
-	ctx.PreDepsMutators(RegisterPreDepsMutators)
-	ctx.PostDepsMutators(RegisterPostDepsMutators)
-
 	ctx.Register()
 
 	return ctx, config
@@ -360,7 +350,7 @@
 
 // Minimal test
 func TestBasicApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_defaults {
 			name: "myapex-defaults",
 			manifest: ":myapex.manifest",
@@ -666,7 +656,7 @@
 }
 
 func TestDefaults(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_defaults {
 			name: "myapex-defaults",
 			key: "myapex.key",
@@ -741,7 +731,7 @@
 }
 
 func TestApexManifest(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -763,7 +753,7 @@
 }
 
 func TestBasicZipApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -814,7 +804,7 @@
 }
 
 func TestApexWithStubs(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -909,7 +899,7 @@
 
 func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
 	t.Parallel()
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1016,7 +1006,7 @@
 	//                                  |
 	//   <platform>                     |
 	//      libplatform ----------------'
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1081,7 +1071,7 @@
 }
 
 func TestApexWithExplicitStubsDependency(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex2",
 			key: "myapex2.key",
@@ -1177,7 +1167,7 @@
 			    |
 			    `------> libbar
 	*/
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1239,7 +1229,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",
@@ -1303,7 +1293,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",
@@ -1389,7 +1379,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",
@@ -1456,7 +1446,7 @@
 }
 
 func TestApexWithSystemLibsStubs(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1552,7 +1542,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",
@@ -1634,7 +1624,7 @@
 }
 
 func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1683,7 +1673,7 @@
 }
 
 func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1729,7 +1719,7 @@
 }
 
 func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1777,7 +1767,7 @@
 }
 
 func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -1816,7 +1806,7 @@
 }
 
 func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2143,7 +2133,7 @@
 }
 
 func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2230,7 +2220,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",
@@ -2264,7 +2254,7 @@
 }
 
 func TestFilesInSubDir(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2327,7 +2317,7 @@
 }
 
 func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2386,7 +2376,7 @@
 }
 
 func TestUseVendor(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2499,7 +2489,7 @@
 }
 
 func TestVendorApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2546,7 +2536,7 @@
 }
 
 func TestVendorApex_use_vndk_as_stable(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2610,7 +2600,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",
@@ -2638,7 +2628,7 @@
 }
 
 func TestAndroidMk_UseVendorRequired(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2673,7 +2663,7 @@
 }
 
 func TestAndroidMk_VendorApexRequired(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2705,7 +2695,7 @@
 }
 
 func TestAndroidMkWritesCommonProperties(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2735,7 +2725,7 @@
 }
 
 func TestStaticLinking(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2780,7 +2770,7 @@
 }
 
 func TestKeys(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex_keytest",
 			key: "myapex.key",
@@ -2838,7 +2828,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",
@@ -2856,7 +2846,7 @@
 		}
 	})
 	t.Run("override when unspecified", func(t *testing.T) {
-		ctx, _ := testApex(t, `
+		ctx := testApex(t, `
 			apex {
 				name: "myapex_keytest",
 				key: "myapex.key",
@@ -2879,7 +2869,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",
@@ -2902,7 +2892,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",
@@ -2926,7 +2916,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",
@@ -2945,7 +2935,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",
@@ -2971,7 +2961,7 @@
 }
 
 func TestMacro(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -3099,7 +3089,7 @@
 }
 
 func TestHeaderLibsDependency(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -3243,7 +3233,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",
@@ -3300,7 +3290,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",
@@ -3384,7 +3374,7 @@
 }
 
 func TestVndkApexVersion(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.v27",
 			key: "myapex.key",
@@ -3453,7 +3443,7 @@
 }
 
 func TestVndkApexNameRule(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.current",
 			key: "myapex.key",
@@ -3486,7 +3476,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",
@@ -3558,7 +3548,7 @@
 }
 
 func TestVndkApexWithBinder32(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_vndk {
 			name: "com.android.vndk.v27",
 			key: "myapex.key",
@@ -3627,7 +3617,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",
@@ -3663,7 +3653,7 @@
 }
 
 func TestDependenciesInApexManifest(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex_nodep",
 			key: "myapex.key",
@@ -3771,7 +3761,7 @@
 }
 
 func TestApexName(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -3816,7 +3806,7 @@
 }
 
 func TestNonTestApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -3869,7 +3859,7 @@
 }
 
 func TestTestApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_test {
 			name: "myapex",
 			key: "myapex.key",
@@ -3918,7 +3908,7 @@
 }
 
 func TestApexWithTarget(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4009,7 +3999,7 @@
 }
 
 func TestApexWithArch(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4068,7 +4058,7 @@
 }
 
 func TestApexWithShBinary(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4109,7 +4099,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",
@@ -4142,7 +4132,7 @@
 }
 
 func TestFileContexts_FindInDefaultLocationIfNotSet(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4196,7 +4186,7 @@
 		}
 	`)
 
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4219,7 +4209,7 @@
 }
 
 func TestFileContexts_SetViaFileGroup(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4247,7 +4237,7 @@
 }
 
 func TestApexKeyFromOtherModule(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_key {
 			name: "myapex.key",
 			public_key: ":my.avbpubkey",
@@ -4280,7 +4270,7 @@
 }
 
 func TestPrebuilt(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		prebuilt_apex {
 			name: "myapex",
 			arch: {
@@ -4303,7 +4293,7 @@
 }
 
 func TestPrebuiltFilenameOverride(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		prebuilt_apex {
 			name: "myapex",
 			src: "myapex-arm.apex",
@@ -4320,7 +4310,7 @@
 }
 
 func TestPrebuiltOverrides(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		prebuilt_apex {
 			name: "myapex.prebuilt",
 			src: "myapex-arm.apex",
@@ -4831,7 +4821,7 @@
 }
 
 func TestApexWithTests(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_test {
 			name: "myapex",
 			key: "myapex.key",
@@ -4943,7 +4933,7 @@
 }
 
 func TestInstallExtraFlattenedApexes(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5013,7 +5003,7 @@
 }
 
 func TestApexWithJavaImport(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5042,7 +5032,7 @@
 }
 
 func TestApexWithApps(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5121,7 +5111,7 @@
 }
 
 func TestApexWithAppImports(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5170,7 +5160,7 @@
 }
 
 func TestApexWithAppImportsPrefer(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5207,13 +5197,12 @@
 	}))
 
 	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
-		// TODO(b/181974714) - this is wrong it should be "app/AppFoo/AppFooPrebuilt.apk"
-		"app/AppFoo/AppFoo.apk",
+		"app/AppFoo/AppFooPrebuilt.apk",
 	})
 }
 
 func TestApexWithTestHelperApp(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5424,7 +5413,7 @@
 }
 
 func TestApexAvailable_CheckForPlatform(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 	apex {
 		name: "myapex",
 		key: "myapex.key",
@@ -5487,7 +5476,7 @@
 }
 
 func TestApexAvailable_CreatedForApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 	apex {
 		name: "myapex",
 		key: "myapex.key",
@@ -5522,7 +5511,7 @@
 }
 
 func TestOverrideApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5606,7 +5595,7 @@
 }
 
 func TestLegacyAndroid10Support(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5666,7 +5655,7 @@
 }
 
 func TestJavaSDKLibrary(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5704,7 +5693,7 @@
 }
 
 func TestJavaSDKLibrary_WithinApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5757,7 +5746,7 @@
 }
 
 func TestJavaSDKLibrary_CrossBoundary(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5808,7 +5797,7 @@
 }
 
 func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		prebuilt_apis {
 			name: "sdk",
 			api_dirs: ["100"],
@@ -5925,7 +5914,7 @@
 }
 
 func TestCompatConfig(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5986,7 +5975,7 @@
 }
 
 func TestCarryRequiredModuleNames(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6130,7 +6119,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")
@@ -6142,7 +6131,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")
@@ -6155,7 +6144,7 @@
 }
 
 func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6207,7 +6196,7 @@
 }
 
 func TestApexWithJniLibs(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6249,7 +6238,7 @@
 }
 
 func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6271,7 +6260,7 @@
 }
 
 func TestAppBundle(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6302,7 +6291,7 @@
 }
 
 func TestAppSetBundle(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6335,7 +6324,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",
@@ -6820,7 +6809,7 @@
 }
 
 func TestTestFor(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6906,7 +6895,7 @@
 }
 
 func TestApexSet(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex_set {
 			name: "myapex",
 			set: "myapex.apks",
@@ -6982,7 +6971,7 @@
 }
 
 func TestApexKeysTxt(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7023,7 +7012,7 @@
 }
 
 func TestAllowedFiles(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7079,7 +7068,7 @@
 }
 
 func TestNonPreferredPrebuiltDependency(t *testing.T) {
-	_, _ = testApex(t, `
+	testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7115,7 +7104,7 @@
 }
 
 func TestCompressedApex(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7150,7 +7139,7 @@
 }
 
 func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7202,7 +7191,7 @@
 }
 
 func TestExcludeDependency(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7346,7 +7335,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/key.go b/apex/key.go
index 752888d..8b33b59 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -27,8 +27,12 @@
 var String = proptools.String
 
 func init() {
-	android.RegisterModuleType("apex_key", ApexKeyFactory)
-	android.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
+	registerApexKeyBuildComponents(android.InitRegistrationContext)
+}
+
+func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("apex_key", ApexKeyFactory)
+	ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
 }
 
 type apexKey struct {
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/bp2build/Android.bp b/bp2build/Android.bp
index 8deb5a2..99d706c 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -19,6 +19,7 @@
         "soong-bazel",
         "soong-cc",
         "soong-genrule",
+        "soong-python",
         "soong-sh",
     ],
     testSrcs: [
@@ -27,6 +28,7 @@
         "cc_library_headers_conversion_test.go",
         "cc_object_conversion_test.go",
         "conversion_test.go",
+        "python_binary_conversion_test.go",
         "sh_conversion_test.go",
         "testing.go",
     ],
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
new file mode 100644
index 0000000..7600e36
--- /dev/null
+++ b/bp2build/python_binary_conversion_test.go
@@ -0,0 +1,170 @@
+package bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/python"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+func TestPythonBinaryHost(t *testing.T) {
+	testCases := []struct {
+		description                        string
+		moduleTypeUnderTest                string
+		moduleTypeUnderTestFactory         android.ModuleFactory
+		moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+		blueprint                          string
+		expectedBazelTargets               []string
+		filesystem                         map[string]string
+	}{
+		{
+			description:                        "simple python_binary_host converts to a native py_binary",
+			moduleTypeUnderTest:                "python_binary_host",
+			moduleTypeUnderTestFactory:         python.PythonBinaryHostFactory,
+			moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+			filesystem: map[string]string{
+				"a.py":           "",
+				"b/c.py":         "",
+				"b/d.py":         "",
+				"b/e.py":         "",
+				"files/data.txt": "",
+			},
+			blueprint: `python_binary_host {
+    name: "foo",
+    main: "a.py",
+    srcs: [
+        "**/*.py"
+    ],
+    exclude_srcs: [
+        "b/e.py"
+    ],
+    data: [
+        "files/data.txt",
+    ],
+
+    bazel_module: { bp2build_available: true },
+}
+`,
+			expectedBazelTargets: []string{`py_binary(
+    name = "foo",
+    data = [
+        "files/data.txt",
+    ],
+    main = "a.py",
+    srcs = [
+        "a.py",
+        "b/c.py",
+        "b/d.py",
+    ],
+)`,
+			},
+		},
+		{
+			description:                        "py2 python_binary_host",
+			moduleTypeUnderTest:                "python_binary_host",
+			moduleTypeUnderTestFactory:         python.PythonBinaryHostFactory,
+			moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+			blueprint: `python_binary_host {
+    name: "foo",
+    srcs: ["a.py"],
+    version: {
+        py2: {
+            enabled: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+
+    bazel_module: { bp2build_available: true },
+}
+`,
+			expectedBazelTargets: []string{`py_binary(
+    name = "foo",
+    python_version = "PY2",
+    srcs = [
+        "a.py",
+    ],
+)`,
+			},
+		},
+		{
+			description:                        "py3 python_binary_host",
+			moduleTypeUnderTest:                "python_binary_host",
+			moduleTypeUnderTestFactory:         python.PythonBinaryHostFactory,
+			moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+			blueprint: `python_binary_host {
+    name: "foo",
+    srcs: ["a.py"],
+    version: {
+        py2: {
+            enabled: false,
+        },
+        py3: {
+            enabled: true,
+        },
+    },
+
+    bazel_module: { bp2build_available: true },
+}
+`,
+			expectedBazelTargets: []string{
+				// python_version is PY3 by default.
+				`py_binary(
+    name = "foo",
+    srcs = [
+        "a.py",
+    ],
+)`,
+			},
+		},
+	}
+
+	dir := "."
+	for _, testCase := range testCases {
+		filesystem := make(map[string][]byte)
+		toParse := []string{
+			"Android.bp",
+		}
+		for f, content := range testCase.filesystem {
+			if strings.HasSuffix(f, "Android.bp") {
+				toParse = append(toParse, f)
+			}
+			filesystem[f] = []byte(content)
+		}
+		config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
+		ctx := android.NewTestContext(config)
+
+		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
+		ctx.RegisterForBazelConversion()
+
+		_, errs := ctx.ParseFileList(dir, toParse)
+		if Errored(t, testCase.description, errs) {
+			continue
+		}
+		_, errs = ctx.ResolveDependencies(config)
+		if Errored(t, testCase.description, errs) {
+			continue
+		}
+
+		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
+		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+			fmt.Println(bazelTargets)
+			t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+		} else {
+			for i, target := range bazelTargets {
+				if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
+					t.Errorf(
+						"%s: Expected generated Bazel target to be '%s', got '%s'",
+						testCase.description,
+						w,
+						g,
+					)
+				}
+			}
+		}
+	}
+}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 8142f10..fa1a84d 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -26,7 +26,7 @@
 )
 
 func init() {
-	android.RegisterModuleType("bpf", BpfFactory)
+	registerBpfBuildComponents(android.InitRegistrationContext)
 	pctx.Import("android/soong/cc/config")
 }
 
@@ -43,6 +43,12 @@
 		"ccCmd", "cFlags")
 )
 
+func registerBpfBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("bpf", BpfFactory)
+}
+
+var PrepareForTestWithBpf = android.FixtureRegisterWithContext(registerBpfBuildComponents)
+
 // BpfModule interface is used by the apex package to gather information from a bpf module.
 type BpfModule interface {
 	android.Module
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index be9e36e..eb0d8c8 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -46,24 +46,20 @@
 	}
 
 	os.Exit(run())
+
 }
 
-func testConfig(buildDir string, env map[string]string, bp string) android.Config {
-	mockFS := map[string][]byte{
-		"bpf.c":       nil,
-		"BpfTest.cpp": nil,
-	}
-
-	return cc.TestConfig(buildDir, android.Android, env, bp, mockFS)
-}
-
-func testContext(config android.Config) *android.TestContext {
-	ctx := cc.CreateTestContext(config)
-	ctx.RegisterModuleType("bpf", BpfFactory)
-	ctx.Register()
-
-	return ctx
-}
+var bpfFactory = android.NewFixtureFactory(
+	&buildDir,
+	cc.PrepareForTestWithCcDefaultModules,
+	android.FixtureMergeMockFs(
+		map[string][]byte{
+			"bpf.c":       nil,
+			"BpfTest.cpp": nil,
+		},
+	),
+	PrepareForTestWithBpf,
+)
 
 func TestBpfDataDependency(t *testing.T) {
 	bp := `
@@ -80,16 +76,7 @@
 		}
 	`
 
-	config := testConfig(buildDir, nil, bp)
-	ctx := testContext(config)
-
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	if errs == nil {
-		_, errs = ctx.PrepareBuildActions(config)
-	}
-	if errs != nil {
-		t.Fatal(errs)
-	}
+	bpfFactory.RunTestWithBp(t, bp)
 
 	// We only verify the above BP configuration is processed successfully since the data property
 	// value is not available for testing from this package.
diff --git a/build_kzip.bash b/build_kzip.bash
index 9564723..a4659d4 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -16,6 +16,7 @@
 : ${BUILD_NUMBER:=$(uuidgen)}
 : ${KYTHE_JAVA_SOURCE_BATCH_SIZE:=500}
 : ${KYTHE_KZIP_ENCODING:=proto}
+: ${XREF_CORPUS:?should be set}
 export KYTHE_JAVA_SOURCE_BATCH_SIZE KYTHE_KZIP_ENCODING
 
 # The extraction might fail for some source files, so run with -k and then check that
@@ -29,11 +30,15 @@
 declare -r abspath_out=$(realpath "${out}")
 declare -r go_extractor=$(realpath prebuilts/build-tools/linux-x86/bin/go_extractor)
 declare -r go_root=$(realpath prebuilts/go/linux-x86)
-declare -r vnames_path=$(realpath build/soong/vnames.go.json)
 declare -r source_root=$PWD
+
+# TODO(asmundak): Until b/182183061 is fixed, default corpus has to be specified 
+# in the rules file. Generate this file on the fly with corpus value set from the
+# environment variable.
 for dir in blueprint soong; do
   (cd "build/$dir";
-   KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" --rules="${vnames_path}" \
+   KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" \
+   --rules=<(printf '[{"pattern": "(.*)","vname": {"path": "@1@", "corpus":"%s"}}]' "${XREF_CORPUS}") \
    --canonicalize_package_corpus --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
   )
 done
diff --git a/cc/cc_test.go b/cc/cc_test.go
index e640f12..4f28eaf 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -52,29 +52,50 @@
 	os.Exit(run())
 }
 
+var ccFixtureFactory = android.NewFixtureFactory(
+	&buildDir,
+	PrepareForTestWithCcIncludeVndk,
+
+	android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+		variables.DeviceVndkVersion = StringPtr("current")
+		variables.ProductVndkVersion = StringPtr("current")
+		variables.Platform_vndk_version = StringPtr("VER")
+	}),
+)
+
+// testCcWithConfig runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testCcWithConfig(t *testing.T, config android.Config) *android.TestContext {
 	t.Helper()
-	ctx := CreateTestContext(config)
-	ctx.Register()
-
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	android.FailIfErrored(t, errs)
-
-	return ctx
+	result := ccFixtureFactory.RunTestWithConfig(t, config)
+	return result.TestContext
 }
 
+// testCc runs tests using the ccFixtureFactory
+//
+// Do not add any new usages of this, instead use the ccFixtureFactory directly as it makes it much
+// easier to customize the test behavior.
+//
+// If it is necessary to customize the behavior of an existing test that uses this then please first
+// convert the test to using ccFixtureFactory first and then in a following change add the
+// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
+// that it did not change the test behavior unexpectedly.
+//
+// deprecated
 func testCc(t *testing.T, bp string) *android.TestContext {
 	t.Helper()
-	config := TestConfig(buildDir, android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.ProductVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
-
-	return testCcWithConfig(t, config)
+	result := ccFixtureFactory.RunTestWithBp(t, bp)
+	return result.TestContext
 }
 
+// testCcNoVndk runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testCcNoVndk(t *testing.T, bp string) *android.TestContext {
 	t.Helper()
 	config := TestConfig(buildDir, android.Android, nil, bp, nil)
@@ -83,6 +104,11 @@
 	return testCcWithConfig(t, config)
 }
 
+// testCcNoProductVndk runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testCcNoProductVndk(t *testing.T, bp string) *android.TestContext {
 	t.Helper()
 	config := TestConfig(buildDir, android.Android, nil, bp, nil)
@@ -92,27 +118,24 @@
 	return testCcWithConfig(t, config)
 }
 
+// testCcErrorWithConfig runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
 	t.Helper()
 
-	ctx := CreateTestContext(config)
-	ctx.Register()
-
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	if len(errs) > 0 {
-		android.FailIfNoMatchingErrors(t, pattern, errs)
-		return
-	}
-
-	_, errs = ctx.PrepareBuildActions(config)
-	if len(errs) > 0 {
-		android.FailIfNoMatchingErrors(t, pattern, errs)
-		return
-	}
-
-	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
+	ccFixtureFactory.Extend().
+		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
+		RunTestWithConfig(t, config)
 }
 
+// testCcError runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testCcError(t *testing.T, pattern string, bp string) {
 	t.Helper()
 	config := TestConfig(buildDir, android.Android, nil, bp, nil)
@@ -122,6 +145,11 @@
 	return
 }
 
+// testCcErrorProductVndk runs tests using the ccFixtureFactory
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testCcErrorProductVndk(t *testing.T, pattern string, bp string) {
 	t.Helper()
 	config := TestConfig(buildDir, android.Android, nil, bp, nil)
diff --git a/cc/testing.go b/cc/testing.go
index f62c5f1..fcd124e 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -37,7 +37,31 @@
 }
 
 func GatherRequiredDepsForTest(oses ...android.OsType) string {
-	ret := `
+	ret := commonDefaultModules()
+
+	supportLinuxBionic := false
+	for _, os := range oses {
+		if os == android.Fuchsia {
+			ret += withFuchsiaModules()
+		}
+		if os == android.Windows {
+			ret += withWindowsModules()
+		}
+		if os == android.LinuxBionic {
+			supportLinuxBionic = true
+			ret += withLinuxBionic()
+		}
+	}
+
+	if !supportLinuxBionic {
+		ret += withoutLinuxBionic()
+	}
+
+	return ret
+}
+
+func commonDefaultModules() string {
+	return `
 		toolchain_library {
 			name: "libatomic",
 			defaults: ["linux_bionic_supported"],
@@ -475,23 +499,10 @@
 			name: "note_memtag_heap_sync",
 		}
 	`
+}
 
-	supportLinuxBionic := false
-	for _, os := range oses {
-		if os == android.Fuchsia {
-			ret += `
-		cc_library {
-			name: "libbioniccompat",
-			stl: "none",
-		}
-		cc_library {
-			name: "libcompiler_rt",
-			stl: "none",
-		}
-		`
-		}
-		if os == android.Windows {
-			ret += `
+func withWindowsModules() string {
+	return `
 		toolchain_library {
 			name: "libwinpthread",
 			host_supported: true,
@@ -504,10 +515,23 @@
 			src: "",
 		}
 		`
+}
+
+func withFuchsiaModules() string {
+	return `
+		cc_library {
+			name: "libbioniccompat",
+			stl: "none",
 		}
-		if os == android.LinuxBionic {
-			supportLinuxBionic = true
-			ret += `
+		cc_library {
+			name: "libcompiler_rt",
+			stl: "none",
+		}
+		`
+}
+
+func withLinuxBionic() string {
+	return `
 				cc_binary {
 					name: "linker",
 					defaults: ["linux_bionic_supported"],
@@ -547,23 +571,104 @@
 					},
 				}
 			`
-		}
-	}
+}
 
-	if !supportLinuxBionic {
-		ret += `
+func withoutLinuxBionic() string {
+	return `
 			cc_defaults {
 				name: "linux_bionic_supported",
 			}
 		`
-	}
-
-	return ret
 }
 
 func GatherRequiredFilesForTest(fs map[string][]byte) {
 }
 
+// The directory in which cc linux bionic default modules will be defined.
+//
+// Placing them here ensures that their location does not conflict with default test modules
+// defined by other packages.
+const linuxBionicDefaultsPath = "defaults/cc/linux-bionic/Android.bp"
+
+// The directory in which the default cc common test modules will be defined.
+//
+// Placing them here ensures that their location does not conflict with default test modules
+// defined by other packages.
+const DefaultCcCommonTestModulesDir = "defaults/cc/common/"
+
+// Test fixture preparer that will register most cc build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of cc
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers(
+	android.PrepareForTestWithAndroidBuildComponents,
+	android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
+	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
+		ctx.RegisterModuleType("cc_test", TestFactory)
+		ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
+		ctx.RegisterModuleType("llndk_headers", llndkHeadersFactory)
+		ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
+		ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
+
+		RegisterVndkLibraryTxtTypes(ctx)
+	}),
+)
+
+// Preparer that will define default cc modules, e.g. standard prebuilt modules.
+var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers(
+	PrepareForTestWithCcBuildComponents,
+	// Place the default cc test modules that are common to all platforms in a location that will not
+	// conflict with default test modules defined by other packages.
+	android.FixtureAddTextFile(DefaultCcCommonTestModulesDir+"Android.bp", commonDefaultModules()),
+	// Disable linux bionic by default.
+	android.FixtureAddTextFile(linuxBionicDefaultsPath, withoutLinuxBionic()),
+)
+
+// Prepare a fixture to use all cc module types, mutators and singletons fully.
+//
+// This should only be used by tests that want to run with as much of the build enabled as possible.
+var PrepareForIntegrationTestWithCc = android.GroupFixturePreparers(
+	android.PrepareForIntegrationTestWithAndroid,
+	genrule.PrepareForIntegrationTestWithGenrule,
+	PrepareForTestWithCcDefaultModules,
+)
+
+// The preparer to include if running a cc related test for windows.
+var PrepareForTestOnWindows = android.GroupFixturePreparers(
+	// Place the default cc test modules for windows platforms in a location that will not conflict
+	// with default test modules defined by other packages.
+	android.FixtureAddTextFile("defaults/cc/windows/Android.bp", withWindowsModules()),
+)
+
+// The preparer to include if running a cc related test for linux bionic.
+var PrepareForTestOnLinuxBionic = android.GroupFixturePreparers(
+	// Enable linux bionic.
+	android.FixtureAddTextFile(linuxBionicDefaultsPath, withLinuxBionic()),
+)
+
+// This adds some additional modules and singletons which might negatively impact the performance
+// of tests so they are not included in the PrepareForIntegrationTestWithCc.
+var PrepareForTestWithCcIncludeVndk = android.GroupFixturePreparers(
+	PrepareForIntegrationTestWithCc,
+	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+		vendorSnapshotImageSingleton.init(ctx)
+		recoverySnapshotImageSingleton.init(ctx)
+		ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
+	}),
+)
+
+// TestConfig is the legacy way of creating a test Config for testing cc modules.
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func TestConfig(buildDir string, os android.OsType, env map[string]string,
 	bp string, fs map[string][]byte) android.Config {
 
@@ -588,6 +693,11 @@
 	return config
 }
 
+// CreateTestContext is the legacy way of creating a TestContext for testing cc modules.
+//
+// See testCc for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func CreateTestContext(config android.Config) *android.TestContext {
 	ctx := android.NewTestArchContext(config)
 	genrule.RegisterGenruleBuildComponents(ctx)
@@ -598,13 +708,15 @@
 	ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
+
 	vendorSnapshotImageSingleton.init(ctx)
 	recoverySnapshotImageSingleton.init(ctx)
+	ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
 	RegisterVndkLibraryTxtTypes(ctx)
+
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	android.RegisterPrebuiltMutators(ctx)
 	RegisterRequiredBuildComponentsForTest(ctx)
-	ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
 
 	return ctx
 }
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index e7f995f..4586f44 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -33,13 +33,17 @@
 	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")
+	flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
 }
 
 func newNameResolver(config android.Config) *android.NameResolver {
@@ -87,9 +91,9 @@
 func main() {
 	flag.Parse()
 
+	shared.ReexecWithDelveMaybe(delveListen, delvePath)
 	android.InitSandbox(topDir)
 	android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available"))
-	android.ReexecWithDelveMaybe()
 
 	// The top-level Blueprints file is passed as the first argument.
 	srcDir := filepath.Dir(flag.Arg(0))
@@ -101,9 +105,7 @@
 	// user sets SOONG_DELVE the first time.
 	configuration.Getenv("SOONG_DELVE")
 	configuration.Getenv("SOONG_DELVE_PATH")
-	// 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 != "" {
+	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"))
@@ -148,7 +150,8 @@
 	if bazelQueryViewDir != "" {
 		// Run the code-generation phase to convert BazelTargetModules to BUILD files.
 		codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
-		if err := createBazelQueryView(codegenContext, bazelQueryViewDir); err != nil {
+		absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir)
+		if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
 			fmt.Fprintf(os.Stderr, "%s", err)
 			os.Exit(1)
 		}
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/dexpreopt/testing.go b/dexpreopt/testing.go
index bccbfc1..8e90295 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -45,3 +45,36 @@
 		}
 	`
 }
+
+// Prepares a test fixture by enabling dexpreopt.
+var PrepareForTestWithDexpreopt = FixtureModifyGlobalConfig(func(*GlobalConfig) {})
+
+// FixtureModifyGlobalConfig enables dexpreopt (unless modified by the mutator) and modifies the
+// configuration.
+func FixtureModifyGlobalConfig(configModifier func(dexpreoptConfig *GlobalConfig)) android.FixturePreparer {
+	return android.FixtureModifyConfig(func(config android.Config) {
+		// Initialize the dexpreopt GlobalConfig to an empty structure. This has no effect if it has
+		// already been set.
+		pathCtx := android.PathContextForTesting(config)
+		dexpreoptConfig := GlobalConfigForTests(pathCtx)
+		SetTestGlobalConfig(config, dexpreoptConfig)
+
+		// Retrieve the existing configuration and modify it.
+		dexpreoptConfig = GetGlobalConfig(pathCtx)
+		configModifier(dexpreoptConfig)
+	})
+}
+
+// FixtureSetArtBootJars enables dexpreopt and sets the ArtApexJars property.
+func FixtureSetArtBootJars(bootJars ...string) android.FixturePreparer {
+	return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+		dexpreoptConfig.ArtApexJars = android.CreateTestConfiguredJarList(bootJars)
+	})
+}
+
+// FixtureSetBootJars enables dexpreopt and sets the BootJars property.
+func FixtureSetBootJars(bootJars ...string) android.FixturePreparer {
+	return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+		dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars)
+	})
+}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index b07ad91..6291325 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -54,6 +54,8 @@
 	ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
 }
 
+var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterPrebuiltEtcBuildComponents)
+
 type prebuiltEtcProperties struct {
 	// Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax.
 	Src *string `android:"path,arch_variant"`
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index 585760d..6727e59 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -18,7 +18,6 @@
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"reflect"
 	"testing"
 
 	"android/soong/android"
@@ -49,60 +48,19 @@
 	os.Exit(run())
 }
 
-func testPrebuiltEtcContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
-	fs := map[string][]byte{
+var prebuiltEtcFixtureFactory = android.NewFixtureFactory(
+	&buildDir,
+	android.PrepareForTestWithArchMutator,
+	PrepareForTestWithPrebuiltEtc,
+	android.FixtureMergeMockFs(android.MockFS{
 		"foo.conf": nil,
 		"bar.conf": nil,
 		"baz.conf": nil,
-	}
+	}),
+)
 
-	config := android.TestArchConfig(buildDir, nil, bp, fs)
-
-	ctx := android.NewTestArchContext(config)
-	ctx.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
-	ctx.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
-	ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
-	ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
-	ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
-	ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
-	ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
-	ctx.Register()
-
-	return ctx, config
-}
-
-func testPrebuiltEtc(t *testing.T, bp string) (*android.TestContext, android.Config) {
-	t.Helper()
-
-	ctx, config := testPrebuiltEtcContext(t, bp)
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	android.FailIfErrored(t, errs)
-
-	return ctx, config
-}
-
-func testPrebuiltEtcError(t *testing.T, pattern, bp string) {
-	t.Helper()
-
-	ctx, config := testPrebuiltEtcContext(t, bp)
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	if len(errs) > 0 {
-		android.FailIfNoMatchingErrors(t, pattern, errs)
-		return
-	}
-
-	_, errs = ctx.PrepareBuildActions(config)
-	if len(errs) > 0 {
-		android.FailIfNoMatchingErrors(t, pattern, errs)
-		return
-	}
-
-	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
-}
 func TestPrebuiltEtcVariants(t *testing.T) {
-	ctx, _ := testPrebuiltEtc(t, `
+	result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
 		prebuilt_etc {
 			name: "foo.conf",
 			src: "foo.conf",
@@ -119,24 +77,24 @@
 		}
 	`)
 
-	foo_variants := ctx.ModuleVariantsForTests("foo.conf")
+	foo_variants := result.ModuleVariantsForTests("foo.conf")
 	if len(foo_variants) != 1 {
 		t.Errorf("expected 1, got %#v", foo_variants)
 	}
 
-	bar_variants := ctx.ModuleVariantsForTests("bar.conf")
+	bar_variants := result.ModuleVariantsForTests("bar.conf")
 	if len(bar_variants) != 2 {
 		t.Errorf("expected 2, got %#v", bar_variants)
 	}
 
-	baz_variants := ctx.ModuleVariantsForTests("baz.conf")
+	baz_variants := result.ModuleVariantsForTests("baz.conf")
 	if len(baz_variants) != 1 {
 		t.Errorf("expected 1, got %#v", bar_variants)
 	}
 }
 
 func TestPrebuiltEtcOutputPath(t *testing.T) {
-	ctx, _ := testPrebuiltEtc(t, `
+	result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
 		prebuilt_etc {
 			name: "foo.conf",
 			src: "foo.conf",
@@ -144,14 +102,12 @@
 		}
 	`)
 
-	p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
-	if p.outputFilePath.Base() != "foo.installed.conf" {
-		t.Errorf("expected foo.installed.conf, got %q", p.outputFilePath.Base())
-	}
+	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+	result.AssertStringEquals("output file path", "foo.installed.conf", p.outputFilePath.Base())
 }
 
 func TestPrebuiltEtcGlob(t *testing.T) {
-	ctx, _ := testPrebuiltEtc(t, `
+	result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
 		prebuilt_etc {
 			name: "my_foo",
 			src: "foo.*",
@@ -163,19 +119,15 @@
 		}
 	`)
 
-	p := ctx.ModuleForTests("my_foo", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
-	if p.outputFilePath.Base() != "my_foo" {
-		t.Errorf("expected my_foo, got %q", p.outputFilePath.Base())
-	}
+	p := result.Module("my_foo", "android_arm64_armv8-a").(*PrebuiltEtc)
+	result.AssertStringEquals("my_foo output file path", "my_foo", p.outputFilePath.Base())
 
-	p = ctx.ModuleForTests("my_bar", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
-	if p.outputFilePath.Base() != "bar.conf" {
-		t.Errorf("expected bar.conf, got %q", p.outputFilePath.Base())
-	}
+	p = result.Module("my_bar", "android_arm64_armv8-a").(*PrebuiltEtc)
+	result.AssertStringEquals("my_bar output file path", "bar.conf", p.outputFilePath.Base())
 }
 
 func TestPrebuiltEtcAndroidMk(t *testing.T) {
-	ctx, _ := testPrebuiltEtc(t, `
+	result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
 		prebuilt_etc {
 			name: "foo",
 			src: "foo.conf",
@@ -197,13 +149,11 @@
 		"LOCAL_TARGET_REQUIRED_MODULES": {"targetModA"},
 	}
 
-	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
-	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
+	mod := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
+	entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0]
 	for k, expectedValue := range expected {
 		if value, ok := entries.EntryMap[k]; ok {
-			if !reflect.DeepEqual(value, expectedValue) {
-				t.Errorf("Incorrect %s '%s', expected '%s'", k, value, expectedValue)
-			}
+			result.AssertDeepEquals(k, expectedValue, value)
 		} else {
 			t.Errorf("No %s defined, saw %q", k, entries.EntryMap)
 		}
@@ -211,7 +161,7 @@
 }
 
 func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) {
-	ctx, _ := testPrebuiltEtc(t, `
+	result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
 		prebuilt_etc {
 			name: "foo.conf",
 			src: "foo.conf",
@@ -219,26 +169,26 @@
 		}
 	`)
 
-	p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
+	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
 	expected := buildDir + "/target/product/test_device/system/etc/bar"
-	if p.installDirPath.String() != expected {
-		t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
-	}
+	result.AssertStringEquals("install dir", expected, p.installDirPath.String())
 }
 
 func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) {
-	testPrebuiltEtcError(t, "relative_install_path is set. Cannot set sub_dir", `
-		prebuilt_etc {
-			name: "foo.conf",
-			src: "foo.conf",
-			sub_dir: "bar",
-			relative_install_path: "bar",
-		}
-	`)
+	prebuiltEtcFixtureFactory.
+		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("relative_install_path is set. Cannot set sub_dir")).
+		RunTestWithBp(t, `
+			prebuilt_etc {
+				name: "foo.conf",
+				src: "foo.conf",
+				sub_dir: "bar",
+				relative_install_path: "bar",
+			}
+		`)
 }
 
 func TestPrebuiltEtcHost(t *testing.T) {
-	ctx, _ := testPrebuiltEtc(t, `
+	result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
 		prebuilt_etc_host {
 			name: "foo.conf",
 			src: "foo.conf",
@@ -246,14 +196,14 @@
 	`)
 
 	buildOS := android.BuildOs.String()
-	p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc)
+	p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
 	if !p.Host() {
 		t.Errorf("host bit is not set for a prebuilt_etc_host module.")
 	}
 }
 
 func TestPrebuiltUserShareInstallDirPath(t *testing.T) {
-	ctx, _ := testPrebuiltEtc(t, `
+	result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
 		prebuilt_usr_share {
 			name: "foo.conf",
 			src: "foo.conf",
@@ -261,15 +211,13 @@
 		}
 	`)
 
-	p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
+	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
 	expected := buildDir + "/target/product/test_device/system/usr/share/bar"
-	if p.installDirPath.String() != expected {
-		t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
-	}
+	result.AssertStringEquals("install dir", expected, p.installDirPath.String())
 }
 
 func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) {
-	ctx, config := testPrebuiltEtc(t, `
+	result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
 		prebuilt_usr_share_host {
 			name: "foo.conf",
 			src: "foo.conf",
@@ -278,26 +226,22 @@
 	`)
 
 	buildOS := android.BuildOs.String()
-	p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc)
-	expected := filepath.Join(buildDir, "host", config.PrebuiltOS(), "usr", "share", "bar")
-	if p.installDirPath.String() != expected {
-		t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
-	}
+	p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
+	expected := filepath.Join(buildDir, "host", result.Config.PrebuiltOS(), "usr", "share", "bar")
+	result.AssertStringEquals("install dir", expected, p.installDirPath.String())
 }
 
 func TestPrebuiltFontInstallDirPath(t *testing.T) {
-	ctx, _ := testPrebuiltEtc(t, `
+	result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
 		prebuilt_font {
 			name: "foo.conf",
 			src: "foo.conf",
 		}
 	`)
 
-	p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
+	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
 	expected := buildDir + "/target/product/test_device/system/fonts"
-	if p.installDirPath.String() != expected {
-		t.Errorf("expected %q, got %q", expected, p.installDirPath.String())
-	}
+	result.AssertStringEquals("install dir", expected, p.installDirPath.String())
 }
 
 func TestPrebuiltFirmwareDirPath(t *testing.T) {
@@ -327,11 +271,9 @@
 	}}
 	for _, tt := range tests {
 		t.Run(tt.description, func(t *testing.T) {
-			ctx, _ := testPrebuiltEtc(t, tt.config)
-			p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
-			if p.installDirPath.String() != tt.expectedPath {
-				t.Errorf("expected %q, got %q", tt.expectedPath, p.installDirPath)
-			}
+			result := prebuiltEtcFixtureFactory.RunTestWithBp(t, tt.config)
+			p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+			result.AssertStringEquals("install dir", tt.expectedPath, p.installDirPath.String())
 		})
 	}
 }
@@ -363,11 +305,9 @@
 	}}
 	for _, tt := range tests {
 		t.Run(tt.description, func(t *testing.T) {
-			ctx, _ := testPrebuiltEtc(t, tt.config)
-			p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
-			if p.installDirPath.String() != tt.expectedPath {
-				t.Errorf("expected %q, got %q", tt.expectedPath, p.installDirPath)
-			}
+			result := prebuiltEtcFixtureFactory.RunTestWithBp(t, tt.config)
+			p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+			result.AssertStringEquals("install dir", tt.expectedPath, p.installDirPath.String())
 		})
 	}
 }
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 50c77cf..5349906 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -37,6 +37,27 @@
 	RegisterGenruleBuildComponents(android.InitRegistrationContext)
 }
 
+// Test fixture preparer that will register most genrule build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of genrule
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+var PrepareForTestWithGenRuleBuildComponents = android.GroupFixturePreparers(
+	android.FixtureRegisterWithContext(RegisterGenruleBuildComponents),
+)
+
+// Prepare a fixture to use all genrule module types, mutators and singletons fully.
+//
+// This should only be used by tests that want to run with as much of the build enabled as possible.
+var PrepareForIntegrationTestWithGenrule = android.GroupFixturePreparers(
+	PrepareForTestWithGenRuleBuildComponents,
+)
+
 func RegisterGenruleBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
 
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 2f5605e..0873704 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -17,8 +17,7 @@
 import (
 	"io/ioutil"
 	"os"
-	"reflect"
-	"strings"
+	"regexp"
 	"testing"
 
 	"android/soong/android"
@@ -51,22 +50,30 @@
 	os.Exit(run())
 }
 
-func testContext(config android.Config) *android.TestContext {
+var genruleFixtureFactory = android.NewFixtureFactory(
+	&buildDir,
+	android.PrepareForTestWithArchMutator,
+	android.PrepareForTestWithDefaults,
 
-	ctx := android.NewTestArchContext(config)
-	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
-	ctx.RegisterModuleType("tool", toolFactory)
+	android.PrepareForTestWithFilegroup,
+	PrepareForTestWithGenRuleBuildComponents,
+	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("tool", toolFactory)
+	}),
+	android.FixtureMergeMockFs(android.MockFS{
+		"tool":       nil,
+		"tool_file1": nil,
+		"tool_file2": nil,
+		"in1":        nil,
+		"in2":        nil,
+		"in1.txt":    nil,
+		"in2.txt":    nil,
+		"in3.txt":    nil,
+	}),
+)
 
-	RegisterGenruleBuildComponents(ctx)
-
-	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
-	ctx.Register()
-
-	return ctx
-}
-
-func testConfig(bp string, fs map[string][]byte) android.Config {
-	bp += `
+func testGenruleBp() string {
+	return `
 		tool {
 			name: "tool",
 		}
@@ -105,23 +112,6 @@
 			name: "empty",
 		}
 	`
-
-	mockFS := map[string][]byte{
-		"tool":       nil,
-		"tool_file1": nil,
-		"tool_file2": nil,
-		"in1":        nil,
-		"in2":        nil,
-		"in1.txt":    nil,
-		"in2.txt":    nil,
-		"in3.txt":    nil,
-	}
-
-	for k, v := range fs {
-		mockFS[k] = v
-	}
-
-	return android.TestArchConfig(buildDir, nil, bp, mockFS)
 }
 
 func TestGenruleCmd(t *testing.T) {
@@ -466,38 +456,28 @@
 			bp += test.prop
 			bp += "}\n"
 
-			config := testConfig(bp, nil)
-			config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
-
-			ctx := testContext(config)
-			ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
-
-			_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-			if errs == nil {
-				_, errs = ctx.PrepareBuildActions(config)
+			var expectedErrors []string
+			if test.err != "" {
+				expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
 			}
-			if errs == nil && test.err != "" {
-				t.Fatalf("want error %q, got no error", test.err)
-			} else if errs != nil && test.err == "" {
-				android.FailIfErrored(t, errs)
-			} else if test.err != "" {
-				if len(errs) != 1 {
-					t.Errorf("want 1 error, got %d errors:", len(errs))
-					for _, err := range errs {
-						t.Errorf("   %s", err.Error())
-					}
-					t.FailNow()
-				}
-				if !strings.Contains(errs[0].Error(), test.err) {
-					t.Fatalf("want %q, got %q", test.err, errs[0].Error())
-				}
+
+			result := genruleFixtureFactory.Extend(
+				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+					variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
+				}),
+				android.FixtureModifyContext(func(ctx *android.TestContext) {
+					ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
+				}),
+			).
+				ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
+				RunTestWithBp(t, testGenruleBp()+bp)
+
+			if expectedErrors != nil {
 				return
 			}
 
-			gen := ctx.ModuleForTests("gen", "").Module().(*Module)
-			if g, w := gen.rawCommands[0], test.expect; w != g {
-				t.Errorf("want %q, got %q", w, g)
-			}
+			gen := result.Module("gen", "").(*Module)
+			result.AssertStringEquals("raw commands", test.expect, gen.rawCommands[0])
 		})
 	}
 }
@@ -557,25 +537,16 @@
 		},
 	}
 
-	config := testConfig(bp, nil)
-	ctx := testContext(config)
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	if errs == nil {
-		_, errs = ctx.PrepareBuildActions(config)
-	}
-	if errs != nil {
-		t.Fatal(errs)
-	}
+	result := genruleFixtureFactory.RunTestWithBp(t, testGenruleBp()+bp)
 
 	for _, test := range testcases {
 		t.Run(test.name, func(t *testing.T) {
-			gen := ctx.ModuleForTests(test.name, "")
+			subResult := result.ResultForSubTest(t)
+			gen := subResult.ModuleForTests(test.name, "")
 			manifest := android.RuleBuilderSboxProtoForTests(t, gen.Output("genrule.sbox.textproto"))
 			hash := manifest.Commands[0].GetInputHash()
 
-			if g, w := hash, test.expectedHash; g != w {
-				t.Errorf("Expected has %q, got %q", w, g)
-			}
+			subResult.AssertStringEquals("hash", test.expectedHash, hash)
 		})
 	}
 }
@@ -630,46 +601,27 @@
 			bp += test.prop
 			bp += "}\n"
 
-			config := testConfig(bp, nil)
-			ctx := testContext(config)
-
-			_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-			if errs == nil {
-				_, errs = ctx.PrepareBuildActions(config)
+			var expectedErrors []string
+			if test.err != "" {
+				expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
 			}
-			if errs == nil && test.err != "" {
-				t.Fatalf("want error %q, got no error", test.err)
-			} else if errs != nil && test.err == "" {
-				android.FailIfErrored(t, errs)
-			} else if test.err != "" {
-				if len(errs) != 1 {
-					t.Errorf("want 1 error, got %d errors:", len(errs))
-					for _, err := range errs {
-						t.Errorf("   %s", err.Error())
-					}
-					t.FailNow()
-				}
-				if !strings.Contains(errs[0].Error(), test.err) {
-					t.Fatalf("want %q, got %q", test.err, errs[0].Error())
-				}
+
+			result := genruleFixtureFactory.
+				ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
+				RunTestWithBp(t, testGenruleBp()+bp)
+
+			if expectedErrors != nil {
 				return
 			}
 
-			gen := ctx.ModuleForTests("gen", "").Module().(*Module)
-			if g, w := gen.rawCommands, test.cmds; !reflect.DeepEqual(w, g) {
-				t.Errorf("want %q, got %q", w, g)
-			}
+			gen := result.Module("gen", "").(*Module)
+			result.AssertDeepEquals("cmd", test.cmds, gen.rawCommands)
 
-			if g, w := gen.outputDeps.Strings(), test.deps; !reflect.DeepEqual(w, g) {
-				t.Errorf("want deps %q, got %q", w, g)
-			}
+			result.AssertDeepEquals("deps", test.deps, gen.outputDeps.Strings())
 
-			if g, w := gen.outputFiles.Strings(), test.files; !reflect.DeepEqual(w, g) {
-				t.Errorf("want files %q, got %q", w, g)
-			}
+			result.AssertDeepEquals("files", test.files, gen.outputFiles.Strings())
 		})
 	}
-
 }
 
 func TestGenruleDefaults(t *testing.T) {
@@ -690,26 +642,16 @@
 					defaults: ["gen_defaults1", "gen_defaults2"],
 				}
 			`
-	config := testConfig(bp, nil)
-	ctx := testContext(config)
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	if errs == nil {
-		_, errs = ctx.PrepareBuildActions(config)
-	}
-	if errs != nil {
-		t.Fatal(errs)
-	}
-	gen := ctx.ModuleForTests("gen", "").Module().(*Module)
+
+	result := genruleFixtureFactory.RunTestWithBp(t, testGenruleBp()+bp)
+
+	gen := result.Module("gen", "").(*Module)
 
 	expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
-	if gen.rawCommands[0] != expectedCmd {
-		t.Errorf("Expected cmd: %q, actual: %q", expectedCmd, gen.rawCommands[0])
-	}
+	result.AssertStringEquals("cmd", expectedCmd, gen.rawCommands[0])
 
 	expectedSrcs := []string{"in1"}
-	if !reflect.DeepEqual(expectedSrcs, gen.properties.Srcs) {
-		t.Errorf("Expected srcs: %q, actual: %q", expectedSrcs, gen.properties.Srcs)
-	}
+	result.AssertDeepEquals("srcs", expectedSrcs, gen.properties.Srcs)
 }
 
 func TestGenruleWithBazel(t *testing.T) {
@@ -721,29 +663,18 @@
 		}
 	`
 
-	config := testConfig(bp, nil)
-	config.BazelContext = android.MockBazelContext{
-		AllFiles: map[string][]string{
-			"//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
+	result := genruleFixtureFactory.Extend(android.FixtureModifyConfig(func(config android.Config) {
+		config.BazelContext = android.MockBazelContext{
+			AllFiles: map[string][]string{
+				"//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
+	})).RunTestWithBp(t, testGenruleBp()+bp)
 
-	ctx := testContext(config)
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	if errs == nil {
-		_, errs = ctx.PrepareBuildActions(config)
-	}
-	if errs != nil {
-		t.Fatal(errs)
-	}
-	gen := ctx.ModuleForTests("foo", "").Module().(*Module)
+	gen := result.Module("foo", "").(*Module)
 
 	expectedOutputFiles := []string{"outputbase/execroot/__main__/bazelone.txt",
 		"outputbase/execroot/__main__/bazeltwo.txt"}
-	if !reflect.DeepEqual(gen.outputFiles.Strings(), expectedOutputFiles) {
-		t.Errorf("Expected output files: %q, actual: %q", expectedOutputFiles, gen.outputFiles)
-	}
-	if !reflect.DeepEqual(gen.outputDeps.Strings(), expectedOutputFiles) {
-		t.Errorf("Expected output deps: %q, actual: %q", expectedOutputFiles, gen.outputDeps)
-	}
+	result.AssertDeepEquals("output files", expectedOutputFiles, gen.outputFiles.Strings())
+	result.AssertDeepEquals("output deps", expectedOutputFiles, gen.outputDeps.Strings())
 }
 
 type testTool struct {
diff --git a/java/app.go b/java/app.go
index 2d918e9..e98fe31 100755
--- a/java/app.go
+++ b/java/app.go
@@ -122,8 +122,8 @@
 	// or an android_app_certificate module name in the form ":module".
 	Certificate *string
 
-	// Name of the signing certificate lineage file.
-	Lineage *string
+	// Name of the signing certificate lineage file or filegroup module.
+	Lineage *string `android:"path"`
 
 	// the package name of this app. The package name in the manifest file is used if one was not given.
 	Package_name *string
@@ -1280,6 +1280,14 @@
 	outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
 	statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
 
+	// Disable verify_uses_libraries check if dexpreopt is globally disabled. Without dexpreopt the
+	// check is not necessary, and although it is good to have, it is difficult to maintain on
+	// non-linux build platforms where dexpreopt is generally disabled (the check may fail due to
+	// various unrelated reasons, such as a failure to get manifest from an APK).
+	if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
+		return manifest
+	}
+
 	rule := android.NewRuleBuilder(pctx, ctx)
 	cmd := rule.Command().BuiltTool("manifest_check").
 		Flag("--enforce-uses-libraries").
@@ -1310,6 +1318,14 @@
 	outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
 	statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
 
+	// Disable verify_uses_libraries check if dexpreopt is globally disabled. Without dexpreopt the
+	// check is not necessary, and although it is good to have, it is difficult to maintain on
+	// non-linux build platforms where dexpreopt is generally disabled (the check may fail due to
+	// various unrelated reasons, such as a failure to get manifest from an APK).
+	if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
+		return apk
+	}
+
 	rule := android.NewRuleBuilder(pctx, ctx)
 	aapt := ctx.Config().HostToolPath(ctx, "aapt")
 	rule.Command().
diff --git a/java/app_import.go b/java/app_import.go
index d69dd10..d4da64d 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -67,12 +67,15 @@
 	// module name in the form ":module". Should be empty if presigned or default_dev_cert is set.
 	Certificate *string
 
+	// Names of extra android_app_certificate modules to sign the apk with in the form ":module".
+	Additional_certificates []string
+
 	// Set this flag to true if the prebuilt apk is already signed. The certificate property must not
 	// be set for presigned modules.
 	Presigned *bool
 
-	// Name of the signing certificate lineage file.
-	Lineage *string
+	// Name of the signing certificate lineage file or filegroup module.
+	Lineage *string `android:"path"`
 
 	// Sign with the default system dev certificate. Must be used judiciously. Most imported apps
 	// need to either specify a specific certificate or be presigned.
@@ -156,6 +159,16 @@
 		ctx.AddDependency(ctx.Module(), certificateTag, cert)
 	}
 
+	for _, cert := range a.properties.Additional_certificates {
+		cert = android.SrcIsModule(cert)
+		if cert != "" {
+			ctx.AddDependency(ctx.Module(), certificateTag, cert)
+		} else {
+			ctx.PropertyErrorf("additional_certificates",
+				`must be names of android_app_certificate modules in the form ":module"`)
+		}
+	}
+
 	a.usesLibrary.deps(ctx, !a.isPrebuiltFrameworkRes())
 }
 
@@ -303,9 +316,6 @@
 		// If the certificate property is empty at this point, default_dev_cert must be set to true.
 		// Which makes processMainCert's behavior for the empty cert string WAI.
 		certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
-		if len(certificates) != 1 {
-			ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
-		}
 		a.certificate = certificates[0]
 		signed := android.PathForModuleOut(ctx, "signed", apkFilename)
 		var lineageFile android.Path
diff --git a/java/app_import_test.go b/java/app_import_test.go
index dc31d07..cae41d0 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -109,14 +109,54 @@
 			name: "foo",
 			apk: "prebuilts/apk/app.apk",
 			certificate: "platform",
+			additional_certificates: [":additional_certificate"],
 			lineage: "lineage.bin",
 		}
+
+		android_app_certificate {
+			name: "additional_certificate",
+			certificate: "cert/additional_cert",
+		}
 	`)
 
 	variant := ctx.ModuleForTests("foo", "android_common")
 
-	// Check cert signing lineage flag.
 	signedApk := variant.Output("signed/foo.apk")
+	// Check certificates
+	certificatesFlag := signedApk.Args["certificates"]
+	expected := "build/make/target/product/security/platform.x509.pem " +
+		"build/make/target/product/security/platform.pk8 " +
+		"cert/additional_cert.x509.pem cert/additional_cert.pk8"
+	if expected != certificatesFlag {
+		t.Errorf("Incorrect certificates flags, expected: %q, got: %q", expected, certificatesFlag)
+	}
+	// Check cert signing lineage flag.
+	signingFlag := signedApk.Args["flags"]
+	expected = "--lineage lineage.bin"
+	if expected != signingFlag {
+		t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
+	}
+}
+
+func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
+	ctx, _ := testJava(t, `
+	  android_app_import {
+			name: "foo",
+			apk: "prebuilts/apk/app.apk",
+			certificate: "platform",
+			lineage: ":lineage_bin",
+		}
+
+		filegroup {
+			name: "lineage_bin",
+			srcs: ["lineage.bin"],
+		}
+	`)
+
+	variant := ctx.ModuleForTests("foo", "android_common")
+
+	signedApk := variant.Output("signed/foo.apk")
+	// Check cert signing lineage flag.
 	signingFlag := signedApk.Args["flags"]
 	expected := "--lineage lineage.bin"
 	if expected != signingFlag {
diff --git a/java/app_test.go b/java/app_test.go
index f41047a..78e1a57 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1576,6 +1576,31 @@
 			expectedLineage:     "--lineage lineage.bin",
 			expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
 		},
+		{
+			name: "lineage from filegroup",
+			bp: `
+				android_app {
+					name: "foo",
+					srcs: ["a.java"],
+					certificate: ":new_certificate",
+					lineage: ":lineage_bin",
+					sdk_version: "current",
+				}
+
+				android_app_certificate {
+					name: "new_certificate",
+					certificate: "cert/new_cert",
+				}
+
+				filegroup {
+					name: "lineage_bin",
+					srcs: ["lineage.bin"],
+				}
+			`,
+			certificateOverride: "",
+			expectedLineage:     "--lineage lineage.bin",
+			expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
+		},
 	}
 
 	for _, test := range testCases {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 8f1644c..f0decec 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1203,8 +1203,14 @@
 }
 
 func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
-	srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicitsRsp android.WritablePath, sandbox bool) *android.RuleBuilderCommand {
+	srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths,
+	implicitsRsp, homeDir android.WritablePath, sandbox bool) *android.RuleBuilderCommand {
+	rule.Command().Text("rm -rf").Flag(homeDir.String())
+	rule.Command().Text("mkdir -p").Flag(homeDir.String())
+
 	cmd := rule.Command()
+	cmd.FlagWithArg("ANDROID_SDK_HOME=", homeDir.String())
+
 	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA") {
 		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
 		pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "metalava")
@@ -1214,17 +1220,21 @@
 			execStrategy = remoteexec.LocalExecStrategy
 			labels["shallow"] = "true"
 		}
-		inputs := []string{android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "metalava.jar").String()}
+		inputs := []string{
+			ctx.Config().HostJavaToolPath(ctx, "metalava").String(),
+			homeDir.String(),
+		}
 		if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" {
 			inputs = append(inputs, strings.Split(v, ",")...)
 		}
 		cmd.Text((&remoteexec.REParams{
-			Labels:          labels,
-			ExecStrategy:    execStrategy,
-			Inputs:          inputs,
-			RSPFile:         implicitsRsp.String(),
-			ToolchainInputs: []string{config.JavaCmd(ctx).String()},
-			Platform:        map[string]string{remoteexec.PoolKey: pool},
+			Labels:               labels,
+			ExecStrategy:         execStrategy,
+			Inputs:               inputs,
+			RSPFile:              implicitsRsp.String(),
+			ToolchainInputs:      []string{config.JavaCmd(ctx).String()},
+			Platform:             map[string]string{remoteexec.PoolKey: pool},
+			EnvironmentVariables: []string{"ANDROID_SDK_HOME"},
 		}).NoVarTemplate(ctx.Config()))
 	}
 
@@ -1302,9 +1312,9 @@
 	srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
 
 	implicitsRsp := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"implicits.rsp")
-
+	homeDir := android.PathForModuleOut(ctx, "metalava-home")
 	cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
-		deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, implicitsRsp,
+		deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, implicitsRsp, homeDir,
 		Bool(d.Javadoc.properties.Sandbox))
 	cmd.Implicits(d.Javadoc.implicits)
 
diff --git a/java/java_test.go b/java/java_test.go
index 9112655..e8c4a0f 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -48,6 +48,26 @@
 	os.RemoveAll(buildDir)
 }
 
+// Factory to use to create fixtures for tests in this package.
+var javaFixtureFactory = android.NewFixtureFactory(
+	&buildDir,
+	genrule.PrepareForTestWithGenRuleBuildComponents,
+	// Get the CC build components but not default modules.
+	cc.PrepareForTestWithCcBuildComponents,
+	// Include all the default java modules.
+	PrepareForTestWithJavaDefaultModules,
+	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("java_plugin", PluginFactory)
+		ctx.RegisterModuleType("python_binary_host", python.PythonBinaryHostFactory)
+
+		ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
+		ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
+		ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
+	}),
+	javaMockFS().AddToFixture(),
+	dexpreopt.PrepareForTestWithDexpreopt,
+)
+
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
@@ -59,10 +79,20 @@
 	os.Exit(run())
 }
 
+// testConfig is a legacy way of creating a test Config for testing java modules.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
 	return TestConfig(buildDir, env, bp, fs)
 }
 
+// testContext is a legacy way of creating a TestContext for testing java modules.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testContext(config android.Config) *android.TestContext {
 
 	ctx := android.NewTestArchContext(config)
@@ -92,6 +122,11 @@
 	return ctx
 }
 
+// run is a legacy way of running tests of java modules.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func run(t *testing.T, ctx *android.TestContext, config android.Config) {
 	t.Helper()
 
@@ -105,23 +140,38 @@
 	android.FailIfErrored(t, errs)
 }
 
+// testJavaError is a legacy way of running tests of java modules that expect errors.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) {
 	t.Helper()
 	return testJavaErrorWithConfig(t, pattern, testConfig(nil, bp, nil))
 }
 
+// testJavaErrorWithConfig is a legacy way of running tests of java modules that expect errors.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testJavaErrorWithConfig(t *testing.T, pattern string, config android.Config) (*android.TestContext, android.Config) {
 	t.Helper()
-	ctx := testContext(config)
-
+	// This must be done on the supplied config and not as part of the fixture because any changes to
+	// the fixture's config will be ignored when RunTestWithConfig replaces it.
 	pathCtx := android.PathContextForTesting(config)
 	dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
-
-	runWithErrors(t, ctx, config, pattern)
-
-	return ctx, config
+	result := javaFixtureFactory.
+		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
+		RunTestWithConfig(t, config)
+	return result.TestContext, result.Config
 }
 
+// runWithErrors is a legacy way of running tests of java modules that expect errors.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func runWithErrors(t *testing.T, ctx *android.TestContext, config android.Config, pattern string) {
 	ctx.Register()
 	_, errs := ctx.ParseBlueprintsFiles("Android.bp")
@@ -139,22 +189,43 @@
 	return
 }
 
-func testJavaWithFS(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) {
+// testJavaWithFS runs tests using the javaFixtureFactory
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
+func testJavaWithFS(t *testing.T, bp string, fs android.MockFS) (*android.TestContext, android.Config) {
 	t.Helper()
-	return testJavaWithConfig(t, testConfig(nil, bp, fs))
+	result := javaFixtureFactory.Extend(fs.AddToFixture()).RunTestWithBp(t, bp)
+	return result.TestContext, result.Config
 }
 
+// testJava runs tests using the javaFixtureFactory
+//
+// Do not add any new usages of this, instead use the javaFixtureFactory directly as it makes it
+// much easier to customize the test behavior.
+//
+// If it is necessary to customize the behavior of an existing test that uses this then please first
+// convert the test to using javaFixtureFactory first and then in a following change add the
+// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
+// that it did not change the test behavior unexpectedly.
+//
+// deprecated
 func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) {
 	t.Helper()
-	return testJavaWithFS(t, bp, nil)
+	result := javaFixtureFactory.RunTestWithBp(t, bp)
+	return result.TestContext, result.Config
 }
 
+// testJavaWithConfig runs tests using the javaFixtureFactory
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
 func testJavaWithConfig(t *testing.T, config android.Config) (*android.TestContext, android.Config) {
 	t.Helper()
-	ctx := testContext(config)
-	run(t, ctx, config)
-
-	return ctx, config
+	result := javaFixtureFactory.RunTestWithConfig(t, config)
+	return result.TestContext, result.Config
 }
 
 func moduleToPath(name string) string {
@@ -168,6 +239,12 @@
 	}
 }
 
+// defaultModuleToPath constructs a path to the turbine generate jar for a default test module that
+// is defined in PrepareForIntegrationTestWithJava
+func defaultModuleToPath(name string) string {
+	return filepath.Join(buildDir, ".intermediates", defaultJavaDir, name, "android_common", "turbine-combined", name+".jar")
+}
+
 func TestJavaLinkType(t *testing.T) {
 	testJava(t, `
 		java_library {
@@ -2352,7 +2429,7 @@
 		expected := "java.base=.:" + buildDir
 		checkPatchModuleFlag(t, ctx, "bar", expected)
 		expected = "java.base=" + strings.Join([]string{
-			".", buildDir, "dir", "dir2", "nested", moduleToPath("ext"), moduleToPath("framework")}, ":")
+			".", buildDir, "dir", "dir2", "nested", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":")
 		checkPatchModuleFlag(t, ctx, "baz", expected)
 	})
 }
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 021920a..874338d 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -19,10 +19,6 @@
 	"android/soong/java/config"
 )
 
-// This variable is effectively unused in pre-master branches, and is
-// included (with the same value as it has in AOSP) only to ease
-// merges between branches (see the comment in the
-// useLegacyCorePlatformApi() function):
 var legacyCorePlatformApiModules = []string{
 	"ahat-test-dump",
 	"android.car",
@@ -34,29 +30,44 @@
 	"art_cts_jvmti_test_library",
 	"art-gtest-jars-MyClassNatives",
 	"BackupFrameworksServicesRoboTests",
+	"backuplib",
 	"BandwidthEnforcementTest",
 	"BlockedNumberProvider",
 	"BluetoothInstrumentationTests",
 	"BluetoothMidiService",
+	"CarDeveloperOptions",
+	"CarService",
+	"CarServiceTest",
 	"car-apps-common",
+	"car-service-test-lib",
+	"car-service-test-static-lib",
 	"CertInstaller",
 	"ConnectivityManagerTest",
 	"ContactsProvider",
+	"CorePerfTests",
 	"core-tests-support",
+	"CtsAppExitTestCases",
 	"CtsContentTestCases",
 	"CtsIkeTestCases",
+	"CtsAppExitTestCases",
 	"CtsLibcoreWycheproofBCTestCases",
 	"CtsMediaTestCases",
 	"CtsNetTestCases",
 	"CtsNetTestCasesLatestSdk",
 	"CtsSecurityTestCases",
+	"CtsSuspendAppsTestCases",
 	"CtsUsageStatsTestCases",
+	"DeadpoolService",
+	"DeadpoolServiceBtServices",
+	"DeviceInfo",
+	"DiagnosticTools",
 	"DisplayCutoutEmulationEmu01Overlay",
 	"DocumentsUIPerfTests",
 	"DocumentsUITests",
 	"DownloadProvider",
 	"DownloadProviderTests",
 	"DownloadProviderUi",
+	"ds-car-docs", // for AAOS API documentation only
 	"DynamicSystemInstallationService",
 	"EmergencyInfo-lib",
 	"ethernet-service",
@@ -73,6 +84,7 @@
 	"FrameworksServicesRoboTests",
 	"FrameworksServicesTests",
 	"FrameworksUtilTests",
+	"FrameworksWifiTests",
 	"hid",
 	"hidl_test_java_java",
 	"hwbinder",
@@ -95,6 +107,9 @@
 	"platform_library-docs",
 	"PrintSpooler",
 	"RollbackTest",
+	"service-blobstore",
+	"service-connectivity",
+	"service-jobscheduler",
 	"services",
 	"services.accessibility",
 	"services.backup",
@@ -136,10 +151,6 @@
 	"wifi-service",
 }
 
-// This variable is effectively unused in pre-master branches, and is
-// included (with the same value as it has in AOSP) only to ease
-// merges between branches (see the comment in the
-// useLegacyCorePlatformApi() function):
 var legacyCorePlatformApiLookup = make(map[string]struct{})
 
 func init() {
@@ -149,12 +160,8 @@
 }
 
 func useLegacyCorePlatformApi(ctx android.EarlyModuleContext) bool {
-	// In pre-master branches, we don't attempt to force usage of the stable
-	// version of the core/platform API. Instead, we always use the legacy
-	// version --- except in tests, where we always use stable, so that we
-	// can make the test assertions the same as other branches.
-	// This should be false in tests and true otherwise:
-	return ctx.Config().TestProductVariables == nil
+	_, found := legacyCorePlatformApiLookup[ctx.ModuleName()]
+	return found
 }
 
 func corePlatformSystemModules(ctx android.EarlyModuleContext) string {
diff --git a/java/lint.go b/java/lint.go
index 50b84dc..5940eac 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -22,6 +22,8 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/java/config"
+	"android/soong/remoteexec"
 )
 
 type LintProperties struct {
@@ -172,8 +174,40 @@
 		extraLintCheckTag, extraCheckModules...)
 }
 
-func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
-	rule *android.RuleBuilder) (projectXMLPath, configXMLPath, cacheDir, homeDir android.WritablePath, deps android.Paths) {
+// lintPaths contains the paths to lint's inputs and outputs to make it easier to pass them
+// around.
+type lintPaths struct {
+	projectXML android.WritablePath
+	configXML  android.WritablePath
+	cacheDir   android.WritablePath
+	homeDir    android.WritablePath
+	srcjarDir  android.WritablePath
+
+	deps android.Paths
+
+	remoteInputs    android.Paths
+	remoteRSPInputs android.Paths
+}
+
+func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder) lintPaths {
+	var deps android.Paths
+	var remoteInputs android.Paths
+	var remoteRSPInputs android.Paths
+
+	// Paths passed to trackInputDependency will be added as dependencies of the rule that runs
+	// lint and passed as inputs to the remote execution proxy.
+	trackInputDependency := func(paths ...android.Path) {
+		deps = append(deps, paths...)
+		remoteInputs = append(remoteInputs, paths...)
+	}
+
+	// Paths passed to trackRSPDependency will be added as dependencies of the rule that runs
+	// lint, but the RSP file will be used by the remote execution proxy to find the files so that
+	// it doesn't overflow command line limits.
+	trackRSPDependency := func(paths android.Paths, rsp android.Path) {
+		deps = append(deps, paths...)
+		remoteRSPInputs = append(remoteRSPInputs, rsp)
+	}
 
 	var resourcesList android.WritablePath
 	if len(l.resources) > 0 {
@@ -184,17 +218,27 @@
 		resListRule := android.NewRuleBuilder(pctx, ctx)
 		resListRule.Command().Text("cp").FlagWithRspFileInputList("", l.resources).Output(resourcesList)
 		resListRule.Build("lint_resources_list", "lint resources list")
-		deps = append(deps, l.resources...)
+		trackRSPDependency(l.resources, resourcesList)
 	}
 
-	projectXMLPath = android.PathForModuleOut(ctx, "lint", "project.xml")
+	projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml")
 	// Lint looks for a lint.xml file next to the project.xml file, give it one.
-	configXMLPath = android.PathForModuleOut(ctx, "lint", "lint.xml")
-	cacheDir = android.PathForModuleOut(ctx, "lint", "cache")
-	homeDir = android.PathForModuleOut(ctx, "lint", "home")
+	configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml")
+	cacheDir := android.PathForModuleOut(ctx, "lint", "cache")
+	homeDir := android.PathForModuleOut(ctx, "lint", "home")
 
 	srcJarDir := android.PathForModuleOut(ctx, "lint-srcjars")
 	srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars)
+	// TODO(ccross): this is a little fishy.  The files extracted from the srcjars are referenced
+	// by the project.xml and used by the later lint rule, but the lint rule depends on the srcjars,
+	// not the extracted files.
+	trackRSPDependency(l.srcJars, srcJarList)
+
+	// TODO(ccross): some of the files in l.srcs are generated sources and should be passed to
+	// lint separately.
+	srcsList := android.PathForModuleOut(ctx, "lint", "srcs.list")
+	rule.Command().Text("cp").FlagWithRspFileInputList("", l.srcs).Output(srcsList)
+	trackRSPDependency(l.srcs, srcsList)
 
 	cmd := rule.Command().
 		BuiltTool("lint-project-xml").
@@ -209,38 +253,39 @@
 		cmd.Flag("--test")
 	}
 	if l.manifest != nil {
-		deps = append(deps, l.manifest)
 		cmd.FlagWithArg("--manifest ", l.manifest.String())
+		trackInputDependency(l.manifest)
 	}
 	if l.mergedManifest != nil {
-		deps = append(deps, l.mergedManifest)
 		cmd.FlagWithArg("--merged_manifest ", l.mergedManifest.String())
+		trackInputDependency(l.mergedManifest)
 	}
 
-	// TODO(ccross): some of the files in l.srcs are generated sources and should be passed to
-	// lint separately.
-	cmd.FlagWithRspFileInputList("--srcs ", l.srcs)
-	deps = append(deps, l.srcs...)
+	cmd.FlagWithInput("--srcs ", srcsList)
 
 	cmd.FlagWithInput("--generated_srcs ", srcJarList)
-	deps = append(deps, l.srcJars...)
 
 	if resourcesList != nil {
 		cmd.FlagWithInput("--resources ", resourcesList)
 	}
 
 	if l.classes != nil {
-		deps = append(deps, l.classes)
 		cmd.FlagWithArg("--classes ", l.classes.String())
+		trackInputDependency(l.classes)
 	}
 
 	cmd.FlagForEachArg("--classpath ", l.classpath.Strings())
-	deps = append(deps, l.classpath...)
+	trackInputDependency(l.classpath...)
 
 	cmd.FlagForEachArg("--extra_checks_jar ", l.extraLintCheckJars.Strings())
-	deps = append(deps, l.extraLintCheckJars...)
+	trackInputDependency(l.extraLintCheckJars...)
 
-	cmd.FlagWithArg("--root_dir ", "$PWD")
+	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") {
+		// TODO(b/181912787): remove these and use "." instead.
+		cmd.FlagWithArg("--root_dir ", "/b/f/w")
+	} else {
+		cmd.FlagWithArg("--root_dir ", "$PWD")
+	}
 
 	// The cache tag in project.xml is relative to the root dir, or the project.xml file if
 	// the root dir is not set.
@@ -254,7 +299,18 @@
 	cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
 	cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
 
-	return projectXMLPath, configXMLPath, cacheDir, homeDir, deps
+	return lintPaths{
+		projectXML: projectXMLPath,
+		configXML:  configXMLPath,
+		cacheDir:   cacheDir,
+		homeDir:    homeDir,
+
+		deps: deps,
+
+		remoteInputs:    remoteInputs,
+		remoteRSPInputs: remoteRSPInputs,
+	}
+
 }
 
 // generateManifest adds a command to the rule to write a simple manifest that contains the
@@ -297,7 +353,7 @@
 		l.manifest = manifest
 	}
 
-	projectXML, lintXML, cacheDir, homeDir, deps := l.writeLintProjectXML(ctx, rule)
+	lintPaths := l.writeLintProjectXML(ctx, rule)
 
 	html := android.PathForModuleOut(ctx, "lint-report.html")
 	text := android.PathForModuleOut(ctx, "lint-report.txt")
@@ -311,8 +367,8 @@
 		}
 	})
 
-	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 -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
+	rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
 	rule.Command().Text("rm -f").Output(html).Output(text).Output(xml)
 
 	var annotationsZipPath, apiVersionsXMLPath android.Path
@@ -324,16 +380,52 @@
 		apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
 	}
 
-	cmd := rule.Command().
-		Text("(").
-		Flag("JAVA_OPTS=-Xmx3072m").
-		FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()).
+	cmd := rule.Command()
+
+	cmd.Flag("JAVA_OPTS=-Xmx3072m").
+		FlagWithArg("ANDROID_SDK_HOME=", lintPaths.homeDir.String()).
 		FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
-		FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath).
-		BuiltTool("lint").
+		FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath)
+
+	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") {
+		pool := ctx.Config().GetenvWithDefault("RBE_LINT_POOL", "java16")
+		// TODO(b/181912787): this should be local fallback once the hack that passes /b/f/w in project.xml
+		// is removed.
+		execStrategy := ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.RemoteExecStrategy)
+		labels := map[string]string{"type": "tool", "name": "lint"}
+		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
+		remoteInputs := lintPaths.remoteInputs
+		remoteInputs = append(remoteInputs,
+			lintPaths.projectXML,
+			lintPaths.configXML,
+			lintPaths.homeDir,
+			lintPaths.cacheDir,
+			ctx.Config().HostJavaToolPath(ctx, "lint.jar"),
+			annotationsZipPath,
+			apiVersionsXMLPath,
+		)
+
+		cmd.Text((&remoteexec.REParams{
+			Labels:          labels,
+			ExecStrategy:    execStrategy,
+			ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+			Inputs:          remoteInputs.Strings(),
+			OutputFiles:     android.Paths{html, text, xml}.Strings(),
+			RSPFile:         strings.Join(lintPaths.remoteRSPInputs.Strings(), ","),
+			EnvironmentVariables: []string{
+				"JAVA_OPTS",
+				"ANDROID_SDK_HOME",
+				"SDK_ANNOTATIONS",
+				"LINT_OPTS",
+			},
+			Platform: map[string]string{remoteexec.PoolKey: pool},
+		}).NoVarTemplate(ctx.Config()))
+	}
+
+	cmd.BuiltTool("lint").
 		Flag("--quiet").
-		FlagWithInput("--project ", projectXML).
-		FlagWithInput("--config ", lintXML).
+		FlagWithInput("--project ", lintPaths.projectXML).
+		FlagWithInput("--config ", lintPaths.configXML).
 		FlagWithOutput("--html ", html).
 		FlagWithOutput("--text ", text).
 		FlagWithOutput("--xml ", xml).
@@ -343,7 +435,9 @@
 		FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
 		Flag("--exitcode").
 		Flags(l.properties.Lint.Flags).
-		Implicits(deps)
+		Implicit(annotationsZipPath).
+		Implicit(apiVersionsXMLPath).
+		Implicits(lintPaths.deps)
 
 	if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
 		cmd.FlagWithArg("--check ", checkOnly)
@@ -362,9 +456,9 @@
 		}
 	}
 
-	cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)").Text(")")
+	cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)")
 
-	rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
+	rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
 
 	rule.Build("lint", "lint")
 
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/testing.go b/java/testing.go
index bfa1e6b..4e1997e 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -29,10 +29,40 @@
 	"github.com/google/blueprint"
 )
 
-func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) android.Config {
-	bp += GatherRequiredDepsForTest()
+const defaultJavaDir = "default/java"
 
-	mockFS := map[string][]byte{
+// Test fixture preparer that will register most java build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of java
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+var PrepareForTestWithJavaBuildComponents = android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest)
+
+// Test fixture preparer that will define default java modules, e.g. standard prebuilt modules.
+var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers(
+	// Make sure that mutators and module types, e.g. prebuilt mutators available.
+	android.PrepareForTestWithAndroidBuildComponents,
+	// Make sure that all the module types used in the defaults are registered.
+	PrepareForTestWithJavaBuildComponents,
+	// The java default module definitions.
+	android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", GatherRequiredDepsForTest()),
+)
+
+// Prepare a fixture to use all java module types, mutators and singletons fully.
+//
+// This should only be used by tests that want to run with as much of the build enabled as possible.
+var PrepareForIntegrationTestWithJava = android.GroupFixturePreparers(
+	cc.PrepareForIntegrationTestWithCc,
+	PrepareForTestWithJavaDefaultModules,
+)
+
+func javaMockFS() android.MockFS {
+	mockFS := android.MockFS{
 		"api/current.txt":        nil,
 		"api/removed.txt":        nil,
 		"api/system-current.txt": nil,
@@ -64,6 +94,14 @@
 		mockFS[k] = v
 	}
 
+	return mockFS
+}
+
+func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) android.Config {
+	bp += GatherRequiredDepsForTest()
+
+	mockFS := javaMockFS()
+
 	cc.GatherRequiredFilesForTest(mockFS)
 
 	for k, v := range fs {
diff --git a/python/binary.go b/python/binary.go
index 416a7ee..372b8a8 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -20,10 +20,92 @@
 	"fmt"
 
 	"android/soong/android"
+	"android/soong/bazel"
+
+	"github.com/google/blueprint/proptools"
 )
 
 func init() {
 	android.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
+	android.RegisterBp2BuildMutator("python_binary_host", PythonBinaryBp2Build)
+}
+
+type bazelPythonBinaryAttributes struct {
+	Main           string
+	Srcs           bazel.LabelList
+	Data           bazel.LabelList
+	Python_version string
+}
+
+type bazelPythonBinary struct {
+	android.BazelTargetModuleBase
+	bazelPythonBinaryAttributes
+}
+
+func BazelPythonBinaryFactory() android.Module {
+	module := &bazelPythonBinary{}
+	module.AddProperties(&module.bazelPythonBinaryAttributes)
+	android.InitBazelTargetModule(module)
+	return module
+}
+
+func (m *bazelPythonBinary) Name() string {
+	return m.BaseModuleName()
+}
+
+func (m *bazelPythonBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
+
+func PythonBinaryBp2Build(ctx android.TopDownMutatorContext) {
+	m, ok := ctx.Module().(*Module)
+	if !ok || !m.ConvertWithBp2build() {
+		return
+	}
+
+	// a Module can be something other than a python_binary_host
+	if ctx.ModuleType() != "python_binary_host" {
+		return
+	}
+
+	var main string
+	for _, propIntf := range m.GetProperties() {
+		if props, ok := propIntf.(*BinaryProperties); ok {
+			// main is optional.
+			if props.Main != nil {
+				main = *props.Main
+				break
+			}
+		}
+	}
+	// TODO(b/182306917): this doesn't fully handle all nested props versioned
+	// by the python version, which would have been handled by the version split
+	// mutator. This is sufficient for very simple python_binary_host modules
+	// under Bionic.
+	py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
+	py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
+	var python_version string
+	if py3Enabled && py2Enabled {
+		panic(fmt.Errorf(
+			"error for '%s' module: bp2build's python_binary_host converter does not support "+
+				"converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name()))
+	} else if py2Enabled {
+		python_version = "PY2"
+	} else {
+		// do nothing, since python_version defaults to PY3.
+	}
+
+	attrs := &bazelPythonBinaryAttributes{
+		Main:           main,
+		Srcs:           android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs),
+		Data:           android.BazelLabelForModuleSrc(ctx, m.properties.Data),
+		Python_version: python_version,
+	}
+
+	props := bazel.BazelTargetModuleProperties{
+		// Use the native py_binary rule.
+		Rule_class: "py_binary",
+	}
+
+	ctx.CreateBazelTargetModule(BazelPythonBinaryFactory, m.Name(), props, attrs)
 }
 
 type BinaryProperties struct {
@@ -81,6 +163,8 @@
 func PythonBinaryHostFactory() android.Module {
 	module, _ := NewBinary(android.HostSupported)
 
+	android.InitBazelModule(module)
+
 	return module.init()
 }
 
diff --git a/python/python.go b/python/python.go
index b3e3d13..a078c0b 100644
--- a/python/python.go
+++ b/python/python.go
@@ -125,6 +125,7 @@
 type Module struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.BazelModuleBase
 
 	properties      BaseProperties
 	protoProperties android.ProtoProperties
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index d6e2c0a..5f0426a 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -81,6 +81,9 @@
 	// ToolchainInputs is a list of paths or ninja variables pointing to the location of
 	// toolchain binaries used by the rule.
 	ToolchainInputs []string
+	// EnvironmentVariables is a list of environment variables whose values should be passed through
+	// to the remote execution.
+	EnvironmentVariables []string
 }
 
 func init() {
@@ -162,6 +165,10 @@
 		args += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
 	}
 
+	if len(r.EnvironmentVariables) > 0 {
+		args += " --env_var_allowlist=" + strings.Join(r.EnvironmentVariables, ",")
+	}
+
 	return args + " -- "
 }
 
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index fc11d29..408d433 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -14,6 +14,7 @@
 		"external/rust",
 		"external/vm_tools/p9",
 		"frameworks/native/libs/binder/rust",
+		"frameworks/proto_logging/stats",
 		"packages/modules/DnsResolver",
 		"packages/modules/Virtualization",
 		"prebuilts/rust",
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index 0813f1a..18174a4 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -36,8 +36,9 @@
 # List of libraries installed on the platform that are needed for ART chroot
 # testing.
 PLATFORM_LIBRARIES=(
-  liblog
+  heapprofd_client_api
   libartpalette-system
+  liblog
 )
 
 # We want to create apex modules for all supported architectures.
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
index e1edc51..a7164a5 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -54,7 +54,7 @@
 	return str
 }
 
-func checkPropertySetFixture(h *TestHelper, val interface{}, hasTags bool) {
+func checkPropertySetFixture(h android.TestHelper, val interface{}, hasTags bool) {
 	set := val.(*bpPropertySet)
 	h.AssertDeepEquals("wrong x value", "taxi", set.getValue("x"))
 	h.AssertDeepEquals("wrong y value", 1729, set.getValue("y"))
@@ -73,7 +73,7 @@
 }
 
 func TestAddPropertySimple(t *testing.T) {
-	h := &TestHelper{t}
+	h := android.TestHelper{t}
 	set := newPropertySet()
 	for name, val := range map[string]interface{}{
 		"x":   "taxi",
@@ -92,7 +92,7 @@
 }
 
 func TestAddPropertySubset(t *testing.T) {
-	h := &TestHelper{t}
+	h := android.TestHelper{t}
 	getFixtureMap := map[string]func() interface{}{
 		"property set":    propertySetFixture,
 		"property struct": propertyStructFixture,
@@ -139,7 +139,7 @@
 }
 
 func TestAddPropertySetNew(t *testing.T) {
-	h := &TestHelper{t}
+	h := android.TestHelper{t}
 	set := newPropertySet()
 	subset := set.AddPropertySet("sub")
 	subset.AddProperty("new", "d^^b")
@@ -147,7 +147,7 @@
 }
 
 func TestAddPropertySetExisting(t *testing.T) {
-	h := &TestHelper{t}
+	h := android.TestHelper{t}
 	set := propertySetFixture().(*bpPropertySet)
 	subset := set.AddPropertySet("sub")
 	subset.AddProperty("new", "d^^b")
@@ -181,7 +181,7 @@
 
 func TestTransformRemoveProperty(t *testing.T) {
 
-	helper := &TestHelper{t}
+	helper := android.TestHelper{t}
 
 	set := newPropertySet()
 	set.AddProperty("name", "name")
@@ -196,7 +196,7 @@
 
 func TestTransformRemovePropertySet(t *testing.T) {
 
-	helper := &TestHelper{t}
+	helper := android.TestHelper{t}
 
 	set := newPropertySet()
 	set.AddProperty("name", "name")
diff --git a/sdk/exports.go b/sdk/exports.go
index d313057..9a0ba4e 100644
--- a/sdk/exports.go
+++ b/sdk/exports.go
@@ -17,8 +17,12 @@
 import "android/soong/android"
 
 func init() {
-	android.RegisterModuleType("module_exports", ModuleExportsFactory)
-	android.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
+	registerModuleExportsBuildComponents(android.InitRegistrationContext)
+}
+
+func registerModuleExportsBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("module_exports", ModuleExportsFactory)
+	ctx.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
 }
 
 // module_exports defines the exports of a mainline module. The exports are Soong modules
diff --git a/sdk/sdk.go b/sdk/sdk.go
index f3d0750..2c84a2e 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -33,10 +33,14 @@
 	pctx.Import("android/soong/android")
 	pctx.Import("android/soong/java/config")
 
-	android.RegisterModuleType("sdk", SdkModuleFactory)
-	android.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
-	android.PreDepsMutators(RegisterPreDepsMutators)
-	android.PostDepsMutators(RegisterPostDepsMutators)
+	registerSdkBuildComponents(android.InitRegistrationContext)
+}
+
+func registerSdkBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("sdk", SdkModuleFactory)
+	ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
+	ctx.PreDepsMutators(RegisterPreDepsMutators)
+	ctx.PostDepsMutators(RegisterPostDepsMutators)
 }
 
 type sdk struct {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index c4dc41b..a7acd0c 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -309,16 +309,13 @@
 `)
 }
 
-func TestSDkInstall(t *testing.T) {
+func TestSdkInstall(t *testing.T) {
 	sdk := `
 		sdk {
 			name: "mysdk",
 		}
 	`
-	result := testSdkWithFs(t, ``,
-		map[string][]byte{
-			"Android.bp": []byte(sdk),
-		})
+	result := testSdkWithFs(t, sdk, nil)
 
 	result.CheckSnapshot("mysdk", "",
 		checkAllOtherCopyRules(`.intermediates/mysdk/common_os/mysdk-current.zip -> mysdk-current.zip`),
@@ -390,7 +387,7 @@
 
 	extractor := newCommonValueExtractor(common)
 
-	h := TestHelper{t}
+	h := android.TestHelper{t}
 
 	err := extractor.extractCommonProperties(common, structs)
 	h.AssertDeepEquals("unexpected error", nil, err)
@@ -465,7 +462,7 @@
 
 	extractor := newCommonValueExtractor(common)
 
-	h := TestHelper{t}
+	h := android.TestHelper{t}
 
 	err := extractor.extractCommonProperties(common, structs)
 	h.AssertErrorMessageEquals("unexpected error", `field "S_Common" is not tagged as "arch_variant" but has arch specific properties:
diff --git a/sdk/testing.go b/sdk/testing.go
index 7a2540a..e291bdb 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -19,7 +19,6 @@
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"reflect"
 	"strings"
 	"testing"
 
@@ -122,12 +121,8 @@
 	ctx.PostDepsMutators(apex.RegisterPostDepsMutators)
 
 	// from this package
-	ctx.RegisterModuleType("sdk", SdkModuleFactory)
-	ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
-	ctx.RegisterModuleType("module_exports", ModuleExportsFactory)
-	ctx.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
-	ctx.PreDepsMutators(RegisterPreDepsMutators)
-	ctx.PostDepsMutators(RegisterPostDepsMutators)
+	registerModuleExportsBuildComponents(ctx)
+	registerSdkBuildComponents(ctx)
 
 	ctx.Register()
 
@@ -141,7 +136,7 @@
 	_, errs = ctx.PrepareBuildActions(config)
 	android.FailIfErrored(t, errs)
 	return &testSdkResult{
-		TestHelper: TestHelper{t: t},
+		TestHelper: android.TestHelper{T: t},
 		ctx:        ctx,
 		config:     config,
 	}
@@ -185,63 +180,10 @@
 	return ret
 }
 
-// Provides general test support.
-type TestHelper struct {
-	t *testing.T
-}
-
-func (h *TestHelper) AssertStringEquals(message string, expected string, actual string) {
-	h.t.Helper()
-	if actual != expected {
-		h.t.Errorf("%s: expected %s, actual %s", message, expected, actual)
-	}
-}
-
-func (h *TestHelper) AssertErrorMessageEquals(message string, expected string, actual error) {
-	h.t.Helper()
-	if actual == nil {
-		h.t.Errorf("Expected error but was nil")
-	} else if actual.Error() != expected {
-		h.t.Errorf("%s: expected %s, actual %s", message, expected, actual.Error())
-	}
-}
-
-func (h *TestHelper) AssertTrimmedStringEquals(message string, expected string, actual string) {
-	h.t.Helper()
-	expected = strings.TrimSpace(expected)
-	actual = strings.TrimSpace(actual)
-	if actual != expected {
-		h.t.Errorf("%s: expected:\n%s\nactual:\n%s\n", message, expected, actual)
-	}
-}
-
-func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actual interface{}) {
-	h.t.Helper()
-	if !reflect.DeepEqual(actual, expected) {
-		h.t.Errorf("%s: expected %#v, actual %#v", message, expected, actual)
-	}
-}
-
-func (h *TestHelper) AssertPanic(message string, funcThatShouldPanic func()) {
-	h.t.Helper()
-	panicked := false
-	func() {
-		defer func() {
-			if x := recover(); x != nil {
-				panicked = true
-			}
-		}()
-		funcThatShouldPanic()
-	}()
-	if !panicked {
-		h.t.Error(message)
-	}
-}
-
 // Encapsulates result of processing an SDK definition. Provides support for
 // checking the state of the build structures.
 type testSdkResult struct {
-	TestHelper
+	android.TestHelper
 	ctx    *android.TestContext
 	config android.Config
 }
@@ -295,7 +237,7 @@
 			info.intermediateZip = info.outputZip
 			mergeInput := android.NormalizePathForTesting(bp.Input)
 			if info.intermediateZip != mergeInput {
-				r.t.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead",
+				r.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead",
 					info.intermediateZip, mergeInput)
 			}
 
@@ -328,7 +270,7 @@
 // Allows each test to customize what is checked without duplicating lots of code
 // or proliferating check methods of different flavors.
 func (r *testSdkResult) CheckSnapshot(name string, dir string, checkers ...snapshotBuildInfoChecker) {
-	r.t.Helper()
+	r.Helper()
 
 	// The sdk CommonOS variant is always responsible for generating the snapshot.
 	variant := android.CommonOS.Name
@@ -358,7 +300,7 @@
 	}
 
 	// Process the generated bp file to make sure it is valid.
-	testSdkWithFs(r.t, snapshotBuildInfo.androidBpContents, fs)
+	testSdkWithFs(r.T, snapshotBuildInfo.androidBpContents, fs)
 }
 
 type snapshotBuildInfoChecker func(info *snapshotBuildInfo)
@@ -368,7 +310,7 @@
 // Both the expected and actual string are both trimmed before comparing.
 func checkAndroidBpContents(expected string) snapshotBuildInfoChecker {
 	return func(info *snapshotBuildInfo) {
-		info.r.t.Helper()
+		info.r.Helper()
 		info.r.AssertTrimmedStringEquals("Android.bp contents do not match", expected, info.androidBpContents)
 	}
 }
@@ -380,7 +322,7 @@
 // Both the expected and actual string are both trimmed before comparing.
 func checkUnversionedAndroidBpContents(expected string) snapshotBuildInfoChecker {
 	return func(info *snapshotBuildInfo) {
-		info.r.t.Helper()
+		info.r.Helper()
 		info.r.AssertTrimmedStringEquals("unversioned Android.bp contents do not match", expected, info.androidUnversionedBpContents)
 	}
 }
@@ -395,7 +337,7 @@
 // Both the expected and actual string are both trimmed before comparing.
 func checkVersionedAndroidBpContents(expected string) snapshotBuildInfoChecker {
 	return func(info *snapshotBuildInfo) {
-		info.r.t.Helper()
+		info.r.Helper()
 		info.r.AssertTrimmedStringEquals("versioned Android.bp contents do not match", expected, info.androidVersionedBpContents)
 	}
 }
@@ -407,14 +349,14 @@
 // before comparing.
 func checkAllCopyRules(expected string) snapshotBuildInfoChecker {
 	return func(info *snapshotBuildInfo) {
-		info.r.t.Helper()
+		info.r.Helper()
 		info.r.AssertTrimmedStringEquals("Incorrect copy rules", expected, info.copyRules)
 	}
 }
 
 func checkAllOtherCopyRules(expected string) snapshotBuildInfoChecker {
 	return func(info *snapshotBuildInfo) {
-		info.r.t.Helper()
+		info.r.Helper()
 		info.r.AssertTrimmedStringEquals("Incorrect copy rules", expected, info.otherCopyRules)
 	}
 }
@@ -422,9 +364,9 @@
 // Check that the specified paths match the list of zips to merge with the intermediate zip.
 func checkMergeZips(expected ...string) snapshotBuildInfoChecker {
 	return func(info *snapshotBuildInfo) {
-		info.r.t.Helper()
+		info.r.Helper()
 		if info.intermediateZip == "" {
-			info.r.t.Errorf("No intermediate zip file was created")
+			info.r.Errorf("No intermediate zip file was created")
 		}
 
 		info.r.AssertDeepEquals("mismatching merge zip files", expected, info.mergeZips)
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 031cd47..49f4961 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -40,14 +40,32 @@
 func init() {
 	pctx.Import("android/soong/android")
 
-	android.RegisterModuleType("sh_binary", ShBinaryFactory)
-	android.RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
-	android.RegisterModuleType("sh_test", ShTestFactory)
-	android.RegisterModuleType("sh_test_host", ShTestHostFactory)
+	registerShBuildComponents(android.InitRegistrationContext)
 
 	android.RegisterBp2BuildMutator("sh_binary", ShBinaryBp2Build)
 }
 
+func registerShBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("sh_binary", ShBinaryFactory)
+	ctx.RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
+	ctx.RegisterModuleType("sh_test", ShTestFactory)
+	ctx.RegisterModuleType("sh_test_host", ShTestHostFactory)
+}
+
+// Test fixture preparer that will register most sh build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of sh
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+var PrepareForTestWithShBuildComponents = android.GroupFixturePreparers(
+	android.FixtureRegisterWithContext(registerShBuildComponents),
+)
+
 type shBinaryProperties struct {
 	// Source file of this prebuilt.
 	Src *string `android:"path,arch_variant"`
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index f48f7fb..7a24168 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -37,28 +37,32 @@
 	os.Exit(run())
 }
 
-func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) {
-	fs := map[string][]byte{
+var shFixtureFactory = android.NewFixtureFactory(
+	&buildDir,
+	cc.PrepareForTestWithCcBuildComponents,
+	PrepareForTestWithShBuildComponents,
+	android.FixtureMergeMockFs(android.MockFS{
 		"test.sh":            nil,
 		"testdata/data1":     nil,
 		"testdata/sub/data2": nil,
-	}
+	}),
+)
 
-	config := android.TestArchConfig(buildDir, nil, bp, fs)
+// testShBinary runs tests using the shFixtureFactory
+//
+// Do not add any new usages of this, instead use the shFixtureFactory directly as it makes it much
+// easier to customize the test behavior.
+//
+// If it is necessary to customize the behavior of an existing test that uses this then please first
+// convert the test to using shFixtureFactory first and then in a following change add the
+// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
+// that it did not change the test behavior unexpectedly.
+//
+// deprecated
+func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) {
+	result := shFixtureFactory.RunTestWithBp(t, bp)
 
-	ctx := android.NewTestArchContext(config)
-	ctx.RegisterModuleType("sh_test", ShTestFactory)
-	ctx.RegisterModuleType("sh_test_host", ShTestHostFactory)
-
-	cc.RegisterRequiredBuildComponentsForTest(ctx)
-
-	ctx.Register()
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	android.FailIfErrored(t, errs)
-
-	return ctx, config
+	return result.TestContext, result.Config
 }
 
 func TestShTestSubDir(t *testing.T) {
diff --git a/shared/debug.go b/shared/debug.go
index 0c9ba4f..5392f2b 100644
--- a/shared/debug.go
+++ b/shared/debug.go
@@ -1,8 +1,15 @@
 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
@@ -15,3 +22,48 @@
 
 	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/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 4ad68ea..892a16c 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -165,6 +165,12 @@
 		// Forwarded to cc_library.min_sdk_version
 		Min_sdk_version *string
 	}
+
+	Java struct {
+		// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+		// Forwarded to java_library.min_sdk_version
+		Min_sdk_version *string
+	}
 }
 
 var (
@@ -403,6 +409,8 @@
 	Libs              []string
 	Stem              *string
 	SyspropPublicStub string
+	Apex_available    []string
+	Min_sdk_version   *string
 }
 
 func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
@@ -508,6 +516,8 @@
 		Sdk_version:       proptools.StringPtr("core_current"),
 		Libs:              []string{javaSyspropStub},
 		SyspropPublicStub: publicStub,
+		Apex_available:    m.ApexProperties.Apex_available,
+		Min_sdk_version:   m.properties.Java.Min_sdk_version,
 	})
 
 	if publicStub != "" {
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 9d914e3..fde41d6 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -81,6 +81,51 @@
 }
 
 func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
+	bp += `
+		cc_library {
+			name: "libbase",
+			host_supported: true,
+		}
+
+		cc_library_headers {
+			name: "libbase_headers",
+			vendor_available: true,
+			recovery_available: true,
+		}
+
+		cc_library {
+			name: "liblog",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			recovery_available: true,
+			host_supported: true,
+			llndk_stubs: "liblog.llndk",
+		}
+
+		llndk_library {
+			name: "liblog.llndk",
+			symbol_file: "",
+		}
+
+		java_library {
+			name: "sysprop-library-stub-platform",
+			sdk_version: "core_current",
+		}
+
+		java_library {
+			name: "sysprop-library-stub-vendor",
+			soc_specific: true,
+			sdk_version: "core_current",
+		}
+
+		java_library {
+			name: "sysprop-library-stub-product",
+			product_specific: true,
+			sdk_version: "core_current",
+		}
+	`
+
 	bp += cc.GatherRequiredDepsForTest(android.Android)
 
 	mockFS := map[string][]byte{
@@ -250,54 +295,11 @@
 			static_libs: ["sysprop-platform", "sysprop-vendor"],
 		}
 
-		cc_library {
-			name: "libbase",
-			host_supported: true,
-		}
-
-		cc_library_headers {
-			name: "libbase_headers",
-			vendor_available: true,
-			recovery_available: true,
-		}
-
-		cc_library {
-			name: "liblog",
-			no_libcrt: true,
-			nocrt: true,
-			system_shared_libs: [],
-			recovery_available: true,
-			host_supported: true,
-			llndk_stubs: "liblog.llndk",
-		}
-
 		cc_binary_host {
 			name: "hostbin",
 			static_libs: ["sysprop-platform"],
 		}
-
-		llndk_library {
-			name: "liblog.llndk",
-			symbol_file: "",
-		}
-
-		java_library {
-			name: "sysprop-library-stub-platform",
-			sdk_version: "core_current",
-		}
-
-		java_library {
-			name: "sysprop-library-stub-vendor",
-			soc_specific: true,
-			sdk_version: "core_current",
-		}
-
-		java_library {
-			name: "sysprop-library-stub-product",
-			product_specific: true,
-			sdk_version: "core_current",
-		}
-		`)
+	`)
 
 	// Check for generated cc_library
 	for _, variant := range []string{
@@ -391,3 +393,62 @@
 		t.Errorf("system api client should use public stub %q, got %q", w, g)
 	}
 }
+
+func TestApexAvailabilityIsForwarded(t *testing.T) {
+	ctx := test(t, `
+		sysprop_library {
+			name: "sysprop-platform",
+			apex_available: ["//apex_available:platform"],
+			srcs: ["android/sysprop/PlatformProperties.sysprop"],
+			api_packages: ["android.sysprop"],
+			property_owner: "Platform",
+		}
+	`)
+
+	expected := []string{"//apex_available:platform"}
+
+	ccModule := ctx.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+	propFromCc := ccModule.ApexProperties.Apex_available
+	if !reflect.DeepEqual(propFromCc, expected) {
+		t.Errorf("apex_available not forwarded to cc module. expected %#v, got %#v",
+			expected, propFromCc)
+	}
+
+	javaModule := ctx.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+	propFromJava := javaModule.ApexProperties.Apex_available
+	if !reflect.DeepEqual(propFromJava, expected) {
+		t.Errorf("apex_available not forwarded to java module. expected %#v, got %#v",
+			expected, propFromJava)
+	}
+}
+
+func TestMinSdkVersionIsForwarded(t *testing.T) {
+	ctx := test(t, `
+		sysprop_library {
+			name: "sysprop-platform",
+			srcs: ["android/sysprop/PlatformProperties.sysprop"],
+			api_packages: ["android.sysprop"],
+			property_owner: "Platform",
+			cpp: {
+				min_sdk_version: "29",
+			},
+			java: {
+				min_sdk_version: "30",
+			},
+		}
+	`)
+
+	ccModule := ctx.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+	propFromCc := proptools.String(ccModule.Properties.Min_sdk_version)
+	if propFromCc != "29" {
+		t.Errorf("min_sdk_version not forwarded to cc module. expected %#v, got %#v",
+			"29", propFromCc)
+	}
+
+	javaModule := ctx.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+	propFromJava := javaModule.MinSdkVersion()
+	if propFromJava != "30" {
+		t.Errorf("min_sdk_version not forwarded to java module. expected %#v, got %#v",
+			"30", propFromJava)
+	}
+}
diff --git a/ui/build/config.go b/ui/build/config.go
index 15da1bc..1152cd7 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -56,7 +56,6 @@
 	katiSuffix      string
 	targetDevice    string
 	targetDeviceDir string
-	fullBuild       bool
 
 	// Autodetected
 	totalRAM uint64
@@ -792,14 +791,6 @@
 	c.targetDevice = device
 }
 
-func (c *configImpl) FullBuild() bool {
-	return c.fullBuild
-}
-
-func (c *configImpl) SetFullBuild(fullBuild bool) {
-	c.fullBuild = fullBuild
-}
-
 func (c *configImpl) TargetBuildVariant() string {
 	if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
 		return v
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index be6f00a..fe0aca9 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -214,9 +214,6 @@
 		// So that later Kati runs can find BoardConfig.mk faster
 		"TARGET_DEVICE_DIR",
 
-		// To decide whether to skip the old installed cleanup step.
-		"FULL_BUILD",
-
 		// Whether --werror_overriding_commands will work
 		"BUILD_BROKEN_DUP_RULES",
 
@@ -281,7 +278,6 @@
 	config.SetNinjaArgs(strings.Fields(makeVars["NINJA_GOALS"]))
 	config.SetTargetDevice(makeVars["TARGET_DEVICE"])
 	config.SetTargetDeviceDir(makeVars["TARGET_DEVICE_DIR"])
-	config.SetFullBuild(makeVars["FULL_BUILD"] == "true")
 
 	config.SetBuildBrokenDupRules(makeVars["BUILD_BROKEN_DUP_RULES"] == "true")
 	config.SetBuildBrokenUsesNetwork(makeVars["BUILD_BROKEN_USES_NETWORK"] == "true")
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 668b20e..06ec646 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -229,11 +229,7 @@
 
 	// Cleanup steps.
 	cleanCopyHeaders(ctx, config)
-	// Skip the old installed file cleanup step for few non-full build goals as we don't create
-	// an installed file list for them.
-	if config.FullBuild() {
-		cleanOldInstalledFiles(ctx, config)
-	}
+	cleanOldInstalledFiles(ctx, config)
 }
 
 // Clean out obsolete header files on the disk that were *not copied* during the
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 242282b..5f4a203 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -105,11 +105,6 @@
 	soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
 	soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
 
-	if os.Getenv("SOONG_DELVE") != "" {
-		// SOONG_DELVE is already in cmd.Environment
-		soongBuildEnv.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
-	}
-
 	err := writeEnvironmentFile(ctx, envFile, soongBuildEnv.AsMap())
 	if err != nil {
 		ctx.Fatalf("failed to write environment file %s: %s", envFile, err)
@@ -175,7 +170,28 @@
 			"--frontend_file", fifo,
 			"-f", filepath.Join(config.SoongOutDir(), file))
 
-		cmd.Environment.Set("SOONG_OUTDIR", config.SoongOutDir())
+		var ninjaEnv Environment
+
+		// This is currently how the command line to invoke soong_build finds the
+		// root of the source tree and the output root
+		ninjaEnv.Set("TOP", os.Getenv("TOP"))
+		ninjaEnv.Set("SOONG_OUTDIR", config.SoongOutDir())
+
+		// Needed for NonHermeticHostSystemTool() and that, only in tests. We should
+		// probably find a better way of running tests other than making $PATH
+		// available also to production builds. Note that this is not get same as
+		// os.Getenv("PATH"): config.Environment() contains the $PATH that redirects
+		// every binary through the path interposer.
+		configPath, _ := config.Environment().Get("PATH")
+		ninjaEnv.Set("PATH", configPath)
+
+		// For debugging
+		if os.Getenv("SOONG_DELVE") != "" {
+			// SOONG_DELVE is already in cmd.Environment
+			ninjaEnv.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
+		}
+
+		cmd.Environment = &ninjaEnv
 		cmd.Sandbox = soongSandbox
 		cmd.RunAndStreamOrFatal()
 	}
diff --git a/vnames.go.json b/vnames.go.json
deleted file mode 100644
index f8c6b7f..0000000
--- a/vnames.go.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[
-    {
-        "pattern": "(.*)",
-        "vname": {
-            "path": "@1@"
-        }
-    }
-]