blob: 8e17d56729d235f3cb340aa50978407faca037fa [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.
Paul Duffin34827d42021-05-13 21:25:05 +0100126func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext, contents []android.Module) map[android.SdkKind]android.Paths {
Paul Duffin74431d52021-04-21 14:10:42 +0100127 m := map[android.SdkKind]android.Paths{}
Paul Duffin34827d42021-05-13 21:25:05 +0100128
129 // If the contents includes any java_sdk_library modules then add them to the stubs.
130 for _, module := range contents {
131 if _, ok := module.(SdkLibraryDependency); ok {
132 for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
133 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
134 if dexJar != nil {
135 m[kind] = append(m[kind], dexJar)
136 }
137 }
138 }
139 }
140
Paul Duffin74431d52021-04-21 14:10:42 +0100141 ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
142 tag := ctx.OtherModuleDependencyTag(module)
143 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
144 kind := hiddenAPIStubsTag.sdkKind
Paul Duffin10931582021-04-25 10:13:54 +0100145 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
Paul Duffin74431d52021-04-21 14:10:42 +0100146 if dexJar != nil {
147 m[kind] = append(m[kind], dexJar)
148 }
149 }
150 })
Paul Duffin34827d42021-05-13 21:25:05 +0100151
152 // Normalize the paths, i.e. remove duplicates and sort.
153 for k, v := range m {
154 m[k] = android.SortedUniquePaths(v)
155 }
156
Paul Duffin74431d52021-04-21 14:10:42 +0100157 return m
158}
159
160// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
161// available, or reports an error.
Paul Duffin10931582021-04-25 10:13:54 +0100162func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
163 var dexJar android.Path
164 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
165 dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
166 } else if j, ok := module.(UsesLibraryDependency); ok {
167 dexJar = j.DexJarBuildPath()
Paul Duffin74431d52021-04-21 14:10:42 +0100168 } else {
169 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 +0100170 return nil
Paul Duffin74431d52021-04-21 14:10:42 +0100171 }
Paul Duffin10931582021-04-25 10:13:54 +0100172
173 if dexJar == nil {
174 ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
175 }
176 return dexJar
Paul Duffin74431d52021-04-21 14:10:42 +0100177}
178
179var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
180 android.SdkPublic: "public-stub-classpath",
181 android.SdkSystem: "system-stub-classpath",
182 android.SdkTest: "test-stub-classpath",
183 android.SdkCorePlatform: "core-platform-stub-classpath",
184}
185
186// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
187//
188// The rule is initialized but not built so that the caller can modify it and select an appropriate
189// name.
Paul Duffin2fef1362021-04-15 13:32:00 +0100190func 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 +0100191 // Singleton rule which applies hiddenapi on all boot class path dex files.
192 rule := android.NewRuleBuilder(pctx, ctx)
193
194 tempPath := tempPathForRestat(ctx, outputPath)
195
196 command := rule.Command().
197 Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
198 Text("list").
199 FlagForEachInput("--boot-dex=", bootDexJars)
200
201 // Iterate over the sdk kinds in a fixed order.
202 for _, sdkKind := range hiddenAPIRelevantSdkKinds {
203 paths := sdkKindToPathList[sdkKind]
204 if len(paths) > 0 {
205 option := sdkKindToHiddenapiListOption[sdkKind]
206 command.FlagWithInputList("--"+option+"=", paths, ":")
207 }
208 }
209
210 // Add the output path.
211 command.FlagWithOutput("--out-api-flags=", tempPath)
212
213 commitChangeForRestat(rule, tempPath, outputPath)
214 return rule
215}
216
Paul Duffin46169772021-04-14 15:01:56 +0100217// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
218// information obtained from annotations within the source code in order to create the complete set
219// of flags that should be applied to the dex implementation jars on the bootclasspath.
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100220//
221// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
222// of each property reference a plain text file that contains a java signature per line. The flags
223// for each of those signatures will be updated in a property specific way.
224//
225// The Unsupported_packages property contains a list of paths, each of which is a plain text file
226// with one Java package per line. All members of all classes within that package (but not nested
227// packages) will be updated in a property specific way.
Paul Duffin46169772021-04-14 15:01:56 +0100228type HiddenAPIFlagFileProperties struct {
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100229 // Marks each signature in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100230 Unsupported []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100231
232 // Marks each signature in the referenced files as being unsupported because it has been removed.
233 // Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100234 Removed []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100235
236 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= R
237 // and low priority.
Paul Duffin702210b2021-04-08 20:12:41 +0100238 Max_target_r_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100239
240 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= Q.
Paul Duffin702210b2021-04-08 20:12:41 +0100241 Max_target_q []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100242
243 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= P.
Paul Duffin702210b2021-04-08 20:12:41 +0100244 Max_target_p []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100245
246 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= O
247 // and low priority. Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100248 Max_target_o_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100249
250 // Marks each signature in the referenced files as being blocked.
Paul Duffin702210b2021-04-08 20:12:41 +0100251 Blocked []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100252
253 // Marks each signature in every package in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100254 Unsupported_packages []string `android:"path"`
255}
256
Paul Duffin46169772021-04-14 15:01:56 +0100257func (p *HiddenAPIFlagFileProperties) hiddenAPIFlagFileInfo(ctx android.ModuleContext) hiddenAPIFlagFileInfo {
258 info := hiddenAPIFlagFileInfo{categoryToPaths: map[*hiddenAPIFlagFileCategory]android.Paths{}}
Paul Duffine3dc6602021-04-14 09:50:43 +0100259 for _, category := range hiddenAPIFlagFileCategories {
Paul Duffincc17bfe2021-04-19 13:21:20 +0100260 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
Paul Duffine3dc6602021-04-14 09:50:43 +0100261 info.categoryToPaths[category] = paths
Paul Duffin702210b2021-04-08 20:12:41 +0100262 }
Paul Duffine3dc6602021-04-14 09:50:43 +0100263 return info
264}
265
266type hiddenAPIFlagFileCategory struct {
267 // propertyName is the name of the property for this category.
268 propertyName string
269
Paul Duffincc17bfe2021-04-19 13:21:20 +0100270 // propertyValueReader retrieves the value of the property for this category from the set of
Paul Duffine3dc6602021-04-14 09:50:43 +0100271 // properties.
Paul Duffincc17bfe2021-04-19 13:21:20 +0100272 propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
Paul Duffine3dc6602021-04-14 09:50:43 +0100273
274 // commandMutator adds the appropriate command line options for this category to the supplied
275 // command
276 commandMutator func(command *android.RuleBuilderCommand, path android.Path)
277}
278
279var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
Paul Duffin46169772021-04-14 15:01:56 +0100280 // See HiddenAPIFlagFileProperties.Unsupported
Paul Duffine3dc6602021-04-14 09:50:43 +0100281 {
282 propertyName: "unsupported",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100283 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100284 return properties.Unsupported
285 },
286 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
287 command.FlagWithInput("--unsupported ", path)
288 },
289 },
Paul Duffin46169772021-04-14 15:01:56 +0100290 // See HiddenAPIFlagFileProperties.Removed
Paul Duffine3dc6602021-04-14 09:50:43 +0100291 {
292 propertyName: "removed",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100293 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100294 return properties.Removed
295 },
296 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
297 command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
298 },
299 },
Paul Duffin46169772021-04-14 15:01:56 +0100300 // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100301 {
302 propertyName: "max_target_r_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100303 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100304 return properties.Max_target_r_low_priority
305 },
306 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
307 command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
308 },
309 },
Paul Duffin46169772021-04-14 15:01:56 +0100310 // See HiddenAPIFlagFileProperties.Max_target_q
Paul Duffine3dc6602021-04-14 09:50:43 +0100311 {
312 propertyName: "max_target_q",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100313 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100314 return properties.Max_target_q
315 },
316 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
317 command.FlagWithInput("--max-target-q ", path)
318 },
319 },
Paul Duffin46169772021-04-14 15:01:56 +0100320 // See HiddenAPIFlagFileProperties.Max_target_p
Paul Duffine3dc6602021-04-14 09:50:43 +0100321 {
322 propertyName: "max_target_p",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100323 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100324 return properties.Max_target_p
325 },
326 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
327 command.FlagWithInput("--max-target-p ", path)
328 },
329 },
Paul Duffin46169772021-04-14 15:01:56 +0100330 // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100331 {
332 propertyName: "max_target_o_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100333 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100334 return properties.Max_target_o_low_priority
335 },
336 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
337 command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
338 },
339 },
Paul Duffin46169772021-04-14 15:01:56 +0100340 // See HiddenAPIFlagFileProperties.Blocked
Paul Duffine3dc6602021-04-14 09:50:43 +0100341 {
342 propertyName: "blocked",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100343 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100344 return properties.Blocked
345 },
346 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
347 command.FlagWithInput("--blocked ", path)
348 },
349 },
Paul Duffin46169772021-04-14 15:01:56 +0100350 // See HiddenAPIFlagFileProperties.Unsupported_packages
Paul Duffine3dc6602021-04-14 09:50:43 +0100351 {
352 propertyName: "unsupported_packages",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100353 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100354 return properties.Unsupported_packages
355 },
356 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
357 command.FlagWithInput("--unsupported ", path).Flag("--packages ")
358 },
359 },
Paul Duffin702210b2021-04-08 20:12:41 +0100360}
361
Paul Duffin2fef1362021-04-15 13:32:00 +0100362// hiddenAPIFlagFileInfo contains paths resolved from HiddenAPIFlagFileProperties and also generated
363// by hidden API processing.
364//
365// This is used both for an individual bootclasspath_fragment to provide it to other modules and
366// for a module to collate the files from the fragments it depends upon. That is why the fields are
367// all Paths even though they are initialized with a single path.
Paul Duffin46169772021-04-14 15:01:56 +0100368type hiddenAPIFlagFileInfo struct {
Paul Duffine3dc6602021-04-14 09:50:43 +0100369 // categoryToPaths maps from the flag file category to the paths containing information for that
370 // category.
371 categoryToPaths map[*hiddenAPIFlagFileCategory]android.Paths
Paul Duffin2fef1362021-04-15 13:32:00 +0100372
373 // The paths to the generated stub-flags.csv files.
374 StubFlagsPaths android.Paths
375
376 // The paths to the generated annotation-flags.csv files.
377 AnnotationFlagsPaths android.Paths
378
379 // The paths to the generated metadata.csv files.
380 MetadataPaths android.Paths
381
382 // The paths to the generated index.csv files.
383 IndexPaths android.Paths
384
385 // The paths to the generated all-flags.csv files.
386 AllFlagsPaths android.Paths
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100387}
Paul Duffin702210b2021-04-08 20:12:41 +0100388
Paul Duffin9b381ef2021-04-08 23:01:37 +0100389func (i *hiddenAPIFlagFileInfo) append(other hiddenAPIFlagFileInfo) {
390 for _, category := range hiddenAPIFlagFileCategories {
391 i.categoryToPaths[category] = append(i.categoryToPaths[category], other.categoryToPaths[category]...)
392 }
Paul Duffin2fef1362021-04-15 13:32:00 +0100393 i.StubFlagsPaths = append(i.StubFlagsPaths, other.StubFlagsPaths...)
394 i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPaths...)
395 i.MetadataPaths = append(i.MetadataPaths, other.MetadataPaths...)
396 i.IndexPaths = append(i.IndexPaths, other.IndexPaths...)
397 i.AllFlagsPaths = append(i.AllFlagsPaths, other.AllFlagsPaths...)
Paul Duffin9b381ef2021-04-08 23:01:37 +0100398}
399
400var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{})
401
Paul Duffindfa10832021-05-13 17:31:51 +0100402// pathForValidation creates a path of the same type as the supplied type but with a name of
403// <path>.valid.
404//
405// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
406// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
407func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
408 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
409 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
410}
411
Paul Duffin2fef1362021-04-15 13:32:00 +0100412// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
413// the flags from all the modules, the stub flags, augmented with some additional configuration
414// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100415//
416// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
417// an entry for every single member in the dex implementation jars of the individual modules. Every
418// signature in any of the other files MUST be included in this file.
419//
420// moduleSpecificFlagsPaths are the paths to the flags files generated by each module using
421// information from the baseFlagsPath as well as from annotations within the source.
422//
423// augmentationInfo is a struct containing paths to files that augment the information provided by
424// the moduleSpecificFlagsPaths.
Paul Duffin2fef1362021-04-15 13:32:00 +0100425func 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 +0100426
427 // The file which is used to record that the flags file is valid.
428 var validFile android.WritablePath
429
430 // If there are flag files that have been generated by fragments on which this depends then use
431 // them to validate the flag file generated by the rules created by this method.
432 if allFlagsPaths := flagFileInfo.AllFlagsPaths; len(allFlagsPaths) > 0 {
433 // The flags file generated by the rule created by this method needs to be validated to ensure
434 // that it is consistent with the flag files generated by the individual fragments.
435
436 validFile = pathForValidation(ctx, outputPath)
437
438 // Create a rule to validate the output from the following rule.
439 rule := android.NewRuleBuilder(pctx, ctx)
440 rule.Command().
441 BuiltTool("verify_overlaps").
442 Input(outputPath).
443 Inputs(allFlagsPaths).
444 // If validation passes then update the file that records that.
445 Text("&& touch").Output(validFile)
446 rule.Build(name+"Validation", desc+" validation")
447 }
448
449 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100450 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100451 rule := android.NewRuleBuilder(pctx, ctx)
452 command := rule.Command().
453 BuiltTool("generate_hiddenapi_lists").
454 FlagWithInput("--csv ", baseFlagsPath).
455 Inputs(moduleSpecificFlagsPaths).
456 FlagWithOutput("--output ", tempPath)
457
Paul Duffine3dc6602021-04-14 09:50:43 +0100458 // Add the options for the different categories of flag files.
459 for _, category := range hiddenAPIFlagFileCategories {
Paul Duffin2fef1362021-04-15 13:32:00 +0100460 paths := flagFileInfo.categoryToPaths[category]
Paul Duffine3dc6602021-04-14 09:50:43 +0100461 for _, path := range paths {
462 category.commandMutator(command, path)
463 }
Paul Duffin702210b2021-04-08 20:12:41 +0100464 }
465
466 commitChangeForRestat(rule, tempPath, outputPath)
467
Paul Duffindfa10832021-05-13 17:31:51 +0100468 if validFile != nil {
469 // Add the file that indicates that the file generated by this is valid.
470 //
471 // This will cause the validation rule above to be run any time that the output of this rule
472 // changes but the validation will run in parallel with other rules that depend on this file.
473 command.Validation(validFile)
474 }
475
Paul Duffin2fef1362021-04-15 13:32:00 +0100476 rule.Build(name, desc)
477}
478
479// hiddenAPIGenerateAllFlagsForBootclasspathFragment will generate all the flags for a fragment
480// of the bootclasspath.
481//
482// It takes:
483// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
484// * The list of modules that are the contents of the fragment.
485// * The additional manually curated flag files to use.
486//
487// It generates:
488// * stub-flags.csv
489// * annotation-flags.csv
490// * metadata.csv
491// * index.csv
492// * all-flags.csv
493func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
494
495 hiddenApiSubDir := "modular-hiddenapi"
496
497 bootDexJars := android.Paths{}
498 classesJars := android.Paths{}
499 for _, module := range contents {
500 if hiddenAPI, ok := module.(hiddenAPIIntf); ok {
501 classesJars = append(classesJars, hiddenAPI.classesJars()...)
502 bootDexJar := hiddenAPI.bootDexJar()
503 if bootDexJar == nil {
504 ctx.ModuleErrorf("module %s does not provide a dex jar", module)
505 } else {
506 bootDexJars = append(bootDexJars, bootDexJar)
507 }
508 } else {
509 ctx.ModuleErrorf("module %s does not implement hiddenAPIIntf", module)
510 }
511 }
512
513 // Generate the stub-flags.csv.
514 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
515 rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, stubJarsByKind)
516 rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
517
518 // Generate the set of flags from the annotations in the source code.
519 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100520 buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100521
522 // Generate the metadata from the annotations in the source code.
523 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100524 buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100525
526 // Generate the index file from the annotations in the source code.
527 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100528 buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100529
530 // Removed APIs need to be marked and in order to do that the flagFileInfo needs to specify files
531 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
532 // manually combining all the removed.txt files for each API and then converting them to dex
533 // signatures, see the combined-removed-dex module. That will all be done automatically in future.
534 // For now removed APIs are ignored.
535 // TODO(b/179354495): handle removed apis automatically.
536
537 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
538 // files.
539 outputPath := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
540 buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, android.Paths{annotationFlagsCSV}, flagFileInfo)
541
542 // Store the paths in the info for use by other modules and sdk snapshot generation.
543 flagFileInfo.StubFlagsPaths = android.Paths{stubFlagsCSV}
544 flagFileInfo.AnnotationFlagsPaths = android.Paths{annotationFlagsCSV}
545 flagFileInfo.MetadataPaths = android.Paths{metadataCSV}
546 flagFileInfo.IndexPaths = android.Paths{indexCSV}
547 flagFileInfo.AllFlagsPaths = android.Paths{outputPath}
Paul Duffin702210b2021-04-08 20:12:41 +0100548}