Declare ConfiguredJarList in specific fragment implementations.

Each specific classpath_fragment module knows what jars must be part
of the corresponding classpaths.proto config.

Note that bootclasspath_fragment does not implement classpath_fragment
yet, thus all boot jars and all system server jars go into corresponding
platform classpaths.

Bug: 180105615
Test: m && launch_cvd; atest CtsClasspathsTestCases
Change-Id: I6a8c7b0a5d17d62e790a441b8e2c5c1a816e7f30
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 00e9591..2e05823 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -51,6 +51,10 @@
 	android.Module
 
 	classpathFragmentBase() *ClasspathFragmentBase
+
+	// ClasspathFragmentToConfiguredJarList returns android.ConfiguredJarList representation of all
+	// the jars in this classpath fragment.
+	ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList
 }
 
 // ClasspathFragmentBase is meant to be embedded in any module types that implement classpathFragment;
@@ -84,24 +88,26 @@
 	maxSdkVersion int32
 }
 
-func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext) {
+// Converts android.ConfiguredJarList into a list of classpathJars for each given classpathType.
+func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, classpaths ...classpathType) []classpathJar {
+	paths := configuredJars.DevicePaths(ctx.Config(), android.Android)
+	jars := make([]classpathJar, 0, len(paths)*len(classpaths))
+	for i := 0; i < len(paths); i++ {
+		for _, classpathType := range classpaths {
+			jars = append(jars, classpathJar{
+				classpath: classpathType,
+				path:      paths[i],
+			})
+		}
+	}
+	return jars
+}
+
+func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, jars []classpathJar) {
 	outputFilename := ctx.ModuleName() + ".pb"
 	c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
 	c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")
 
-	var jars []classpathJar
-	switch c.classpathType {
-	case BOOTCLASSPATH:
-		jars = appendClasspathJar(jars, BOOTCLASSPATH, defaultBootclasspath(ctx)...)
-		jars = appendClasspathJar(jars, DEX2OATBOOTCLASSPATH, defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps...)
-	case SYSTEMSERVERCLASSPATH:
-		jars = appendClasspathJar(jars, SYSTEMSERVERCLASSPATH, systemServerClasspath(ctx)...)
-	default:
-		// Only supported classpath fragments are BOOTCLASSPATH and SYSTEMSERVERCLASSPATH.
-		// DEX2OATBOOTCLASSPATH is a special case of BOOTCLASSPATH and is auto-generated.
-		panic(fmt.Errorf("found %v, expected either BOOTCLASSPATH or SYSTEMSERVERCLASSPATH", c.classpathType))
-	}
-
 	generatedJson := android.PathForModuleOut(ctx, outputFilename+".json")
 	writeClasspathsJson(ctx, generatedJson, jars)
 
@@ -137,19 +143,8 @@
 	android.WriteFileRule(ctx, output, content.String())
 }
 
-func appendClasspathJar(slice []classpathJar, classpathType classpathType, paths ...string) (result []classpathJar) {
-	result = append(result, slice...)
-	for _, path := range paths {
-		result = append(result, classpathJar{
-			path:      path,
-			classpath: classpathType,
-		})
-	}
-	return
-}
-
 func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries {
-	return []android.AndroidMkEntries{android.AndroidMkEntries{
+	return []android.AndroidMkEntries{{
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(c.outputFilepath),
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 72b61e3..e95b4cb 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -163,18 +163,6 @@
 	return genBootImageConfigs(ctx)[frameworkBootImageName]
 }
 
-func defaultBootclasspath(ctx android.PathContext) []string {
-	return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string {
-		global := dexpreopt.GetGlobalConfig(ctx)
-		image := defaultBootImageConfig(ctx)
-
-		updatableBootclasspath := global.UpdatableBootJars.DevicePaths(ctx.Config(), android.Android)
-
-		bootclasspath := append(copyOf(image.getAnyAndroidVariant().dexLocationsDeps), updatableBootclasspath...)
-		return bootclasspath
-	})
-}
-
 // Updatable boot config allows to access build/install paths of updatable boot jars without going
 // through the usual trouble of registering dependencies on those modules and extracting build paths
 // from those dependencies.
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 1f24942..1caffe4 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -167,8 +167,6 @@
 }
 
 func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx)
-
 	// Gather all the dependencies from the art, updatable and non-updatable boot jars.
 	artModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathArtBootJarDepTag)
 	nonUpdatableModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathNonUpdatableBootJarDepTag)
@@ -189,6 +187,8 @@
 	b.checkNonUpdatableModules(ctx, nonUpdatableModules)
 	b.checkUpdatableModules(ctx, updatableModules)
 
+	b.generateClasspathProtoBuildActions(ctx)
+
 	b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
 
 	// Nothing to do if skipping the dexpreopt of boot image jars.
@@ -199,6 +199,23 @@
 	b.generateBootImageBuildActions(ctx, updatableModules)
 }
 
+// Generate classpaths.proto config
+func (b *platformBootclasspathModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) {
+	// ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH
+	classpathJars := configuredJarListToClasspathJars(ctx, b.ClasspathFragmentToConfiguredJarList(ctx), BOOTCLASSPATH, DEX2OATBOOTCLASSPATH)
+	// TODO(satayev): remove updatable boot jars once each apex has its own fragment
+	global := dexpreopt.GetGlobalConfig(ctx)
+	classpathJars = append(classpathJars, configuredJarListToClasspathJars(ctx, global.UpdatableBootJars, BOOTCLASSPATH)...)
+
+	b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars)
+}
+
+func (b *platformBootclasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList {
+	global := dexpreopt.GetGlobalConfig(ctx)
+	// TODO(satayev): split ART apex jars into their own classpathFragment
+	return global.BootJars
+}
+
 // checkNonUpdatableModules ensures that the non-updatable modules supplied are not part of an
 // updatable module.
 func (b *platformBootclasspathModule) checkNonUpdatableModules(ctx android.ModuleContext, modules []android.Module) {
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 3f8a083..82cdb89 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/dexpreopt"
 )
 
 func init() {
@@ -45,6 +46,22 @@
 }
 
 func (b *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	// TODO(satayev): split apex jars into separate configs.
-	b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx)
+	configuredJars := configuredJarListToClasspathJars(ctx, b.ClasspathFragmentToConfiguredJarList(ctx), b.classpathType)
+	b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars)
+}
+
+var platformSystemServerClasspathKey = android.NewOnceKey("platform_systemserverclasspath")
+
+func (b *platformSystemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList {
+	return ctx.Config().Once(platformSystemServerClasspathKey, func() interface{} {
+		global := dexpreopt.GetGlobalConfig(ctx)
+
+		jars := global.SystemServerJars
+
+		// TODO(satayev): split apex jars into separate configs.
+		for i := 0; i < global.UpdatableSystemServerJars.Len(); i++ {
+			jars = jars.Append(global.UpdatableSystemServerJars.Apex(i), global.UpdatableSystemServerJars.Jar(i))
+		}
+		return jars
+	}).(android.ConfiguredJarList)
 }