blob: f5afe5d5b3591e79961b41ddf110018178fd2a3e [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 Duffin7487a7a2021-05-19 09:36:09 +010018 "fmt"
Paul Duffindfa10832021-05-13 17:31:51 +010019 "strings"
20
Paul Duffinc6bb7cf2021-04-08 17:49:27 +010021 "android/soong/android"
Paul Duffin9b381ef2021-04-08 23:01:37 +010022 "github.com/google/blueprint"
Paul Duffinc6bb7cf2021-04-08 17:49:27 +010023)
24
25// Contains support for processing hiddenAPI in a modular fashion.
26
Paul Duffin74431d52021-04-21 14:10:42 +010027type hiddenAPIStubsDependencyTag struct {
28 blueprint.BaseDependencyTag
29 sdkKind android.SdkKind
30}
31
32func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
33}
34
35func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
36 return false
37}
38
Paul Duffin976b0e52021-04-27 23:20:26 +010039func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
40 // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
41 // property, otherwise treat if it was specified in the java_header_libs property.
42 if javaSdkLibrarySdkMemberType.IsInstance(child) {
43 return javaSdkLibrarySdkMemberType
44 }
45
46 return javaHeaderLibsSdkMemberType
47}
48
49func (b hiddenAPIStubsDependencyTag) ExportMember() bool {
50 // Export the module added via this dependency tag from the sdk.
51 return true
52}
53
Paul Duffin74431d52021-04-21 14:10:42 +010054// Avoid having to make stubs content explicitly visible to dependent modules.
55//
56// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
57// with proper dependencies.
58// TODO(b/177892522): Remove this and add needed visibility.
59func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
60}
61
62var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
63var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
64var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
Paul Duffin976b0e52021-04-27 23:20:26 +010065var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
Paul Duffin74431d52021-04-21 14:10:42 +010066
Paul Duffin3e7fcc32021-04-15 13:31:38 +010067// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
68// API processing.
69var hiddenAPIRelevantSdkKinds = []android.SdkKind{
70 android.SdkPublic,
71 android.SdkSystem,
72 android.SdkTest,
73 android.SdkCorePlatform,
74}
75
Paul Duffin74431d52021-04-21 14:10:42 +010076// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
77// needed to produce the hidden API monolithic stub flags file.
78func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string {
79 var publicStubModules []string
80 var systemStubModules []string
81 var testStubModules []string
82 var corePlatformStubModules []string
83
84 if config.AlwaysUsePrebuiltSdks() {
85 // Build configuration mandates using prebuilt stub modules
86 publicStubModules = append(publicStubModules, "sdk_public_current_android")
87 systemStubModules = append(systemStubModules, "sdk_system_current_android")
88 testStubModules = append(testStubModules, "sdk_test_current_android")
89 } else {
90 // Use stub modules built from source
91 publicStubModules = append(publicStubModules, "android_stubs_current")
92 systemStubModules = append(systemStubModules, "android_system_stubs_current")
93 testStubModules = append(testStubModules, "android_test_stubs_current")
94 }
95 // We do not have prebuilts of the core platform api yet
96 corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
97
98 // Allow products to define their own stubs for custom product jars that apps can use.
99 publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
100 systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
101 testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
102 if config.IsEnvTrue("EMMA_INSTRUMENT") {
Paul Duffin098c8782021-05-14 10:45:25 +0100103 // Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
104 // allows everyone access but it is needed to ensure consistent flags between the
105 // bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
Paul Duffin74431d52021-04-21 14:10:42 +0100106 publicStubModules = append(publicStubModules, "jacoco-stubs")
Paul Duffin098c8782021-05-14 10:45:25 +0100107 systemStubModules = append(systemStubModules, "jacoco-stubs")
108 testStubModules = append(testStubModules, "jacoco-stubs")
Paul Duffin74431d52021-04-21 14:10:42 +0100109 }
110
111 m := map[android.SdkKind][]string{}
112 m[android.SdkPublic] = publicStubModules
113 m[android.SdkSystem] = systemStubModules
114 m[android.SdkTest] = testStubModules
115 m[android.SdkCorePlatform] = corePlatformStubModules
116 return m
117}
118
119// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
120// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
121// identify the source of the dependency.
122func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) {
123 module := ctx.Module()
124 for _, sdkKind := range hiddenAPIRelevantSdkKinds {
125 modules := sdkKindToStubLibModules[sdkKind]
126 ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...)
127 }
128}
129
130// hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added
131// in hiddenAPIAddStubLibDependencies.
Paul Duffin34827d42021-05-13 21:25:05 +0100132func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext, contents []android.Module) map[android.SdkKind]android.Paths {
Paul Duffin74431d52021-04-21 14:10:42 +0100133 m := map[android.SdkKind]android.Paths{}
Paul Duffin34827d42021-05-13 21:25:05 +0100134
135 // If the contents includes any java_sdk_library modules then add them to the stubs.
136 for _, module := range contents {
137 if _, ok := module.(SdkLibraryDependency); ok {
138 for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
139 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
140 if dexJar != nil {
141 m[kind] = append(m[kind], dexJar)
142 }
143 }
144 }
145 }
146
Paul Duffin74431d52021-04-21 14:10:42 +0100147 ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
148 tag := ctx.OtherModuleDependencyTag(module)
149 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
150 kind := hiddenAPIStubsTag.sdkKind
Paul Duffin10931582021-04-25 10:13:54 +0100151 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
Paul Duffin74431d52021-04-21 14:10:42 +0100152 if dexJar != nil {
153 m[kind] = append(m[kind], dexJar)
154 }
155 }
156 })
Paul Duffin34827d42021-05-13 21:25:05 +0100157
158 // Normalize the paths, i.e. remove duplicates and sort.
159 for k, v := range m {
160 m[k] = android.SortedUniquePaths(v)
161 }
162
Paul Duffin74431d52021-04-21 14:10:42 +0100163 return m
164}
165
166// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
167// available, or reports an error.
Paul Duffin10931582021-04-25 10:13:54 +0100168func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
169 var dexJar android.Path
170 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
171 dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
172 } else if j, ok := module.(UsesLibraryDependency); ok {
173 dexJar = j.DexJarBuildPath()
Paul Duffin74431d52021-04-21 14:10:42 +0100174 } else {
175 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 +0100176 return nil
Paul Duffin74431d52021-04-21 14:10:42 +0100177 }
Paul Duffin10931582021-04-25 10:13:54 +0100178
179 if dexJar == nil {
180 ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
181 }
182 return dexJar
Paul Duffin74431d52021-04-21 14:10:42 +0100183}
184
185var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
186 android.SdkPublic: "public-stub-classpath",
187 android.SdkSystem: "system-stub-classpath",
188 android.SdkTest: "test-stub-classpath",
189 android.SdkCorePlatform: "core-platform-stub-classpath",
190}
191
192// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
193//
194// The rule is initialized but not built so that the caller can modify it and select an appropriate
195// name.
Paul Duffin2fef1362021-04-15 13:32:00 +0100196func 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 +0100197 // Singleton rule which applies hiddenapi on all boot class path dex files.
198 rule := android.NewRuleBuilder(pctx, ctx)
199
200 tempPath := tempPathForRestat(ctx, outputPath)
201
202 command := rule.Command().
203 Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
204 Text("list").
205 FlagForEachInput("--boot-dex=", bootDexJars)
206
207 // Iterate over the sdk kinds in a fixed order.
208 for _, sdkKind := range hiddenAPIRelevantSdkKinds {
209 paths := sdkKindToPathList[sdkKind]
210 if len(paths) > 0 {
211 option := sdkKindToHiddenapiListOption[sdkKind]
212 command.FlagWithInputList("--"+option+"=", paths, ":")
213 }
214 }
215
216 // Add the output path.
217 command.FlagWithOutput("--out-api-flags=", tempPath)
218
219 commitChangeForRestat(rule, tempPath, outputPath)
220 return rule
221}
222
Paul Duffin46169772021-04-14 15:01:56 +0100223// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
224// information obtained from annotations within the source code in order to create the complete set
225// of flags that should be applied to the dex implementation jars on the bootclasspath.
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100226//
227// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
228// of each property reference a plain text file that contains a java signature per line. The flags
229// for each of those signatures will be updated in a property specific way.
230//
231// The Unsupported_packages property contains a list of paths, each of which is a plain text file
232// with one Java package per line. All members of all classes within that package (but not nested
233// packages) will be updated in a property specific way.
Paul Duffin46169772021-04-14 15:01:56 +0100234type HiddenAPIFlagFileProperties struct {
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100235 // Marks each signature in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100236 Unsupported []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100237
238 // Marks each signature in the referenced files as being unsupported because it has been removed.
239 // Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100240 Removed []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100241
242 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= R
243 // and low priority.
Paul Duffin702210b2021-04-08 20:12:41 +0100244 Max_target_r_low_priority []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 <= Q.
Paul Duffin702210b2021-04-08 20:12:41 +0100247 Max_target_q []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100248
249 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= P.
Paul Duffin702210b2021-04-08 20:12:41 +0100250 Max_target_p []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100251
252 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= O
253 // and low priority. Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100254 Max_target_o_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100255
256 // Marks each signature in the referenced files as being blocked.
Paul Duffin702210b2021-04-08 20:12:41 +0100257 Blocked []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100258
259 // Marks each signature in every package in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100260 Unsupported_packages []string `android:"path"`
261}
262
Paul Duffin46169772021-04-14 15:01:56 +0100263func (p *HiddenAPIFlagFileProperties) hiddenAPIFlagFileInfo(ctx android.ModuleContext) hiddenAPIFlagFileInfo {
264 info := hiddenAPIFlagFileInfo{categoryToPaths: map[*hiddenAPIFlagFileCategory]android.Paths{}}
Paul Duffine3dc6602021-04-14 09:50:43 +0100265 for _, category := range hiddenAPIFlagFileCategories {
Paul Duffincc17bfe2021-04-19 13:21:20 +0100266 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
Paul Duffine3dc6602021-04-14 09:50:43 +0100267 info.categoryToPaths[category] = paths
Paul Duffin702210b2021-04-08 20:12:41 +0100268 }
Paul Duffine3dc6602021-04-14 09:50:43 +0100269 return info
270}
271
272type hiddenAPIFlagFileCategory struct {
273 // propertyName is the name of the property for this category.
274 propertyName string
275
Paul Duffincc17bfe2021-04-19 13:21:20 +0100276 // propertyValueReader retrieves the value of the property for this category from the set of
Paul Duffine3dc6602021-04-14 09:50:43 +0100277 // properties.
Paul Duffincc17bfe2021-04-19 13:21:20 +0100278 propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
Paul Duffine3dc6602021-04-14 09:50:43 +0100279
280 // commandMutator adds the appropriate command line options for this category to the supplied
281 // command
282 commandMutator func(command *android.RuleBuilderCommand, path android.Path)
283}
284
285var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
Paul Duffin46169772021-04-14 15:01:56 +0100286 // See HiddenAPIFlagFileProperties.Unsupported
Paul Duffine3dc6602021-04-14 09:50:43 +0100287 {
288 propertyName: "unsupported",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100289 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100290 return properties.Unsupported
291 },
292 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
293 command.FlagWithInput("--unsupported ", path)
294 },
295 },
Paul Duffin46169772021-04-14 15:01:56 +0100296 // See HiddenAPIFlagFileProperties.Removed
Paul Duffine3dc6602021-04-14 09:50:43 +0100297 {
298 propertyName: "removed",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100299 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100300 return properties.Removed
301 },
302 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
303 command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
304 },
305 },
Paul Duffin46169772021-04-14 15:01:56 +0100306 // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100307 {
308 propertyName: "max_target_r_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100309 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100310 return properties.Max_target_r_low_priority
311 },
312 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
313 command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
314 },
315 },
Paul Duffin46169772021-04-14 15:01:56 +0100316 // See HiddenAPIFlagFileProperties.Max_target_q
Paul Duffine3dc6602021-04-14 09:50:43 +0100317 {
318 propertyName: "max_target_q",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100319 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100320 return properties.Max_target_q
321 },
322 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
323 command.FlagWithInput("--max-target-q ", path)
324 },
325 },
Paul Duffin46169772021-04-14 15:01:56 +0100326 // See HiddenAPIFlagFileProperties.Max_target_p
Paul Duffine3dc6602021-04-14 09:50:43 +0100327 {
328 propertyName: "max_target_p",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100329 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100330 return properties.Max_target_p
331 },
332 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
333 command.FlagWithInput("--max-target-p ", path)
334 },
335 },
Paul Duffin46169772021-04-14 15:01:56 +0100336 // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100337 {
338 propertyName: "max_target_o_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100339 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100340 return properties.Max_target_o_low_priority
341 },
342 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
343 command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
344 },
345 },
Paul Duffin46169772021-04-14 15:01:56 +0100346 // See HiddenAPIFlagFileProperties.Blocked
Paul Duffine3dc6602021-04-14 09:50:43 +0100347 {
348 propertyName: "blocked",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100349 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100350 return properties.Blocked
351 },
352 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
353 command.FlagWithInput("--blocked ", path)
354 },
355 },
Paul Duffin46169772021-04-14 15:01:56 +0100356 // See HiddenAPIFlagFileProperties.Unsupported_packages
Paul Duffine3dc6602021-04-14 09:50:43 +0100357 {
358 propertyName: "unsupported_packages",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100359 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100360 return properties.Unsupported_packages
361 },
362 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
363 command.FlagWithInput("--unsupported ", path).Flag("--packages ")
364 },
365 },
Paul Duffin702210b2021-04-08 20:12:41 +0100366}
367
Paul Duffin2fef1362021-04-15 13:32:00 +0100368// hiddenAPIFlagFileInfo contains paths resolved from HiddenAPIFlagFileProperties and also generated
369// by hidden API processing.
370//
371// This is used both for an individual bootclasspath_fragment to provide it to other modules and
372// for a module to collate the files from the fragments it depends upon. That is why the fields are
373// all Paths even though they are initialized with a single path.
Paul Duffin46169772021-04-14 15:01:56 +0100374type hiddenAPIFlagFileInfo struct {
Paul Duffine3dc6602021-04-14 09:50:43 +0100375 // categoryToPaths maps from the flag file category to the paths containing information for that
376 // category.
377 categoryToPaths map[*hiddenAPIFlagFileCategory]android.Paths
Paul Duffin2fef1362021-04-15 13:32:00 +0100378
379 // The paths to the generated stub-flags.csv files.
380 StubFlagsPaths android.Paths
381
382 // The paths to the generated annotation-flags.csv files.
383 AnnotationFlagsPaths android.Paths
384
385 // The paths to the generated metadata.csv files.
386 MetadataPaths android.Paths
387
388 // The paths to the generated index.csv files.
389 IndexPaths android.Paths
390
391 // The paths to the generated all-flags.csv files.
392 AllFlagsPaths android.Paths
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100393}
Paul Duffin702210b2021-04-08 20:12:41 +0100394
Paul Duffin9b381ef2021-04-08 23:01:37 +0100395func (i *hiddenAPIFlagFileInfo) append(other hiddenAPIFlagFileInfo) {
396 for _, category := range hiddenAPIFlagFileCategories {
397 i.categoryToPaths[category] = append(i.categoryToPaths[category], other.categoryToPaths[category]...)
398 }
Paul Duffin2fef1362021-04-15 13:32:00 +0100399 i.StubFlagsPaths = append(i.StubFlagsPaths, other.StubFlagsPaths...)
400 i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPaths...)
401 i.MetadataPaths = append(i.MetadataPaths, other.MetadataPaths...)
402 i.IndexPaths = append(i.IndexPaths, other.IndexPaths...)
403 i.AllFlagsPaths = append(i.AllFlagsPaths, other.AllFlagsPaths...)
Paul Duffin9b381ef2021-04-08 23:01:37 +0100404}
405
406var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{})
407
Paul Duffindfa10832021-05-13 17:31:51 +0100408// pathForValidation creates a path of the same type as the supplied type but with a name of
409// <path>.valid.
410//
411// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
412// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
413func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
414 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
415 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
416}
417
Paul Duffin2fef1362021-04-15 13:32:00 +0100418// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
419// the flags from all the modules, the stub flags, augmented with some additional configuration
420// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100421//
422// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
423// an entry for every single member in the dex implementation jars of the individual modules. Every
424// signature in any of the other files MUST be included in this file.
425//
Paul Duffin537ea3d2021-05-14 10:38:00 +0100426// annotationFlags is the path to the annotation flags file generated from annotation information
427// in each module.
Paul Duffin702210b2021-04-08 20:12:41 +0100428//
Paul Duffin537ea3d2021-05-14 10:38:00 +0100429// flagFileInfo is a struct containing paths to files that augment the information provided by
430// the annotationFlags.
431func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlags android.Path, flagFileInfo *hiddenAPIFlagFileInfo) {
Paul Duffindfa10832021-05-13 17:31:51 +0100432
433 // The file which is used to record that the flags file is valid.
434 var validFile android.WritablePath
435
436 // If there are flag files that have been generated by fragments on which this depends then use
437 // them to validate the flag file generated by the rules created by this method.
438 if allFlagsPaths := flagFileInfo.AllFlagsPaths; len(allFlagsPaths) > 0 {
439 // The flags file generated by the rule created by this method needs to be validated to ensure
440 // that it is consistent with the flag files generated by the individual fragments.
441
442 validFile = pathForValidation(ctx, outputPath)
443
444 // Create a rule to validate the output from the following rule.
445 rule := android.NewRuleBuilder(pctx, ctx)
446 rule.Command().
447 BuiltTool("verify_overlaps").
448 Input(outputPath).
449 Inputs(allFlagsPaths).
450 // If validation passes then update the file that records that.
451 Text("&& touch").Output(validFile)
452 rule.Build(name+"Validation", desc+" validation")
453 }
454
455 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100456 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100457 rule := android.NewRuleBuilder(pctx, ctx)
458 command := rule.Command().
459 BuiltTool("generate_hiddenapi_lists").
460 FlagWithInput("--csv ", baseFlagsPath).
Paul Duffin537ea3d2021-05-14 10:38:00 +0100461 Input(annotationFlags).
Paul Duffin702210b2021-04-08 20:12:41 +0100462 FlagWithOutput("--output ", tempPath)
463
Paul Duffine3dc6602021-04-14 09:50:43 +0100464 // Add the options for the different categories of flag files.
465 for _, category := range hiddenAPIFlagFileCategories {
Paul Duffin2fef1362021-04-15 13:32:00 +0100466 paths := flagFileInfo.categoryToPaths[category]
Paul Duffine3dc6602021-04-14 09:50:43 +0100467 for _, path := range paths {
468 category.commandMutator(command, path)
469 }
Paul Duffin702210b2021-04-08 20:12:41 +0100470 }
471
472 commitChangeForRestat(rule, tempPath, outputPath)
473
Paul Duffindfa10832021-05-13 17:31:51 +0100474 if validFile != nil {
475 // Add the file that indicates that the file generated by this is valid.
476 //
477 // This will cause the validation rule above to be run any time that the output of this rule
478 // changes but the validation will run in parallel with other rules that depend on this file.
479 command.Validation(validFile)
480 }
481
Paul Duffin2fef1362021-04-15 13:32:00 +0100482 rule.Build(name, desc)
483}
484
485// hiddenAPIGenerateAllFlagsForBootclasspathFragment will generate all the flags for a fragment
486// of the bootclasspath.
487//
488// It takes:
489// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
490// * The list of modules that are the contents of the fragment.
491// * The additional manually curated flag files to use.
492//
493// It generates:
494// * stub-flags.csv
495// * annotation-flags.csv
496// * metadata.csv
497// * index.csv
498// * all-flags.csv
Paul Duffin537ea3d2021-05-14 10:38:00 +0100499func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
Paul Duffin2fef1362021-04-15 13:32:00 +0100500 hiddenApiSubDir := "modular-hiddenapi"
501
Paul Duffin2fef1362021-04-15 13:32:00 +0100502 // Generate the stub-flags.csv.
Paul Duffin537ea3d2021-05-14 10:38:00 +0100503 bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, contents)
Paul Duffin2fef1362021-04-15 13:32:00 +0100504 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
505 rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, stubJarsByKind)
506 rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
507
Paul Duffin537ea3d2021-05-14 10:38:00 +0100508 // Extract the classes jars from the contents.
509 classesJars := extractClassJarsFromHiddenAPIModules(ctx, contents)
510
Paul Duffin2fef1362021-04-15 13:32:00 +0100511 // Generate the set of flags from the annotations in the source code.
512 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100513 buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100514
515 // Generate the metadata from the annotations in the source code.
516 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100517 buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100518
Paul Duffin537ea3d2021-05-14 10:38:00 +0100519 // Generate the index file from the CSV files in the classes jars.
Paul Duffin2fef1362021-04-15 13:32:00 +0100520 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100521 buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100522
523 // Removed APIs need to be marked and in order to do that the flagFileInfo needs to specify files
524 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
525 // manually combining all the removed.txt files for each API and then converting them to dex
526 // signatures, see the combined-removed-dex module. That will all be done automatically in future.
527 // For now removed APIs are ignored.
528 // TODO(b/179354495): handle removed apis automatically.
529
530 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
531 // files.
532 outputPath := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
Paul Duffin537ea3d2021-05-14 10:38:00 +0100533 buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, flagFileInfo)
Paul Duffin2fef1362021-04-15 13:32:00 +0100534
535 // Store the paths in the info for use by other modules and sdk snapshot generation.
536 flagFileInfo.StubFlagsPaths = android.Paths{stubFlagsCSV}
537 flagFileInfo.AnnotationFlagsPaths = android.Paths{annotationFlagsCSV}
538 flagFileInfo.MetadataPaths = android.Paths{metadataCSV}
539 flagFileInfo.IndexPaths = android.Paths{indexCSV}
540 flagFileInfo.AllFlagsPaths = android.Paths{outputPath}
Paul Duffin702210b2021-04-08 20:12:41 +0100541}
Paul Duffin537ea3d2021-05-14 10:38:00 +0100542
543// gatherHiddenAPIModuleFromContents gathers the hiddenAPIModule from the supplied contents.
544func gatherHiddenAPIModuleFromContents(ctx android.ModuleContext, contents []android.Module) []hiddenAPIModule {
545 hiddenAPIModules := []hiddenAPIModule{}
546 for _, module := range contents {
547 if hiddenAPI, ok := module.(hiddenAPIModule); ok {
548 hiddenAPIModules = append(hiddenAPIModules, hiddenAPI)
549 } else if _, ok := module.(*DexImport); ok {
550 // Ignore this for the purposes of hidden API processing
551 } else {
552 ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
553 }
554 }
555 return hiddenAPIModules
556}
557
558// extractBootDexJarsFromHiddenAPIModules extracts the boot dex jars from the supplied modules.
559func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
560 bootDexJars := android.Paths{}
561 for _, module := range contents {
562 bootDexJar := module.bootDexJar()
563 if bootDexJar == nil {
Paul Duffin7487a7a2021-05-19 09:36:09 +0100564 if ctx.Config().AlwaysUsePrebuiltSdks() {
565 // TODO(b/179354495): Remove this work around when it is unnecessary.
566 // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
567 // create a fake one that will cause a build error only if it is used.
568 fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name())
569
570 // Create an error rule that pretends to create the output file but will actually fail if it
571 // is run.
572 ctx.Build(pctx, android.BuildParams{
573 Rule: android.ErrorRule,
574 Output: fake,
575 Args: map[string]string{
576 "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
577 },
578 })
579 bootDexJars = append(bootDexJars, fake)
580 } else {
581 ctx.ModuleErrorf("module %s does not provide a dex jar", module)
582 }
Paul Duffin537ea3d2021-05-14 10:38:00 +0100583 } else {
584 bootDexJars = append(bootDexJars, bootDexJar)
585 }
586 }
587 return bootDexJars
588}
589
590// extractClassJarsFromHiddenAPIModules extracts the class jars from the supplied modules.
591func extractClassJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
592 classesJars := android.Paths{}
593 for _, module := range contents {
594 classesJars = append(classesJars, module.classesJars()...)
595 }
596 return classesJars
597}