Use two-column format for PRODUCT_BOOT_JARS components.

The first component is the apex name, or a special name "platform"
if the boot jar is a platform jar rather than a part of some apex.
This is a prerequisite change for moving core-icu4j to a separate
com.android.i18n apex.

Old one-column format is still supported, but all unqualified
components of PRODUCT_BOOT_JARS get "platform:" prepended to them
after reading the product makefiles.

Test: aosp_walleye-userdebug boots
Bug: 138994281
Change-Id: Ic229159fdcdaf6182210a53b63850a389dd786fc
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index c3825cb..dffdc24 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -113,7 +113,7 @@
 	// Dexpreopt on the boot class path produces multiple files. The first dex file
 	// is converted into 'name'.art (to match the legacy assumption that 'name'.art
 	// exists), and the rest are converted to 'name'-<jar>.art.
-	m := image.modules[idx]
+	_, m := android.SplitApexJarPair(image.modules[idx])
 	name := image.stem
 	if idx != 0 || image.extends != nil {
 		name += "-" + stemOf(m)
@@ -261,7 +261,7 @@
 	}
 
 	name := ctx.ModuleName(module)
-	index := android.IndexList(name, image.modules)
+	index := android.IndexList(name, android.GetJarsFromApexJarPairs(image.modules))
 	if index == -1 {
 		return -1, nil
 	}
@@ -314,13 +314,13 @@
 	// Ensure all modules were converted to paths
 	for i := range bootDexJars {
 		if bootDexJars[i] == nil {
+			_, m := android.SplitApexJarPair(image.modules[i])
 			if ctx.Config().AllowMissingDependencies() {
-				missingDeps = append(missingDeps, image.modules[i])
+				missingDeps = append(missingDeps, m)
 				bootDexJars[i] = android.PathForOutput(ctx, "missing")
 			} else {
 				ctx.Errorf("failed to find a dex jar path for module '%s'"+
-					", note that some jars may be filtered out by module constraints",
-					image.modules[i])
+					", note that some jars may be filtered out by module constraints", m)
 			}
 		}
 	}
@@ -614,7 +614,7 @@
 
 	return ctx.Config().Once(updatableBcpPackagesRuleKey, func() interface{} {
 		global := dexpreopt.GetGlobalConfig(ctx)
-		updatableModules := dexpreopt.GetJarsFromApexJarPairs(global.UpdatableBootJars)
+		updatableModules := android.GetJarsFromApexJarPairs(global.UpdatableBootJars)
 
 		// Collect `permitted_packages` for updatable boot jars.
 		var updatablePackages []string
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 127c201..0946bf0 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -48,7 +48,7 @@
 
 	pathCtx := android.PathContextForTesting(config)
 	dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
-	dexpreoptConfig.BootJars = []string{"foo", "bar", "baz"}
+	dexpreoptConfig.BootJars = []string{"platform:foo", "platform:bar", "platform:baz"}
 	dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
 
 	ctx := testContext()
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 066694c..d849dc2 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -79,7 +79,20 @@
 	return moduleName
 }
 
-func getDexLocation(ctx android.PathContext, target android.Target, subdir string, name string) string {
+func getDexLocation(ctx android.PathContext, target android.Target, module string) string {
+	apex, jar := android.SplitApexJarPair(module)
+
+	name := stemOf(jar) + ".jar"
+
+	var subdir string
+	if apex == "platform" {
+		// Special apex name "platform" denotes jars do not come from an apex, but are part
+		// of the platform. Such jars are installed on the /system partition on device.
+		subdir = "system/framework"
+	} else {
+		subdir = filepath.Join("apex", apex, "javalib")
+	}
+
 	if target.Os.Class == android.Host {
 		return filepath.Join(ctx.Config().Getenv("OUT_DIR"), "host", ctx.Config().PrebuiltOS(), subdir, name)
 	} else {
@@ -106,8 +119,7 @@
 		if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
 			artModules = append(artModules, "jacocoagent")
 		}
-		frameworkModules := android.RemoveListFromList(global.BootJars,
-			concat(artModules, dexpreopt.GetJarsFromApexJarPairs(global.UpdatableBootJars)))
+		frameworkModules := android.RemoveListFromList(global.BootJars, artModules)
 
 		artSubdir := "apex/com.android.art/javalib"
 		frameworkSubdir := "system/framework"
@@ -150,7 +162,8 @@
 			// TODO(b/143682396): use module dependencies instead
 			inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input")
 			for _, m := range c.modules {
-				c.dexPaths = append(c.dexPaths, inputDir.Join(ctx, stemOf(m)+".jar"))
+				_, jar := android.SplitApexJarPair(m)
+				c.dexPaths = append(c.dexPaths, inputDir.Join(ctx, stemOf(jar)+".jar"))
 			}
 			c.dexPathsDeps = c.dexPaths
 
@@ -165,7 +178,7 @@
 					imagesDeps:      c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
 				}
 				for _, m := range c.modules {
-					variant.dexLocations = append(variant.dexLocations, getDexLocation(ctx, target, c.installSubdir, stemOf(m)+".jar"))
+					variant.dexLocations = append(variant.dexLocations, getDexLocation(ctx, target, m))
 				}
 				variant.dexLocationsDeps = variant.dexLocations
 				c.variants = append(c.variants, variant)