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/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index fb6b47e..809b494 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -409,6 +409,13 @@
 		// Perform hidden API processing.
 		hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
 
+		if imageConfig != nil {
+			if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
+				// Copy the dex jars of this fragment's content modules to their predefined locations.
+				copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
+			}
+		}
+
 		// A prebuilt fragment cannot contribute to an apex.
 		if !android.IsModulePrebuilt(ctx.Module()) {
 			// Provide the apex content info.
@@ -417,6 +424,29 @@
 	}
 }
 
+// shouldCopyBootFilesToPredefinedLocations determines whether the current module should copy boot
+// files, e.g. boot dex jars or boot image files, to the predefined location expected by the rest
+// of the build.
+//
+// This ensures that only a single module will copy its files to the image configuration.
+func shouldCopyBootFilesToPredefinedLocations(ctx android.ModuleContext, imageConfig *bootImageConfig) bool {
+	// Bootclasspath fragment modules that are for the platform do not produce boot related files.
+	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+	if apexInfo.IsForPlatform() {
+		return false
+	}
+
+	// If the image configuration has no modules specified then it means that the build has been
+	// configured to build something other than a boot image, e.g. an sdk, so do not try and copy the
+	// files.
+	if imageConfig.modules.Len() == 0 {
+		return false
+	}
+
+	// Only copy files from the module that is preferred.
+	return isActiveModule(ctx.Module())
+}
+
 // provideApexContentInfo creates, initializes and stores the apex content info for use by other
 // modules.
 func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module, hiddenAPIOutput *HiddenAPIOutput) {
@@ -635,10 +665,6 @@
 		return false
 	}
 
-	// Copy the dex jars of this fragment's content modules to their predefined locations.
-	bootDexJarByModule := extractEncodedDexJarsFromModules(ctx, contents)
-	copyBootJarsToPredefinedLocations(ctx, bootDexJarByModule, imageConfig.dexPathsByModule)
-
 	// Build a profile for the image config and then use that to build the boot image.
 	profile := bootImageProfileRule(ctx, imageConfig)
 	buildBootImage(ctx, imageConfig, profile)