From 2a999332efcbf95c44593c1a9d0f83410b247d19 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Mon, 7 Jun 2021 21:36:01 +0100 Subject: [PATCH] Fix monolithic hidden API processing with prebuilts Prebuilt modules do not provide classesJars containing annotations. Previously, the monolithic hidden API processing just used classesJars from all the modules that provided them so when building against prebuilts would have fewer classesJars than when building against sources and so would produce different hidden API flags. This change will generate the monolithic files from both classesJars and files previously generated from hidden API processing. A fragment that has performed hidden API processing will contribute its generated files whereas standalone libraries and fragments which have not performed hidden API processing will contribute classesJars. Bug: 177892522 Test: m out/soong/hiddenapi/hiddenapi-flags.csv m SOONG_CONFIG_art_module_source_build=false out/soong/hiddenapi/hiddenapi-flags.csv - verify that the files are identical whether built from source or prebuilts. Merged-In: I06f3c7df49626bec21a452bc9abf1bb9e7545e5c Change-Id: I06f3c7df49626bec21a452bc9abf1bb9e7545e5c (cherry picked from commit d061d40eb6ffbc9d7cece2945b7276fe2f6759d1) --- apex/apex_test.go | 8 +++-- java/hiddenapi_modular.go | 8 ++--- java/hiddenapi_monolithic.go | 8 +++++ java/platform_bootclasspath.go | 46 ++++++++++++++++++-------- java/platform_bootclasspath_test.go | 43 ++++++++++++++++++++---- sdk/bootclasspath_fragment_sdk_test.go | 22 ++++++++++++ 6 files changed, 109 insertions(+), 26 deletions(-) diff --git a/apex/apex_test.go b/apex/apex_test.go index ecc585ee4..c50c4a94f 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -4416,11 +4416,13 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { } } - checkHiddenAPIIndexInputs := func(t *testing.T, ctx *android.TestContext, expectedInputs string) { + checkHiddenAPIIndexInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) { t.Helper() platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common") - indexRule := platformBootclasspath.Rule("monolithic_hidden_API_index") - java.CheckHiddenAPIRuleInputs(t, "index", expectedInputs, indexRule) + var rule android.TestingBuildParams + + rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv") + java.CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule) } fragment := java.ApexVariantReference{ diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index de72b39aa..6e2261480 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -524,7 +524,7 @@ func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, conten } } - ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) { + ctx.VisitDirectDeps(func(module android.Module) { tag := ctx.OtherModuleDependencyTag(module) if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok { kind := hiddenAPIStubsTag.sdkKind @@ -634,7 +634,7 @@ func pathForValidation(ctx android.PathContext, path android.WritablePath) andro // hiddenAPIInfo 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, + outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths, flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths, generatedRemovedDexSignatures android.OptionalPath) { // The file which is used to record that the flags file is valid. @@ -665,7 +665,7 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st command := rule.Command(). BuiltTool("generate_hiddenapi_lists"). FlagWithInput("--csv ", baseFlagsPath). - Input(annotationFlags). + Inputs(annotationFlagPaths). FlagWithOutput("--output ", tempPath) // Add the options for the different categories of flag files. @@ -747,7 +747,7 @@ func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex // files. allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv") - buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, annotationFlagsCSV, input.FlagFilesByCategory, nil, removedDexSignatures) + buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures) // Encode the flags into the boot dex files. encodedBootDexJarsByModule := map[string]android.Path{} diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go index 8a83d1006..52f0770f3 100644 --- a/java/hiddenapi_monolithic.go +++ b/java/hiddenapi_monolithic.go @@ -68,6 +68,14 @@ func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory F if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) { info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo) monolithicInfo.append(&info) + + // If the bootclasspath fragment actually perform hidden API processing itself then use the + // CSV files it provides and do not bother processing the classesJars files. This ensures + // consistent behavior between source and prebuilt as prebuilt modules do not provide + // classesJars. + if info.AllFlagsPath != nil { + continue + } } classesJars = extractClassesJarsFromModules(e.Contents) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 46fc7b5fd..7b651baff 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -303,28 +303,48 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags") // Generate the annotation-flags.csv file from all the module annotations. - annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags.csv") - buildRuleToGenerateAnnotationFlags(ctx, "monolithic hiddenapi flags", classesJars, stubFlags, annotationFlags) + annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags-from-classes.csv") + buildRuleToGenerateAnnotationFlags(ctx, "intermediate hidden API flags", classesJars, stubFlags, annotationFlags) - // Generate the monotlithic hiddenapi-flags.csv file. + // Generate the monolithic hiddenapi-flags.csv file. + // + // Use annotation flags generated directly from the classes jars as well as annotation flag files + // provided by prebuilts. + allAnnotationFlagFiles := android.Paths{annotationFlags} + allAnnotationFlagFiles = append(allAnnotationFlagFiles, monolithicInfo.AnnotationFlagsPaths...) allFlags := hiddenAPISingletonPaths(ctx).flags - buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "hiddenapi flags", allFlags, stubFlags, annotationFlags, monolithicInfo.FlagsFilesByCategory, monolithicInfo.AllFlagsPaths, android.OptionalPath{}) + buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "monolithic hidden API flags", allFlags, stubFlags, allAnnotationFlagFiles, monolithicInfo.FlagsFilesByCategory, monolithicInfo.AllFlagsPaths, android.OptionalPath{}) // Generate an intermediate monolithic hiddenapi-metadata.csv file directly from the annotations // in the source code. - intermediateMetadataCSV := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "intermediate-metadata.csv") - buildRuleToGenerateMetadata(ctx, "monolithic hidden API metadata", classesJars, stubFlags, intermediateMetadataCSV) + intermediateMetadataCSV := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "metadata-from-classes.csv") + buildRuleToGenerateMetadata(ctx, "intermediate hidden API metadata", classesJars, stubFlags, intermediateMetadataCSV) - // Reformat the intermediate file to add | quotes just in case that is important for the tools - // that consume the metadata file. - // TODO(b/179354495): Investigate whether it is possible to remove this reformatting step. + // Generate the monolithic hiddenapi-metadata.csv file. + // + // Use metadata files generated directly from the classes jars as well as metadata files provided + // by prebuilts. + // + // This has the side effect of ensuring that the output file uses | quotes just in case that is + // important for the tools that consume the metadata file. + allMetadataFlagFiles := android.Paths{intermediateMetadataCSV} + allMetadataFlagFiles = append(allMetadataFlagFiles, monolithicInfo.MetadataPaths...) metadataCSV := hiddenAPISingletonPaths(ctx).metadata - b.buildRuleMergeCSV(ctx, "reformat monolithic hidden API metadata", android.Paths{intermediateMetadataCSV}, metadataCSV) + b.buildRuleMergeCSV(ctx, "monolithic hidden API metadata", allMetadataFlagFiles, metadataCSV) - // Generate the monolithic hiddenapi-index.csv file directly from the CSV files in the classes - // jars. + // Generate an intermediate monolithic hiddenapi-index.csv file directly from the CSV files in the + // classes jars. + intermediateIndexCSV := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "index-from-classes.csv") + buildRuleToGenerateIndex(ctx, "intermediate hidden API index", classesJars, intermediateIndexCSV) + + // Generate the monolithic hiddenapi-index.csv file. + // + // Use index files generated directly from the classes jars as well as index files provided + // by prebuilts. + allIndexFlagFiles := android.Paths{intermediateIndexCSV} + allIndexFlagFiles = append(allIndexFlagFiles, monolithicInfo.IndexPaths...) indexCSV := hiddenAPISingletonPaths(ctx).index - buildRuleToGenerateIndex(ctx, "monolithic hidden API index", classesJars, indexCSV) + b.buildRuleMergeCSV(ctx, "monolithic hidden API index", allIndexFlagFiles, indexCSV) return bootDexJarByModule } diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go index 87a641118..1c2a3aee5 100644 --- a/java/platform_bootclasspath_test.go +++ b/java/platform_bootclasspath_test.go @@ -318,10 +318,41 @@ func TestPlatformBootclasspath_HiddenAPIMonolithicFiles(t *testing.T) { // Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that // creates the index.csv file. platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common") - indexRule := platformBootclasspath.Rule("monolithic_hidden_API_index") - CheckHiddenAPIRuleInputs(t, "index", ` - out/soong/.intermediates/bar/android_common/javac/bar.jar - out/soong/.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar - out/soong/.intermediates/foo/android_common/javac/foo.jar - `, indexRule) + + var rule android.TestingBuildParams + + // All the intermediate rules use the same inputs. + expectedIntermediateInputs := ` + out/soong/.intermediates/bar/android_common/javac/bar.jar + out/soong/.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar + out/soong/.intermediates/foo/android_common/javac/foo.jar + ` + + // Check flags output. + rule = platformBootclasspath.Output("hiddenapi-monolithic/annotation-flags-from-classes.csv") + CheckHiddenAPIRuleInputs(t, "intermediate flags", expectedIntermediateInputs, rule) + + rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-flags.csv") + CheckHiddenAPIRuleInputs(t, "monolithic flags", ` + out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/annotation-flags-from-classes.csv + out/soong/hiddenapi/hiddenapi-stub-flags.txt + `, rule) + + // Check metadata output. + rule = platformBootclasspath.Output("hiddenapi-monolithic/metadata-from-classes.csv") + CheckHiddenAPIRuleInputs(t, "intermediate metadata", expectedIntermediateInputs, rule) + + rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-unsupported.csv") + CheckHiddenAPIRuleInputs(t, "monolithic metadata", ` + out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/metadata-from-classes.csv + `, rule) + + // Check index output. + rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv") + CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule) + + rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-index.csv") + CheckHiddenAPIRuleInputs(t, "monolithic index", ` + out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv + `, rule) } diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go index 1f28ed39a..378f7cfaa 100644 --- a/sdk/bootclasspath_fragment_sdk_test.go +++ b/sdk/bootclasspath_fragment_sdk_test.go @@ -484,6 +484,28 @@ sdk_snapshot { .intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt `), snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot), + snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) { + module := result.ModuleForTests("platform-bootclasspath", "android_common") + var rule android.TestingBuildParams + rule = module.Output("out/soong/hiddenapi/hiddenapi-flags.csv") + java.CheckHiddenAPIRuleInputs(t, "monolithic flags", ` + out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/annotation-flags-from-classes.csv + out/soong/hiddenapi/hiddenapi-stub-flags.txt + snapshot/hiddenapi/annotation-flags.csv + `, rule) + + rule = module.Output("out/soong/hiddenapi/hiddenapi-unsupported.csv") + java.CheckHiddenAPIRuleInputs(t, "monolithic metadata", ` + out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/metadata-from-classes.csv + snapshot/hiddenapi/metadata.csv + `, rule) + + rule = module.Output("out/soong/hiddenapi/hiddenapi-index.csv") + java.CheckHiddenAPIRuleInputs(t, "monolithic index", ` + out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv + snapshot/hiddenapi/index.csv + `, rule) + }), snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot), snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot), )