Extract ruleToGenerateHiddenApiFlags

Extracts the code for creating the rule that creates the monolithic
hidden API flags file which is encoded into dex implementation jars.
This refactoring is in preparation for moving the functionality from
the hiddenapi_singleton into the platform_bootclasspath.

A follow up change will move the method into the new
hiddenapi_modular.go alongside the hiddenAPIAugmentationInfo as they
will both be used to perform hidden API processing for a
bootclasspath_fragment.

Bug: 177892522
Test: verified that the out/soong/hiddenapi/... files are unchanged
      by this change
Change-Id: I2729afa80cdfd2d1d4717365001648453d65632f
diff --git a/java/Android.bp b/java/Android.bp
index 8334b85..f8ba1b6 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -42,6 +42,7 @@
         "gen.go",
         "genrule.go",
         "hiddenapi.go",
+        "hiddenapi_modular.go",
         "hiddenapi_singleton.go",
         "jacoco.go",
         "java.go",
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
new file mode 100644
index 0000000..eef0320
--- /dev/null
+++ b/java/hiddenapi_modular.go
@@ -0,0 +1,61 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+	"android/soong/android"
+)
+
+// Contains support for processing hiddenAPI in a modular fashion.
+
+// hiddenAPIAugmentationInfo contains paths to the files that can be used to augment the information
+// obtained from annotations within the source code in order to create the complete set of flags
+// that should be applied to the dex implementation jars on the bootclasspath.
+//
+// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
+// of each property reference a plain text file that contains a java signature per line. The flags
+// for each of those signatures will be updated in a property specific way.
+//
+// The Unsupported_packages property contains a list of paths, each of which is a plain text file
+// with one Java package per line. All members of all classes within that package (but not nested
+// packages) will be updated in a property specific way.
+type hiddenAPIAugmentationInfo struct {
+	// Marks each signature in the referenced files as being unsupported.
+	Unsupported android.Paths
+
+	// Marks each signature in the referenced files as being unsupported because it has been removed.
+	// Any conflicts with other flags are ignored.
+	Removed android.Paths
+
+	// Marks each signature in the referenced files as being supported only for targetSdkVersion <= R
+	// and low priority.
+	Max_target_r_low_priority android.Paths
+
+	// Marks each signature in the referenced files as being supported only for targetSdkVersion <= Q.
+	Max_target_q android.Paths
+
+	// Marks each signature in the referenced files as being supported only for targetSdkVersion <= P.
+	Max_target_p android.Paths
+
+	// Marks each signature in the referenced files as being supported only for targetSdkVersion <= O
+	// and low priority. Any conflicts with other flags are ignored.
+	Max_target_o_low_priority android.Paths
+
+	// Marks each signature in the referenced files as being blocked.
+	Blocked android.Paths
+
+	// Marks each signature in every package in the referenced files as being unsupported.
+	Unsupported_packages android.Paths
+}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 7e9477b..341381a 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -346,39 +346,82 @@
 		ctx.Errorf("Failed to find combined-removed-dex.")
 	}
 
-	rule := android.NewRuleBuilder(pctx, ctx)
-
 	outputPath := hiddenAPISingletonPaths(ctx).flags
-	tempPath := android.PathForOutput(ctx, outputPath.Rel()+".tmp")
 
 	stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
 
-	rule.Command().
+	pathsForSource := func(paths ...string) android.Paths { return android.PathsForSource(ctx, paths) }
+
+	ruleToGenerateHiddenApiFlags(ctx, outputPath, stubFlags, flagsCSV, hiddenAPIAugmentationInfo{
+		Unsupported:               pathsForSource("frameworks/base/boot/hiddenapi/hiddenapi-unsupported.txt"),
+		Removed:                   android.Paths{combinedRemovedApis},
+		Max_target_r_low_priority: pathsForSource("frameworks/base/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt"),
+		Max_target_q:              pathsForSource("frameworks/base/boot/hiddenapi/hiddenapi-max-target-q.txt"),
+		Max_target_p:              pathsForSource("frameworks/base/boot/hiddenapi/hiddenapi-max-target-p.txt"),
+		Max_target_o_low_priority: pathsForSource("frameworks/base/boot/hiddenapi/hiddenapi-max-target-o.txt"),
+		Blocked:                   pathsForSource("frameworks/base/boot/hiddenapi/hiddenapi-force-blocked.txt"),
+		Unsupported_packages:      pathsForSource("frameworks/base/boot/hiddenapi/hiddenapi-unsupported-packages.txt"),
+	})
+
+	return outputPath
+}
+
+// ruleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from the
+// flags from all the modules, the stub flags, augmented with some additional configuration files.
+//
+// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
+// an entry for every single member in the dex implementation jars of the individual modules. Every
+// signature in any of the other files MUST be included in this file.
+//
+// moduleSpecificFlagsPaths are the paths to the flags files generated by each module using
+// information from the baseFlagsPath as well as from annotations within the source.
+//
+// augmentationInfo is a struct containing paths to files that augment the information provided by
+// the moduleSpecificFlagsPaths.
+func ruleToGenerateHiddenApiFlags(ctx android.BuilderContext, outputPath android.WritablePath, baseFlagsPath android.Path, moduleSpecificFlagsPaths android.Paths, augmentationInfo hiddenAPIAugmentationInfo) {
+	tempPath := android.PathForOutput(ctx, outputPath.Rel()+".tmp")
+	rule := android.NewRuleBuilder(pctx, ctx)
+	command := rule.Command().
 		BuiltTool("generate_hiddenapi_lists").
-		FlagWithInput("--csv ", stubFlags).
-		Inputs(flagsCSV).
-		FlagWithInput("--unsupported ",
-			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-unsupported.txt")).
-		FlagWithInput("--unsupported ", combinedRemovedApis).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed").
-		FlagWithInput("--max-target-r ",
-			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt")).FlagWithArg("--tag ", "lo-prio").
-		FlagWithInput("--max-target-q ",
-			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-max-target-q.txt")).
-		FlagWithInput("--max-target-p ",
-			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-max-target-p.txt")).
-		FlagWithInput("--max-target-o ", android.PathForSource(
-			ctx, "frameworks/base/boot/hiddenapi/hiddenapi-max-target-o.txt")).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio").
-		FlagWithInput("--blocked ",
-			android.PathForSource(ctx, "frameworks/base/boot/hiddenapi/hiddenapi-force-blocked.txt")).
-		FlagWithInput("--unsupported ", android.PathForSource(
-			ctx, "frameworks/base/boot/hiddenapi/hiddenapi-unsupported-packages.txt")).Flag("--packages ").
+		FlagWithInput("--csv ", baseFlagsPath).
+		Inputs(moduleSpecificFlagsPaths).
 		FlagWithOutput("--output ", tempPath)
 
+	for _, path := range augmentationInfo.Unsupported {
+		command.FlagWithInput("--unsupported ", path)
+	}
+
+	for _, path := range augmentationInfo.Removed {
+		command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
+	}
+
+	for _, path := range augmentationInfo.Max_target_r_low_priority {
+		command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
+	}
+
+	for _, path := range augmentationInfo.Max_target_q {
+		command.FlagWithInput("--max-target-q ", path)
+	}
+
+	for _, path := range augmentationInfo.Max_target_p {
+		command.FlagWithInput("--max-target-p ", path)
+	}
+
+	for _, path := range augmentationInfo.Max_target_o_low_priority {
+		command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
+	}
+
+	for _, path := range augmentationInfo.Blocked {
+		command.FlagWithInput("--blocked ", path)
+	}
+
+	for _, path := range augmentationInfo.Unsupported_packages {
+		command.FlagWithInput("--unsupported ", path).Flag("--packages ")
+	}
+
 	commitChangeForRestat(rule, tempPath, outputPath)
 
 	rule.Build("hiddenAPIFlagsFile", "hiddenapi flags")
-
-	return outputPath
 }
 
 // emptyFlagsRule creates a rule to build an empty hiddenapi-flags.csv, which is needed by master-art-host builds that