blob: d1d9a7541ffcb4817ba3dfd0ec244dd1f3029502 [file] [log] [blame]
Paul Duffinc6bb7cf2021-04-08 17:49:27 +01001// Copyright (C) 2021 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
Paul Duffindfa10832021-05-13 17:31:51 +010018 "strings"
19
Paul Duffinc6bb7cf2021-04-08 17:49:27 +010020 "android/soong/android"
Paul Duffin9b381ef2021-04-08 23:01:37 +010021 "github.com/google/blueprint"
Paul Duffinc6bb7cf2021-04-08 17:49:27 +010022)
23
24// Contains support for processing hiddenAPI in a modular fashion.
25
Paul Duffin74431d52021-04-21 14:10:42 +010026type hiddenAPIStubsDependencyTag struct {
27 blueprint.BaseDependencyTag
28 sdkKind android.SdkKind
29}
30
31func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
32}
33
34func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
35 return false
36}
37
Paul Duffin976b0e52021-04-27 23:20:26 +010038func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
39 // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
40 // property, otherwise treat if it was specified in the java_header_libs property.
41 if javaSdkLibrarySdkMemberType.IsInstance(child) {
42 return javaSdkLibrarySdkMemberType
43 }
44
45 return javaHeaderLibsSdkMemberType
46}
47
48func (b hiddenAPIStubsDependencyTag) ExportMember() bool {
49 // Export the module added via this dependency tag from the sdk.
50 return true
51}
52
Paul Duffin74431d52021-04-21 14:10:42 +010053// Avoid having to make stubs content explicitly visible to dependent modules.
54//
55// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
56// with proper dependencies.
57// TODO(b/177892522): Remove this and add needed visibility.
58func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
59}
60
61var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
62var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
63var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
Paul Duffin976b0e52021-04-27 23:20:26 +010064var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
Paul Duffin74431d52021-04-21 14:10:42 +010065
Paul Duffin3e7fcc32021-04-15 13:31:38 +010066// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
67// API processing.
68var hiddenAPIRelevantSdkKinds = []android.SdkKind{
69 android.SdkPublic,
70 android.SdkSystem,
71 android.SdkTest,
72 android.SdkCorePlatform,
73}
74
Paul Duffin74431d52021-04-21 14:10:42 +010075// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
76// needed to produce the hidden API monolithic stub flags file.
77func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string {
78 var publicStubModules []string
79 var systemStubModules []string
80 var testStubModules []string
81 var corePlatformStubModules []string
82
83 if config.AlwaysUsePrebuiltSdks() {
84 // Build configuration mandates using prebuilt stub modules
85 publicStubModules = append(publicStubModules, "sdk_public_current_android")
86 systemStubModules = append(systemStubModules, "sdk_system_current_android")
87 testStubModules = append(testStubModules, "sdk_test_current_android")
88 } else {
89 // Use stub modules built from source
90 publicStubModules = append(publicStubModules, "android_stubs_current")
91 systemStubModules = append(systemStubModules, "android_system_stubs_current")
92 testStubModules = append(testStubModules, "android_test_stubs_current")
93 }
94 // We do not have prebuilts of the core platform api yet
95 corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
96
97 // Allow products to define their own stubs for custom product jars that apps can use.
98 publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
99 systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
100 testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
101 if config.IsEnvTrue("EMMA_INSTRUMENT") {
102 publicStubModules = append(publicStubModules, "jacoco-stubs")
103 }
104
105 m := map[android.SdkKind][]string{}
106 m[android.SdkPublic] = publicStubModules
107 m[android.SdkSystem] = systemStubModules
108 m[android.SdkTest] = testStubModules
109 m[android.SdkCorePlatform] = corePlatformStubModules
110 return m
111}
112
113// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
114// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
115// identify the source of the dependency.
116func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) {
117 module := ctx.Module()
118 for _, sdkKind := range hiddenAPIRelevantSdkKinds {
119 modules := sdkKindToStubLibModules[sdkKind]
120 ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...)
121 }
122}
123
124// hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added
125// in hiddenAPIAddStubLibDependencies.
126func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext) map[android.SdkKind]android.Paths {
127 m := map[android.SdkKind]android.Paths{}
128 ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
129 tag := ctx.OtherModuleDependencyTag(module)
130 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
131 kind := hiddenAPIStubsTag.sdkKind
Paul Duffin10931582021-04-25 10:13:54 +0100132 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
Paul Duffin74431d52021-04-21 14:10:42 +0100133 if dexJar != nil {
134 m[kind] = append(m[kind], dexJar)
135 }
136 }
137 })
138 return m
139}
140
141// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
142// available, or reports an error.
Paul Duffin10931582021-04-25 10:13:54 +0100143func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
144 var dexJar android.Path
145 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
146 dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
147 } else if j, ok := module.(UsesLibraryDependency); ok {
148 dexJar = j.DexJarBuildPath()
Paul Duffin74431d52021-04-21 14:10:42 +0100149 } else {
150 ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module))
Paul Duffin10931582021-04-25 10:13:54 +0100151 return nil
Paul Duffin74431d52021-04-21 14:10:42 +0100152 }
Paul Duffin10931582021-04-25 10:13:54 +0100153
154 if dexJar == nil {
155 ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
156 }
157 return dexJar
Paul Duffin74431d52021-04-21 14:10:42 +0100158}
159
160var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
161 android.SdkPublic: "public-stub-classpath",
162 android.SdkSystem: "system-stub-classpath",
163 android.SdkTest: "test-stub-classpath",
164 android.SdkCorePlatform: "core-platform-stub-classpath",
165}
166
167// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
168//
169// The rule is initialized but not built so that the caller can modify it and select an appropriate
170// name.
Paul Duffin2fef1362021-04-15 13:32:00 +0100171func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
Paul Duffin74431d52021-04-21 14:10:42 +0100172 // Singleton rule which applies hiddenapi on all boot class path dex files.
173 rule := android.NewRuleBuilder(pctx, ctx)
174
175 tempPath := tempPathForRestat(ctx, outputPath)
176
177 command := rule.Command().
178 Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
179 Text("list").
180 FlagForEachInput("--boot-dex=", bootDexJars)
181
182 // Iterate over the sdk kinds in a fixed order.
183 for _, sdkKind := range hiddenAPIRelevantSdkKinds {
184 paths := sdkKindToPathList[sdkKind]
185 if len(paths) > 0 {
186 option := sdkKindToHiddenapiListOption[sdkKind]
187 command.FlagWithInputList("--"+option+"=", paths, ":")
188 }
189 }
190
191 // Add the output path.
192 command.FlagWithOutput("--out-api-flags=", tempPath)
193
194 commitChangeForRestat(rule, tempPath, outputPath)
195 return rule
196}
197
Paul Duffin46169772021-04-14 15:01:56 +0100198// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
199// information obtained from annotations within the source code in order to create the complete set
200// of flags that should be applied to the dex implementation jars on the bootclasspath.
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100201//
202// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
203// of each property reference a plain text file that contains a java signature per line. The flags
204// for each of those signatures will be updated in a property specific way.
205//
206// The Unsupported_packages property contains a list of paths, each of which is a plain text file
207// with one Java package per line. All members of all classes within that package (but not nested
208// packages) will be updated in a property specific way.
Paul Duffin46169772021-04-14 15:01:56 +0100209type HiddenAPIFlagFileProperties struct {
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100210 // Marks each signature in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100211 Unsupported []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100212
213 // Marks each signature in the referenced files as being unsupported because it has been removed.
214 // Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100215 Removed []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100216
217 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= R
218 // and low priority.
Paul Duffin702210b2021-04-08 20:12:41 +0100219 Max_target_r_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100220
221 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= Q.
Paul Duffin702210b2021-04-08 20:12:41 +0100222 Max_target_q []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100223
224 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= P.
Paul Duffin702210b2021-04-08 20:12:41 +0100225 Max_target_p []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100226
227 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= O
228 // and low priority. Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100229 Max_target_o_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100230
231 // Marks each signature in the referenced files as being blocked.
Paul Duffin702210b2021-04-08 20:12:41 +0100232 Blocked []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100233
234 // Marks each signature in every package in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100235 Unsupported_packages []string `android:"path"`
236}
237
Paul Duffin46169772021-04-14 15:01:56 +0100238func (p *HiddenAPIFlagFileProperties) hiddenAPIFlagFileInfo(ctx android.ModuleContext) hiddenAPIFlagFileInfo {
239 info := hiddenAPIFlagFileInfo{categoryToPaths: map[*hiddenAPIFlagFileCategory]android.Paths{}}
Paul Duffine3dc6602021-04-14 09:50:43 +0100240 for _, category := range hiddenAPIFlagFileCategories {
Paul Duffincc17bfe2021-04-19 13:21:20 +0100241 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
Paul Duffine3dc6602021-04-14 09:50:43 +0100242 info.categoryToPaths[category] = paths
Paul Duffin702210b2021-04-08 20:12:41 +0100243 }
Paul Duffine3dc6602021-04-14 09:50:43 +0100244 return info
245}
246
247type hiddenAPIFlagFileCategory struct {
248 // propertyName is the name of the property for this category.
249 propertyName string
250
Paul Duffincc17bfe2021-04-19 13:21:20 +0100251 // propertyValueReader retrieves the value of the property for this category from the set of
Paul Duffine3dc6602021-04-14 09:50:43 +0100252 // properties.
Paul Duffincc17bfe2021-04-19 13:21:20 +0100253 propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
Paul Duffine3dc6602021-04-14 09:50:43 +0100254
255 // commandMutator adds the appropriate command line options for this category to the supplied
256 // command
257 commandMutator func(command *android.RuleBuilderCommand, path android.Path)
258}
259
260var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
Paul Duffin46169772021-04-14 15:01:56 +0100261 // See HiddenAPIFlagFileProperties.Unsupported
Paul Duffine3dc6602021-04-14 09:50:43 +0100262 {
263 propertyName: "unsupported",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100264 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100265 return properties.Unsupported
266 },
267 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
268 command.FlagWithInput("--unsupported ", path)
269 },
270 },
Paul Duffin46169772021-04-14 15:01:56 +0100271 // See HiddenAPIFlagFileProperties.Removed
Paul Duffine3dc6602021-04-14 09:50:43 +0100272 {
273 propertyName: "removed",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100274 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100275 return properties.Removed
276 },
277 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
278 command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
279 },
280 },
Paul Duffin46169772021-04-14 15:01:56 +0100281 // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100282 {
283 propertyName: "max_target_r_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100284 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100285 return properties.Max_target_r_low_priority
286 },
287 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
288 command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
289 },
290 },
Paul Duffin46169772021-04-14 15:01:56 +0100291 // See HiddenAPIFlagFileProperties.Max_target_q
Paul Duffine3dc6602021-04-14 09:50:43 +0100292 {
293 propertyName: "max_target_q",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100294 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100295 return properties.Max_target_q
296 },
297 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
298 command.FlagWithInput("--max-target-q ", path)
299 },
300 },
Paul Duffin46169772021-04-14 15:01:56 +0100301 // See HiddenAPIFlagFileProperties.Max_target_p
Paul Duffine3dc6602021-04-14 09:50:43 +0100302 {
303 propertyName: "max_target_p",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100304 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100305 return properties.Max_target_p
306 },
307 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
308 command.FlagWithInput("--max-target-p ", path)
309 },
310 },
Paul Duffin46169772021-04-14 15:01:56 +0100311 // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100312 {
313 propertyName: "max_target_o_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100314 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100315 return properties.Max_target_o_low_priority
316 },
317 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
318 command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
319 },
320 },
Paul Duffin46169772021-04-14 15:01:56 +0100321 // See HiddenAPIFlagFileProperties.Blocked
Paul Duffine3dc6602021-04-14 09:50:43 +0100322 {
323 propertyName: "blocked",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100324 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100325 return properties.Blocked
326 },
327 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
328 command.FlagWithInput("--blocked ", path)
329 },
330 },
Paul Duffin46169772021-04-14 15:01:56 +0100331 // See HiddenAPIFlagFileProperties.Unsupported_packages
Paul Duffine3dc6602021-04-14 09:50:43 +0100332 {
333 propertyName: "unsupported_packages",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100334 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100335 return properties.Unsupported_packages
336 },
337 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
338 command.FlagWithInput("--unsupported ", path).Flag("--packages ")
339 },
340 },
Paul Duffin702210b2021-04-08 20:12:41 +0100341}
342
Paul Duffin2fef1362021-04-15 13:32:00 +0100343// hiddenAPIFlagFileInfo contains paths resolved from HiddenAPIFlagFileProperties and also generated
344// by hidden API processing.
345//
346// This is used both for an individual bootclasspath_fragment to provide it to other modules and
347// for a module to collate the files from the fragments it depends upon. That is why the fields are
348// all Paths even though they are initialized with a single path.
Paul Duffin46169772021-04-14 15:01:56 +0100349type hiddenAPIFlagFileInfo struct {
Paul Duffine3dc6602021-04-14 09:50:43 +0100350 // categoryToPaths maps from the flag file category to the paths containing information for that
351 // category.
352 categoryToPaths map[*hiddenAPIFlagFileCategory]android.Paths
Paul Duffin2fef1362021-04-15 13:32:00 +0100353
354 // The paths to the generated stub-flags.csv files.
355 StubFlagsPaths android.Paths
356
357 // The paths to the generated annotation-flags.csv files.
358 AnnotationFlagsPaths android.Paths
359
360 // The paths to the generated metadata.csv files.
361 MetadataPaths android.Paths
362
363 // The paths to the generated index.csv files.
364 IndexPaths android.Paths
365
366 // The paths to the generated all-flags.csv files.
367 AllFlagsPaths android.Paths
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100368}
Paul Duffin702210b2021-04-08 20:12:41 +0100369
Paul Duffin9b381ef2021-04-08 23:01:37 +0100370func (i *hiddenAPIFlagFileInfo) append(other hiddenAPIFlagFileInfo) {
371 for _, category := range hiddenAPIFlagFileCategories {
372 i.categoryToPaths[category] = append(i.categoryToPaths[category], other.categoryToPaths[category]...)
373 }
Paul Duffin2fef1362021-04-15 13:32:00 +0100374 i.StubFlagsPaths = append(i.StubFlagsPaths, other.StubFlagsPaths...)
375 i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPaths...)
376 i.MetadataPaths = append(i.MetadataPaths, other.MetadataPaths...)
377 i.IndexPaths = append(i.IndexPaths, other.IndexPaths...)
378 i.AllFlagsPaths = append(i.AllFlagsPaths, other.AllFlagsPaths...)
Paul Duffin9b381ef2021-04-08 23:01:37 +0100379}
380
381var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{})
382
Paul Duffindfa10832021-05-13 17:31:51 +0100383// pathForValidation creates a path of the same type as the supplied type but with a name of
384// <path>.valid.
385//
386// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
387// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
388func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
389 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
390 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
391}
392
Paul Duffin2fef1362021-04-15 13:32:00 +0100393// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
394// the flags from all the modules, the stub flags, augmented with some additional configuration
395// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100396//
397// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
398// an entry for every single member in the dex implementation jars of the individual modules. Every
399// signature in any of the other files MUST be included in this file.
400//
401// moduleSpecificFlagsPaths are the paths to the flags files generated by each module using
402// information from the baseFlagsPath as well as from annotations within the source.
403//
404// augmentationInfo is a struct containing paths to files that augment the information provided by
405// the moduleSpecificFlagsPaths.
Paul Duffin2fef1362021-04-15 13:32:00 +0100406func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, baseFlagsPath android.Path, moduleSpecificFlagsPaths android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
Paul Duffindfa10832021-05-13 17:31:51 +0100407
408 // The file which is used to record that the flags file is valid.
409 var validFile android.WritablePath
410
411 // If there are flag files that have been generated by fragments on which this depends then use
412 // them to validate the flag file generated by the rules created by this method.
413 if allFlagsPaths := flagFileInfo.AllFlagsPaths; len(allFlagsPaths) > 0 {
414 // The flags file generated by the rule created by this method needs to be validated to ensure
415 // that it is consistent with the flag files generated by the individual fragments.
416
417 validFile = pathForValidation(ctx, outputPath)
418
419 // Create a rule to validate the output from the following rule.
420 rule := android.NewRuleBuilder(pctx, ctx)
421 rule.Command().
422 BuiltTool("verify_overlaps").
423 Input(outputPath).
424 Inputs(allFlagsPaths).
425 // If validation passes then update the file that records that.
426 Text("&& touch").Output(validFile)
427 rule.Build(name+"Validation", desc+" validation")
428 }
429
430 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100431 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100432 rule := android.NewRuleBuilder(pctx, ctx)
433 command := rule.Command().
434 BuiltTool("generate_hiddenapi_lists").
435 FlagWithInput("--csv ", baseFlagsPath).
436 Inputs(moduleSpecificFlagsPaths).
437 FlagWithOutput("--output ", tempPath)
438
Paul Duffine3dc6602021-04-14 09:50:43 +0100439 // Add the options for the different categories of flag files.
440 for _, category := range hiddenAPIFlagFileCategories {
Paul Duffin2fef1362021-04-15 13:32:00 +0100441 paths := flagFileInfo.categoryToPaths[category]
Paul Duffine3dc6602021-04-14 09:50:43 +0100442 for _, path := range paths {
443 category.commandMutator(command, path)
444 }
Paul Duffin702210b2021-04-08 20:12:41 +0100445 }
446
447 commitChangeForRestat(rule, tempPath, outputPath)
448
Paul Duffindfa10832021-05-13 17:31:51 +0100449 if validFile != nil {
450 // Add the file that indicates that the file generated by this is valid.
451 //
452 // This will cause the validation rule above to be run any time that the output of this rule
453 // changes but the validation will run in parallel with other rules that depend on this file.
454 command.Validation(validFile)
455 }
456
Paul Duffin2fef1362021-04-15 13:32:00 +0100457 rule.Build(name, desc)
458}
459
460// hiddenAPIGenerateAllFlagsForBootclasspathFragment will generate all the flags for a fragment
461// of the bootclasspath.
462//
463// It takes:
464// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
465// * The list of modules that are the contents of the fragment.
466// * The additional manually curated flag files to use.
467//
468// It generates:
469// * stub-flags.csv
470// * annotation-flags.csv
471// * metadata.csv
472// * index.csv
473// * all-flags.csv
474func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
475
476 hiddenApiSubDir := "modular-hiddenapi"
477
478 bootDexJars := android.Paths{}
479 classesJars := android.Paths{}
480 for _, module := range contents {
481 if hiddenAPI, ok := module.(hiddenAPIIntf); ok {
482 classesJars = append(classesJars, hiddenAPI.classesJars()...)
483 bootDexJar := hiddenAPI.bootDexJar()
484 if bootDexJar == nil {
485 ctx.ModuleErrorf("module %s does not provide a dex jar", module)
486 } else {
487 bootDexJars = append(bootDexJars, bootDexJar)
488 }
489 } else {
490 ctx.ModuleErrorf("module %s does not implement hiddenAPIIntf", module)
491 }
492 }
493
494 // Generate the stub-flags.csv.
495 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
496 rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, stubJarsByKind)
497 rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
498
499 // Generate the set of flags from the annotations in the source code.
500 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
501 ctx.Build(pctx, android.BuildParams{
502 Rule: hiddenAPIGenerateCSVRule,
503 Description: "modular hiddenapi annotation flags",
504 Inputs: classesJars,
505 Output: annotationFlagsCSV,
506 Implicit: stubFlagsCSV,
507 Args: map[string]string{
508 "outFlag": "--write-flags-csv",
509 "stubAPIFlags": stubFlagsCSV.String(),
510 },
511 })
512
513 // Generate the metadata from the annotations in the source code.
514 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
515 ctx.Build(pctx, android.BuildParams{
516 Rule: hiddenAPIGenerateCSVRule,
517 Description: "modular hiddenapi metadata",
518 Inputs: classesJars,
519 Output: metadataCSV,
520 Implicit: stubFlagsCSV,
521 Args: map[string]string{
522 "outFlag": "--write-metadata-csv",
523 "stubAPIFlags": stubFlagsCSV.String(),
524 },
525 })
526
527 // Generate the index file from the annotations in the source code.
528 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
529 rule = android.NewRuleBuilder(pctx, ctx)
530 rule.Command().
531 BuiltTool("merge_csv").
532 Flag("--zip_input").
533 Flag("--key_field signature").
534 FlagWithOutput("--output=", indexCSV).
535 Inputs(classesJars)
536 rule.Build("modular-hiddenapi-index", "modular hiddenapi index")
537
538 // Removed APIs need to be marked and in order to do that the flagFileInfo needs to specify files
539 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
540 // manually combining all the removed.txt files for each API and then converting them to dex
541 // signatures, see the combined-removed-dex module. That will all be done automatically in future.
542 // For now removed APIs are ignored.
543 // TODO(b/179354495): handle removed apis automatically.
544
545 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
546 // files.
547 outputPath := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
548 buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, android.Paths{annotationFlagsCSV}, flagFileInfo)
549
550 // Store the paths in the info for use by other modules and sdk snapshot generation.
551 flagFileInfo.StubFlagsPaths = android.Paths{stubFlagsCSV}
552 flagFileInfo.AnnotationFlagsPaths = android.Paths{annotationFlagsCSV}
553 flagFileInfo.MetadataPaths = android.Paths{metadataCSV}
554 flagFileInfo.IndexPaths = android.Paths{indexCSV}
555 flagFileInfo.AllFlagsPaths = android.Paths{outputPath}
Paul Duffin702210b2021-04-08 20:12:41 +0100556}