Merge "Convert cc/prebuilt_test.go to use fixtures"
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 9cd9fad..6675840 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -37,6 +37,7 @@
 const (
 	getAllFiles CqueryRequestType = iota
 	getCcObjectFiles
+	getAllFilesAndCcObjectFiles
 )
 
 // Map key to describe bazel cquery requests.
@@ -58,7 +59,9 @@
 	// Retrieves these files from Bazel's CcInfo provider.
 	GetCcObjectFiles(label string, archType ArchType) ([]string, bool)
 
-	// TODO(cparsons): Other cquery-related methods should be added here.
+	// Returns the results of GetAllFiles and GetCcObjectFiles in a single query (in that order).
+	GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool)
+
 	// ** End cquery methods
 
 	// Issues commands to Bazel to receive results for all cquery requests
@@ -116,6 +119,11 @@
 	return result, ok
 }
 
+func (m MockBazelContext) GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
+	result, ok := m.AllFiles[label]
+	return result, result, ok
+}
+
 func (m MockBazelContext) InvokeBazel() error {
 	panic("unimplemented")
 }
@@ -154,6 +162,22 @@
 	}
 }
 
+func (bazelCtx *bazelContext) GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
+	var allFiles []string
+	var ccObjects []string
+
+	result, ok := bazelCtx.cquery(label, getAllFilesAndCcObjectFiles, archType)
+	if ok {
+		bazelOutput := strings.TrimSpace(result)
+		splitString := strings.Split(bazelOutput, "|")
+		allFilesString := splitString[0]
+		ccObjectsString := splitString[1]
+		allFiles = strings.Split(allFilesString, ", ")
+		ccObjects = strings.Split(ccObjectsString, ", ")
+	}
+	return allFiles, ccObjects, ok
+}
+
 func (n noopBazelContext) GetAllFiles(label string, archType ArchType) ([]string, bool) {
 	panic("unimplemented")
 }
@@ -162,6 +186,10 @@
 	panic("unimplemented")
 }
 
+func (n noopBazelContext) GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
+	panic("unimplemented")
+}
+
 func (n noopBazelContext) InvokeBazel() error {
 	panic("unimplemented")
 }
@@ -253,8 +281,12 @@
 	return ""
 }
 
+// Issues the given bazel command with given build label and additional flags.
+// Returns (stdout, stderr, error). The first and second return values are strings
+// containing the stdout and stderr of the run command, and an error is returned if
+// the invocation returned an error code.
 func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command string, labels []string,
-	extraFlags ...string) (string, error) {
+	extraFlags ...string) (string, string, error) {
 
 	cmdFlags := []string{"--output_base=" + context.outputBase, command}
 	cmdFlags = append(cmdFlags, labels...)
@@ -281,9 +313,10 @@
 	bazelCmd.Stderr = stderr
 
 	if output, err := bazelCmd.Output(); err != nil {
-		return "", fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
+		return "", string(stderr.Bytes()),
+			fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
 	} else {
-		return string(output), nil
+		return string(output), string(stderr.Bytes()), nil
 	}
 }
 
@@ -452,6 +485,11 @@
 		strings.Join(deps_arm, ",\n            ")))
 }
 
+// Returns the file contents of the buildroot.cquery file that should be used for the cquery
+// expression in order to obtain information about buildroot and its dependencies.
+// The contents of this file depend on the bazelContext's requests; requests are enumerated
+// and grouped by their request type. The data retrieved for each label depends on its
+// request type.
 func (context *bazelContext) cqueryStarlarkFileContents() []byte {
 	formatString := `
 # This file is generated by soong_build. Do not edit.
@@ -463,6 +501,13 @@
   %s
 }
 
+getAllFilesAndCcObjectFilesLabels = {
+  %s
+}
+
+def get_all_files(target):
+  return [f.path for f in target.files.to_list()]
+
 def get_cc_object_files(target):
   result = []
   linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list()
@@ -492,9 +537,11 @@
 def format(target):
   id_string = str(target.label) + "|" + get_arch(target)
   if id_string in getAllFilesLabels:
-    return id_string + ">>" + ', '.join([f.path for f in target.files.to_list()])
+    return id_string + ">>" + ', '.join(get_all_files(target))
   elif id_string in getCcObjectFilesLabels:
     return id_string + ">>" + ', '.join(get_cc_object_files(target))
+  elif id_string in getAllFilesAndCcObjectFilesLabels:
+    return id_string + ">>" + ', '.join(get_all_files(target)) + "|" + ', '.join(get_cc_object_files(target))
   else:
     # This target was not requested via cquery, and thus must be a dependency
     # of a requested target.
@@ -502,6 +549,7 @@
 `
 	var getAllFilesDeps []string = nil
 	var getCcObjectFilesDeps []string = nil
+	var getAllFilesAndCcObjectFilesDeps []string = nil
 
 	for val, _ := range context.requests {
 		labelWithArch := getCqueryId(val)
@@ -511,12 +559,16 @@
 			getAllFilesDeps = append(getAllFilesDeps, mapEntryString)
 		case getCcObjectFiles:
 			getCcObjectFilesDeps = append(getCcObjectFilesDeps, mapEntryString)
+		case getAllFilesAndCcObjectFiles:
+			getAllFilesAndCcObjectFilesDeps = append(getAllFilesAndCcObjectFilesDeps, mapEntryString)
 		}
 	}
 	getAllFilesDepsString := strings.Join(getAllFilesDeps, ",\n  ")
 	getCcObjectFilesDepsString := strings.Join(getCcObjectFilesDeps, ",\n  ")
+	getAllFilesAndCcObjectFilesDepsString := strings.Join(getAllFilesAndCcObjectFilesDeps, ",\n  ")
 
-	return []byte(fmt.Sprintf(formatString, getAllFilesDepsString, getCcObjectFilesDepsString))
+	return []byte(fmt.Sprintf(formatString, getAllFilesDepsString, getCcObjectFilesDepsString,
+		getAllFilesAndCcObjectFilesDepsString))
 }
 
 // Returns a workspace-relative path containing build-related metadata required
@@ -531,6 +583,7 @@
 	context.results = make(map[cqueryKey]string)
 
 	var cqueryOutput string
+	var cqueryErr string
 	var err error
 
 	intermediatesDirPath := absolutePath(context.intermediatesDir())
@@ -568,7 +621,7 @@
 		return err
 	}
 	buildrootLabel := "//:buildroot"
-	cqueryOutput, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
+	cqueryOutput, cqueryErr, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
 		[]string{fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)},
 		"--output=starlark",
 		"--starlark:file="+cqueryFileRelpath)
@@ -595,7 +648,8 @@
 		if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
 			context.results[val] = string(cqueryResult)
 		} else {
-			return fmt.Errorf("missing result for bazel target %s. query output: [%s]", getCqueryId(val), cqueryOutput)
+			return fmt.Errorf("missing result for bazel target %s. query output: [%s], cquery err: [%s]",
+				getCqueryId(val), cqueryOutput, cqueryErr)
 		}
 	}
 
@@ -603,7 +657,7 @@
 	//
 	// TODO(cparsons): Use --target_pattern_file to avoid command line limits.
 	var aqueryOutput string
-	aqueryOutput, err = context.issueBazelCommand(bazel.AqueryBuildRootRunName, "aquery",
+	aqueryOutput, _, err = context.issueBazelCommand(bazel.AqueryBuildRootRunName, "aquery",
 		[]string{fmt.Sprintf("deps(%s)", buildrootLabel),
 			// Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
 			// proto sources, which would add a number of unnecessary dependencies.
@@ -621,7 +675,7 @@
 	// Issue a build command of the phony root to generate symlink forests for dependencies of the
 	// Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
 	// but some of symlinks may be required to resolve source dependencies of the build.
-	_, err = context.issueBazelCommand(bazel.BazelBuildPhonyRootRunName, "build",
+	_, _, err = context.issueBazelCommand(bazel.BazelBuildPhonyRootRunName, "build",
 		[]string{"//:phonyroot"})
 
 	if err != nil {
diff --git a/android/config.go b/android/config.go
index d42b4c6..bc1aa3a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -524,25 +524,6 @@
 	return PathForOutput(ctx, "host", c.PrebuiltOS(), "framework", path)
 }
 
-// NonHermeticHostSystemTool looks for non-hermetic tools from the system we're
-// running on. These tools are not checked-in to AOSP, and therefore could lead
-// to reproducibility problems. Should not be used for other than finding the
-// XCode SDK (xcrun, sw_vers), etc. See ui/build/paths/config.go for the
-// allowlist of host system tools.
-func (c *config) NonHermeticHostSystemTool(name string) string {
-	for _, dir := range filepath.SplitList(c.Getenv("PATH")) {
-		path := filepath.Join(dir, name)
-		if s, err := os.Stat(path); err != nil {
-			continue
-		} else if m := s.Mode(); !s.IsDir() && m&0111 != 0 {
-			return path
-		}
-	}
-	panic(fmt.Errorf(
-		"Cannot find non-hermetic system tool '%s' on path '%s'",
-		name, c.Getenv("PATH")))
-}
-
 // PrebuiltOS returns the name of the host OS used in prebuilts directories.
 func (c *config) PrebuiltOS() string {
 	switch runtime.GOOS {
diff --git a/android/writedocs.go b/android/writedocs.go
index 6cb2f10..67b9aa3 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -35,10 +35,11 @@
 
 func primaryBuilderPath(ctx SingletonContext) Path {
 	buildDir := absolutePath(ctx.Config().BuildDir())
-	primaryBuilder, err := filepath.Rel(buildDir, os.Args[0])
+	binary := absolutePath(os.Args[0])
+	primaryBuilder, err := filepath.Rel(buildDir, binary)
 	if err != nil {
-		ctx.Errorf("path to primary builder %q is not in build dir %q",
-			os.Args[0], ctx.Config().BuildDir())
+		ctx.Errorf("path to primary builder %q is not in build dir %q (%q)",
+			os.Args[0], ctx.Config().BuildDir(), err)
 	}
 
 	return PathForOutput(ctx, primaryBuilder)
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 1035df3..b0344af 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -136,7 +136,7 @@
 
 func getMacTools(ctx android.PackageVarContext) *macPlatformTools {
 	macTools.once.Do(func() {
-		xcrunTool := ctx.Config().NonHermeticHostSystemTool("xcrun")
+		xcrunTool := "/usr/bin/xcrun"
 
 		xcrun := func(args ...string) string {
 			if macTools.err != nil {
diff --git a/cc/library.go b/cc/library.go
index 0e6e107..6a3b876 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -230,6 +230,7 @@
 	module, library := NewLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyStatic()
 	module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
+	module.bazelHandler = &staticLibraryBazelHandler{module: module}
 	return module.Init()
 }
 
@@ -406,6 +407,49 @@
 	collectedSnapshotHeaders android.Paths
 }
 
+type staticLibraryBazelHandler struct {
+	bazelHandler
+
+	module *Module
+}
+
+func (handler *staticLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+	bazelCtx := ctx.Config().BazelContext
+	outputPaths, objPaths, ok := bazelCtx.GetAllFilesAndCcObjectFiles(label, ctx.Arch().ArchType)
+	if ok {
+		if len(outputPaths) != 1 {
+			// TODO(cparsons): This is actually expected behavior for static libraries with no srcs.
+			// We should support this.
+			ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, objPaths)
+			return false
+		}
+		outputFilePath := android.PathForBazelOut(ctx, outputPaths[0])
+		handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
+
+		objFiles := make(android.Paths, len(objPaths))
+		for i, objPath := range objPaths {
+			objFiles[i] = android.PathForBazelOut(ctx, objPath)
+		}
+		objects := Objects{
+			objFiles: objFiles,
+		}
+
+		ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+			StaticLibrary: outputFilePath,
+			ReuseObjects:  objects,
+			Objects:       objects,
+
+			// TODO(cparsons): Include transitive static libraries in this provider to support
+			// static libraries with deps.
+			TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
+				Direct(outputFilePath).
+				Build(),
+		})
+		handler.module.outputFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, objPaths[0]))
+	}
+	return ok
+}
+
 // collectHeadersForSnapshot collects all exported headers from library.
 // It globs header files in the source tree for exported include directories,
 // and tracks generated header files separately.
diff --git a/java/Android.bp b/java/Android.bp
index 461b16d..9e2db83 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -78,6 +78,7 @@
         "plugin_test.go",
         "rro_test.go",
         "sdk_test.go",
+        "system_modules_test.go",
     ],
     pluginFor: ["soong_build"],
 }
diff --git a/java/java_test.go b/java/java_test.go
index e8c4a0f..670eefc 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2434,70 +2434,6 @@
 	})
 }
 
-func TestJavaSystemModules(t *testing.T) {
-	ctx, _ := testJava(t, `
-		java_system_modules {
-			name: "system-modules",
-			libs: ["system-module1", "system-module2"],
-		}
-		java_library {
-			name: "system-module1",
-			srcs: ["a.java"],
-			sdk_version: "none",
-			system_modules: "none",
-		}
-		java_library {
-			name: "system-module2",
-			srcs: ["b.java"],
-			sdk_version: "none",
-			system_modules: "none",
-		}
-		`)
-
-	// check the existence of the module
-	systemModules := ctx.ModuleForTests("system-modules", "android_common")
-
-	cmd := systemModules.Rule("jarsTosystemModules")
-
-	// make sure the command compiles against the supplied modules.
-	for _, module := range []string{"system-module1.jar", "system-module2.jar"} {
-		if !strings.Contains(cmd.Args["classpath"], module) {
-			t.Errorf("system modules classpath %v does not contain %q", cmd.Args["classpath"],
-				module)
-		}
-	}
-}
-
-func TestJavaSystemModulesImport(t *testing.T) {
-	ctx, _ := testJava(t, `
-		java_system_modules_import {
-			name: "system-modules",
-			libs: ["system-module1", "system-module2"],
-		}
-		java_import {
-			name: "system-module1",
-			jars: ["a.jar"],
-		}
-		java_import {
-			name: "system-module2",
-			jars: ["b.jar"],
-		}
-		`)
-
-	// check the existence of the module
-	systemModules := ctx.ModuleForTests("system-modules", "android_common")
-
-	cmd := systemModules.Rule("jarsTosystemModules")
-
-	// make sure the command compiles against the supplied modules.
-	for _, module := range []string{"system-module1.jar", "system-module2.jar"} {
-		if !strings.Contains(cmd.Args["classpath"], module) {
-			t.Errorf("system modules classpath %v does not contain %q", cmd.Args["classpath"],
-				module)
-		}
-	}
-}
-
 func TestJavaLibraryWithSystemModules(t *testing.T) {
 	ctx, _ := testJava(t, `
 		java_library {
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index c91b321..8a442b5 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -178,7 +178,7 @@
 	props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", "public", apiver))
 	props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", "public", apiver))
 
-	mctx.CreateModule(SystemModulesFactory, &props)
+	mctx.CreateModule(systemModulesImportFactory, &props)
 }
 
 func prebuiltSdkSystemModules(mctx android.LoadHookContext, p *prebuiltApis) {
@@ -248,9 +248,9 @@
 	}
 
 	// Create incompatibilities tracking files for all modules, if we have a "next" api.
+	incompatibilities := make(map[string]bool)
 	if nextApiDir := String(p.properties.Next_api_dir); nextApiDir != "" {
 		files := getPrebuiltFilesInSubdir(mctx, nextApiDir, "api/*incompatibilities.txt")
-		incompatibilities := make(map[string]bool)
 		for _, f := range files {
 			localPath := strings.TrimPrefix(f, mydir)
 			module, _, scope := parseApiFilePath(mctx, localPath)
@@ -266,11 +266,11 @@
 
 			incompatibilities[referencedModule+"."+scope] = true
 		}
-		// Create empty incompatibilities files for remaining modules
-		for _, k := range android.SortedStringKeys(m) {
-			if _, ok := incompatibilities[k]; !ok {
-				createEmptyFile(mctx, apiModuleName(m[k].module+"-incompatibilities", m[k].scope, "latest"))
-			}
+	}
+	// Create empty incompatibilities files for remaining modules
+	for _, k := range android.SortedStringKeys(m) {
+		if _, ok := incompatibilities[k]; !ok {
+			createEmptyFile(mctx, apiModuleName(m[k].module+"-incompatibilities", m[k].scope, "latest"))
 		}
 	}
 }
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 30d120d..b03f90c 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -452,6 +452,7 @@
 	// that references the latest released API and remove API specification files.
 	// * API specification filegroup -> <dist-stem>.api.<scope>.latest
 	// * Removed API specification filegroup -> <dist-stem>-removed.api.<scope>.latest
+	// * API incompatibilities baseline filegroup -> <dist-stem>-incompatibilities.api.<scope>.latest
 	Dist_stem *string
 
 	// A compatibility mode that allows historical API-tracking files to not exist.
@@ -1059,6 +1060,9 @@
 		if m := android.SrcIsModule(module.latestRemovedApiFilegroupName(apiScope)); !ctx.OtherModuleExists(m) {
 			missingApiModules = append(missingApiModules, m)
 		}
+		if m := android.SrcIsModule(module.latestIncompatibilitiesFilegroupName(apiScope)); !ctx.OtherModuleExists(m) {
+			missingApiModules = append(missingApiModules, m)
+		}
 	}
 	if len(missingApiModules) != 0 && !module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api {
 		m := module.Name() + " is missing tracking files for previously released library versions.\n"
@@ -1165,6 +1169,10 @@
 	return ":" + module.distStem() + "-removed.api." + apiScope.name + ".latest"
 }
 
+func (module *SdkLibrary) latestIncompatibilitiesFilegroupName(apiScope *apiScope) string {
+	return ":" + module.distStem() + "-incompatibilities.api." + apiScope.name + ".latest"
+}
+
 func childModuleVisibility(childVisibility []string) []string {
 	if childVisibility == nil {
 		// No child visibility set. The child will use the visibility of the sdk_library.
@@ -1389,6 +1397,8 @@
 		props.Check_api.Last_released.Api_file = latestApiFilegroupName
 		props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
 			module.latestRemovedApiFilegroupName(apiScope))
+		props.Check_api.Last_released.Baseline_file = proptools.StringPtr(
+			module.latestIncompatibilitiesFilegroupName(apiScope))
 
 		if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
 			// Enable api lint.
diff --git a/java/system_modules.go b/java/system_modules.go
index 95f71b8..8c69051 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -169,7 +169,13 @@
 	system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, jars)
 }
 
-func (system *SystemModules) DepsMutator(ctx android.BottomUpMutatorContext) {
+// ComponentDepsMutator is called before prebuilt modules without a corresponding source module are
+// renamed so unless the supplied libs specifically includes the prebuilt_ prefix this is guaranteed
+// to only add dependencies on source modules.
+//
+// The systemModuleLibsTag will prevent the prebuilt mutators from replacing this dependency so it
+// will never be changed to depend on a prebuilt either.
+func (system *SystemModules) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
 	ctx.AddVariationDependencies(nil, systemModulesLibsTag, system.properties.Libs...)
 }
 
@@ -225,6 +231,15 @@
 	return &system.prebuilt
 }
 
+// ComponentDepsMutator is called before prebuilt modules without a corresponding source module are
+// renamed so as this adds a prebuilt_ prefix this is guaranteed to only add dependencies on source
+// modules.
+func (system *systemModulesImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
+	for _, lib := range system.properties.Libs {
+		ctx.AddVariationDependencies(nil, systemModulesLibsTag, "prebuilt_"+lib)
+	}
+}
+
 type systemModulesSdkMemberType struct {
 	android.SdkMemberTypeBase
 }
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
new file mode 100644
index 0000000..44049ee
--- /dev/null
+++ b/java/system_modules_test.go
@@ -0,0 +1,112 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+	"testing"
+
+	"android/soong/android"
+)
+
+func normalizedPathsToHeaderJars(result *android.TestResult, moduleNames ...string) []string {
+	paths := []string{}
+	for _, moduleName := range moduleNames {
+		module := result.Module(moduleName, "android_common")
+		info := result.ModuleProvider(module, JavaInfoProvider).(JavaInfo)
+		paths = append(paths, result.NormalizePathsForTesting(info.HeaderJars)...)
+	}
+	return paths
+}
+
+var addSourceSystemModules = android.FixtureAddTextFile("source/Android.bp", `
+		java_system_modules {
+			name: "system-modules",
+			libs: ["system-module1", "system-module2"],
+		}
+		java_library {
+			name: "system-module1",
+			srcs: ["a.java"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+		java_library {
+			name: "system-module2",
+			srcs: ["b.java"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+`)
+
+func TestJavaSystemModules(t *testing.T) {
+	result := javaFixtureFactory.RunTest(t, addSourceSystemModules)
+
+	// check the existence of the source module
+	sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
+	sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs
+
+	// The expected paths are the header jars from the source input modules.
+	expectedSourcePaths := normalizedPathsToHeaderJars(result, "system-module1", "system-module2")
+	result.AssertArrayString("source system modules inputs", expectedSourcePaths, result.NormalizePathsForTesting(sourceInputs))
+}
+
+var addPrebuiltSystemModules = android.FixtureAddTextFile("prebuilts/Android.bp", `
+		java_system_modules_import {
+			name: "system-modules",
+			libs: ["system-module1", "system-module2"],
+		}
+		java_import {
+			name: "system-module1",
+			jars: ["a.jar"],
+		}
+		java_import {
+			name: "system-module2",
+			jars: ["b.jar"],
+		}
+`)
+
+func TestJavaSystemModulesImport(t *testing.T) {
+	result := javaFixtureFactory.RunTest(t, addPrebuiltSystemModules)
+
+	// check the existence of the renamed prebuilt module
+	prebuiltSystemModules := result.ModuleForTests("system-modules", "android_common")
+	prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs
+
+	// The expected paths are the header jars from the renamed prebuilt input modules.
+	expectedPrebuiltPaths := normalizedPathsToHeaderJars(result, "system-module1", "system-module2")
+	result.AssertArrayString("renamed prebuilt system modules inputs", expectedPrebuiltPaths, result.NormalizePathsForTesting(prebuiltInputs))
+}
+
+func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) {
+	result := javaFixtureFactory.RunTest(t,
+		addSourceSystemModules,
+		addPrebuiltSystemModules,
+	)
+
+	// check the existence of the source module
+	sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
+	sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs
+
+	// The expected paths are the header jars from the source input modules.
+	expectedSourcePaths := normalizedPathsToHeaderJars(result, "system-module1", "system-module2")
+	result.AssertArrayString("source system modules inputs", expectedSourcePaths, result.NormalizePathsForTesting(sourceInputs))
+
+	// check the existence of the renamed prebuilt module
+	prebuiltSystemModules := result.ModuleForTests("prebuilt_system-modules", "android_common")
+	prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs
+
+	// The expected paths are the header jars from the renamed prebuilt input modules.
+	expectedPrebuiltPaths := normalizedPathsToHeaderJars(result, "prebuilt_system-module1", "prebuilt_system-module2")
+	result.AssertArrayString("prebuilt system modules inputs", expectedPrebuiltPaths, result.NormalizePathsForTesting(prebuiltInputs))
+}
diff --git a/rust/testing.go b/rust/testing.go
index 9534ab5..5be71c9 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -20,6 +20,30 @@
 	"android/soong/genrule"
 )
 
+// Preparer that will define all cc module types and a limited set of mutators and singletons that
+// make those module types usable.
+var PrepareForTestWithRustBuildComponents = android.GroupFixturePreparers(
+	android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
+)
+
+// The directory in which rust test default modules will be defined.
+//
+// Placing them here ensures that their location does not conflict with default test modules
+// defined by other packages.
+const rustDefaultsDir = "defaults/rust/"
+
+// Preparer that will define default rust modules, e.g. standard prebuilt modules.
+var PrepareForTestWithRustDefaultModules = android.GroupFixturePreparers(
+	cc.PrepareForTestWithCcDefaultModules,
+	PrepareForTestWithRustBuildComponents,
+	android.FixtureAddTextFile(rustDefaultsDir+"Android.bp", GatherRequiredDepsForTest()),
+)
+
+// Preparer that will allow use of all rust modules fully.
+var PrepareForIntegrationTestWithRust = android.GroupFixturePreparers(
+	PrepareForTestWithRustDefaultModules,
+)
+
 func GatherRequiredDepsForTest() string {
 	bp := `
 		rust_prebuilt_library {
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 3591777..6da135a 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -101,7 +101,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -353,7 +353,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -440,7 +440,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAllCopyRules(`
 myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib1/android_arm64_armv8-a_shared/mynativelib1.so -> arm64/lib/mynativelib1.so
@@ -486,7 +486,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -556,7 +556,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -615,7 +615,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mymodule_exports", "",
+	CheckSnapshot(result, "mymodule_exports", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -700,7 +700,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -853,7 +853,7 @@
 
 	result := runTests(t, ctx, config)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -991,7 +991,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mymodule_exports", "",
+	CheckSnapshot(result, "mymodule_exports", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1099,7 +1099,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1200,7 +1200,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1297,7 +1297,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1424,7 +1424,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1552,7 +1552,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1615,7 +1615,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1729,7 +1729,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1843,7 +1843,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1940,7 +1940,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1978,7 +1978,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -2080,7 +2080,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -2193,7 +2193,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -2266,7 +2266,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -2377,7 +2377,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -2430,7 +2430,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -2543,7 +2543,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -2658,7 +2658,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
index 1c59244..54a40d2 100644
--- a/sdk/exports_test.go
+++ b/sdk/exports_test.go
@@ -42,7 +42,7 @@
 			"package/Android.bp": []byte(packageBp),
 		})
 
-	result.CheckSnapshot("myexports", "package",
+	CheckSnapshot(result, "myexports", "package",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 111b22c..ef8e4a0 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -125,9 +125,9 @@
 	`)
 
 	// Make sure that the mysdk module depends on "sdkmember" and not "prebuilt_sdkmember".
-	java.CheckModuleDependencies(t, result.ctx, "mysdk", "android_common", []string{"sdkmember"})
+	java.CheckModuleDependencies(t, result.TestContext, "mysdk", "android_common", []string{"sdkmember"})
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`// This is auto-generated. DO NOT EDIT.
 
 java_import {
@@ -224,11 +224,11 @@
 		}
 	`)
 
-	sdkMemberV1 := result.ctx.ModuleForTests("sdkmember_mysdk_1", "android_common").Rule("combineJar").Output
-	sdkMemberV2 := result.ctx.ModuleForTests("sdkmember_mysdk_2", "android_common").Rule("combineJar").Output
+	sdkMemberV1 := result.ModuleForTests("sdkmember_mysdk_1", "android_common").Rule("combineJar").Output
+	sdkMemberV2 := result.ModuleForTests("sdkmember_mysdk_2", "android_common").Rule("combineJar").Output
 
-	javalibForMyApex := result.ctx.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_1")
-	javalibForMyApex2 := result.ctx.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_2")
+	javalibForMyApex := result.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_1")
+	javalibForMyApex2 := result.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_2")
 
 	// Depending on the uses_sdks value, different libs are linked
 	ensureListContains(t, pathsToStrings(javalibForMyApex.Rule("javac").Implicits), sdkMemberV1.String())
@@ -255,7 +255,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -312,7 +312,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -369,7 +369,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -440,7 +440,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -496,7 +496,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -551,7 +551,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -607,7 +607,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -662,7 +662,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -731,7 +731,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -827,7 +827,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -918,7 +918,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("myexports", "",
+	CheckSnapshot(result, "myexports", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1032,7 +1032,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1133,7 +1133,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1202,7 +1202,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1274,7 +1274,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1367,7 +1367,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1475,7 +1475,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1563,7 +1563,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -1639,7 +1639,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index a7acd0c..65a9001 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -169,7 +169,7 @@
 			"package/Android.bp": []byte(packageBp),
 		})
 
-	result.CheckSnapshot("mysdk", "package",
+	CheckSnapshot(result, "mysdk", "package",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -317,7 +317,7 @@
 	`
 	result := testSdkWithFs(t, sdk, nil)
 
-	result.CheckSnapshot("mysdk", "",
+	CheckSnapshot(result, "mysdk", "",
 		checkAllOtherCopyRules(`.intermediates/mysdk/common_os/mysdk-current.zip -> mysdk-current.zip`),
 	)
 }
diff --git a/sdk/testing.go b/sdk/testing.go
index e291bdb..3fb27ca 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -136,9 +136,8 @@
 	_, errs = ctx.PrepareBuildActions(config)
 	android.FailIfErrored(t, errs)
 	return &testSdkResult{
-		TestHelper: android.TestHelper{T: t},
-		ctx:        ctx,
-		config:     config,
+		TestHelper:  android.TestHelper{T: t},
+		TestContext: ctx,
 	}
 }
 
@@ -184,17 +183,20 @@
 // checking the state of the build structures.
 type testSdkResult struct {
 	android.TestHelper
-	ctx    *android.TestContext
-	config android.Config
+	*android.TestContext
+}
+
+func (result *testSdkResult) Module(name string, variant string) android.Module {
+	return result.ModuleForTests(name, variant).Module()
 }
 
 // Analyse the sdk build rules to extract information about what it is doing.
-
+//
 // e.g. find the src/dest pairs from each cp command, the various zip files
 // generated, etc.
-func (r *testSdkResult) getSdkSnapshotBuildInfo(sdk *sdk) *snapshotBuildInfo {
+func getSdkSnapshotBuildInfo(result *testSdkResult, sdk *sdk) *snapshotBuildInfo {
 	info := &snapshotBuildInfo{
-		r:                            r,
+		r:                            result,
 		androidBpContents:            sdk.GetAndroidBpContentsForTests(),
 		androidUnversionedBpContents: sdk.GetUnversionedAndroidBpContentsForTests(),
 		androidVersionedBpContents:   sdk.GetVersionedAndroidBpContentsForTests(),
@@ -237,7 +239,7 @@
 			info.intermediateZip = info.outputZip
 			mergeInput := android.NormalizePathForTesting(bp.Input)
 			if info.intermediateZip != mergeInput {
-				r.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead",
+				result.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead",
 					info.intermediateZip, mergeInput)
 			}
 
@@ -256,28 +258,20 @@
 	return info
 }
 
-func (r *testSdkResult) Module(name string, variant string) android.Module {
-	return r.ctx.ModuleForTests(name, variant).Module()
-}
-
-func (r *testSdkResult) ModuleForTests(name string, variant string) android.TestingModule {
-	return r.ctx.ModuleForTests(name, variant)
-}
-
 // Check the snapshot build rules.
 //
 // Takes a list of functions which check different facets of the snapshot build rules.
 // 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.Helper()
+func CheckSnapshot(result *testSdkResult, name string, dir string, checkers ...snapshotBuildInfoChecker) {
+	result.Helper()
 
 	// The sdk CommonOS variant is always responsible for generating the snapshot.
 	variant := android.CommonOS.Name
 
-	sdk := r.Module(name, variant).(*sdk)
+	sdk := result.Module(name, variant).(*sdk)
 
-	snapshotBuildInfo := r.getSdkSnapshotBuildInfo(sdk)
+	snapshotBuildInfo := getSdkSnapshotBuildInfo(result, sdk)
 
 	// Check state of the snapshot build.
 	for _, checker := range checkers {
@@ -289,7 +283,7 @@
 	if dir != "" {
 		dir = filepath.Clean(dir) + "/"
 	}
-	r.AssertStringEquals("Snapshot zip file in wrong place",
+	result.AssertStringEquals("Snapshot zip file in wrong place",
 		fmt.Sprintf(".intermediates/%s%s/%s/%s-current.zip", dir, name, variant, name), actual)
 
 	// Populate a mock filesystem with the files that would have been copied by
@@ -300,7 +294,7 @@
 	}
 
 	// Process the generated bp file to make sure it is valid.
-	testSdkWithFs(r.T, snapshotBuildInfo.androidBpContents, fs)
+	testSdkWithFs(result.T, snapshotBuildInfo.androidBpContents, fs)
 }
 
 type snapshotBuildInfoChecker func(info *snapshotBuildInfo)
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 500abda..884e957 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -177,14 +177,6 @@
 		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") != "" {
 			ninjaEnv.Set("SOONG_DELVE", os.Getenv("SOONG_DELVE"))