blob: 0bf39ffe25075c471700de2fe67be300743cf719 [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 Duffin62370922021-05-23 16:55:37 +010023 "github.com/google/blueprint/proptools"
Paul Duffinc6bb7cf2021-04-08 17:49:27 +010024)
25
26// Contains support for processing hiddenAPI in a modular fashion.
27
Paul Duffin74431d52021-04-21 14:10:42 +010028type hiddenAPIStubsDependencyTag struct {
29 blueprint.BaseDependencyTag
30 sdkKind android.SdkKind
31}
32
33func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
34}
35
36func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
37 return false
38}
39
Paul Duffin976b0e52021-04-27 23:20:26 +010040func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
41 // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
42 // property, otherwise treat if it was specified in the java_header_libs property.
43 if javaSdkLibrarySdkMemberType.IsInstance(child) {
44 return javaSdkLibrarySdkMemberType
45 }
46
47 return javaHeaderLibsSdkMemberType
48}
49
50func (b hiddenAPIStubsDependencyTag) ExportMember() bool {
51 // Export the module added via this dependency tag from the sdk.
52 return true
53}
54
Paul Duffin74431d52021-04-21 14:10:42 +010055// Avoid having to make stubs content explicitly visible to dependent modules.
56//
57// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
58// with proper dependencies.
59// TODO(b/177892522): Remove this and add needed visibility.
60func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
61}
62
63var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
64var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
65var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
Paul Duffin976b0e52021-04-27 23:20:26 +010066var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
Paul Duffin74431d52021-04-21 14:10:42 +010067
Paul Duffin3e7fcc32021-04-15 13:31:38 +010068// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
69// API processing.
70var hiddenAPIRelevantSdkKinds = []android.SdkKind{
71 android.SdkPublic,
72 android.SdkSystem,
73 android.SdkTest,
74 android.SdkCorePlatform,
75}
76
Paul Duffin74431d52021-04-21 14:10:42 +010077// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
78// needed to produce the hidden API monolithic stub flags file.
79func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string {
80 var publicStubModules []string
81 var systemStubModules []string
82 var testStubModules []string
83 var corePlatformStubModules []string
84
85 if config.AlwaysUsePrebuiltSdks() {
86 // Build configuration mandates using prebuilt stub modules
87 publicStubModules = append(publicStubModules, "sdk_public_current_android")
88 systemStubModules = append(systemStubModules, "sdk_system_current_android")
89 testStubModules = append(testStubModules, "sdk_test_current_android")
90 } else {
91 // Use stub modules built from source
92 publicStubModules = append(publicStubModules, "android_stubs_current")
93 systemStubModules = append(systemStubModules, "android_system_stubs_current")
94 testStubModules = append(testStubModules, "android_test_stubs_current")
95 }
96 // We do not have prebuilts of the core platform api yet
97 corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
98
99 // Allow products to define their own stubs for custom product jars that apps can use.
100 publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
101 systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
102 testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
103 if config.IsEnvTrue("EMMA_INSTRUMENT") {
Paul Duffin098c8782021-05-14 10:45:25 +0100104 // Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
105 // allows everyone access but it is needed to ensure consistent flags between the
106 // bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
Paul Duffin74431d52021-04-21 14:10:42 +0100107 publicStubModules = append(publicStubModules, "jacoco-stubs")
Paul Duffin098c8782021-05-14 10:45:25 +0100108 systemStubModules = append(systemStubModules, "jacoco-stubs")
109 testStubModules = append(testStubModules, "jacoco-stubs")
Paul Duffin74431d52021-04-21 14:10:42 +0100110 }
111
112 m := map[android.SdkKind][]string{}
113 m[android.SdkPublic] = publicStubModules
114 m[android.SdkSystem] = systemStubModules
115 m[android.SdkTest] = testStubModules
116 m[android.SdkCorePlatform] = corePlatformStubModules
117 return m
118}
119
120// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
121// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
122// identify the source of the dependency.
123func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) {
124 module := ctx.Module()
125 for _, sdkKind := range hiddenAPIRelevantSdkKinds {
126 modules := sdkKindToStubLibModules[sdkKind]
127 ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...)
128 }
129}
130
Paul Duffin74431d52021-04-21 14:10:42 +0100131// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
132// available, or reports an error.
Paul Duffin10931582021-04-25 10:13:54 +0100133func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
134 var dexJar android.Path
135 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
136 dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
137 } else if j, ok := module.(UsesLibraryDependency); ok {
138 dexJar = j.DexJarBuildPath()
Paul Duffin74431d52021-04-21 14:10:42 +0100139 } else {
140 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 +0100141 return nil
Paul Duffin74431d52021-04-21 14:10:42 +0100142 }
Paul Duffin10931582021-04-25 10:13:54 +0100143
144 if dexJar == nil {
145 ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
146 }
147 return dexJar
Paul Duffin74431d52021-04-21 14:10:42 +0100148}
149
150var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
151 android.SdkPublic: "public-stub-classpath",
152 android.SdkSystem: "system-stub-classpath",
153 android.SdkTest: "test-stub-classpath",
154 android.SdkCorePlatform: "core-platform-stub-classpath",
155}
156
157// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
158//
159// The rule is initialized but not built so that the caller can modify it and select an appropriate
160// name.
Paul Duffin1352f7c2021-05-21 22:18:49 +0100161func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput) *android.RuleBuilder {
Paul Duffin74431d52021-04-21 14:10:42 +0100162 // Singleton rule which applies hiddenapi on all boot class path dex files.
163 rule := android.NewRuleBuilder(pctx, ctx)
164
165 tempPath := tempPathForRestat(ctx, outputPath)
166
167 command := rule.Command().
168 Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
169 Text("list").
170 FlagForEachInput("--boot-dex=", bootDexJars)
171
172 // Iterate over the sdk kinds in a fixed order.
173 for _, sdkKind := range hiddenAPIRelevantSdkKinds {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100174 paths := input.StubDexJarsByKind[sdkKind]
Paul Duffin74431d52021-04-21 14:10:42 +0100175 if len(paths) > 0 {
176 option := sdkKindToHiddenapiListOption[sdkKind]
177 command.FlagWithInputList("--"+option+"=", paths, ":")
178 }
179 }
180
181 // Add the output path.
182 command.FlagWithOutput("--out-api-flags=", tempPath)
183
184 commitChangeForRestat(rule, tempPath, outputPath)
185 return rule
186}
187
Paul Duffin46169772021-04-14 15:01:56 +0100188// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
189// information obtained from annotations within the source code in order to create the complete set
190// of flags that should be applied to the dex implementation jars on the bootclasspath.
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100191//
192// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
193// of each property reference a plain text file that contains a java signature per line. The flags
194// for each of those signatures will be updated in a property specific way.
195//
196// The Unsupported_packages property contains a list of paths, each of which is a plain text file
197// with one Java package per line. All members of all classes within that package (but not nested
198// packages) will be updated in a property specific way.
Paul Duffin46169772021-04-14 15:01:56 +0100199type HiddenAPIFlagFileProperties struct {
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100200 // Marks each signature in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100201 Unsupported []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100202
203 // Marks each signature in the referenced files as being unsupported because it has been removed.
204 // Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100205 Removed []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100206
207 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= R
208 // and low priority.
Paul Duffin702210b2021-04-08 20:12:41 +0100209 Max_target_r_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100210
211 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= Q.
Paul Duffin702210b2021-04-08 20:12:41 +0100212 Max_target_q []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100213
214 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= P.
Paul Duffin702210b2021-04-08 20:12:41 +0100215 Max_target_p []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100216
217 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= O
218 // and low priority. Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100219 Max_target_o_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100220
221 // Marks each signature in the referenced files as being blocked.
Paul Duffin702210b2021-04-08 20:12:41 +0100222 Blocked []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100223
224 // Marks each signature in every package in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100225 Unsupported_packages []string `android:"path"`
226}
227
Paul Duffine3dc6602021-04-14 09:50:43 +0100228type hiddenAPIFlagFileCategory struct {
229 // propertyName is the name of the property for this category.
230 propertyName string
231
Paul Duffincc17bfe2021-04-19 13:21:20 +0100232 // propertyValueReader retrieves the value of the property for this category from the set of
Paul Duffine3dc6602021-04-14 09:50:43 +0100233 // properties.
Paul Duffincc17bfe2021-04-19 13:21:20 +0100234 propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
Paul Duffine3dc6602021-04-14 09:50:43 +0100235
236 // commandMutator adds the appropriate command line options for this category to the supplied
237 // command
238 commandMutator func(command *android.RuleBuilderCommand, path android.Path)
239}
240
241var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
Paul Duffin46169772021-04-14 15:01:56 +0100242 // See HiddenAPIFlagFileProperties.Unsupported
Paul Duffine3dc6602021-04-14 09:50:43 +0100243 {
244 propertyName: "unsupported",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100245 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100246 return properties.Unsupported
247 },
248 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
249 command.FlagWithInput("--unsupported ", path)
250 },
251 },
Paul Duffin46169772021-04-14 15:01:56 +0100252 // See HiddenAPIFlagFileProperties.Removed
Paul Duffine3dc6602021-04-14 09:50:43 +0100253 {
254 propertyName: "removed",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100255 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100256 return properties.Removed
257 },
258 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
259 command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
260 },
261 },
Paul Duffin46169772021-04-14 15:01:56 +0100262 // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100263 {
264 propertyName: "max_target_r_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100265 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100266 return properties.Max_target_r_low_priority
267 },
268 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
269 command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
270 },
271 },
Paul Duffin46169772021-04-14 15:01:56 +0100272 // See HiddenAPIFlagFileProperties.Max_target_q
Paul Duffine3dc6602021-04-14 09:50:43 +0100273 {
274 propertyName: "max_target_q",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100275 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100276 return properties.Max_target_q
277 },
278 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
279 command.FlagWithInput("--max-target-q ", path)
280 },
281 },
Paul Duffin46169772021-04-14 15:01:56 +0100282 // See HiddenAPIFlagFileProperties.Max_target_p
Paul Duffine3dc6602021-04-14 09:50:43 +0100283 {
284 propertyName: "max_target_p",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100285 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100286 return properties.Max_target_p
287 },
288 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
289 command.FlagWithInput("--max-target-p ", path)
290 },
291 },
Paul Duffin46169772021-04-14 15:01:56 +0100292 // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100293 {
294 propertyName: "max_target_o_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100295 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100296 return properties.Max_target_o_low_priority
297 },
298 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
299 command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
300 },
301 },
Paul Duffin46169772021-04-14 15:01:56 +0100302 // See HiddenAPIFlagFileProperties.Blocked
Paul Duffine3dc6602021-04-14 09:50:43 +0100303 {
304 propertyName: "blocked",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100305 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100306 return properties.Blocked
307 },
308 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
309 command.FlagWithInput("--blocked ", path)
310 },
311 },
Paul Duffin46169772021-04-14 15:01:56 +0100312 // See HiddenAPIFlagFileProperties.Unsupported_packages
Paul Duffine3dc6602021-04-14 09:50:43 +0100313 {
314 propertyName: "unsupported_packages",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100315 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100316 return properties.Unsupported_packages
317 },
318 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
319 command.FlagWithInput("--unsupported ", path).Flag("--packages ")
320 },
321 },
Paul Duffin702210b2021-04-08 20:12:41 +0100322}
323
Paul Duffin438eb572021-05-21 16:58:23 +0100324// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
325type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths
326
327// append appends the supplied flags files to the corresponding category in this map.
328func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
329 for _, category := range hiddenAPIFlagFileCategories {
330 s[category] = append(s[category], other[category]...)
331 }
332}
333
334// dedup removes duplicates in the flag files, while maintaining the order in which they were
335// appended.
336func (s FlagFilesByCategory) dedup() {
337 for category, paths := range s {
338 s[category] = android.FirstUniquePaths(paths)
339 }
340}
341
Paul Duffinaf99afa2021-05-21 22:18:56 +0100342// HiddenAPIInfo contains information provided by the hidden API processing.
Paul Duffin2fef1362021-04-15 13:32:00 +0100343//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100344// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
345// processing.
346type HiddenAPIInfo struct {
Paul Duffin438eb572021-05-21 16:58:23 +0100347 // FlagFilesByCategory maps from the flag file category to the paths containing information for
348 // that category.
349 FlagFilesByCategory FlagFilesByCategory
Paul Duffin2fef1362021-04-15 13:32:00 +0100350
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100351 // The output from the hidden API processing needs to be made available to other modules.
352 HiddenAPIFlagOutput
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100353}
Paul Duffin702210b2021-04-08 20:12:41 +0100354
Paul Duffinaf99afa2021-05-21 22:18:56 +0100355var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
Paul Duffin9b381ef2021-04-08 23:01:37 +0100356
Paul Duffin1352f7c2021-05-21 22:18:49 +0100357// StubDexJarsByKind maps an android.SdkKind to the paths to stub dex jars appropriate for that
358// level. See hiddenAPIRelevantSdkKinds for a list of the acceptable android.SdkKind values.
359type StubDexJarsByKind map[android.SdkKind]android.Paths
360
361// append appends the supplied kind specific stub dex jar pargs to the corresponding kind in this
362// map.
363func (s StubDexJarsByKind) append(other StubDexJarsByKind) {
364 for _, kind := range hiddenAPIRelevantSdkKinds {
365 s[kind] = append(s[kind], other[kind]...)
366 }
367}
368
369// dedupAndSort removes duplicates in the stub dex jar paths and sorts them into a consistent and
370// deterministic order.
371func (s StubDexJarsByKind) dedupAndSort() {
372 for kind, paths := range s {
373 s[kind] = android.SortedUniquePaths(paths)
374 }
375}
376
377// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
378// needed for hidden API flag generation.
379type HiddenAPIFlagInput struct {
380 // FlagFilesByCategory contains the flag files that override the initial flags that are derived
381 // from the stub dex files.
382 FlagFilesByCategory FlagFilesByCategory
383
384 // StubDexJarsByKind contains the stub dex jars for different android.SdkKind and which determine
385 // the initial flags for each dex member.
386 StubDexJarsByKind StubDexJarsByKind
387}
388
389// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
390func newHiddenAPIFlagInput() HiddenAPIFlagInput {
391 input := HiddenAPIFlagInput{
392 FlagFilesByCategory: FlagFilesByCategory{},
393 StubDexJarsByKind: StubDexJarsByKind{},
394 }
395
396 return input
397}
398
Paul Duffin62370922021-05-23 16:55:37 +0100399// canPerformHiddenAPIProcessing determines whether hidden API processing should be performed.
400//
401// A temporary workaround to avoid existing bootclasspath_fragments that do not provide the
402// appropriate information needed for hidden API processing breaking the build.
403// TODO(b/179354495): Remove this workaround.
404func (i *HiddenAPIFlagInput) canPerformHiddenAPIProcessing(ctx android.ModuleContext, properties bootclasspathFragmentProperties) bool {
405 // Performing hidden API processing without stubs is not supported and it is unlikely to ever be
406 // required as the whole point of adding something to the bootclasspath fragment is to add it to
407 // the bootclasspath in order to be used by something else in the system. Without any stubs it
408 // cannot do that.
409 if len(i.StubDexJarsByKind) == 0 {
410 return false
411 }
412
413 // Hidden API processing is always enabled in tests.
414 if ctx.Config().TestProductVariables != nil {
415 return true
416 }
417
418 // A module that has fragments should have access to the information it needs in order to perform
419 // hidden API processing.
420 if len(properties.Fragments) != 0 {
421 return true
422 }
423
424 // The art bootclasspath fragment does not depend on any other fragments but already supports
425 // hidden API processing.
426 imageName := proptools.String(properties.Image_name)
427 if imageName == "art" {
428 return true
429 }
430
431 // Disable it for everything else.
432 return false
433}
434
Paul Duffin1352f7c2021-05-21 22:18:49 +0100435// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
436// dependencies added in hiddenAPIAddStubLibDependencies.
437//
438// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
439func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
440 addFromModule := func(ctx android.ModuleContext, module android.Module, kind android.SdkKind) {
441 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
442 if dexJar != nil {
443 i.StubDexJarsByKind[kind] = append(i.StubDexJarsByKind[kind], dexJar)
444 }
445 }
446
447 // If the contents includes any java_sdk_library modules then add them to the stubs.
448 for _, module := range contents {
449 if _, ok := module.(SdkLibraryDependency); ok {
450 // Add information for every possible kind needed by hidden API. SdkCorePlatform is not used
451 // as the java_sdk_library does not have special support for core_platform API, instead it is
452 // implemented as a customized form of SdkPublic.
453 for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
454 addFromModule(ctx, module, kind)
455 }
456 }
457 }
458
459 ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
460 tag := ctx.OtherModuleDependencyTag(module)
461 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
462 kind := hiddenAPIStubsTag.sdkKind
463 addFromModule(ctx, module, kind)
464 }
465 })
466
467 // Normalize the paths, i.e. remove duplicates and sort.
468 i.StubDexJarsByKind.dedupAndSort()
469}
470
471// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
472// supplied properties and stores them in this struct.
473func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
474 for _, category := range hiddenAPIFlagFileCategories {
475 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
476 i.FlagFilesByCategory[category] = paths
477 }
478}
479
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100480// HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
481// bootclasspath_fragment module.
482type HiddenAPIFlagOutput struct {
483 // The path to the generated stub-flags.csv file.
484 StubFlagsPath android.Path
485
486 // The path to the generated annotation-flags.csv file.
487 AnnotationFlagsPath android.Path
488
489 // The path to the generated metadata.csv file.
490 MetadataPath android.Path
491
492 // The path to the generated index.csv file.
493 IndexPath android.Path
494
495 // The path to the generated all-flags.csv file.
496 AllFlagsPath android.Path
497}
498
Paul Duffindfa10832021-05-13 17:31:51 +0100499// pathForValidation creates a path of the same type as the supplied type but with a name of
500// <path>.valid.
501//
502// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
503// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
504func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
505 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
506 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
507}
508
Paul Duffin2fef1362021-04-15 13:32:00 +0100509// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
510// the flags from all the modules, the stub flags, augmented with some additional configuration
511// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100512//
513// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
514// an entry for every single member in the dex implementation jars of the individual modules. Every
515// signature in any of the other files MUST be included in this file.
516//
Paul Duffin537ea3d2021-05-14 10:38:00 +0100517// annotationFlags is the path to the annotation flags file generated from annotation information
518// in each module.
Paul Duffin702210b2021-04-08 20:12:41 +0100519//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100520// hiddenAPIInfo is a struct containing paths to files that augment the information provided by
Paul Duffin537ea3d2021-05-14 10:38:00 +0100521// the annotationFlags.
Paul Duffin438eb572021-05-21 16:58:23 +0100522func 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 +0100523
524 // The file which is used to record that the flags file is valid.
525 var validFile android.WritablePath
526
527 // If there are flag files that have been generated by fragments on which this depends then use
528 // them to validate the flag file generated by the rules created by this method.
Paul Duffin438eb572021-05-21 16:58:23 +0100529 if len(allFlagsPaths) > 0 {
Paul Duffindfa10832021-05-13 17:31:51 +0100530 // The flags file generated by the rule created by this method needs to be validated to ensure
531 // that it is consistent with the flag files generated by the individual fragments.
532
533 validFile = pathForValidation(ctx, outputPath)
534
535 // Create a rule to validate the output from the following rule.
536 rule := android.NewRuleBuilder(pctx, ctx)
537 rule.Command().
538 BuiltTool("verify_overlaps").
539 Input(outputPath).
540 Inputs(allFlagsPaths).
541 // If validation passes then update the file that records that.
542 Text("&& touch").Output(validFile)
543 rule.Build(name+"Validation", desc+" validation")
544 }
545
546 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100547 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100548 rule := android.NewRuleBuilder(pctx, ctx)
549 command := rule.Command().
550 BuiltTool("generate_hiddenapi_lists").
551 FlagWithInput("--csv ", baseFlagsPath).
Paul Duffin537ea3d2021-05-14 10:38:00 +0100552 Input(annotationFlags).
Paul Duffin702210b2021-04-08 20:12:41 +0100553 FlagWithOutput("--output ", tempPath)
554
Paul Duffine3dc6602021-04-14 09:50:43 +0100555 // Add the options for the different categories of flag files.
556 for _, category := range hiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +0100557 paths := flagFilesByCategory[category]
Paul Duffine3dc6602021-04-14 09:50:43 +0100558 for _, path := range paths {
559 category.commandMutator(command, path)
560 }
Paul Duffin702210b2021-04-08 20:12:41 +0100561 }
562
563 commitChangeForRestat(rule, tempPath, outputPath)
564
Paul Duffindfa10832021-05-13 17:31:51 +0100565 if validFile != nil {
566 // Add the file that indicates that the file generated by this is valid.
567 //
568 // This will cause the validation rule above to be run any time that the output of this rule
569 // changes but the validation will run in parallel with other rules that depend on this file.
570 command.Validation(validFile)
571 }
572
Paul Duffin2fef1362021-04-15 13:32:00 +0100573 rule.Build(name, desc)
574}
575
576// hiddenAPIGenerateAllFlagsForBootclasspathFragment will generate all the flags for a fragment
577// of the bootclasspath.
578//
579// It takes:
580// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
581// * The list of modules that are the contents of the fragment.
582// * The additional manually curated flag files to use.
583//
584// It generates:
585// * stub-flags.csv
586// * annotation-flags.csv
587// * metadata.csv
588// * index.csv
589// * all-flags.csv
Paul Duffin1352f7c2021-05-21 22:18:49 +0100590func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
Paul Duffin2fef1362021-04-15 13:32:00 +0100591 hiddenApiSubDir := "modular-hiddenapi"
592
Paul Duffin1352f7c2021-05-21 22:18:49 +0100593 // Gather the dex files for the boot libraries provided by this fragment.
Paul Duffin537ea3d2021-05-14 10:38:00 +0100594 bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, contents)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100595
596 // Generate the stub-flags.csv.
Paul Duffin2fef1362021-04-15 13:32:00 +0100597 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
Paul Duffin1352f7c2021-05-21 22:18:49 +0100598 rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, input)
Paul Duffin2fef1362021-04-15 13:32:00 +0100599 rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
600
Paul Duffin537ea3d2021-05-14 10:38:00 +0100601 // Extract the classes jars from the contents.
602 classesJars := extractClassJarsFromHiddenAPIModules(ctx, contents)
603
Paul Duffin2fef1362021-04-15 13:32:00 +0100604 // Generate the set of flags from the annotations in the source code.
605 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100606 buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100607
608 // Generate the metadata from the annotations in the source code.
609 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100610 buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100611
Paul Duffin537ea3d2021-05-14 10:38:00 +0100612 // Generate the index file from the CSV files in the classes jars.
Paul Duffin2fef1362021-04-15 13:32:00 +0100613 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100614 buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100615
Paul Duffinaf99afa2021-05-21 22:18:56 +0100616 // 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 +0100617 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
618 // manually combining all the removed.txt files for each API and then converting them to dex
619 // signatures, see the combined-removed-dex module. That will all be done automatically in future.
620 // For now removed APIs are ignored.
621 // TODO(b/179354495): handle removed apis automatically.
622
623 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
624 // files.
625 outputPath := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
Paul Duffin1352f7c2021-05-21 22:18:49 +0100626 buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, input.FlagFilesByCategory, nil)
Paul Duffin2fef1362021-04-15 13:32:00 +0100627
628 // Store the paths in the info for use by other modules and sdk snapshot generation.
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100629 output := HiddenAPIFlagOutput{
630 StubFlagsPath: stubFlagsCSV,
631 AnnotationFlagsPath: annotationFlagsCSV,
632 MetadataPath: metadataCSV,
633 IndexPath: indexCSV,
634 AllFlagsPath: outputPath,
635 }
636 return &output
Paul Duffin702210b2021-04-08 20:12:41 +0100637}
Paul Duffin537ea3d2021-05-14 10:38:00 +0100638
639// gatherHiddenAPIModuleFromContents gathers the hiddenAPIModule from the supplied contents.
640func gatherHiddenAPIModuleFromContents(ctx android.ModuleContext, contents []android.Module) []hiddenAPIModule {
641 hiddenAPIModules := []hiddenAPIModule{}
642 for _, module := range contents {
643 if hiddenAPI, ok := module.(hiddenAPIModule); ok {
644 hiddenAPIModules = append(hiddenAPIModules, hiddenAPI)
645 } else if _, ok := module.(*DexImport); ok {
646 // Ignore this for the purposes of hidden API processing
647 } else {
648 ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
649 }
650 }
651 return hiddenAPIModules
652}
653
654// extractBootDexJarsFromHiddenAPIModules extracts the boot dex jars from the supplied modules.
655func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
656 bootDexJars := android.Paths{}
657 for _, module := range contents {
658 bootDexJar := module.bootDexJar()
659 if bootDexJar == nil {
Paul Duffin7487a7a2021-05-19 09:36:09 +0100660 if ctx.Config().AlwaysUsePrebuiltSdks() {
661 // TODO(b/179354495): Remove this work around when it is unnecessary.
662 // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
663 // create a fake one that will cause a build error only if it is used.
664 fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name())
665
666 // Create an error rule that pretends to create the output file but will actually fail if it
667 // is run.
668 ctx.Build(pctx, android.BuildParams{
669 Rule: android.ErrorRule,
670 Output: fake,
671 Args: map[string]string{
672 "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
673 },
674 })
675 bootDexJars = append(bootDexJars, fake)
676 } else {
677 ctx.ModuleErrorf("module %s does not provide a dex jar", module)
678 }
Paul Duffin537ea3d2021-05-14 10:38:00 +0100679 } else {
680 bootDexJars = append(bootDexJars, bootDexJar)
681 }
682 }
683 return bootDexJars
684}
685
686// extractClassJarsFromHiddenAPIModules extracts the class jars from the supplied modules.
687func extractClassJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
688 classesJars := android.Paths{}
689 for _, module := range contents {
690 classesJars = append(classesJars, module.classesJars()...)
691 }
692 return classesJars
693}