blob: b8ffdd66463ae8d1fad77442b52e936e649eb5c9 [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
Paul Duffin74431d52021-04-21 14:10:42 +0100130// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
131// available, or reports an error.
Paul Duffin10931582021-04-25 10:13:54 +0100132func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
133 var dexJar android.Path
134 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
135 dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
136 } else if j, ok := module.(UsesLibraryDependency); ok {
137 dexJar = j.DexJarBuildPath()
Paul Duffin74431d52021-04-21 14:10:42 +0100138 } else {
139 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 +0100140 return nil
Paul Duffin74431d52021-04-21 14:10:42 +0100141 }
Paul Duffin10931582021-04-25 10:13:54 +0100142
143 if dexJar == nil {
144 ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
145 }
146 return dexJar
Paul Duffin74431d52021-04-21 14:10:42 +0100147}
148
149var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
150 android.SdkPublic: "public-stub-classpath",
151 android.SdkSystem: "system-stub-classpath",
152 android.SdkTest: "test-stub-classpath",
153 android.SdkCorePlatform: "core-platform-stub-classpath",
154}
155
156// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
157//
158// The rule is initialized but not built so that the caller can modify it and select an appropriate
159// name.
Paul Duffin1352f7c2021-05-21 22:18:49 +0100160func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput) *android.RuleBuilder {
Paul Duffin74431d52021-04-21 14:10:42 +0100161 // Singleton rule which applies hiddenapi on all boot class path dex files.
162 rule := android.NewRuleBuilder(pctx, ctx)
163
164 tempPath := tempPathForRestat(ctx, outputPath)
165
166 command := rule.Command().
167 Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
168 Text("list").
169 FlagForEachInput("--boot-dex=", bootDexJars)
170
171 // Iterate over the sdk kinds in a fixed order.
172 for _, sdkKind := range hiddenAPIRelevantSdkKinds {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100173 paths := input.StubDexJarsByKind[sdkKind]
Paul Duffin74431d52021-04-21 14:10:42 +0100174 if len(paths) > 0 {
175 option := sdkKindToHiddenapiListOption[sdkKind]
176 command.FlagWithInputList("--"+option+"=", paths, ":")
177 }
178 }
179
180 // Add the output path.
181 command.FlagWithOutput("--out-api-flags=", tempPath)
182
183 commitChangeForRestat(rule, tempPath, outputPath)
184 return rule
185}
186
Paul Duffin46169772021-04-14 15:01:56 +0100187// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
188// information obtained from annotations within the source code in order to create the complete set
189// of flags that should be applied to the dex implementation jars on the bootclasspath.
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100190//
191// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
192// of each property reference a plain text file that contains a java signature per line. The flags
193// for each of those signatures will be updated in a property specific way.
194//
195// The Unsupported_packages property contains a list of paths, each of which is a plain text file
196// with one Java package per line. All members of all classes within that package (but not nested
197// packages) will be updated in a property specific way.
Paul Duffin46169772021-04-14 15:01:56 +0100198type HiddenAPIFlagFileProperties struct {
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100199 // Marks each signature in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100200 Unsupported []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100201
202 // Marks each signature in the referenced files as being unsupported because it has been removed.
203 // Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100204 Removed []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100205
206 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= R
207 // and low priority.
Paul Duffin702210b2021-04-08 20:12:41 +0100208 Max_target_r_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100209
210 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= Q.
Paul Duffin702210b2021-04-08 20:12:41 +0100211 Max_target_q []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100212
213 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= P.
Paul Duffin702210b2021-04-08 20:12:41 +0100214 Max_target_p []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100215
216 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= O
217 // and low priority. Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100218 Max_target_o_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100219
220 // Marks each signature in the referenced files as being blocked.
Paul Duffin702210b2021-04-08 20:12:41 +0100221 Blocked []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100222
223 // Marks each signature in every package in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100224 Unsupported_packages []string `android:"path"`
225}
226
Paul Duffine3dc6602021-04-14 09:50:43 +0100227type hiddenAPIFlagFileCategory struct {
228 // propertyName is the name of the property for this category.
229 propertyName string
230
Paul Duffincc17bfe2021-04-19 13:21:20 +0100231 // propertyValueReader retrieves the value of the property for this category from the set of
Paul Duffine3dc6602021-04-14 09:50:43 +0100232 // properties.
Paul Duffincc17bfe2021-04-19 13:21:20 +0100233 propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
Paul Duffine3dc6602021-04-14 09:50:43 +0100234
235 // commandMutator adds the appropriate command line options for this category to the supplied
236 // command
237 commandMutator func(command *android.RuleBuilderCommand, path android.Path)
238}
239
240var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
Paul Duffin46169772021-04-14 15:01:56 +0100241 // See HiddenAPIFlagFileProperties.Unsupported
Paul Duffine3dc6602021-04-14 09:50:43 +0100242 {
243 propertyName: "unsupported",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100244 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100245 return properties.Unsupported
246 },
247 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
248 command.FlagWithInput("--unsupported ", path)
249 },
250 },
Paul Duffin46169772021-04-14 15:01:56 +0100251 // See HiddenAPIFlagFileProperties.Removed
Paul Duffine3dc6602021-04-14 09:50:43 +0100252 {
253 propertyName: "removed",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100254 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100255 return properties.Removed
256 },
257 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
258 command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
259 },
260 },
Paul Duffin46169772021-04-14 15:01:56 +0100261 // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100262 {
263 propertyName: "max_target_r_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100264 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100265 return properties.Max_target_r_low_priority
266 },
267 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
268 command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
269 },
270 },
Paul Duffin46169772021-04-14 15:01:56 +0100271 // See HiddenAPIFlagFileProperties.Max_target_q
Paul Duffine3dc6602021-04-14 09:50:43 +0100272 {
273 propertyName: "max_target_q",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100274 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100275 return properties.Max_target_q
276 },
277 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
278 command.FlagWithInput("--max-target-q ", path)
279 },
280 },
Paul Duffin46169772021-04-14 15:01:56 +0100281 // See HiddenAPIFlagFileProperties.Max_target_p
Paul Duffine3dc6602021-04-14 09:50:43 +0100282 {
283 propertyName: "max_target_p",
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_p
286 },
287 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
288 command.FlagWithInput("--max-target-p ", path)
289 },
290 },
Paul Duffin46169772021-04-14 15:01:56 +0100291 // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100292 {
293 propertyName: "max_target_o_low_priority",
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_o_low_priority
296 },
297 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
298 command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
299 },
300 },
Paul Duffin46169772021-04-14 15:01:56 +0100301 // See HiddenAPIFlagFileProperties.Blocked
Paul Duffine3dc6602021-04-14 09:50:43 +0100302 {
303 propertyName: "blocked",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100304 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100305 return properties.Blocked
306 },
307 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
308 command.FlagWithInput("--blocked ", path)
309 },
310 },
Paul Duffin46169772021-04-14 15:01:56 +0100311 // See HiddenAPIFlagFileProperties.Unsupported_packages
Paul Duffine3dc6602021-04-14 09:50:43 +0100312 {
313 propertyName: "unsupported_packages",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100314 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100315 return properties.Unsupported_packages
316 },
317 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
318 command.FlagWithInput("--unsupported ", path).Flag("--packages ")
319 },
320 },
Paul Duffin702210b2021-04-08 20:12:41 +0100321}
322
Paul Duffin438eb572021-05-21 16:58:23 +0100323// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
324type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths
325
326// append appends the supplied flags files to the corresponding category in this map.
327func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
328 for _, category := range hiddenAPIFlagFileCategories {
329 s[category] = append(s[category], other[category]...)
330 }
331}
332
333// dedup removes duplicates in the flag files, while maintaining the order in which they were
334// appended.
335func (s FlagFilesByCategory) dedup() {
336 for category, paths := range s {
337 s[category] = android.FirstUniquePaths(paths)
338 }
339}
340
Paul Duffinaf99afa2021-05-21 22:18:56 +0100341// HiddenAPIInfo contains information provided by the hidden API processing.
Paul Duffin2fef1362021-04-15 13:32:00 +0100342//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100343// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
344// processing.
345type HiddenAPIInfo struct {
Paul Duffin438eb572021-05-21 16:58:23 +0100346 // FlagFilesByCategory maps from the flag file category to the paths containing information for
347 // that category.
348 FlagFilesByCategory FlagFilesByCategory
Paul Duffin2fef1362021-04-15 13:32:00 +0100349
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100350 // The output from the hidden API processing needs to be made available to other modules.
351 HiddenAPIFlagOutput
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100352}
Paul Duffin702210b2021-04-08 20:12:41 +0100353
Paul Duffinaf99afa2021-05-21 22:18:56 +0100354var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
Paul Duffin9b381ef2021-04-08 23:01:37 +0100355
Paul Duffin1352f7c2021-05-21 22:18:49 +0100356// StubDexJarsByKind maps an android.SdkKind to the paths to stub dex jars appropriate for that
357// level. See hiddenAPIRelevantSdkKinds for a list of the acceptable android.SdkKind values.
358type StubDexJarsByKind map[android.SdkKind]android.Paths
359
360// append appends the supplied kind specific stub dex jar pargs to the corresponding kind in this
361// map.
362func (s StubDexJarsByKind) append(other StubDexJarsByKind) {
363 for _, kind := range hiddenAPIRelevantSdkKinds {
364 s[kind] = append(s[kind], other[kind]...)
365 }
366}
367
368// dedupAndSort removes duplicates in the stub dex jar paths and sorts them into a consistent and
369// deterministic order.
370func (s StubDexJarsByKind) dedupAndSort() {
371 for kind, paths := range s {
372 s[kind] = android.SortedUniquePaths(paths)
373 }
374}
375
376// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
377// needed for hidden API flag generation.
378type HiddenAPIFlagInput struct {
379 // FlagFilesByCategory contains the flag files that override the initial flags that are derived
380 // from the stub dex files.
381 FlagFilesByCategory FlagFilesByCategory
382
383 // StubDexJarsByKind contains the stub dex jars for different android.SdkKind and which determine
384 // the initial flags for each dex member.
385 StubDexJarsByKind StubDexJarsByKind
386}
387
388// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
389func newHiddenAPIFlagInput() HiddenAPIFlagInput {
390 input := HiddenAPIFlagInput{
391 FlagFilesByCategory: FlagFilesByCategory{},
392 StubDexJarsByKind: StubDexJarsByKind{},
393 }
394
395 return input
396}
397
398// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
399// dependencies added in hiddenAPIAddStubLibDependencies.
400//
401// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
402func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
403 addFromModule := func(ctx android.ModuleContext, module android.Module, kind android.SdkKind) {
404 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
405 if dexJar != nil {
406 i.StubDexJarsByKind[kind] = append(i.StubDexJarsByKind[kind], dexJar)
407 }
408 }
409
410 // If the contents includes any java_sdk_library modules then add them to the stubs.
411 for _, module := range contents {
412 if _, ok := module.(SdkLibraryDependency); ok {
413 // Add information for every possible kind needed by hidden API. SdkCorePlatform is not used
414 // as the java_sdk_library does not have special support for core_platform API, instead it is
415 // implemented as a customized form of SdkPublic.
416 for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
417 addFromModule(ctx, module, kind)
418 }
419 }
420 }
421
422 ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
423 tag := ctx.OtherModuleDependencyTag(module)
424 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
425 kind := hiddenAPIStubsTag.sdkKind
426 addFromModule(ctx, module, kind)
427 }
428 })
429
430 // Normalize the paths, i.e. remove duplicates and sort.
431 i.StubDexJarsByKind.dedupAndSort()
432}
433
434// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
435// supplied properties and stores them in this struct.
436func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
437 for _, category := range hiddenAPIFlagFileCategories {
438 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
439 i.FlagFilesByCategory[category] = paths
440 }
441}
442
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100443// HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
444// bootclasspath_fragment module.
445type HiddenAPIFlagOutput struct {
446 // The path to the generated stub-flags.csv file.
447 StubFlagsPath android.Path
448
449 // The path to the generated annotation-flags.csv file.
450 AnnotationFlagsPath android.Path
451
452 // The path to the generated metadata.csv file.
453 MetadataPath android.Path
454
455 // The path to the generated index.csv file.
456 IndexPath android.Path
457
458 // The path to the generated all-flags.csv file.
459 AllFlagsPath android.Path
460}
461
Paul Duffindfa10832021-05-13 17:31:51 +0100462// pathForValidation creates a path of the same type as the supplied type but with a name of
463// <path>.valid.
464//
465// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
466// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
467func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
468 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
469 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
470}
471
Paul Duffin2fef1362021-04-15 13:32:00 +0100472// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
473// the flags from all the modules, the stub flags, augmented with some additional configuration
474// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100475//
476// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
477// an entry for every single member in the dex implementation jars of the individual modules. Every
478// signature in any of the other files MUST be included in this file.
479//
Paul Duffin537ea3d2021-05-14 10:38:00 +0100480// annotationFlags is the path to the annotation flags file generated from annotation information
481// in each module.
Paul Duffin702210b2021-04-08 20:12:41 +0100482//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100483// hiddenAPIInfo is a struct containing paths to files that augment the information provided by
Paul Duffin537ea3d2021-05-14 10:38:00 +0100484// the annotationFlags.
Paul Duffin438eb572021-05-21 16:58:23 +0100485func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlags android.Path, flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths) {
Paul Duffindfa10832021-05-13 17:31:51 +0100486
487 // The file which is used to record that the flags file is valid.
488 var validFile android.WritablePath
489
490 // If there are flag files that have been generated by fragments on which this depends then use
491 // them to validate the flag file generated by the rules created by this method.
Paul Duffin438eb572021-05-21 16:58:23 +0100492 if len(allFlagsPaths) > 0 {
Paul Duffindfa10832021-05-13 17:31:51 +0100493 // The flags file generated by the rule created by this method needs to be validated to ensure
494 // that it is consistent with the flag files generated by the individual fragments.
495
496 validFile = pathForValidation(ctx, outputPath)
497
498 // Create a rule to validate the output from the following rule.
499 rule := android.NewRuleBuilder(pctx, ctx)
500 rule.Command().
501 BuiltTool("verify_overlaps").
502 Input(outputPath).
503 Inputs(allFlagsPaths).
504 // If validation passes then update the file that records that.
505 Text("&& touch").Output(validFile)
506 rule.Build(name+"Validation", desc+" validation")
507 }
508
509 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100510 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100511 rule := android.NewRuleBuilder(pctx, ctx)
512 command := rule.Command().
513 BuiltTool("generate_hiddenapi_lists").
514 FlagWithInput("--csv ", baseFlagsPath).
Paul Duffin537ea3d2021-05-14 10:38:00 +0100515 Input(annotationFlags).
Paul Duffin702210b2021-04-08 20:12:41 +0100516 FlagWithOutput("--output ", tempPath)
517
Paul Duffine3dc6602021-04-14 09:50:43 +0100518 // Add the options for the different categories of flag files.
519 for _, category := range hiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +0100520 paths := flagFilesByCategory[category]
Paul Duffine3dc6602021-04-14 09:50:43 +0100521 for _, path := range paths {
522 category.commandMutator(command, path)
523 }
Paul Duffin702210b2021-04-08 20:12:41 +0100524 }
525
526 commitChangeForRestat(rule, tempPath, outputPath)
527
Paul Duffindfa10832021-05-13 17:31:51 +0100528 if validFile != nil {
529 // Add the file that indicates that the file generated by this is valid.
530 //
531 // This will cause the validation rule above to be run any time that the output of this rule
532 // changes but the validation will run in parallel with other rules that depend on this file.
533 command.Validation(validFile)
534 }
535
Paul Duffin2fef1362021-04-15 13:32:00 +0100536 rule.Build(name, desc)
537}
538
539// hiddenAPIGenerateAllFlagsForBootclasspathFragment will generate all the flags for a fragment
540// of the bootclasspath.
541//
542// It takes:
543// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
544// * The list of modules that are the contents of the fragment.
545// * The additional manually curated flag files to use.
546//
547// It generates:
548// * stub-flags.csv
549// * annotation-flags.csv
550// * metadata.csv
551// * index.csv
552// * all-flags.csv
Paul Duffin1352f7c2021-05-21 22:18:49 +0100553func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
Paul Duffin2fef1362021-04-15 13:32:00 +0100554 hiddenApiSubDir := "modular-hiddenapi"
555
Paul Duffin1352f7c2021-05-21 22:18:49 +0100556 // Gather the dex files for the boot libraries provided by this fragment.
Paul Duffin537ea3d2021-05-14 10:38:00 +0100557 bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, contents)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100558
559 // Generate the stub-flags.csv.
Paul Duffin2fef1362021-04-15 13:32:00 +0100560 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
Paul Duffin1352f7c2021-05-21 22:18:49 +0100561 rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, input)
Paul Duffin2fef1362021-04-15 13:32:00 +0100562 rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
563
Paul Duffin537ea3d2021-05-14 10:38:00 +0100564 // Extract the classes jars from the contents.
565 classesJars := extractClassJarsFromHiddenAPIModules(ctx, contents)
566
Paul Duffin2fef1362021-04-15 13:32:00 +0100567 // Generate the set of flags from the annotations in the source code.
568 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100569 buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100570
571 // Generate the metadata from the annotations in the source code.
572 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100573 buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100574
Paul Duffin537ea3d2021-05-14 10:38:00 +0100575 // Generate the index file from the CSV files in the classes jars.
Paul Duffin2fef1362021-04-15 13:32:00 +0100576 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100577 buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100578
Paul Duffinaf99afa2021-05-21 22:18:56 +0100579 // Removed APIs need to be marked and in order to do that the hiddenAPIInfo needs to specify files
Paul Duffin2fef1362021-04-15 13:32:00 +0100580 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
581 // manually combining all the removed.txt files for each API and then converting them to dex
582 // signatures, see the combined-removed-dex module. That will all be done automatically in future.
583 // For now removed APIs are ignored.
584 // TODO(b/179354495): handle removed apis automatically.
585
586 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
587 // files.
588 outputPath := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
Paul Duffin1352f7c2021-05-21 22:18:49 +0100589 buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, input.FlagFilesByCategory, nil)
Paul Duffin2fef1362021-04-15 13:32:00 +0100590
591 // Store the paths in the info for use by other modules and sdk snapshot generation.
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100592 output := HiddenAPIFlagOutput{
593 StubFlagsPath: stubFlagsCSV,
594 AnnotationFlagsPath: annotationFlagsCSV,
595 MetadataPath: metadataCSV,
596 IndexPath: indexCSV,
597 AllFlagsPath: outputPath,
598 }
599 return &output
Paul Duffin702210b2021-04-08 20:12:41 +0100600}
Paul Duffin537ea3d2021-05-14 10:38:00 +0100601
602// gatherHiddenAPIModuleFromContents gathers the hiddenAPIModule from the supplied contents.
603func gatherHiddenAPIModuleFromContents(ctx android.ModuleContext, contents []android.Module) []hiddenAPIModule {
604 hiddenAPIModules := []hiddenAPIModule{}
605 for _, module := range contents {
606 if hiddenAPI, ok := module.(hiddenAPIModule); ok {
607 hiddenAPIModules = append(hiddenAPIModules, hiddenAPI)
608 } else if _, ok := module.(*DexImport); ok {
609 // Ignore this for the purposes of hidden API processing
610 } else {
611 ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
612 }
613 }
614 return hiddenAPIModules
615}
616
617// extractBootDexJarsFromHiddenAPIModules extracts the boot dex jars from the supplied modules.
618func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
619 bootDexJars := android.Paths{}
620 for _, module := range contents {
621 bootDexJar := module.bootDexJar()
622 if bootDexJar == nil {
Paul Duffin7487a7a2021-05-19 09:36:09 +0100623 if ctx.Config().AlwaysUsePrebuiltSdks() {
624 // TODO(b/179354495): Remove this work around when it is unnecessary.
625 // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
626 // create a fake one that will cause a build error only if it is used.
627 fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name())
628
629 // Create an error rule that pretends to create the output file but will actually fail if it
630 // is run.
631 ctx.Build(pctx, android.BuildParams{
632 Rule: android.ErrorRule,
633 Output: fake,
634 Args: map[string]string{
635 "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
636 },
637 })
638 bootDexJars = append(bootDexJars, fake)
639 } else {
640 ctx.ModuleErrorf("module %s does not provide a dex jar", module)
641 }
Paul Duffin537ea3d2021-05-14 10:38:00 +0100642 } else {
643 bootDexJars = append(bootDexJars, bootDexJar)
644 }
645 }
646 return bootDexJars
647}
648
649// extractClassJarsFromHiddenAPIModules extracts the class jars from the supplied modules.
650func extractClassJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
651 classesJars := android.Paths{}
652 for _, module := range contents {
653 classesJars = append(classesJars, module.classesJars()...)
654 }
655 return classesJars
656}