Generate the ART boot image for host as well (used by ART tests).

This will allow us to remove the core.art image compiled in make.

Test: lunch aosp_x86_64 && m test-art-host-gtest
Bug: 147817558
Bug: 147819342
Change-Id: I864f72198d875dc1421c9c029a683bafbe7b71ac
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index d7adb40..670cb97 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -176,11 +176,6 @@
 		return true
 	}
 
-	if len(ctx.Config().Targets[android.Android]) == 0 {
-		// Host-only build
-		return true
-	}
-
 	return false
 }
 
@@ -199,7 +194,10 @@
 	// Include dexpreopt files for the primary boot image.
 	files := map[android.ArchType]android.OutputPaths{}
 	for _, variant := range artBootImageConfig(ctx).variants {
-		files[variant.target.Arch.ArchType] = variant.imagesDeps
+		// We also generate boot images for host (for testing), but we don't need those in the apex.
+		if variant.target.Os == android.Android {
+			files[variant.target.Arch.ArchType] = variant.imagesDeps
+		}
 	}
 	return files
 }
@@ -305,9 +303,10 @@
 	global := dexpreopt.GetGlobalConfig(ctx)
 
 	arch := image.target.Arch.ArchType
-	symbolsDir := image.symbolsDir.Join(ctx, image.installSubdir, arch.String())
+	os := image.target.Os.String() // We need to distinguish host-x86 and device-x86.
+	symbolsDir := image.symbolsDir.Join(ctx, os, image.installSubdir, arch.String())
 	symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
-	outputDir := image.dir.Join(ctx, image.installSubdir, arch.String())
+	outputDir := image.dir.Join(ctx, os, image.installSubdir, arch.String())
 	outputPath := outputDir.Join(ctx, image.stem+".oat")
 	oatLocation := dexpreopt.PathToLocation(outputPath, arch)
 	imagePath := outputPath.ReplaceExtension(ctx, "art")
@@ -375,12 +374,17 @@
 		FlagWithArg("--oat-location=", oatLocation).
 		FlagWithArg("--image=", imagePath.String()).
 		FlagWithArg("--instruction-set=", arch.String()).
-		FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]).
-		FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]).
 		FlagWithArg("--android-root=", global.EmptyDirectory).
 		FlagWithArg("--no-inline-from=", "core-oj.jar").
 		Flag("--abort-on-hard-verifier-error")
 
+	// Use the default variant/features for host builds.
+	// The map below contains only device CPU info (which might be x86 on some devices).
+	if image.target.Os == android.Android {
+		cmd.FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch])
+		cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
+	}
+
 	if global.BootFlags != "" {
 		cmd.Flag(global.BootFlags)
 	}
@@ -392,7 +396,6 @@
 	cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage))
 
 	installDir := filepath.Join("/", image.installSubdir, arch.String())
-	vdexInstallDir := filepath.Join("/", image.installSubdir)
 
 	var vdexInstalls android.RuleBuilderInstalls
 	var unstrippedInstalls android.RuleBuilderInstalls
@@ -411,11 +414,10 @@
 		cmd.ImplicitOutput(vdex)
 		zipFiles = append(zipFiles, vdex)
 
-		// The vdex files are identical between architectures, install them to a shared location.  The Make rules will
-		// only use the install rules for one architecture, and will create symlinks into the architecture-specific
-		// directories.
+		// Note that the vdex files are identical between architectures.
+		// Make rules will create symlinks to share them between architectures.
 		vdexInstalls = append(vdexInstalls,
-			android.RuleBuilderInstall{vdex, filepath.Join(vdexInstallDir, vdex.Base())})
+			android.RuleBuilderInstall{vdex, filepath.Join(installDir, vdex.Base())})
 	}
 
 	for _, unstrippedOat := range image.moduleFiles(ctx, symbolsDir, ".oat") {
@@ -426,7 +428,7 @@
 			android.RuleBuilderInstall{unstrippedOat, filepath.Join(installDir, unstrippedOat.Base())})
 	}
 
-	rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+arch.String(), "dexpreopt "+image.name+" jars "+arch.String())
+	rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String())
 
 	// save output and installed files for makevars
 	image.installs = rule.Installs()
@@ -544,8 +546,9 @@
 	var allPhonies android.Paths
 	for _, image := range image.variants {
 		arch := image.target.Arch.ArchType
+		suffix := image.target.String()
 		// Create a rule to call oatdump.
-		output := android.PathForOutput(ctx, "boot."+arch.String()+".oatdump.txt")
+		output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
 		rule := android.NewRuleBuilder()
 		rule.Command().
 			// TODO: for now, use the debug version for better error reporting
@@ -555,16 +558,16 @@
 			FlagWithArg("--image=", strings.Join(image.imageLocations, ":")).Implicits(image.imagesDeps.Paths()).
 			FlagWithOutput("--output=", output).
 			FlagWithArg("--instruction-set=", arch.String())
-		rule.Build(pctx, ctx, "dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
+		rule.Build(pctx, ctx, "dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
 
 		// Create a phony rule that depends on the output file and prints the path.
-		phony := android.PathForPhony(ctx, "dump-oat-boot-"+arch.String())
+		phony := android.PathForPhony(ctx, "dump-oat-boot-"+suffix)
 		rule = android.NewRuleBuilder()
 		rule.Command().
 			Implicit(output).
 			ImplicitOutput(phony).
 			Text("echo").FlagWithArg("Output in ", output.String())
-		rule.Build(pctx, ctx, "phony-dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
+		rule.Build(pctx, ctx, "phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
 
 		allPhonies = append(allPhonies, phony)
 	}
@@ -608,7 +611,11 @@
 		for _, current := range append(d.otherImages, image) {
 			imageNames = append(imageNames, current.name)
 			for _, current := range current.variants {
-				sfx := current.name + "_" + current.target.Arch.ArchType.String()
+				suffix := ""
+				if current.target.Os.Class == android.Host {
+					suffix = "_host"
+				}
+				sfx := current.name + suffix + "_" + current.target.Arch.ArchType.String()
 				ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, current.vdexInstalls.String())
 				ctx.Strict("DEXPREOPT_IMAGE_"+sfx, current.images.String())
 				ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(current.imagesDeps.Strings(), " "))
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index c3b2133..94ca8bb 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -62,7 +62,7 @@
 	bootArt := dexpreoptBootJars.Output("boot-foo.art")
 
 	expectedInputs := []string{
-		"dex_artjars/apex/com.android.art/javalib/arm64/boot.art",
+		"dex_artjars/android/apex/com.android.art/javalib/arm64/boot.art",
 		"dex_bootjars_input/foo.jar",
 		"dex_bootjars_input/bar.jar",
 		"dex_bootjars_input/baz.jar",
@@ -81,23 +81,23 @@
 	}
 
 	expectedOutputs := []string{
-		"dex_bootjars/system/framework/arm64/boot.invocation",
+		"dex_bootjars/android/system/framework/arm64/boot.invocation",
 
-		"dex_bootjars/system/framework/arm64/boot-foo.art",
-		"dex_bootjars/system/framework/arm64/boot-bar.art",
-		"dex_bootjars/system/framework/arm64/boot-baz.art",
+		"dex_bootjars/android/system/framework/arm64/boot-foo.art",
+		"dex_bootjars/android/system/framework/arm64/boot-bar.art",
+		"dex_bootjars/android/system/framework/arm64/boot-baz.art",
 
-		"dex_bootjars/system/framework/arm64/boot-foo.oat",
-		"dex_bootjars/system/framework/arm64/boot-bar.oat",
-		"dex_bootjars/system/framework/arm64/boot-baz.oat",
+		"dex_bootjars/android/system/framework/arm64/boot-foo.oat",
+		"dex_bootjars/android/system/framework/arm64/boot-bar.oat",
+		"dex_bootjars/android/system/framework/arm64/boot-baz.oat",
 
-		"dex_bootjars/system/framework/arm64/boot-foo.vdex",
-		"dex_bootjars/system/framework/arm64/boot-bar.vdex",
-		"dex_bootjars/system/framework/arm64/boot-baz.vdex",
+		"dex_bootjars/android/system/framework/arm64/boot-foo.vdex",
+		"dex_bootjars/android/system/framework/arm64/boot-bar.vdex",
+		"dex_bootjars/android/system/framework/arm64/boot-baz.vdex",
 
-		"dex_bootjars_unstripped/system/framework/arm64/boot-foo.oat",
-		"dex_bootjars_unstripped/system/framework/arm64/boot-bar.oat",
-		"dex_bootjars_unstripped/system/framework/arm64/boot-baz.oat",
+		"dex_bootjars_unstripped/android/system/framework/arm64/boot-foo.oat",
+		"dex_bootjars_unstripped/android/system/framework/arm64/boot-bar.oat",
+		"dex_bootjars_unstripped/android/system/framework/arm64/boot-baz.oat",
 	}
 
 	for i := range expectedOutputs {
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index a06aec4..d77d3e1 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -68,6 +68,10 @@
 			targets = append(targets, target)
 		}
 	}
+	// We may also need the images on host in order to run host-based tests.
+	for _, target := range ctx.Config().Targets[android.BuildOs] {
+		targets = append(targets, target)
+	}
 
 	return targets
 }
@@ -152,7 +156,7 @@
 			// expands to <stem>.art for primary image and <stem>-<1st module>.art for extension
 			imageName := c.firstModuleNameOrStem() + ".art"
 
-			c.imageLocations = []string{c.dir.Join(ctx, c.installSubdir, imageName).String()}
+			c.imageLocations = []string{c.dir.Join(ctx, "android", c.installSubdir, imageName).String()}
 
 			// The path to bootclasspath dex files needs to be known at module
 			// GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled.
@@ -167,7 +171,7 @@
 			// Create target-specific variants.
 			for _, target := range targets {
 				arch := target.Arch.ArchType
-				imageDir := c.dir.Join(ctx, c.installSubdir, arch.String())
+				imageDir := c.dir.Join(ctx, target.Os.String(), c.installSubdir, arch.String())
 				variant := &bootImageVariant{
 					bootImageConfig: c,
 					target:          target,