Copy boot dex jars from prebuilt art-bootclasspath-fragment if preferred

Previously, the boot dex jars were only copied to the predefined
locations used by the build from the source art-bootclasspath-fragment
if it was preferred, otherwise no files were copied. That caused build
failures when attempting to build with ART prebuilts. This change
copies the files from prebuilts too.

Bug: 177892522
Bug: 189298093
Test: m nothing
      m droid SOONG_CONFIG_art_module_source_build=false SKIP_BOOT_JARS_CHECK=true
      - the previous command does not work but this change does fix one
        of the issues reported.
Change-Id: I35b37355170546daf6ecac2134d1ca9a73d0e3bc
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 1971dcd..8b6e876 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"sort"
 	"strings"
 	"testing"
 
@@ -359,6 +360,19 @@
 
 	addPrebuilt := func(prefer bool, contents ...string) android.FixturePreparer {
 		text := fmt.Sprintf(`
+			prebuilt_apex {
+				name: "com.android.art",
+				arch: {
+					arm64: {
+						src: "com.android.art-arm64.apex",
+					},
+					arm: {
+						src: "com.android.art-arm.apex",
+					},
+				},
+				exported_bootclasspath_fragments: ["mybootclasspathfragment"],
+			}
+
 			prebuilt_bootclasspath_fragment {
 				name: "mybootclasspathfragment",
 				image_name: "art",
@@ -372,7 +386,47 @@
 		return android.FixtureAddTextFile("prebuilts/module_sdk/art/Android.bp", text)
 	}
 
-	t.Run("boot image files", func(t *testing.T) {
+	t.Run("boot image files from source", func(t *testing.T) {
+		result := android.GroupFixturePreparers(
+			commonPreparer,
+
+			// Configure some libraries in the art bootclasspath_fragment that match the source
+			// bootclasspath_fragment's contents property.
+			java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+			addSource("foo", "bar"),
+		).RunTest(t)
+
+		ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+			"etc/classpaths/bootclasspath.pb",
+			"javalib/arm/boot.art",
+			"javalib/arm/boot.oat",
+			"javalib/arm/boot.vdex",
+			"javalib/arm/boot-bar.art",
+			"javalib/arm/boot-bar.oat",
+			"javalib/arm/boot-bar.vdex",
+			"javalib/arm64/boot.art",
+			"javalib/arm64/boot.oat",
+			"javalib/arm64/boot.vdex",
+			"javalib/arm64/boot-bar.art",
+			"javalib/arm64/boot-bar.oat",
+			"javalib/arm64/boot-bar.vdex",
+			"javalib/bar.jar",
+			"javalib/foo.jar",
+		})
+
+		java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+			`bar`,
+			`com.android.art.key`,
+			`mybootclasspathfragment`,
+		})
+
+		// Make sure that the source bootclasspath_fragment copies its dex files to the predefined
+		// locations for the art image.
+		module := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
+	})
+
+	t.Run("boot image files with preferred prebuilt", func(t *testing.T) {
 		result := android.GroupFixturePreparers(
 			commonPreparer,
 
@@ -407,7 +461,13 @@
 			`bar`,
 			`com.android.art.key`,
 			`mybootclasspathfragment`,
+			`prebuilt_com.android.art`,
 		})
+
+		// Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined
+		// locations for the art image.
+		module := result.ModuleForTests("prebuilt_mybootclasspathfragment", "android_common_com.android.art")
+		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
 	})
 
 	t.Run("source with inconsistency between config and contents", func(t *testing.T) {
@@ -528,11 +588,36 @@
 		`prebuilt_mybootclasspathfragment`,
 	})
 
-	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common", []string{
+	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_com.android.art", []string{
 		`dex2oatd`,
 		`prebuilt_bar`,
 		`prebuilt_foo`,
 	})
+
+	module := result.ModuleForTests("mybootclasspathfragment", "android_common_com.android.art")
+	checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
+}
+
+// checkCopiesToPredefinedLocationForArt checks that the supplied modules are copied to the
+// predefined locations of boot dex jars used as inputs for the ART boot image.
+func checkCopiesToPredefinedLocationForArt(t *testing.T, config android.Config, module android.TestingModule, modules ...string) {
+	t.Helper()
+	bootJarLocations := []string{}
+	for _, output := range module.AllOutputs() {
+		output = android.StringRelativeToTop(config, output)
+		if strings.HasPrefix(output, "out/soong/test_device/dex_artjars_input/") {
+			bootJarLocations = append(bootJarLocations, output)
+		}
+	}
+
+	sort.Strings(bootJarLocations)
+	expected := []string{}
+	for _, m := range modules {
+		expected = append(expected, fmt.Sprintf("out/soong/test_device/dex_artjars_input/%s.jar", m))
+	}
+	sort.Strings(expected)
+
+	android.AssertArrayString(t, "copies to predefined locations for art", expected, bootJarLocations)
 }
 
 func TestBootclasspathFragmentContentsNoName(t *testing.T) {