diff --git a/android/config.go b/android/config.go
index 8c7d789..202898b 100644
--- a/android/config.go
+++ b/android/config.go
@@ -19,7 +19,6 @@
 
 import (
 	"encoding/json"
-	"errors"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -341,123 +340,6 @@
 	}
 }
 
-// TestConfig returns a Config object for testing.
-func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
-	envCopy := make(map[string]string)
-	for k, v := range env {
-		envCopy[k] = v
-	}
-
-	// Copy the real PATH value to the test environment, it's needed by
-	// NonHermeticHostSystemTool() used in x86_darwin_host.go
-	envCopy["PATH"] = os.Getenv("PATH")
-
-	config := &config{
-		productVariables: productVariables{
-			DeviceName:                          stringPtr("test_device"),
-			DeviceProduct:                       stringPtr("test_product"),
-			Platform_sdk_version:                intPtr(30),
-			Platform_sdk_codename:               stringPtr("S"),
-			Platform_base_sdk_extension_version: intPtr(1),
-			Platform_version_active_codenames:   []string{"S", "Tiramisu"},
-			DeviceSystemSdkVersions:             []string{"14", "15"},
-			Platform_systemsdk_versions:         []string{"29", "30"},
-			AAPTConfig:                          []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
-			AAPTPreferredConfig:                 stringPtr("xhdpi"),
-			AAPTCharacteristics:                 stringPtr("nosdcard"),
-			AAPTPrebuiltDPI:                     []string{"xhdpi", "xxhdpi"},
-			UncompressPrivAppDex:                boolPtr(true),
-			ShippingApiLevel:                    stringPtr("30"),
-		},
-
-		outDir:       buildDir,
-		soongOutDir:  filepath.Join(buildDir, "soong"),
-		captureBuild: true,
-		env:          envCopy,
-
-		// Set testAllowNonExistentPaths so that test contexts don't need to specify every path
-		// passed to PathForSource or PathForModuleSrc.
-		TestAllowNonExistentPaths: true,
-
-		BazelContext:              noopBazelContext{},
-		mixedBuildDisabledModules: make(map[string]struct{}),
-		mixedBuildEnabledModules:  make(map[string]struct{}),
-	}
-	config.deviceConfig = &deviceConfig{
-		config: config,
-	}
-	config.TestProductVariables = &config.productVariables
-
-	config.mockFileSystem(bp, fs)
-
-	determineBuildOS(config)
-
-	return Config{config}
-}
-
-func modifyTestConfigToSupportArchMutator(testConfig Config) {
-	config := testConfig.config
-
-	config.Targets = map[OsType][]Target{
-		Android: []Target{
-			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
-			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
-		},
-		config.BuildOS: []Target{
-			{config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
-			{config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
-		},
-	}
-
-	if runtime.GOOS == "darwin" {
-		config.Targets[config.BuildOS] = config.Targets[config.BuildOS][:1]
-	}
-
-	config.BuildOSTarget = config.Targets[config.BuildOS][0]
-	config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
-	config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
-	config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
-	config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
-	config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
-	config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
-	config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
-}
-
-func modifyTestConfigForMusl(config Config) {
-	delete(config.Targets, config.BuildOS)
-	config.productVariables.HostMusl = boolPtr(true)
-	determineBuildOS(config.config)
-	config.Targets[config.BuildOS] = []Target{
-		{config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
-		{config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
-	}
-
-	config.BuildOSTarget = config.Targets[config.BuildOS][0]
-	config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
-}
-
-// TestArchConfig returns a Config object suitable for using for tests that
-// need to run the arch mutator.
-func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
-	testConfig := TestConfig(buildDir, env, bp, fs)
-	modifyTestConfigToSupportArchMutator(testConfig)
-	return testConfig
-}
-
-// ConfigForAdditionalRun is a config object which is "reset" for another
-// bootstrap run. Only per-run data is reset. Data which needs to persist across
-// multiple runs in the same program execution is carried over (such as Bazel
-// context or environment deps).
-func ConfigForAdditionalRun(c Config) (Config, error) {
-	newConfig, err := NewConfig(c.moduleListFile, c.runGoTests, c.outDir, c.soongOutDir, c.env)
-	if err != nil {
-		return Config{}, err
-	}
-	newConfig.BazelContext = c.BazelContext
-	newConfig.envDeps = c.envDeps
-	return newConfig, nil
-}
-
 // NewConfig creates a new Config object. The srcDir argument specifies the path
 // to the root source directory. It also loads the config file, if found.
 func NewConfig(moduleListFile string, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string) (Config, error) {
@@ -740,7 +622,8 @@
 // these per device type.
 //
 // NOTE: Do not base conditional logic on this value. It may break product
-//       inheritance.
+//
+//	inheritance.
 func (c *config) DeviceProduct() string {
 	return *c.productVariables.DeviceProduct
 }
@@ -1729,316 +1612,6 @@
 	return c.productVariables.IgnorePrefer32OnDevice
 }
 
-// The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
-// Such lists are used in the build system for things like bootclasspath jars or system server jars.
-// The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
-// module name. The pairs come from Make product variables as a list of colon-separated strings.
-//
-// Examples:
-//   - "com.android.art:core-oj"
-//   - "platform:framework"
-//   - "system_ext:foo"
-//
-type ConfiguredJarList struct {
-	// A list of apex components, which can be an apex name,
-	// or special names like "platform" or "system_ext".
-	apexes []string
-
-	// A list of jar module name components.
-	jars []string
-}
-
-// Len returns the length of the list of jars.
-func (l *ConfiguredJarList) Len() int {
-	return len(l.jars)
-}
-
-// Jar returns the idx-th jar component of (apex, jar) pairs.
-func (l *ConfiguredJarList) Jar(idx int) string {
-	return l.jars[idx]
-}
-
-// Apex returns the idx-th apex component of (apex, jar) pairs.
-func (l *ConfiguredJarList) Apex(idx int) string {
-	return l.apexes[idx]
-}
-
-// ContainsJar returns true if the (apex, jar) pairs contains a pair with the
-// given jar module name.
-func (l *ConfiguredJarList) ContainsJar(jar string) bool {
-	return InList(jar, l.jars)
-}
-
-// If the list contains the given (apex, jar) pair.
-func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool {
-	for i := 0; i < l.Len(); i++ {
-		if apex == l.apexes[i] && jar == l.jars[i] {
-			return true
-		}
-	}
-	return false
-}
-
-// ApexOfJar returns the apex component of the first pair with the given jar name on the list, or
-// an empty string if not found.
-func (l *ConfiguredJarList) ApexOfJar(jar string) string {
-	if idx := IndexList(jar, l.jars); idx != -1 {
-		return l.Apex(IndexList(jar, l.jars))
-	}
-	return ""
-}
-
-// IndexOfJar returns the first pair with the given jar name on the list, or -1
-// if not found.
-func (l *ConfiguredJarList) IndexOfJar(jar string) int {
-	return IndexList(jar, l.jars)
-}
-
-func copyAndAppend(list []string, item string) []string {
-	// Create the result list to be 1 longer than the input.
-	result := make([]string, len(list)+1)
-
-	// Copy the whole input list into the result.
-	count := copy(result, list)
-
-	// Insert the extra item at the end.
-	result[count] = item
-
-	return result
-}
-
-// Append an (apex, jar) pair to the list.
-func (l *ConfiguredJarList) Append(apex string, jar string) ConfiguredJarList {
-	// Create a copy of the backing arrays before appending to avoid sharing backing
-	// arrays that are mutated across instances.
-	apexes := copyAndAppend(l.apexes, apex)
-	jars := copyAndAppend(l.jars, jar)
-
-	return ConfiguredJarList{apexes, jars}
-}
-
-// Append a list of (apex, jar) pairs to the list.
-func (l *ConfiguredJarList) AppendList(other *ConfiguredJarList) ConfiguredJarList {
-	apexes := make([]string, 0, l.Len()+other.Len())
-	jars := make([]string, 0, l.Len()+other.Len())
-
-	apexes = append(apexes, l.apexes...)
-	jars = append(jars, l.jars...)
-
-	apexes = append(apexes, other.apexes...)
-	jars = append(jars, other.jars...)
-
-	return ConfiguredJarList{apexes, jars}
-}
-
-// RemoveList filters out a list of (apex, jar) pairs from the receiving list of pairs.
-func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) ConfiguredJarList {
-	apexes := make([]string, 0, l.Len())
-	jars := make([]string, 0, l.Len())
-
-	for i, jar := range l.jars {
-		apex := l.apexes[i]
-		if !list.containsApexJarPair(apex, jar) {
-			apexes = append(apexes, apex)
-			jars = append(jars, jar)
-		}
-	}
-
-	return ConfiguredJarList{apexes, jars}
-}
-
-// Filter keeps the entries if a jar appears in the given list of jars to keep. Returns a new list
-// and any remaining jars that are not on this list.
-func (l *ConfiguredJarList) Filter(jarsToKeep []string) (ConfiguredJarList, []string) {
-	var apexes []string
-	var jars []string
-
-	for i, jar := range l.jars {
-		if InList(jar, jarsToKeep) {
-			apexes = append(apexes, l.apexes[i])
-			jars = append(jars, jar)
-		}
-	}
-
-	return ConfiguredJarList{apexes, jars}, RemoveListFromList(jarsToKeep, jars)
-}
-
-// CopyOfJars returns a copy of the list of strings containing jar module name
-// components.
-func (l *ConfiguredJarList) CopyOfJars() []string {
-	return CopyOf(l.jars)
-}
-
-// CopyOfApexJarPairs returns a copy of the list of strings with colon-separated
-// (apex, jar) pairs.
-func (l *ConfiguredJarList) CopyOfApexJarPairs() []string {
-	pairs := make([]string, 0, l.Len())
-
-	for i, jar := range l.jars {
-		apex := l.apexes[i]
-		pairs = append(pairs, apex+":"+jar)
-	}
-
-	return pairs
-}
-
-// BuildPaths returns a list of build paths based on the given directory prefix.
-func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths {
-	paths := make(WritablePaths, l.Len())
-	for i, jar := range l.jars {
-		paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar")
-	}
-	return paths
-}
-
-// BuildPathsByModule returns a map from module name to build paths based on the given directory
-// prefix.
-func (l *ConfiguredJarList) BuildPathsByModule(ctx PathContext, dir OutputPath) map[string]WritablePath {
-	paths := map[string]WritablePath{}
-	for _, jar := range l.jars {
-		paths[jar] = dir.Join(ctx, ModuleStem(jar)+".jar")
-	}
-	return paths
-}
-
-// UnmarshalJSON converts JSON configuration from raw bytes into a
-// ConfiguredJarList structure.
-func (l *ConfiguredJarList) UnmarshalJSON(b []byte) error {
-	// Try and unmarshal into a []string each item of which contains a pair
-	// <apex>:<jar>.
-	var list []string
-	err := json.Unmarshal(b, &list)
-	if err != nil {
-		// Did not work so return
-		return err
-	}
-
-	apexes, jars, err := splitListOfPairsIntoPairOfLists(list)
-	if err != nil {
-		return err
-	}
-	l.apexes = apexes
-	l.jars = jars
-	return nil
-}
-
-func (l *ConfiguredJarList) MarshalJSON() ([]byte, error) {
-	if len(l.apexes) != len(l.jars) {
-		return nil, errors.New(fmt.Sprintf("Inconsistent ConfiguredJarList: apexes: %q, jars: %q", l.apexes, l.jars))
-	}
-
-	list := make([]string, 0, len(l.apexes))
-
-	for i := 0; i < len(l.apexes); i++ {
-		list = append(list, l.apexes[i]+":"+l.jars[i])
-	}
-
-	return json.Marshal(list)
-}
-
-// ModuleStem hardcodes the stem of framework-minus-apex to return "framework".
-//
-// TODO(b/139391334): hard coded until we find a good way to query the stem of a
-// module before any other mutators are run.
-func ModuleStem(module string) string {
-	if module == "framework-minus-apex" {
-		return "framework"
-	}
-	return module
-}
-
-// DevicePaths computes the on-device paths for the list of (apex, jar) pairs,
-// based on the operating system.
-func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string {
-	paths := make([]string, l.Len())
-	for i, jar := range l.jars {
-		apex := l.apexes[i]
-		name := ModuleStem(jar) + ".jar"
-
-		var subdir string
-		if apex == "platform" {
-			subdir = "system/framework"
-		} else if apex == "system_ext" {
-			subdir = "system_ext/framework"
-		} else {
-			subdir = filepath.Join("apex", apex, "javalib")
-		}
-
-		if ostype.Class == Host {
-			paths[i] = filepath.Join(cfg.Getenv("OUT_DIR"), "host", cfg.PrebuiltOS(), subdir, name)
-		} else {
-			paths[i] = filepath.Join("/", subdir, name)
-		}
-	}
-	return paths
-}
-
-func (l *ConfiguredJarList) String() string {
-	var pairs []string
-	for i := 0; i < l.Len(); i++ {
-		pairs = append(pairs, l.apexes[i]+":"+l.jars[i])
-	}
-	return strings.Join(pairs, ",")
-}
-
-func splitListOfPairsIntoPairOfLists(list []string) ([]string, []string, error) {
-	// Now we need to populate this list by splitting each item in the slice of
-	// pairs and appending them to the appropriate list of apexes or jars.
-	apexes := make([]string, len(list))
-	jars := make([]string, len(list))
-
-	for i, apexjar := range list {
-		apex, jar, err := splitConfiguredJarPair(apexjar)
-		if err != nil {
-			return nil, nil, err
-		}
-		apexes[i] = apex
-		jars[i] = jar
-	}
-
-	return apexes, jars, nil
-}
-
-// Expected format for apexJarValue = <apex name>:<jar name>
-func splitConfiguredJarPair(str string) (string, string, error) {
-	pair := strings.SplitN(str, ":", 2)
-	if len(pair) == 2 {
-		apex := pair[0]
-		jar := pair[1]
-		if apex == "" {
-			return apex, jar, fmt.Errorf("invalid apex '%s' in <apex>:<jar> pair '%s', expected format: <apex>:<jar>", apex, str)
-		}
-		return apex, jar, nil
-	} else {
-		return "error-apex", "error-jar", fmt.Errorf("malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
-	}
-}
-
-// CreateTestConfiguredJarList is a function to create ConfiguredJarList for tests.
-func CreateTestConfiguredJarList(list []string) ConfiguredJarList {
-	// Create the ConfiguredJarList in as similar way as it is created at runtime by marshalling to
-	// a json list of strings and then unmarshalling into a ConfiguredJarList instance.
-	b, err := json.Marshal(list)
-	if err != nil {
-		panic(err)
-	}
-
-	var jarList ConfiguredJarList
-	err = json.Unmarshal(b, &jarList)
-	if err != nil {
-		panic(err)
-	}
-
-	return jarList
-}
-
-// EmptyConfiguredJarList returns an empty jar list.
-func EmptyConfiguredJarList() ConfiguredJarList {
-	return ConfiguredJarList{}
-}
-
-var earlyBootJarsKey = NewOnceKey("earlyBootJars")
-
 func (c *config) BootJars() []string {
 	return c.Once(earlyBootJarsKey, func() interface{} {
 		list := c.productVariables.BootJars.CopyOfJars()
