Move boot jars package check into platform_bootclasspath

Bug: 177892522
Bug: 189298093
Test: m check-boot-jars
      m SOONG_CONFIG_art_module_source_build=false check-boot-jars
      - Ran both commands with and without java.lang in the
        package_allowed_list.txt
Change-Id: Iba1a881c8f6b6919d5c0c0520eb3073658f3b8d2
diff --git a/java/boot_jars.go b/java/boot_jars.go
index 7abda80..5ec9f71 100644
--- a/java/boot_jars.go
+++ b/java/boot_jars.go
@@ -18,37 +18,6 @@
 	"android/soong/android"
 )
 
-func init() {
-	android.RegisterSingletonType("boot_jars", bootJarsSingletonFactory)
-}
-
-func bootJarsSingletonFactory() android.Singleton {
-	return &bootJarsSingleton{}
-}
-
-type bootJarsSingleton struct{}
-
-func populateMapFromConfiguredJarList(ctx android.SingletonContext, moduleToApex map[string]string, list android.ConfiguredJarList, name string) bool {
-	for i := 0; i < list.Len(); i++ {
-		module := list.Jar(i)
-		// Ignore jacocoagent it is only added when instrumenting and so has no impact on
-		// app compatibility.
-		if module == "jacocoagent" {
-			continue
-		}
-		apex := list.Apex(i)
-		if existing, ok := moduleToApex[module]; ok {
-			ctx.Errorf("Configuration property %q is invalid as it contains multiple references to module (%s) in APEXes (%s and %s)",
-				module, existing, apex)
-			return false
-		}
-
-		moduleToApex[module] = apex
-	}
-
-	return true
-}
-
 // isActiveModule returns true if the given module should be considered for boot
 // jars, i.e. if it's enabled and the preferred one in case of source and
 // prebuilt alternatives.
@@ -59,73 +28,17 @@
 	return android.IsModulePreferred(module)
 }
 
-func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
-	config := ctx.Config()
-	if config.SkipBootJarsCheck() {
-		return
-	}
-
-	// Populate a map from module name to APEX from the boot jars. If there is a
-	// problem such as duplicate modules then fail and return immediately. Note
-	// that both module and APEX names are tracked by base names here, so we need
-	// to be careful to remove "prebuilt_" prefixes when comparing them with
-	// actual modules and APEX bundles.
-	moduleToApex := make(map[string]string)
-	if !populateMapFromConfiguredJarList(ctx, moduleToApex, config.NonUpdatableBootJars(), "BootJars") ||
-		!populateMapFromConfiguredJarList(ctx, moduleToApex, config.UpdatableBootJars(), "UpdatableBootJars") {
-		return
-	}
-
-	// Map from module name to the correct apex variant.
-	nameToApexVariant := make(map[string]android.Module)
-
-	// Scan all the modules looking for the module/apex variants corresponding to the
-	// boot jars.
-	ctx.VisitAllModules(func(module android.Module) {
-		if !isActiveModule(module) {
-			return
-		}
-
-		name := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName(module))
-		if apex, ok := moduleToApex[name]; ok {
-			apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
-			if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApexModule(apex) {
-				// The module name/apex variant should be unique in the system but double check
-				// just in case something has gone wrong.
-				if existing, ok := nameToApexVariant[name]; ok {
-					ctx.Errorf("found multiple variants matching %s:%s: %q and %q", apex, name, existing, module)
-				}
-				nameToApexVariant[name] = module
-			}
-		}
-	})
-
+// buildRuleForBootJarsPackageCheck generates the build rule to perform the boot jars package
+// check.
+func buildRuleForBootJarsPackageCheck(ctx android.ModuleContext, bootDexJarByModule bootDexJarByModule) {
 	timestamp := android.PathForOutput(ctx, "boot-jars-package-check/stamp")
 
 	rule := android.NewRuleBuilder(pctx, ctx)
-	checkBootJars := rule.Command().BuiltTool("check_boot_jars").
+	rule.Command().BuiltTool("check_boot_jars").
 		Input(ctx.Config().HostToolPath(ctx, "dexdump")).
-		Input(android.PathForSource(ctx, "build/soong/scripts/check_boot_jars/package_allowed_list.txt"))
-
-	// If this is not an unbundled build and missing dependencies are not allowed
-	// then all the boot jars listed must have been found.
-	strict := !config.UnbundledBuild() && !config.AllowMissingDependencies()
-
-	// Iterate over the module names on the boot classpath in order
-	for _, name := range android.SortedStringKeys(moduleToApex) {
-		if apexVariant, ok := nameToApexVariant[name]; ok {
-			if dep, ok := apexVariant.(interface{ DexJarBuildPath() android.Path }); ok {
-				// Add the dex implementation jar for the module to be checked.
-				checkBootJars.Input(dep.DexJarBuildPath())
-			} else {
-				ctx.Errorf("module %q is of type %q which is not supported as a boot jar", name, ctx.ModuleType(apexVariant))
-			}
-		} else if strict {
-			ctx.Errorf("boot jars package check failed as it could not find module %q for apex %q", name, moduleToApex[name])
-		}
-	}
-
-	checkBootJars.Text("&& touch").Output(timestamp)
+		Input(android.PathForSource(ctx, "build/soong/scripts/check_boot_jars/package_allowed_list.txt")).
+		Inputs(bootDexJarByModule.bootDexJars()).
+		Text("&& touch").Output(timestamp)
 	rule.Build("boot_jars_package_check", "check boot jar packages")
 
 	// The check-boot-jars phony target depends on the timestamp created if the check succeeds.
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 75a2bda..8bea9bb 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -189,7 +189,8 @@
 
 	b.generateClasspathProtoBuildActions(ctx)
 
-	b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
+	bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
+	buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)
 
 	// Nothing to do if skipping the dexpreopt of boot image jars.
 	if SkipDexpreoptBootJars(ctx) {
@@ -258,7 +259,7 @@
 }
 
 // generateHiddenAPIBuildActions generates all the hidden API related build rules.
-func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) {
+func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) bootDexJarByModule {
 
 	// Save the paths to the monolithic files for retrieval via OutputFiles().
 	b.hiddenAPIFlagsCSV = hiddenAPISingletonPaths(ctx).flags
@@ -276,7 +277,7 @@
 				Output: path,
 			})
 		}
-		return
+		return nil
 	}
 
 	monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments)
@@ -322,6 +323,8 @@
 	// jars.
 	indexCSV := hiddenAPISingletonPaths(ctx).index
 	buildRuleToGenerateIndex(ctx, "monolithic hidden API index", classesJars, indexCSV)
+
+	return bootDexJarByModule
 }
 
 // createAndProvideMonolithicHiddenAPIInfo creates a MonolithicHiddenAPIInfo and provides it for