Allow using updatable boot jars in dexpreopt (but don't use them yet).

This CL handles updatable boot jars in the same hacky way as we handle
non-updatable boot jars: it creates a set of predefined paths to the dex
jars in a global config, then traverses all modules in a singleton
context, finds updatable boot jars and adds copy rules from these jars
to the predefined paths. A proper way would be to register dependencies
of the dexpreopted modules on the boot jars and extracting paths to dex
files by walking these dependencies.

Bug: 178467404
Test: lunch aosp_cf_x86_64_phone-userdebug && m
Test: added new Soong test
Change-Id: I87f764109315f79315d73bf43799b70eb010fc0b
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 17499ee..6dc408b 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -439,6 +439,8 @@
 	// Create boot image for the ART apex (build artifacts are accessed via the global boot image config).
 	d.otherImages = append(d.otherImages, buildBootImage(ctx, artBootImageConfig(ctx)))
 
+	copyUpdatableBootJars(ctx)
+
 	dumpOatRules(ctx, d.defaultBootImage)
 }
 
@@ -630,6 +632,21 @@
 	return image
 }
 
+// Generate commands that will copy updatable boot jars to predefined paths in the global config.
+func copyUpdatableBootJars(ctx android.SingletonContext) {
+	config := GetUpdatableBootConfig(ctx)
+	getBootJarFunc := func(module android.Module) (int, android.Path) {
+		index, jar, _ := getBootJar(ctx, config.modules, module, "configured in updatable boot jars ")
+		return index, jar
+	}
+	missingDeps := findAndCopyBootJars(ctx, config.modules, config.dexPaths, getBootJarFunc)
+	// Ignoring missing dependencies here. Ideally they should be added to the dexpreopt rule, but
+	// that is not possible as this rule is created after dexpreopt rules (it's in a singleton
+	// context, and they are in a module context). The true fix is to add dependencies from the
+	// dexpreopted modules on updatable boot jars and avoid this copying altogether.
+	_ = missingDeps
+}
+
 // Generate boot image build rules for a specific target.
 func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant,
 	profile android.Path, missingDeps []string) android.WritablePaths {
@@ -997,8 +1014,11 @@
 	image := d.defaultBootImage
 	if image != nil {
 		ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
-		ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPathsDeps.Strings(), " "))
-		ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.getAnyAndroidVariant().dexLocationsDeps, " "))
+
+		global := dexpreopt.GetGlobalConfig(ctx)
+		dexPaths, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)
+		ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " "))
+		ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(dexLocations, " "))
 
 		var imageNames []string
 		// TODO: the primary ART boot image should not be exposed to Make, as it is installed in a