Move dexpreopt image selection out of dexpreopt package

Instead of passing both the module and global dexpreopt image
selection into the dexpreopt package, determine the correct
dexpreopt image in the java package.

Also stop using the boot image "location" as an input, only
track the real path, and then convert it to the "location"
that dex2oat expects when constructing the command line.

Test: m checkbuild
Change-Id: I2be2b5917e09fd57428dab27849c0153fdc75722
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 319e36e..064992f 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -66,9 +66,9 @@
 
 	EmptyDirectory string // path to an empty directory
 
-	DefaultDexPreoptImageLocation map[string]string // default boot image location for each architecture
-	CpuVariant                    map[string]string // cpu variant for each architecture
-	InstructionSetFeatures        map[string]string // instruction set for each architecture
+	DefaultDexPreoptImage  map[string]string // default boot image location for each architecture
+	CpuVariant             map[string]string // cpu variant for each architecture
+	InstructionSetFeatures map[string]string // instruction set for each architecture
 
 	Tools Tools // paths to tools possibly used by the generated commands
 }
@@ -103,8 +103,8 @@
 	UsesLibraries         []string
 	LibraryPaths          map[string]string
 
-	Archs                  []string
-	DexPreoptImageLocation string
+	Archs           []string
+	DexPreoptImages []string
 
 	PreoptExtractedApk bool // Overrides OnlyPreoptModules
 
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index c38fbff..660a6d0 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -113,12 +113,9 @@
 
 			generateDM := shouldGenerateDM(module, global)
 
-			for _, arch := range module.Archs {
-				imageLocation := module.DexPreoptImageLocation
-				if imageLocation == "" {
-					imageLocation = global.DefaultDexPreoptImageLocation[arch]
-				}
-				dexpreoptCommand(global, module, rule, profile, arch, imageLocation, appImage, generateDM)
+			for i, arch := range module.Archs {
+				image := module.DexPreoptImages[i]
+				dexpreoptCommand(global, module, rule, profile, arch, image, appImage, generateDM)
 			}
 		}
 	}
@@ -181,7 +178,7 @@
 }
 
 func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder,
-	profile, arch, bootImageLocation string, appImage, generateDM bool) {
+	profile, arch, bootImage string, appImage, generateDM bool) {
 
 	// HACK: make soname in Soong-generated .odex files match Make.
 	base := filepath.Base(module.DexLocation)
@@ -213,11 +210,11 @@
 
 	invocationPath := pathtools.ReplaceExtension(odexPath, "invocation")
 
-	// bootImageLocation is $OUT/dex_bootjars/system/framework/boot.art, but dex2oat actually reads
-	// $OUT/dex_bootjars/system/framework/arm64/boot.art
-	var bootImagePath string
-	if bootImageLocation != "" {
-		bootImagePath = filepath.Join(filepath.Dir(bootImageLocation), arch, filepath.Base(bootImageLocation))
+	// 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 != "" {
+		bootImageLocation = PathToLocation(bootImage, arch)
 	}
 
 	// Lists of used and optional libraries from the build config to be verified against the manifest in the APK
@@ -325,7 +322,7 @@
 		Flag("--runtime-arg").FlagWithArg("-Xbootclasspath-locations:", bcp_locations).
 		Flag("${class_loader_context_arg}").
 		Flag("${stored_class_loader_context_arg}").
-		FlagWithArg("--boot-image=", bootImageLocation).Implicit(bootImagePath).
+		FlagWithArg("--boot-image=", bootImageLocation).Implicit(bootImage).
 		FlagWithInput("--dex-file=", module.DexPath).
 		FlagWithArg("--dex-location=", module.DexLocation).
 		FlagWithOutput("--oat-file=", odexPath).ImplicitOutput(vdexPath).
@@ -521,6 +518,15 @@
 	return false
 }
 
+// PathToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art
+func PathToLocation(path, arch string) string {
+	pathArch := filepath.Base(filepath.Dir(path))
+	if pathArch != arch {
+		panic(fmt.Errorf("last directory in %q must be %q", path, arch))
+	}
+	return filepath.Join(filepath.Dir(filepath.Dir(path)), filepath.Base(path))
+}
+
 func pathForLibrary(module ModuleConfig, lib string) string {
 	path := module.LibraryPaths[lib]
 	if path == "" {
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index d949852..bcfd73c 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -48,7 +48,7 @@
 	Dex2oatXmx:                         "",
 	Dex2oatXms:                         "",
 	EmptyDirectory:                     "",
-	DefaultDexPreoptImageLocation:      nil,
+	DefaultDexPreoptImage:              nil,
 	CpuVariant:                         nil,
 	InstructionSetFeatures:             nil,
 	Tools: Tools{
@@ -63,28 +63,28 @@
 }
 
 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:                  nil,
-	DexPreoptImageLocation: "",
-	PreoptExtractedApk:     false,
-	NoCreateAppImage:       false,
-	ForceCreateAppImage:    false,
-	PresignedPrebuilt:      false,
-	NoStripping:            false,
-	StripInputPath:         "",
-	StripOutputPath:        "",
+	Name:                  "",
+	DexLocation:           "",
+	BuildPath:             "",
+	DexPath:               "",
+	UncompressedDex:       false,
+	HasApkLibraries:       false,
+	PreoptFlags:           nil,
+	ProfileClassListing:   "",
+	ProfileIsTextListing:  false,
+	EnforceUsesLibraries:  false,
+	OptionalUsesLibraries: nil,
+	UsesLibraries:         nil,
+	LibraryPaths:          nil,
+	Archs:                 []string{"arm"},
+	DexPreoptImages:       []string{"system/framework/arm/boot.art"},
+	PreoptExtractedApk:    false,
+	NoCreateAppImage:      false,
+	ForceCreateAppImage:   false,
+	PresignedPrebuilt:     false,
+	NoStripping:           false,
+	StripInputPath:        "",
+	StripOutputPath:       "",
 }
 
 func TestDexPreopt(t *testing.T) {
@@ -93,7 +93,6 @@
 	module.Name = "test"
 	module.DexLocation = "/system/app/test/test.apk"
 	module.BuildPath = "out/test/test.apk"
-	module.Archs = []string{"arm"}
 
 	rule, err := GenerateDexpreoptRule(global, module)
 	if err != nil {
@@ -119,7 +118,6 @@
 	module.Name = "test"
 	module.DexLocation = "/system/app/test/test.apk"
 	module.BuildPath = "out/test/test.apk"
-	module.Archs = []string{"arm"}
 
 	rule, err := GenerateDexpreoptRule(global, module)
 	if err != nil {
@@ -143,7 +141,6 @@
 	module.DexLocation = "/system/app/test/test.apk"
 	module.BuildPath = "out/test/test.apk"
 	module.ProfileClassListing = "profile"
-	module.Archs = []string{"arm"}
 
 	rule, err := GenerateDexpreoptRule(global, module)
 	if err != nil {
@@ -193,7 +190,6 @@
 			module.Name = "test"
 			module.DexLocation = "/system/app/test/test.apk"
 			module.BuildPath = "out/test/test.apk"
-			module.Archs = []string{"arm"}
 			module.StripInputPath = "$1"
 			module.StripOutputPath = "$2"
 
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 55662cf..eef51a9 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -119,6 +119,11 @@
 		archs = archs[:1]
 	}
 
+	var images []string
+	for _, arch := range archs {
+		images = append(images, globalConfig.DefaultDexPreoptImage[arch])
+	}
+
 	dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
 
 	strippedDexJarFile := android.PathForModuleOut(ctx, "dexpreopt", dexJarFile.Base())
@@ -161,8 +166,8 @@
 		UsesLibraries:         nil,
 		LibraryPaths:          nil,
 
-		Archs:                  archs,
-		DexPreoptImageLocation: "",
+		Archs:           archs,
+		DexPreoptImages: images,
 
 		PreoptExtractedApk: false,