Revert "Make RuleBuilder methods take Paths"

This reverts commit acdd6940719125104dfd2f692990c99682f95f05.

Reason for revert: broke ndk build

Change-Id: I5655e48c15eb8f5f0267afdd853fbc25765b8623
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 6f8ea3a..ee3cc8d 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -17,7 +17,6 @@
 import (
 	"encoding/json"
 	"io/ioutil"
-	"strings"
 
 	"android/soong/android"
 )
@@ -75,13 +74,12 @@
 	InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture
 
 	// Only used for boot image
-	DirtyImageObjects      android.OptionalPath // path to a dirty-image-objects file
-	PreloadedClasses       android.OptionalPath // path to a preloaded-classes file
-	BootImageProfiles      android.Paths        // path to a boot-image-profile.txt file
-	UseProfileForBootImage bool                 // whether a profile should be used to compile the boot image
-	BootFlags              string               // extra flags to pass to dex2oat for the boot image
-	Dex2oatImageXmx        string               // max heap size for dex2oat for the boot image
-	Dex2oatImageXms        string               // initial heap size for dex2oat for the boot image
+	DirtyImageObjects string   // path to a dirty-image-objects file
+	PreloadedClasses  string   // path to a preloaded-classes file
+	BootImageProfiles []string // path to a boot-image-profile.txt file
+	BootFlags         string   // extra flags to pass to dex2oat for the boot image
+	Dex2oatImageXmx   string   // max heap size for dex2oat for the boot image
+	Dex2oatImageXms   string   // initial heap size for dex2oat for the boot image
 
 	Tools Tools // paths to tools possibly used by the generated commands
 }
@@ -89,38 +87,38 @@
 // Tools contains paths to tools possibly used by the generated commands.  If you add a new tool here you MUST add it
 // to the order-only dependency list in DEXPREOPT_GEN_DEPS.
 type Tools struct {
-	Profman  android.Path
-	Dex2oat  android.Path
-	Aapt     android.Path
-	SoongZip android.Path
-	Zip2zip  android.Path
+	Profman  string
+	Dex2oat  string
+	Aapt     string
+	SoongZip string
+	Zip2zip  string
 
-	VerifyUsesLibraries android.Path
-	ConstructContext    android.Path
+	VerifyUsesLibraries string
+	ConstructContext    string
 }
 
 type ModuleConfig struct {
 	Name            string
 	DexLocation     string // dex location on device
-	BuildPath       android.OutputPath
-	DexPath         android.Path
+	BuildPath       string
+	DexPath         string
 	UncompressedDex bool
 	HasApkLibraries bool
 	PreoptFlags     []string
 
-	ProfileClassListing  android.OptionalPath
+	ProfileClassListing  string
 	ProfileIsTextListing bool
 
 	EnforceUsesLibraries  bool
 	OptionalUsesLibraries []string
 	UsesLibraries         []string
-	LibraryPaths          map[string]android.Path
+	LibraryPaths          map[string]string
 
 	Archs           []android.ArchType
-	DexPreoptImages []android.Path
+	DexPreoptImages []string
 
-	PreoptBootClassPathDexFiles     android.Paths // file paths of boot class path files
-	PreoptBootClassPathDexLocations []string      // virtual locations of boot class path files
+	PreoptBootClassPathDexFiles     []string // file paths of boot class path files
+	PreoptBootClassPathDexLocations []string // virtual locations of boot class path files
 
 	PreoptExtractedApk bool // Overrides OnlyPreoptModules
 
@@ -130,137 +128,24 @@
 	PresignedPrebuilt bool
 
 	NoStripping     bool
-	StripInputPath  android.Path
-	StripOutputPath android.WritablePath
+	StripInputPath  string
+	StripOutputPath string
 }
 
-func constructPath(ctx android.PathContext, path string) android.Path {
-	buildDirPrefix := ctx.Config().BuildDir() + "/"
-	if path == "" {
-		return nil
-	} else if strings.HasPrefix(path, buildDirPrefix) {
-		return android.PathForOutput(ctx, strings.TrimPrefix(path, buildDirPrefix))
-	} else {
-		return android.PathForSource(ctx, path)
-	}
+func LoadGlobalConfig(path string) (GlobalConfig, error) {
+	config := GlobalConfig{}
+	err := loadConfig(path, &config)
+	return config, err
 }
 
-func constructPaths(ctx android.PathContext, paths []string) android.Paths {
-	var ret android.Paths
-	for _, path := range paths {
-		ret = append(ret, constructPath(ctx, path))
-	}
-	return ret
+func LoadModuleConfig(path string) (ModuleConfig, error) {
+	config := ModuleConfig{}
+	err := loadConfig(path, &config)
+	return config, err
 }
 
-func constructPathMap(ctx android.PathContext, paths map[string]string) map[string]android.Path {
-	ret := map[string]android.Path{}
-	for key, path := range paths {
-		ret[key] = constructPath(ctx, path)
-	}
-	return ret
-}
-
-func constructWritablePath(ctx android.PathContext, path string) android.WritablePath {
-	if path == "" {
-		return nil
-	}
-	return constructPath(ctx, path).(android.WritablePath)
-}
-
-// LoadGlobalConfig reads the global dexpreopt.config file into a GlobalConfig struct.  It is used directly in Soong
-// and in dexpreopt_gen called from Make to read the $OUT/dexpreopt.config written by Make.
-func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, error) {
-	type GlobalJSONConfig struct {
-		GlobalConfig
-
-		// Copies of entries in GlobalConfig that are not constructable without extra parameters.  They will be
-		// used to construct the real value manually below.
-		DirtyImageObjects string
-		PreloadedClasses  string
-		BootImageProfiles []string
-
-		Tools struct {
-			Profman  string
-			Dex2oat  string
-			Aapt     string
-			SoongZip string
-			Zip2zip  string
-
-			VerifyUsesLibraries string
-			ConstructContext    string
-		}
-	}
-
-	config := GlobalJSONConfig{}
-	err := loadConfig(ctx, path, &config)
-	if err != nil {
-		return config.GlobalConfig, err
-	}
-
-	// Construct paths that require a PathContext.
-	config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
-	config.GlobalConfig.PreloadedClasses = android.OptionalPathForPath(constructPath(ctx, config.PreloadedClasses))
-	config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
-
-	config.GlobalConfig.Tools.Profman = constructPath(ctx, config.Tools.Profman)
-	config.GlobalConfig.Tools.Dex2oat = constructPath(ctx, config.Tools.Dex2oat)
-	config.GlobalConfig.Tools.Aapt = constructPath(ctx, config.Tools.Aapt)
-	config.GlobalConfig.Tools.SoongZip = constructPath(ctx, config.Tools.SoongZip)
-	config.GlobalConfig.Tools.Zip2zip = constructPath(ctx, config.Tools.Zip2zip)
-	config.GlobalConfig.Tools.VerifyUsesLibraries = constructPath(ctx, config.Tools.VerifyUsesLibraries)
-	config.GlobalConfig.Tools.ConstructContext = constructPath(ctx, config.Tools.ConstructContext)
-
-	return config.GlobalConfig, nil
-}
-
-// LoadModuleConfig reads a per-module dexpreopt.config file into a ModuleConfig struct.  It is not used in Soong, which
-// receives a ModuleConfig struct directly from java/dexpreopt.go.  It is used in dexpreopt_gen called from oMake to
-// read the module dexpreopt.config written by Make.
-func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error) {
-	type ModuleJSONConfig struct {
-		ModuleConfig
-
-		// Copies of entries in ModuleConfig that are not constructable without extra parameters.  They will be
-		// used to construct the real value manually below.
-		BuildPath                   string
-		DexPath                     string
-		ProfileClassListing         string
-		LibraryPaths                map[string]string
-		DexPreoptImages             []string
-		PreoptBootClassPathDexFiles []string
-		StripInputPath              string
-		StripOutputPath             string
-	}
-
-	config := ModuleJSONConfig{}
-
-	err := loadConfig(ctx, path, &config)
-	if err != nil {
-		return config.ModuleConfig, err
-	}
-
-	// Construct paths that require a PathContext.
-	config.ModuleConfig.BuildPath = constructPath(ctx, config.BuildPath).(android.OutputPath)
-	config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath)
-	config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
-	config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths)
-	config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
-	config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
-	config.ModuleConfig.StripInputPath = constructPath(ctx, config.StripInputPath)
-	config.ModuleConfig.StripOutputPath = constructWritablePath(ctx, config.StripOutputPath)
-
-	return config.ModuleConfig, nil
-}
-
-func loadConfig(ctx android.PathContext, path string, config interface{}) error {
-	r, err := ctx.Fs().Open(path)
-	if err != nil {
-		return err
-	}
-	defer r.Close()
-
-	data, err := ioutil.ReadAll(r)
+func loadConfig(path string, config interface{}) error {
+	data, err := ioutil.ReadFile(path)
 	if err != nil {
 		return err
 	}
@@ -272,56 +157,3 @@
 
 	return nil
 }
-
-func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
-	return GlobalConfig{
-		DefaultNoStripping:                 false,
-		DisablePreoptModules:               nil,
-		OnlyPreoptBootImageAndSystemServer: false,
-		HasSystemOther:                     false,
-		PatternsOnSystemOther:              nil,
-		DisableGenerateProfile:             false,
-		BootJars:                           nil,
-		RuntimeApexJars:                    nil,
-		ProductUpdatableBootModules:        nil,
-		ProductUpdatableBootLocations:      nil,
-		SystemServerJars:                   nil,
-		SystemServerApps:                   nil,
-		SpeedApps:                          nil,
-		PreoptFlags:                        nil,
-		DefaultCompilerFilter:              "",
-		SystemServerCompilerFilter:         "",
-		GenerateDMFiles:                    false,
-		NeverAllowStripping:                false,
-		NoDebugInfo:                        false,
-		AlwaysSystemServerDebugInfo:        false,
-		NeverSystemServerDebugInfo:         false,
-		AlwaysOtherDebugInfo:               false,
-		NeverOtherDebugInfo:                false,
-		MissingUsesLibraries:               nil,
-		IsEng:                              false,
-		SanitizeLite:                       false,
-		DefaultAppImages:                   false,
-		Dex2oatXmx:                         "",
-		Dex2oatXms:                         "",
-		EmptyDirectory:                     "empty_dir",
-		CpuVariant:                         nil,
-		InstructionSetFeatures:             nil,
-		DirtyImageObjects:                  android.OptionalPath{},
-		PreloadedClasses:                   android.OptionalPath{},
-		BootImageProfiles:                  nil,
-		UseProfileForBootImage:             false,
-		BootFlags:                          "",
-		Dex2oatImageXmx:                    "",
-		Dex2oatImageXms:                    "",
-		Tools: Tools{
-			Profman:             android.PathForTesting("profman"),
-			Dex2oat:             android.PathForTesting("dex2oat"),
-			Aapt:                android.PathForTesting("aapt"),
-			SoongZip:            android.PathForTesting("soong_zip"),
-			Zip2zip:             android.PathForTesting("zip2zip"),
-			VerifyUsesLibraries: android.PathForTesting("verify_uses_libraries.sh"),
-			ConstructContext:    android.PathForTesting("construct_context.sh"),
-		},
-	}
-}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 9e333c1..7fdfb49 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -37,7 +37,6 @@
 import (
 	"fmt"
 	"path/filepath"
-	"runtime"
 	"strings"
 
 	"android/soong/android"
@@ -53,9 +52,7 @@
 func GenerateStripRule(global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) {
 	defer func() {
 		if r := recover(); r != nil {
-			if _, ok := r.(runtime.Error); ok {
-				panic(r)
-			} else if e, ok := r.(error); ok {
+			if e, ok := r.(error); ok {
 				err = e
 				rule = nil
 			} else {
@@ -89,14 +86,10 @@
 
 // GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a
 // ModuleConfig.  The produced files and their install locations will be available through rule.Installs().
-func GenerateDexpreoptRule(ctx android.PathContext,
-	global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) {
-
+func GenerateDexpreoptRule(global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) {
 	defer func() {
 		if r := recover(); r != nil {
-			if _, ok := r.(runtime.Error); ok {
-				panic(r)
-			} else if e, ok := r.(error); ok {
+			if e, ok := r.(error); ok {
 				err = e
 				rule = nil
 			} else {
@@ -107,11 +100,11 @@
 
 	rule = android.NewRuleBuilder()
 
-	generateProfile := module.ProfileClassListing.Valid() && !global.DisableGenerateProfile
+	generateProfile := module.ProfileClassListing != "" && !global.DisableGenerateProfile
 
-	var profile android.WritablePath
+	var profile string
 	if generateProfile {
-		profile = profileCommand(ctx, global, module, rule)
+		profile = profileCommand(global, module, rule)
 	}
 
 	if !dexpreoptDisabled(global, module) {
@@ -125,7 +118,7 @@
 
 			for i, arch := range module.Archs {
 				image := module.DexPreoptImages[i]
-				dexpreoptCommand(ctx, global, module, rule, arch, profile, image, appImage, generateDM)
+				dexpreoptCommand(global, module, rule, arch, profile, image, appImage, generateDM)
 			}
 		}
 	}
@@ -150,10 +143,8 @@
 	return false
 }
 
-func profileCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig,
-	rule *android.RuleBuilder) android.WritablePath {
-
-	profilePath := module.BuildPath.InSameDir(ctx, "profile.prof")
+func profileCommand(global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder) string {
+	profilePath := filepath.Join(filepath.Dir(module.BuildPath), "profile.prof")
 	profileInstalledPath := module.DexLocation + ".prof"
 
 	if !module.ProfileIsTextListing {
@@ -167,13 +158,13 @@
 	if module.ProfileIsTextListing {
 		// The profile is a test listing of classes (used for framework jars).
 		// We need to generate the actual binary profile before being able to compile.
-		cmd.FlagWithInput("--create-profile-from=", module.ProfileClassListing.Path())
+		cmd.FlagWithInput("--create-profile-from=", module.ProfileClassListing)
 	} else {
 		// The profile is binary profile (used for apps). Run it through profman to
 		// ensure the profile keys match the apk.
 		cmd.
 			Flag("--copy-and-update-profile-key").
-			FlagWithInput("--profile-file=", module.ProfileClassListing.Path())
+			FlagWithInput("--profile-file=", module.ProfileClassListing)
 	}
 
 	cmd.
@@ -189,8 +180,8 @@
 	return profilePath
 }
 
-func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder,
-	arch android.ArchType, profile, bootImage android.Path, appImage, generateDM bool) {
+func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder,
+	arch android.ArchType, profile, bootImage string, appImage, generateDM bool) {
 
 	// HACK: make soname in Soong-generated .odex files match Make.
 	base := filepath.Base(module.DexLocation)
@@ -208,21 +199,21 @@
 			pathtools.ReplaceExtension(filepath.Base(path), "odex"))
 	}
 
-	odexPath := module.BuildPath.InSameDir(ctx, "oat", arch.String(), pathtools.ReplaceExtension(base, "odex"))
+	odexPath := toOdexPath(filepath.Join(filepath.Dir(module.BuildPath), base))
 	odexInstallPath := toOdexPath(module.DexLocation)
 	if odexOnSystemOther(module, global) {
 		odexInstallPath = strings.Replace(odexInstallPath, SystemPartition, SystemOtherPartition, 1)
 	}
 
-	vdexPath := odexPath.ReplaceExtension(ctx, "vdex")
+	vdexPath := pathtools.ReplaceExtension(odexPath, "vdex")
 	vdexInstallPath := pathtools.ReplaceExtension(odexInstallPath, "vdex")
 
-	invocationPath := odexPath.ReplaceExtension(ctx, "invocation")
+	invocationPath := pathtools.ReplaceExtension(odexPath, "invocation")
 
 	// bootImage is .../dex_bootjars/system/framework/arm64/boot.art, but dex2oat wants
 	// .../dex_bootjars/system/framework/boot.art on the command line
 	var bootImageLocation string
-	if bootImage != nil {
+	if bootImage != "" {
 		bootImageLocation = PathToLocation(bootImage, arch)
 	}
 
@@ -236,21 +227,19 @@
 	var filteredOptionalUsesLibs []string
 
 	// The class loader context using paths in the build
-	var classLoaderContextHost android.Paths
+	var classLoaderContextHost []string
 
 	// The class loader context using paths as they will be on the device
 	var classLoaderContextTarget []string
 
 	// Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 28
-	var conditionalClassLoaderContextHost28 android.Paths
+	var conditionalClassLoaderContextHost28 []string
 	var conditionalClassLoaderContextTarget28 []string
 
 	// Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 29
-	var conditionalClassLoaderContextHost29 android.Paths
+	var conditionalClassLoaderContextHost29 []string
 	var conditionalClassLoaderContextTarget29 []string
 
-	var classLoaderContextHostString string
-
 	if module.EnforceUsesLibraries {
 		verifyUsesLibs = copyOf(module.UsesLibraries)
 		verifyOptionalUsesLibs = copyOf(module.OptionalUsesLibraries)
@@ -292,41 +281,31 @@
 			pathForLibrary(module, hidlBase))
 		conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
 			filepath.Join("/system/framework", hidlBase+".jar"))
-
-		classLoaderContextHostString = strings.Join(classLoaderContextHost.Strings(), ":")
 	} else {
 		// 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 &.
-		classLoaderContextHostString = `\&`
+		classLoaderContextHost = []string{`\&`}
 	}
 
-	rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
+	rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath))
 	rule.Command().FlagWithOutput("rm -f ", odexPath)
 	// Set values in the environment of the rule.  These may be modified by construct_context.sh.
-	rule.Command().FlagWithArg("class_loader_context_arg=--class-loader-context=", classLoaderContextHostString)
+	rule.Command().FlagWithArg("class_loader_context_arg=--class-loader-context=",
+		strings.Join(classLoaderContextHost, ":"))
 	rule.Command().Text(`stored_class_loader_context_arg=""`)
 
 	if module.EnforceUsesLibraries {
 		rule.Command().Textf(`uses_library_names="%s"`, strings.Join(verifyUsesLibs, " "))
 		rule.Command().Textf(`optional_uses_library_names="%s"`, strings.Join(verifyOptionalUsesLibs, " "))
 		rule.Command().Textf(`aapt_binary="%s"`, global.Tools.Aapt)
-		rule.Command().Textf(`dex_preopt_host_libraries="%s"`,
-			strings.Join(classLoaderContextHost.Strings(), " ")).
-			Implicits(classLoaderContextHost)
-		rule.Command().Textf(`dex_preopt_target_libraries="%s"`,
-			strings.Join(classLoaderContextTarget, " "))
-		rule.Command().Textf(`conditional_host_libs_28="%s"`,
-			strings.Join(conditionalClassLoaderContextHost28.Strings(), " ")).
-			Implicits(conditionalClassLoaderContextHost28)
-		rule.Command().Textf(`conditional_target_libs_28="%s"`,
-			strings.Join(conditionalClassLoaderContextTarget28, " "))
-		rule.Command().Textf(`conditional_host_libs_29="%s"`,
-			strings.Join(conditionalClassLoaderContextHost29.Strings(), " ")).
-			Implicits(conditionalClassLoaderContextHost29)
-		rule.Command().Textf(`conditional_target_libs_29="%s"`,
-			strings.Join(conditionalClassLoaderContextTarget29, " "))
+		rule.Command().Textf(`dex_preopt_host_libraries="%s"`, strings.Join(classLoaderContextHost, " "))
+		rule.Command().Textf(`dex_preopt_target_libraries="%s"`, strings.Join(classLoaderContextTarget, " "))
+		rule.Command().Textf(`conditional_host_libs_28="%s"`, strings.Join(conditionalClassLoaderContextHost28, " "))
+		rule.Command().Textf(`conditional_target_libs_28="%s"`, strings.Join(conditionalClassLoaderContextTarget28, " "))
+		rule.Command().Textf(`conditional_host_libs_29="%s"`, strings.Join(conditionalClassLoaderContextHost29, " "))
+		rule.Command().Textf(`conditional_target_libs_29="%s"`, strings.Join(conditionalClassLoaderContextTarget29, " "))
 		rule.Command().Text("source").Tool(global.Tools.VerifyUsesLibraries).Input(module.DexPath)
 		rule.Command().Text("source").Tool(global.Tools.ConstructContext)
 	}
@@ -385,7 +364,7 @@
 			// Apps loaded into system server, and apps the product default to being compiled with the
 			// 'speed' compiler filter.
 			compilerFilter = "speed"
-		} else if profile != nil {
+		} else if profile != "" {
 			// For non system server jars, use speed-profile when we have a profile.
 			compilerFilter = "speed-profile"
 		} else if global.DefaultCompilerFilter != "" {
@@ -398,9 +377,9 @@
 
 	if generateDM {
 		cmd.FlagWithArg("--copy-dex-files=", "false")
-		dmPath := module.BuildPath.InSameDir(ctx, "generated.dm")
+		dmPath := filepath.Join(filepath.Dir(module.BuildPath), "generated.dm")
 		dmInstalledPath := pathtools.ReplaceExtension(module.DexLocation, "dm")
-		tmpPath := module.BuildPath.InSameDir(ctx, "primary.vdex")
+		tmpPath := filepath.Join(filepath.Dir(module.BuildPath), "primary.vdex")
 		rule.Command().Text("cp -f").Input(vdexPath).Output(tmpPath)
 		rule.Command().Tool(global.Tools.SoongZip).
 			FlagWithArg("-L", "9").
@@ -449,15 +428,15 @@
 	cmd.FlagWithArg("--compilation-reason=", "prebuilt")
 
 	if appImage {
-		appImagePath := odexPath.ReplaceExtension(ctx, "art")
+		appImagePath := pathtools.ReplaceExtension(odexPath, "art")
 		appImageInstallPath := pathtools.ReplaceExtension(odexInstallPath, "art")
 		cmd.FlagWithOutput("--app-image-file=", appImagePath).
 			FlagWithArg("--image-format=", "lz4")
 		rule.Install(appImagePath, appImageInstallPath)
 	}
 
-	if profile != nil {
-		cmd.FlagWithInput("--profile-file=", profile)
+	if profile != "" {
+		cmd.FlagWithArg("--profile-file=", profile)
 	}
 
 	rule.Install(odexPath, odexInstallPath)
@@ -543,17 +522,17 @@
 }
 
 // PathToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art
-func PathToLocation(path android.Path, arch android.ArchType) string {
-	pathArch := filepath.Base(filepath.Dir(path.String()))
+func PathToLocation(path string, arch android.ArchType) string {
+	pathArch := filepath.Base(filepath.Dir(path))
 	if pathArch != arch.String() {
 		panic(fmt.Errorf("last directory in %q must be %q", path, arch.String()))
 	}
-	return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String()))
+	return filepath.Join(filepath.Dir(filepath.Dir(path)), filepath.Base(path))
 }
 
-func pathForLibrary(module ModuleConfig, lib string) android.Path {
-	path, ok := module.LibraryPaths[lib]
-	if !ok {
+func pathForLibrary(module ModuleConfig, lib string) string {
+	path := module.LibraryPaths[lib]
+	if path == "" {
 		panic(fmt.Errorf("unknown library path for %q", lib))
 	}
 	return path
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index c72f684..cc3c1f1 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -21,7 +21,6 @@
 	"os"
 	"path/filepath"
 	"runtime"
-	"strings"
 
 	"android/soong/android"
 	"android/soong/dexpreopt"
@@ -34,17 +33,8 @@
 	stripScriptPath     = flag.String("strip_script", "", "path to output strip script")
 	globalConfigPath    = flag.String("global", "", "path to global configuration file")
 	moduleConfigPath    = flag.String("module", "", "path to module configuration file")
-	outDir              = flag.String("out_dir", "", "path to output directory")
 )
 
-type pathContext struct {
-	config android.Config
-}
-
-func (x *pathContext) Fs() pathtools.FileSystem   { return pathtools.OsFs }
-func (x *pathContext) Config() android.Config     { return x.config }
-func (x *pathContext) AddNinjaFileDeps(...string) {}
-
 func main() {
 	flag.Parse()
 
@@ -76,26 +66,18 @@
 		usage("path to module configuration file is required")
 	}
 
-	ctx := &pathContext{android.TestConfig(*outDir, nil)}
-
-	globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath)
+	globalConfig, err := dexpreopt.LoadGlobalConfig(*globalConfigPath)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err)
 		os.Exit(2)
 	}
 
-	moduleConfig, err := dexpreopt.LoadModuleConfig(ctx, *moduleConfigPath)
+	moduleConfig, err := dexpreopt.LoadModuleConfig(*moduleConfigPath)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "error loading module config %q: %s\n", *moduleConfigPath, err)
 		os.Exit(2)
 	}
 
-	// This shouldn't be using *PathForTesting, but it's outside of soong_build so its OK for now.
-	moduleConfig.StripInputPath = android.PathForTesting("$1")
-	moduleConfig.StripOutputPath = android.WritablePathForTesting("$2")
-
-	moduleConfig.DexPath = android.PathForTesting("$1")
-
 	defer func() {
 		if r := recover(); r != nil {
 			switch x := r.(type) {
@@ -110,30 +92,30 @@
 		}
 	}()
 
-	writeScripts(ctx, globalConfig, moduleConfig, *dexpreoptScriptPath, *stripScriptPath)
+	writeScripts(globalConfig, moduleConfig, *dexpreoptScriptPath, *stripScriptPath)
 }
 
-func writeScripts(ctx android.PathContext, global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
+func writeScripts(global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
 	dexpreoptScriptPath, stripScriptPath string) {
-	dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, global, module)
+	dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(global, module)
 	if err != nil {
 		panic(err)
 	}
 
-	installDir := module.BuildPath.InSameDir(ctx, "dexpreopt_install")
+	installDir := filepath.Join(filepath.Dir(module.BuildPath), "dexpreopt_install")
 
-	dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir.String())
-	dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir.String())
+	dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir)
+	dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir)
 
 	for _, install := range dexpreoptRule.Installs() {
-		installPath := installDir.Join(ctx, strings.TrimPrefix(install.To, "/"))
-		dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String()))
+		installPath := filepath.Join(installDir, install.To)
+		dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath))
 		dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath)
 	}
 	dexpreoptRule.Command().Tool(global.Tools.SoongZip).
-		FlagWithArg("-o ", "$2").
-		FlagWithArg("-C ", installDir.String()).
-		FlagWithArg("-D ", installDir.String())
+		FlagWithOutput("-o ", "$2").
+		FlagWithArg("-C ", installDir).
+		FlagWithArg("-D ", installDir)
 
 	stripRule, err := dexpreopt.GenerateStripRule(global, module)
 	if err != nil {
@@ -157,7 +139,7 @@
 		for _, input := range rule.Inputs() {
 			// Assume the rule that ran the script already has a dependency on the input file passed on the
 			// command line.
-			if input.String() != "$1" {
+			if input != "$1" {
 				fmt.Fprintf(depFile, `    %s \`+"\n", input)
 			}
 		}
@@ -177,13 +159,13 @@
 	}
 
 	// The written scripts will assume the input is $1 and the output is $2
-	if module.DexPath.String() != "$1" {
+	if module.DexPath != "$1" {
 		panic(fmt.Errorf("module.DexPath must be '$1', was %q", module.DexPath))
 	}
-	if module.StripInputPath.String() != "$1" {
+	if module.StripInputPath != "$1" {
 		panic(fmt.Errorf("module.StripInputPath must be '$1', was %q", module.StripInputPath))
 	}
-	if module.StripOutputPath.String() != "$2" {
+	if module.StripOutputPath != "$2" {
 		panic(fmt.Errorf("module.StripOutputPath must be '$2', was %q", module.StripOutputPath))
 	}
 
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 2a58ab9..949f91f 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -21,47 +21,98 @@
 	"testing"
 )
 
-func testModuleConfig(ctx android.PathContext) ModuleConfig {
-	return ModuleConfig{
-		Name:                            "test",
-		DexLocation:                     "/system/app/test/test.apk",
-		BuildPath:                       android.PathForOutput(ctx, "test/test.apk"),
-		DexPath:                         android.PathForOutput(ctx, "test/dex/test.jar"),
-		UncompressedDex:                 false,
-		HasApkLibraries:                 false,
-		PreoptFlags:                     nil,
-		ProfileClassListing:             android.OptionalPath{},
-		ProfileIsTextListing:            false,
-		EnforceUsesLibraries:            false,
-		OptionalUsesLibraries:           nil,
-		UsesLibraries:                   nil,
-		LibraryPaths:                    nil,
-		Archs:                           []android.ArchType{android.Arm},
-		DexPreoptImages:                 android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
-		PreoptBootClassPathDexFiles:     nil,
-		PreoptBootClassPathDexLocations: nil,
-		PreoptExtractedApk:              false,
-		NoCreateAppImage:                false,
-		ForceCreateAppImage:             false,
-		PresignedPrebuilt:               false,
-		NoStripping:                     false,
-		StripInputPath:                  android.PathForOutput(ctx, "unstripped/test.apk"),
-		StripOutputPath:                 android.PathForOutput(ctx, "stripped/test.apk"),
-	}
+var testGlobalConfig = GlobalConfig{
+	DefaultNoStripping:                 false,
+	DisablePreoptModules:               nil,
+	OnlyPreoptBootImageAndSystemServer: false,
+	HasSystemOther:                     false,
+	PatternsOnSystemOther:              nil,
+	DisableGenerateProfile:             false,
+	BootJars:                           nil,
+	RuntimeApexJars:                    nil,
+	ProductUpdatableBootModules:        nil,
+	ProductUpdatableBootLocations:      nil,
+	SystemServerJars:                   nil,
+	SystemServerApps:                   nil,
+	SpeedApps:                          nil,
+	PreoptFlags:                        nil,
+	DefaultCompilerFilter:              "",
+	SystemServerCompilerFilter:         "",
+	GenerateDMFiles:                    false,
+	NeverAllowStripping:                false,
+	NoDebugInfo:                        false,
+	AlwaysSystemServerDebugInfo:        false,
+	NeverSystemServerDebugInfo:         false,
+	AlwaysOtherDebugInfo:               false,
+	NeverOtherDebugInfo:                false,
+	MissingUsesLibraries:               nil,
+	IsEng:                              false,
+	SanitizeLite:                       false,
+	DefaultAppImages:                   false,
+	Dex2oatXmx:                         "",
+	Dex2oatXms:                         "",
+	EmptyDirectory:                     "",
+	CpuVariant:                         nil,
+	InstructionSetFeatures:             nil,
+	DirtyImageObjects:                  "",
+	PreloadedClasses:                   "",
+	BootImageProfiles:                  nil,
+	BootFlags:                          "",
+	Dex2oatImageXmx:                    "",
+	Dex2oatImageXms:                    "",
+	Tools: Tools{
+		Profman:             "profman",
+		Dex2oat:             "dex2oat",
+		Aapt:                "aapt",
+		SoongZip:            "soong_zip",
+		Zip2zip:             "zip2zip",
+		VerifyUsesLibraries: "verify_uses_libraries.sh",
+		ConstructContext:    "construct_context.sh",
+	},
+}
+
+var testModuleConfig = ModuleConfig{
+	Name:                            "",
+	DexLocation:                     "",
+	BuildPath:                       "",
+	DexPath:                         "",
+	UncompressedDex:                 false,
+	HasApkLibraries:                 false,
+	PreoptFlags:                     nil,
+	ProfileClassListing:             "",
+	ProfileIsTextListing:            false,
+	EnforceUsesLibraries:            false,
+	OptionalUsesLibraries:           nil,
+	UsesLibraries:                   nil,
+	LibraryPaths:                    nil,
+	Archs:                           []android.ArchType{android.Arm},
+	DexPreoptImages:                 []string{"system/framework/arm/boot.art"},
+	PreoptBootClassPathDexFiles:     nil,
+	PreoptBootClassPathDexLocations: nil,
+	PreoptExtractedApk:              false,
+	NoCreateAppImage:                false,
+	ForceCreateAppImage:             false,
+	PresignedPrebuilt:               false,
+	NoStripping:                     false,
+	StripInputPath:                  "",
+	StripOutputPath:                 "",
 }
 
 func TestDexPreopt(t *testing.T) {
-	ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
-	global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+	global, module := testGlobalConfig, testModuleConfig
 
-	rule, err := GenerateDexpreoptRule(ctx, global, module)
+	module.Name = "test"
+	module.DexLocation = "/system/app/test/test.apk"
+	module.BuildPath = "out/test/test.apk"
+
+	rule, err := GenerateDexpreoptRule(global, module)
 	if err != nil {
-		t.Fatal(err)
+		t.Error(err)
 	}
 
 	wantInstalls := android.RuleBuilderInstalls{
-		{android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system/app/test/oat/arm/test.odex"},
-		{android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system/app/test/oat/arm/test.vdex"},
+		{"out/test/oat/arm/package.odex", "/system/app/test/oat/arm/test.odex"},
+		{"out/test/oat/arm/package.vdex", "/system/app/test/oat/arm/test.vdex"},
 	}
 
 	if !reflect.DeepEqual(rule.Installs(), wantInstalls) {
@@ -71,11 +122,13 @@
 
 func TestDexPreoptStrip(t *testing.T) {
 	// Test that we panic if we strip in a configuration where stripping is not allowed.
-	ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
-	global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+	global, module := testGlobalConfig, testModuleConfig
 
 	global.NeverAllowStripping = true
 	module.NoStripping = false
+	module.Name = "test"
+	module.DexLocation = "/system/app/test/test.apk"
+	module.BuildPath = "out/test/test.apk"
 
 	_, err := GenerateStripRule(global, module)
 	if err == nil {
@@ -84,20 +137,23 @@
 }
 
 func TestDexPreoptSystemOther(t *testing.T) {
-	ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
-	global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+	global, module := testGlobalConfig, testModuleConfig
 
 	global.HasSystemOther = true
 	global.PatternsOnSystemOther = []string{"app/%"}
 
-	rule, err := GenerateDexpreoptRule(ctx, global, module)
+	module.Name = "test"
+	module.DexLocation = "/system/app/test/test.apk"
+	module.BuildPath = "out/test/test.apk"
+
+	rule, err := GenerateDexpreoptRule(global, module)
 	if err != nil {
-		t.Fatal(err)
+		t.Error(err)
 	}
 
 	wantInstalls := android.RuleBuilderInstalls{
-		{android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system_other/app/test/oat/arm/test.odex"},
-		{android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system_other/app/test/oat/arm/test.vdex"},
+		{"out/test/oat/arm/package.odex", "/system_other/app/test/oat/arm/test.odex"},
+		{"out/test/oat/arm/package.vdex", "/system_other/app/test/oat/arm/test.vdex"},
 	}
 
 	if !reflect.DeepEqual(rule.Installs(), wantInstalls) {
@@ -106,21 +162,23 @@
 }
 
 func TestDexPreoptProfile(t *testing.T) {
-	ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
-	global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+	global, module := testGlobalConfig, testModuleConfig
 
-	module.ProfileClassListing = android.OptionalPathForPath(android.PathForTesting("profile"))
+	module.Name = "test"
+	module.DexLocation = "/system/app/test/test.apk"
+	module.BuildPath = "out/test/test.apk"
+	module.ProfileClassListing = "profile"
 
-	rule, err := GenerateDexpreoptRule(ctx, global, module)
+	rule, err := GenerateDexpreoptRule(global, module)
 	if err != nil {
-		t.Fatal(err)
+		t.Error(err)
 	}
 
 	wantInstalls := android.RuleBuilderInstalls{
-		{android.PathForOutput(ctx, "test/profile.prof"), "/system/app/test/test.apk.prof"},
-		{android.PathForOutput(ctx, "test/oat/arm/package.art"), "/system/app/test/oat/arm/test.art"},
-		{android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system/app/test/oat/arm/test.odex"},
-		{android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system/app/test/oat/arm/test.vdex"},
+		{"out/test/profile.prof", "/system/app/test/test.apk.prof"},
+		{"out/test/oat/arm/package.art", "/system/app/test/oat/arm/test.art"},
+		{"out/test/oat/arm/package.odex", "/system/app/test/oat/arm/test.odex"},
+		{"out/test/oat/arm/package.vdex", "/system/app/test/oat/arm/test.vdex"},
 	}
 
 	if !reflect.DeepEqual(rule.Installs(), wantInstalls) {
@@ -154,24 +212,29 @@
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
 
-			ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
-			global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
+			global, module := testGlobalConfig, testModuleConfig
+
+			module.Name = "test"
+			module.DexLocation = "/system/app/test/test.apk"
+			module.BuildPath = "out/test/test.apk"
+			module.StripInputPath = "$1"
+			module.StripOutputPath = "$2"
 
 			test.setup(&global, &module)
 
 			rule, err := GenerateStripRule(global, module)
 			if err != nil {
-				t.Fatal(err)
+				t.Error(err)
 			}
 
 			if test.strip {
-				want := `zip2zip -i out/unstripped/test.apk -o out/stripped/test.apk -x "classes*.dex"`
+				want := `zip2zip -i $1 -o $2 -x "classes*.dex"`
 				if len(rule.Commands()) < 1 || !strings.Contains(rule.Commands()[0], want) {
 					t.Errorf("\nwant commands[0] to have:\n   %v\ngot:\n   %v", want, rule.Commands()[0])
 				}
 			} else {
 				wantCommands := []string{
-					"cp -f out/unstripped/test.apk out/stripped/test.apk",
+					"cp -f $1 $2",
 				}
 				if !reflect.DeepEqual(rule.Commands(), wantCommands) {
 					t.Errorf("\nwant commands:\n   %v\ngot:\n   %v", wantCommands, rule.Commands())