Support removed API members in modular hidden API processing
Previously, the hidden API flags generated for a bootclasspath_fragment
did not include removed API members. That was because it did not supply
a file containing the dex signatures of the removed API members.
The monolithic hidden API processing uses combined-removed-dex which is
the output of a genrule that takes as input the *removed.txt files from
all the APIs and uses metalava to construct the dex signatures file.
This change does the equivalent for the *removed.txt files for the APIs
provided by a bootclasspath_fragment and then passes them to the rule
that generates the final all-flags.csv.
Bug: 179354495
Test: - Update packages/modules/RuntimeI18N to enable hidden API
processing.
m out/soong/hiddenapi/hiddenapi-flags.csv
- Before this change that fails as the flags generated for the
i18n-bootclasspath-fragment differ from the monolithic flags.
After this change that passes.
- Verify that this change does not change any of the monolithic
hidden API files.
m com.android.i18n
- Verify that the apex file before and after this change are byte
for byte identical.
Change-Id: I6a21edb8a5231666e3f35b2c99a8687f36dd98fd
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 3707942..f2649d3 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -260,6 +260,22 @@
commandMutator func(command *android.RuleBuilderCommand, path android.Path)
}
+// The flag file category for removed members of the API.
+//
+// This is extracted from hiddenAPIFlagFileCategories as it is needed to add the dex signatures
+// list of removed API members that are generated automatically from the removed.txt files provided
+// by API stubs.
+var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{
+ // See HiddenAPIFlagFileProperties.Removed
+ propertyName: "removed",
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
+ return properties.Removed
+ },
+ commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
+ command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
+ },
+}
+
var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Unsupported
{
@@ -271,16 +287,7 @@
command.FlagWithInput("--unsupported ", path)
},
},
- // See HiddenAPIFlagFileProperties.Removed
- {
- propertyName: "removed",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Removed
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
- },
- },
+ hiddenAPIRemovedFlagFileCategory,
// See HiddenAPIFlagFileProperties.Max_target_r_low_priority
{
propertyName: "max_target_r_low_priority",
@@ -436,6 +443,10 @@
// depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByKind from each
// fragment on which this depends.
DependencyStubDexJarsByKind StubDexJarsByKind
+
+ // RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
+ // specified in the bootclasspath_fragment's stub_libs and contents properties.
+ RemovedTxtFiles android.Paths
}
// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
@@ -494,6 +505,11 @@
if dexJar != nil {
i.StubDexJarsByKind[kind] = append(i.StubDexJarsByKind[kind], dexJar)
}
+
+ if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
+ removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, kind)
+ i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
+ }
}
// If the contents includes any java_sdk_library modules then add them to the stubs.
@@ -518,6 +534,7 @@
// Normalize the paths, i.e. remove duplicates and sort.
i.StubDexJarsByKind.dedupAndSort()
+ i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
}
// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
@@ -577,7 +594,9 @@
//
// 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, flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths) {
+func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string,
+ outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlags android.Path,
+ flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths, generatedRemovedDexSignatures android.OptionalPath) {
// The file which is used to record that the flags file is valid.
var validFile android.WritablePath
@@ -618,6 +637,12 @@
}
}
+ // If available then pass the automatically generated file containing dex signatures of removed
+ // API members to the rule so they can be marked as removed.
+ if generatedRemovedDexSignatures.Valid() {
+ hiddenAPIRemovedFlagFileCategory.commandMutator(command, generatedRemovedDexSignatures.Path())
+ }
+
commitChangeForRestat(rule, tempPath, outputPath)
if validFile != nil {
@@ -674,14 +699,15 @@
// Removed APIs need to be marked and in order to do that the hiddenAPIInfo needs to specify files
// containing dex signatures of all the removed APIs. In the monolithic files that is done by
// manually combining all the removed.txt files for each API and then converting them to dex
- // signatures, see the combined-removed-dex module. That will all be done automatically in future.
- // For now removed APIs are ignored.
- // TODO(b/179354495): handle removed apis automatically.
+ // signatures, see the combined-removed-dex module. This does that automatically by using the
+ // *removed.txt files retrieved from the java_sdk_library modules that are specified in the
+ // stub_libs and contents properties of a bootclasspath_fragment.
+ removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, input.RemovedTxtFiles)
// 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, input.FlagFilesByCategory, nil)
+ buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, input.FlagFilesByCategory, nil, removedDexSignatures)
// Store the paths in the info for use by other modules and sdk snapshot generation.
output := HiddenAPIFlagOutput{
@@ -694,6 +720,23 @@
return &output
}
+func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedTxtFiles android.Paths) android.OptionalPath {
+ if len(removedTxtFiles) == 0 {
+ return android.OptionalPath{}
+ }
+
+ output := android.PathForModuleOut(ctx, "modular-hiddenapi/removed-dex-signatures.txt")
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ BuiltTool("metalava").
+ Flag("--no-banner").
+ Inputs(removedTxtFiles).
+ FlagWithOutput("--dex-api ", output)
+ rule.Build("modular-hiddenapi-removed-dex-signatures", "modular hiddenapi removed dex signatures")
+ return android.OptionalPathForPath(output)
+}
+
// gatherHiddenAPIModuleFromContents gathers the hiddenAPIModule from the supplied contents.
func gatherHiddenAPIModuleFromContents(ctx android.ModuleContext, contents []android.Module) []hiddenAPIModule {
hiddenAPIModules := []hiddenAPIModule{}