From 9e3b906581c7b1e1019ed3d2a2a2bec67d3ef501 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 21 May 2021 16:58:23 +0100 Subject: [PATCH] Separate monolithic hidden API processing from hiddenAPIFlagFileInfo The hiddenAPIFlagFileInfo was being used for both the input and output of bootclasspath_fragment and platform_bootclasspath and also to pass information around to various hidden API rule methods. Supporting multiple different uses in this way made it hard to reason about. This change creates a separate structure for use by the platform_bootclasspath. Follow up changes will split out other functionality into separate types. 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 Merged-In: Ia5c5f65ae5645486c42819c669a8601588217f88 Change-Id: Ia5c5f65ae5645486c42819c669a8601588217f88 (cherry picked from commit 438eb57a2744b9b0bd38a5526e67cacf43c42b31) --- java/Android.bp | 1 + java/bootclasspath_fragment.go | 4 +- java/hiddenapi_modular.go | 47 ++++++++------- java/hiddenapi_monolithic.go | 91 +++++++++++++++++++++++++++++ java/platform_bootclasspath.go | 28 ++++----- java/platform_bootclasspath_test.go | 4 +- 6 files changed, 138 insertions(+), 37 deletions(-) create mode 100644 java/hiddenapi_monolithic.go diff --git a/java/Android.bp b/java/Android.bp index 623a6c577..680f3a17c 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -45,6 +45,7 @@ bootstrap_go_package { "genrule.go", "hiddenapi.go", "hiddenapi_modular.go", + "hiddenapi_monolithic.go", "hiddenapi_singleton.go", "jacoco.go", "java.go", diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index e151d6315..9310b12b1 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -651,7 +651,7 @@ type bootclasspathFragmentSdkMemberProperties struct { Core_platform_stub_libs []string // Flag files by *hiddenAPIFlagFileCategory - Flag_files_by_category map[*hiddenAPIFlagFileCategory]android.Paths + Flag_files_by_category FlagFilesByCategory // The path to the generated stub-flags.csv file. Stub_flags_path android.OptionalPath @@ -689,7 +689,7 @@ func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx andro // Get the flag file information from the module. mctx := ctx.SdkModuleContext() flagFileInfo := mctx.OtherModuleProvider(module, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo) - b.Flag_files_by_category = flagFileInfo.categoryToPaths + b.Flag_files_by_category = flagFileInfo.FlagFilesByCategory // Copy all the generated file paths. b.Stub_flags_path = pathsToOptionalPath(flagFileInfo.StubFlagsPaths) diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index f5afe5d5b..83721324a 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -261,10 +261,10 @@ type HiddenAPIFlagFileProperties struct { } func (p *HiddenAPIFlagFileProperties) hiddenAPIFlagFileInfo(ctx android.ModuleContext) hiddenAPIFlagFileInfo { - info := hiddenAPIFlagFileInfo{categoryToPaths: map[*hiddenAPIFlagFileCategory]android.Paths{}} + info := hiddenAPIFlagFileInfo{FlagFilesByCategory: FlagFilesByCategory{}} for _, category := range hiddenAPIFlagFileCategories { paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p)) - info.categoryToPaths[category] = paths + info.FlagFilesByCategory[category] = paths } return info } @@ -365,6 +365,24 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ }, } +// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category. +type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths + +// append appends the supplied flags files to the corresponding category in this map. +func (s FlagFilesByCategory) append(other FlagFilesByCategory) { + for _, category := range hiddenAPIFlagFileCategories { + s[category] = append(s[category], other[category]...) + } +} + +// dedup removes duplicates in the flag files, while maintaining the order in which they were +// appended. +func (s FlagFilesByCategory) dedup() { + for category, paths := range s { + s[category] = android.FirstUniquePaths(paths) + } +} + // hiddenAPIFlagFileInfo contains paths resolved from HiddenAPIFlagFileProperties and also generated // by hidden API processing. // @@ -372,9 +390,9 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ // for a module to collate the files from the fragments it depends upon. That is why the fields are // all Paths even though they are initialized with a single path. type hiddenAPIFlagFileInfo struct { - // categoryToPaths maps from the flag file category to the paths containing information for that - // category. - categoryToPaths map[*hiddenAPIFlagFileCategory]android.Paths + // FlagFilesByCategory maps from the flag file category to the paths containing information for + // that category. + FlagFilesByCategory FlagFilesByCategory // The paths to the generated stub-flags.csv files. StubFlagsPaths android.Paths @@ -392,17 +410,6 @@ type hiddenAPIFlagFileInfo struct { AllFlagsPaths android.Paths } -func (i *hiddenAPIFlagFileInfo) append(other hiddenAPIFlagFileInfo) { - for _, category := range hiddenAPIFlagFileCategories { - i.categoryToPaths[category] = append(i.categoryToPaths[category], other.categoryToPaths[category]...) - } - i.StubFlagsPaths = append(i.StubFlagsPaths, other.StubFlagsPaths...) - i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPaths...) - i.MetadataPaths = append(i.MetadataPaths, other.MetadataPaths...) - i.IndexPaths = append(i.IndexPaths, other.IndexPaths...) - i.AllFlagsPaths = append(i.AllFlagsPaths, other.AllFlagsPaths...) -} - var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{}) // pathForValidation creates a path of the same type as the supplied type but with a name of @@ -428,14 +435,14 @@ func pathForValidation(ctx android.PathContext, path android.WritablePath) andro // // flagFileInfo is a struct containing paths to files that augment the information provided by // the annotationFlags. -func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlags android.Path, flagFileInfo *hiddenAPIFlagFileInfo) { +func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlags android.Path, flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths) { // The file which is used to record that the flags file is valid. var validFile android.WritablePath // If there are flag files that have been generated by fragments on which this depends then use // them to validate the flag file generated by the rules created by this method. - if allFlagsPaths := flagFileInfo.AllFlagsPaths; len(allFlagsPaths) > 0 { + if len(allFlagsPaths) > 0 { // The flags file generated by the rule created by this method needs to be validated to ensure // that it is consistent with the flag files generated by the individual fragments. @@ -463,7 +470,7 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st // Add the options for the different categories of flag files. for _, category := range hiddenAPIFlagFileCategories { - paths := flagFileInfo.categoryToPaths[category] + paths := flagFilesByCategory[category] for _, path := range paths { category.commandMutator(command, path) } @@ -530,7 +537,7 @@ func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext // 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) + buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, flagFileInfo.FlagFilesByCategory, nil) // Store the paths in the info for use by other modules and sdk snapshot generation. flagFileInfo.StubFlagsPaths = android.Paths{stubFlagsCSV} diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go new file mode 100644 index 000000000..9ca3cfb7d --- /dev/null +++ b/java/hiddenapi_monolithic.go @@ -0,0 +1,91 @@ +// 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" + "github.com/google/blueprint" +) + +// MonolithicHiddenAPIInfo contains information needed/provided by the hidden API generation of the +// monolithic hidden API files. +// +// Each list of paths includes all the equivalent paths from each of the bootclasspath_fragment +// modules that contribute to the platform-bootclasspath. +type MonolithicHiddenAPIInfo struct { + // FlagsFilesByCategory maps from the flag file category to the paths containing information for + // that category. + FlagsFilesByCategory FlagFilesByCategory + + // The paths to the generated stub-flags.csv files. + StubFlagsPaths android.Paths + + // The paths to the generated annotation-flags.csv files. + AnnotationFlagsPaths android.Paths + + // The paths to the generated metadata.csv files. + MetadataPaths android.Paths + + // The paths to the generated index.csv files. + IndexPaths android.Paths + + // The paths to the generated all-flags.csv files. + AllFlagsPaths android.Paths +} + +// newMonolithicHiddenAPIInfo creates a new MonolithicHiddenAPIInfo from the flagFilesByCategory +// plus information provided by each of the fragments. +func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory FlagFilesByCategory, fragments []android.Module) MonolithicHiddenAPIInfo { + monolithicInfo := MonolithicHiddenAPIInfo{} + + monolithicInfo.FlagsFilesByCategory = flagFilesByCategory + + // Merge all the information from the fragments. The fragments form a DAG so it is possible that + // this will introduce duplicates so they will be resolved after processing all the fragments. + for _, fragment := range fragments { + if ctx.OtherModuleHasProvider(fragment, hiddenAPIFlagFileInfoProvider) { + info := ctx.OtherModuleProvider(fragment, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo) + monolithicInfo.append(&info) + } + } + + // Dedup paths. + monolithicInfo.dedup() + + return monolithicInfo +} + +// append appends all the files from the supplied info to the corresponding files in this struct. +func (i *MonolithicHiddenAPIInfo) append(other *hiddenAPIFlagFileInfo) { + i.FlagsFilesByCategory.append(other.FlagFilesByCategory) + i.StubFlagsPaths = append(i.StubFlagsPaths, other.StubFlagsPaths...) + i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPaths...) + i.MetadataPaths = append(i.MetadataPaths, other.MetadataPaths...) + i.IndexPaths = append(i.IndexPaths, other.IndexPaths...) + i.AllFlagsPaths = append(i.AllFlagsPaths, other.AllFlagsPaths...) +} + +// dedup removes duplicates in all the paths, while maintaining the order in which they were +// appended. +func (i *MonolithicHiddenAPIInfo) dedup() { + i.FlagsFilesByCategory.dedup() + i.StubFlagsPaths = android.FirstUniquePaths(i.StubFlagsPaths) + i.AnnotationFlagsPaths = android.FirstUniquePaths(i.AnnotationFlagsPaths) + i.MetadataPaths = android.FirstUniquePaths(i.MetadataPaths) + i.IndexPaths = android.FirstUniquePaths(i.IndexPaths) + i.AllFlagsPaths = android.FirstUniquePaths(i.AllFlagsPaths) +} + +var monolithicHiddenAPIInfoProvider = blueprint.NewProvider(MonolithicHiddenAPIInfo{}) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 5db2efe40..df0ba2a42 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -279,21 +279,12 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. return } - flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx) - for _, fragment := range fragments { - if ctx.OtherModuleHasProvider(fragment, hiddenAPIFlagFileInfoProvider) { - info := ctx.OtherModuleProvider(fragment, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo) - flagFileInfo.append(info) - } - } - - // Store the information for testing. - ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo) - - hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, modules) + monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments) sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx, nil) + hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, modules) + // Generate the monolithic stub-flags.csv file. bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, hiddenAPIModules) stubFlags := hiddenAPISingletonPaths(ctx).stubFlags @@ -309,7 +300,7 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. // Generate the monotlithic hiddenapi-flags.csv file. allFlags := hiddenAPISingletonPaths(ctx).flags - buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "hiddenapi flags", allFlags, stubFlags, annotationFlags, &flagFileInfo) + buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "hiddenapi flags", allFlags, stubFlags, annotationFlags, monolithicInfo.FlagsFilesByCategory, monolithicInfo.AllFlagsPaths) // Generate an intermediate monolithic hiddenapi-metadata.csv file directly from the annotations // in the source code. @@ -328,6 +319,17 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. buildRuleToGenerateIndex(ctx, "monolithic hidden API index", classesJars, indexCSV) } +// 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) + + // Store the information for testing. + ctx.SetProvider(monolithicHiddenAPIInfoProvider, monolithicInfo) + return monolithicInfo +} + func (b *platformBootclasspathModule) buildRuleMergeCSV(ctx android.ModuleContext, desc string, inputPaths android.Paths, outputPath android.WritablePath) { rule := android.NewRuleBuilder(pctx, ctx) rule.Command(). diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go index efcbc80d0..d332f63df 100644 --- a/java/platform_bootclasspath_test.go +++ b/java/platform_bootclasspath_test.go @@ -245,14 +245,14 @@ func TestPlatformBootclasspath_Fragments(t *testing.T) { ).RunTest(t) pbcp := result.Module("platform-bootclasspath", "android_common") - info := result.ModuleProvider(pbcp, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo) + info := result.ModuleProvider(pbcp, monolithicHiddenAPIInfoProvider).(MonolithicHiddenAPIInfo) for _, category := range hiddenAPIFlagFileCategories { name := category.propertyName message := fmt.Sprintf("category %s", name) filename := strings.ReplaceAll(name, "_", "-") expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)} - android.AssertPathsRelativeToTopEquals(t, message, expected, info.categoryToPaths[category]) + android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category]) } android.AssertPathsRelativeToTopEquals(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/stub-flags.csv"}, info.StubFlagsPaths)