Separate input to flag generation from hiddenAPIFlagFileInfo
Encapsulating the information needed by hidden API processing in a
struct makes it easy to add additional information in future and allows
the code to populate that struct from various different sources to be
grouped together.
Bug: 179354495
Test: m com.android.art com.android.ipsec com.android.os.statsd com.android.conscrypt
- verify that this does not change the contents of the apex files
Change-Id: I53805737dff36a3ae87aca5aad51cf46ae1361fe
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 3857b20..a7c1e78 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -133,8 +133,8 @@
type commonBootclasspathFragment interface {
// produceHiddenAPIAllFlagsFile produces the all-flags.csv and intermediate files.
//
- // Updates the supplied flagFileInfo with the paths to the generated files set.
- produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) *HiddenAPIFlagOutput
+ // Updates the supplied hiddenAPIInfo with the paths to the generated files set.
+ produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput
}
var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil)
@@ -538,45 +538,61 @@
return nil
}
- // Convert the kind specific lists of modules into kind specific lists of jars.
- stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(ctx, contents)
+ // Create hidden API input structure.
+ input := b.createHiddenAPIFlagInput(ctx, contents)
// Performing hidden API processing without stubs is not supported and it is unlikely to ever be
// required as the whole point of adding something to the bootclasspath fragment is to add it to
// the bootclasspath in order to be used by something else in the system. Without any stubs it
// cannot do that.
- if len(stubJarsByKind) == 0 {
+ if len(input.StubDexJarsByKind) == 0 {
return nil
}
// Store the information for use by other modules.
- bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: stubJarsByKind}
+ bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: input.StubDexJarsByKind}
ctx.SetProvider(bootclasspathApiInfoProvider, bootclasspathApiInfo)
- // Resolve the properties to paths.
- flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
-
hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, contents)
// Delegate the production of the hidden API all flags file to a module type specific method.
common := ctx.Module().(commonBootclasspathFragment)
- output := common.produceHiddenAPIAllFlagsFile(ctx, hiddenAPIModules, stubJarsByKind, &flagFileInfo)
+ output := common.produceHiddenAPIAllFlagsFile(ctx, hiddenAPIModules, input)
- // Copy the output into the flagFileInfo
- flagFileInfo.HiddenAPIFlagOutput = *output
+ // Initialize a hiddenAPIFlagFileInfo structure and provide it for use by other modules.
+ flagFileInfo := hiddenAPIFlagFileInfo{
+ // The monolithic hidden API processing needs access to the flag files from all the fragments.
+ FlagFilesByCategory: input.FlagFilesByCategory,
- // Store the information for use by platform_bootclasspath.
+ // The monolithic hidden API processing also needs access to all the output files produced by
+ // hidden API processing of this fragment.
+ HiddenAPIFlagOutput: *output,
+ }
ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
return output
}
+// createHiddenAPIFlagInput creates a HiddenAPIFlagInput struct and initializes it with information derived
+// from the properties on this module and its dependencies.
+func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.ModuleContext, contents []android.Module) HiddenAPIFlagInput {
+ input := newHiddenAPIFlagInput()
+
+ // Update the input structure with information obtained from the stub libraries.
+ input.gatherStubLibInfo(ctx, contents)
+
+ // Populate with flag file paths from the properties.
+ input.extractFlagFilesFromProperties(ctx, &b.properties.Hidden_api)
+
+ return input
+}
+
// produceHiddenAPIAllFlagsFile produces the hidden API all-flags.csv file (and supporting files)
// for the fragment.
-func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) *HiddenAPIFlagOutput {
- // Generate the rules to create the hidden API flags and update the supplied flagFileInfo with the
+func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
+ // Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the
// paths to the created files.
- return hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, stubJarsByKind, flagFileInfo)
+ return hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, input)
}
// generateBootImageBuildActions generates ninja rules to create the boot image if required for this
@@ -800,7 +816,7 @@
// produceHiddenAPIAllFlagsFile returns a path to the prebuilt all-flags.csv or nil if none is
// specified.
-func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) *HiddenAPIFlagOutput {
+func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, _ HiddenAPIFlagInput) *HiddenAPIFlagOutput {
pathForOptionalSrc := func(src *string) android.Path {
if src == nil {
// TODO(b/179354495): Fail if this is not provided once prebuilts have been updated.
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 99485b4..b5969e9 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -127,42 +127,6 @@
}
}
-// hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added
-// in hiddenAPIAddStubLibDependencies.
-func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext, contents []android.Module) map[android.SdkKind]android.Paths {
- m := map[android.SdkKind]android.Paths{}
-
- // If the contents includes any java_sdk_library modules then add them to the stubs.
- for _, module := range contents {
- if _, ok := module.(SdkLibraryDependency); ok {
- for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
- dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
- if dexJar != nil {
- m[kind] = append(m[kind], dexJar)
- }
- }
- }
- }
-
- ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
- tag := ctx.OtherModuleDependencyTag(module)
- if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
- kind := hiddenAPIStubsTag.sdkKind
- dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
- if dexJar != nil {
- m[kind] = append(m[kind], dexJar)
- }
- }
- })
-
- // Normalize the paths, i.e. remove duplicates and sort.
- for k, v := range m {
- m[k] = android.SortedUniquePaths(v)
- }
-
- return m
-}
-
// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
// available, or reports an error.
func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
@@ -193,7 +157,7 @@
//
// The rule is initialized but not built so that the caller can modify it and select an appropriate
// name.
-func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
+func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput) *android.RuleBuilder {
// Singleton rule which applies hiddenapi on all boot class path dex files.
rule := android.NewRuleBuilder(pctx, ctx)
@@ -206,7 +170,7 @@
// Iterate over the sdk kinds in a fixed order.
for _, sdkKind := range hiddenAPIRelevantSdkKinds {
- paths := sdkKindToPathList[sdkKind]
+ paths := input.StubDexJarsByKind[sdkKind]
if len(paths) > 0 {
option := sdkKindToHiddenapiListOption[sdkKind]
command.FlagWithInputList("--"+option+"=", paths, ":")
@@ -260,15 +224,6 @@
Unsupported_packages []string `android:"path"`
}
-func (p *HiddenAPIFlagFileProperties) hiddenAPIFlagFileInfo(ctx android.ModuleContext) hiddenAPIFlagFileInfo {
- info := hiddenAPIFlagFileInfo{FlagFilesByCategory: FlagFilesByCategory{}}
- for _, category := range hiddenAPIFlagFileCategories {
- paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
- info.FlagFilesByCategory[category] = paths
- }
- return info
-}
-
type hiddenAPIFlagFileCategory struct {
// propertyName is the name of the property for this category.
propertyName string
@@ -400,6 +355,93 @@
var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{})
+// StubDexJarsByKind maps an android.SdkKind to the paths to stub dex jars appropriate for that
+// level. See hiddenAPIRelevantSdkKinds for a list of the acceptable android.SdkKind values.
+type StubDexJarsByKind map[android.SdkKind]android.Paths
+
+// append appends the supplied kind specific stub dex jar pargs to the corresponding kind in this
+// map.
+func (s StubDexJarsByKind) append(other StubDexJarsByKind) {
+ for _, kind := range hiddenAPIRelevantSdkKinds {
+ s[kind] = append(s[kind], other[kind]...)
+ }
+}
+
+// dedupAndSort removes duplicates in the stub dex jar paths and sorts them into a consistent and
+// deterministic order.
+func (s StubDexJarsByKind) dedupAndSort() {
+ for kind, paths := range s {
+ s[kind] = android.SortedUniquePaths(paths)
+ }
+}
+
+// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
+// needed for hidden API flag generation.
+type HiddenAPIFlagInput struct {
+ // FlagFilesByCategory contains the flag files that override the initial flags that are derived
+ // from the stub dex files.
+ FlagFilesByCategory FlagFilesByCategory
+
+ // StubDexJarsByKind contains the stub dex jars for different android.SdkKind and which determine
+ // the initial flags for each dex member.
+ StubDexJarsByKind StubDexJarsByKind
+}
+
+// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
+func newHiddenAPIFlagInput() HiddenAPIFlagInput {
+ input := HiddenAPIFlagInput{
+ FlagFilesByCategory: FlagFilesByCategory{},
+ StubDexJarsByKind: StubDexJarsByKind{},
+ }
+
+ return input
+}
+
+// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
+// dependencies added in hiddenAPIAddStubLibDependencies.
+//
+// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
+func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
+ addFromModule := func(ctx android.ModuleContext, module android.Module, kind android.SdkKind) {
+ dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
+ if dexJar != nil {
+ i.StubDexJarsByKind[kind] = append(i.StubDexJarsByKind[kind], dexJar)
+ }
+ }
+
+ // If the contents includes any java_sdk_library modules then add them to the stubs.
+ for _, module := range contents {
+ if _, ok := module.(SdkLibraryDependency); ok {
+ // Add information for every possible kind needed by hidden API. SdkCorePlatform is not used
+ // as the java_sdk_library does not have special support for core_platform API, instead it is
+ // implemented as a customized form of SdkPublic.
+ for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
+ addFromModule(ctx, module, kind)
+ }
+ }
+ }
+
+ ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
+ tag := ctx.OtherModuleDependencyTag(module)
+ if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
+ kind := hiddenAPIStubsTag.sdkKind
+ addFromModule(ctx, module, kind)
+ }
+ })
+
+ // Normalize the paths, i.e. remove duplicates and sort.
+ i.StubDexJarsByKind.dedupAndSort()
+}
+
+// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
+// supplied properties and stores them in this struct.
+func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
+ for _, category := range hiddenAPIFlagFileCategories {
+ paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
+ i.FlagFilesByCategory[category] = paths
+ }
+}
+
// HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
// bootclasspath_fragment module.
type HiddenAPIFlagOutput struct {
@@ -510,13 +552,15 @@
// * metadata.csv
// * index.csv
// * all-flags.csv
-func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) *HiddenAPIFlagOutput {
+func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
hiddenApiSubDir := "modular-hiddenapi"
- // Generate the stub-flags.csv.
+ // Gather the dex files for the boot libraries provided by this fragment.
bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, contents)
+
+ // Generate the stub-flags.csv.
stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
- rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, stubJarsByKind)
+ rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, input)
rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
// Extract the classes jars from the contents.
@@ -544,7 +588,7 @@
// Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
// files.
outputPath := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
- buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, flagFileInfo.FlagFilesByCategory, nil)
+ buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, input.FlagFilesByCategory, nil)
// Store the paths in the info for use by other modules and sdk snapshot generation.
output := HiddenAPIFlagOutput{
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index df0ba2a..854179e 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -281,14 +281,22 @@
monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments)
- sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx, nil)
+ // Create the input to pass to ruleToGenerateHiddenAPIStubFlagsFile
+ input := newHiddenAPIFlagInput()
+
+ // Gather stub library information from the dependencies on modules provided by
+ // hiddenAPIComputeMonolithicStubLibModules.
+ input.gatherStubLibInfo(ctx, nil)
+
+ // Use the flag files from this module and all the fragments.
+ input.FlagFilesByCategory = monolithicInfo.FlagsFilesByCategory
hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, modules)
// Generate the monolithic stub-flags.csv file.
bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, hiddenAPIModules)
stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
- rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJars, sdkKindToStubPaths)
+ rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJars, input)
rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
// Extract the classes jars from the contents.
@@ -322,8 +330,16 @@
// createAndProvideMonolithicHiddenAPIInfo creates a MonolithicHiddenAPIInfo and provides it for
// testing.
func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ctx android.ModuleContext, fragments []android.Module) MonolithicHiddenAPIInfo {
- flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
- monolithicInfo := newMonolithicHiddenAPIInfo(ctx, flagFileInfo.FlagFilesByCategory, fragments)
+ // Create a temporary input structure in which to collate information provided directly by this
+ // module, either through properties or direct dependencies.
+ temporaryInput := newHiddenAPIFlagInput()
+
+ // Create paths to the flag files specified in the properties.
+ temporaryInput.extractFlagFilesFromProperties(ctx, &b.properties.Hidden_api)
+
+ // Create the monolithic info, by starting with the flag files specified on this and then merging
+ // in information from all the fragment dependencies of this.
+ monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, fragments)
// Store the information for testing.
ctx.SetProvider(monolithicHiddenAPIInfoProvider, monolithicInfo)