blob: 96534ad7d695af5c00419a2e2e193771977d4e93 [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 Duffin31fad802021-06-18 18:14:25 +010028// HiddenAPIScope encapsulates all the information that the hidden API processing needs about API
29// scopes, i.e. what is called android.SdkKind and apiScope. It does not just use those as they do
30// not provide the information needed by hidden API processing.
31type HiddenAPIScope struct {
32 // The name of the scope, used for debug purposes.
33 name string
34
35 // The corresponding android.SdkKind, used for retrieving paths from java_sdk_library* modules.
36 sdkKind android.SdkKind
37
38 // The option needed to passed to "hiddenapi list".
39 hiddenAPIListOption string
40}
41
42// initHiddenAPIScope initializes the scope.
43func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
44 return apiScope
45}
46
47func (l *HiddenAPIScope) String() string {
48 return fmt.Sprintf("HiddenAPIScope{%s}", l.name)
49}
50
51var (
52 PublicHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
53 name: "public",
54 sdkKind: android.SdkPublic,
55 hiddenAPIListOption: "--public-stub-classpath",
56 })
57 SystemHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
58 name: "system",
59 sdkKind: android.SdkSystem,
60 hiddenAPIListOption: "--system-stub-classpath",
61 })
62 TestHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
63 name: "test",
64 sdkKind: android.SdkTest,
65 hiddenAPIListOption: "--test-stub-classpath",
66 })
Paul Duffinb51db2e2021-06-21 14:08:08 +010067 ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
68 name: "module-lib",
69 sdkKind: android.SdkModule,
70 })
Paul Duffin31fad802021-06-18 18:14:25 +010071 CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
72 name: "core-platform",
73 sdkKind: android.SdkCorePlatform,
74 hiddenAPIListOption: "--core-platform-stub-classpath",
75 })
76
77 // hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
78 // API processing.
79 //
80 // These are roughly in order from narrowest API surface to widest. Widest means the API stubs
81 // with the biggest API surface, e.g. test is wider than system is wider than public.
82 //
Paul Duffinb51db2e2021-06-21 14:08:08 +010083 // Core platform is considered wider than system/module-lib because those modules that provide
84 // core platform APIs either do not have any system/module-lib APIs at all, or if they do it is
85 // because the core platform API is being converted to system/module-lib APIs. In either case the
86 // system/module-lib APIs are subsets of the core platform API.
Paul Duffin31fad802021-06-18 18:14:25 +010087 //
88 // This is not strictly in order from narrowest to widest as the Test API is wider than system but
Paul Duffinb51db2e2021-06-21 14:08:08 +010089 // is neither wider or narrower than the module-lib or core platform APIs. However, this works
90 // well enough at the moment.
Paul Duffin31fad802021-06-18 18:14:25 +010091 // TODO(b/191644675): Correctly reflect the sub/superset relationships between APIs.
92 hiddenAPIScopes = []*HiddenAPIScope{
93 PublicHiddenAPIScope,
94 SystemHiddenAPIScope,
95 TestHiddenAPIScope,
Paul Duffinb51db2e2021-06-21 14:08:08 +010096 ModuleLibHiddenAPIScope,
Paul Duffin31fad802021-06-18 18:14:25 +010097 CorePlatformHiddenAPIScope,
98 }
99
100 // The HiddenAPIScope instances that are supported by a java_sdk_library.
101 //
102 // CorePlatformHiddenAPIScope is not used as the java_sdk_library does not have special support
103 // for core_platform API, instead it is implemented as a customized form of PublicHiddenAPIScope.
104 hiddenAPISdkLibrarySupportedScopes = []*HiddenAPIScope{
105 PublicHiddenAPIScope,
106 SystemHiddenAPIScope,
107 TestHiddenAPIScope,
Paul Duffinb51db2e2021-06-21 14:08:08 +0100108 ModuleLibHiddenAPIScope,
Paul Duffin31fad802021-06-18 18:14:25 +0100109 }
110
111 // The HiddenAPIScope instances that are supported by the `hiddenapi list`.
112 hiddenAPIFlagScopes = []*HiddenAPIScope{
113 PublicHiddenAPIScope,
114 SystemHiddenAPIScope,
115 TestHiddenAPIScope,
116 CorePlatformHiddenAPIScope,
117 }
118)
119
Paul Duffin74431d52021-04-21 14:10:42 +0100120type hiddenAPIStubsDependencyTag struct {
121 blueprint.BaseDependencyTag
Paul Duffin31fad802021-06-18 18:14:25 +0100122
123 // The api scope for which this dependency was added.
124 apiScope *HiddenAPIScope
Paul Duffin74431d52021-04-21 14:10:42 +0100125}
126
127func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
128}
129
130func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
131 return false
132}
133
Paul Duffin976b0e52021-04-27 23:20:26 +0100134func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
135 // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
136 // property, otherwise treat if it was specified in the java_header_libs property.
137 if javaSdkLibrarySdkMemberType.IsInstance(child) {
138 return javaSdkLibrarySdkMemberType
139 }
140
141 return javaHeaderLibsSdkMemberType
142}
143
144func (b hiddenAPIStubsDependencyTag) ExportMember() bool {
145 // Export the module added via this dependency tag from the sdk.
146 return true
147}
148
Paul Duffin74431d52021-04-21 14:10:42 +0100149// Avoid having to make stubs content explicitly visible to dependent modules.
150//
151// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
152// with proper dependencies.
153// TODO(b/177892522): Remove this and add needed visibility.
154func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
155}
156
157var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
158var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
159var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
Paul Duffin976b0e52021-04-27 23:20:26 +0100160var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
Paul Duffin74431d52021-04-21 14:10:42 +0100161
Paul Duffin74431d52021-04-21 14:10:42 +0100162// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
163// needed to produce the hidden API monolithic stub flags file.
Paul Duffin31fad802021-06-18 18:14:25 +0100164func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*HiddenAPIScope][]string {
Paul Duffin74431d52021-04-21 14:10:42 +0100165 var publicStubModules []string
166 var systemStubModules []string
167 var testStubModules []string
168 var corePlatformStubModules []string
169
170 if config.AlwaysUsePrebuiltSdks() {
171 // Build configuration mandates using prebuilt stub modules
172 publicStubModules = append(publicStubModules, "sdk_public_current_android")
173 systemStubModules = append(systemStubModules, "sdk_system_current_android")
174 testStubModules = append(testStubModules, "sdk_test_current_android")
175 } else {
176 // Use stub modules built from source
177 publicStubModules = append(publicStubModules, "android_stubs_current")
178 systemStubModules = append(systemStubModules, "android_system_stubs_current")
179 testStubModules = append(testStubModules, "android_test_stubs_current")
180 }
181 // We do not have prebuilts of the core platform api yet
182 corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
183
184 // Allow products to define their own stubs for custom product jars that apps can use.
185 publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
186 systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
187 testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
188 if config.IsEnvTrue("EMMA_INSTRUMENT") {
Paul Duffin098c8782021-05-14 10:45:25 +0100189 // Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
190 // allows everyone access but it is needed to ensure consistent flags between the
191 // bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
Paul Duffin74431d52021-04-21 14:10:42 +0100192 publicStubModules = append(publicStubModules, "jacoco-stubs")
Paul Duffin098c8782021-05-14 10:45:25 +0100193 systemStubModules = append(systemStubModules, "jacoco-stubs")
194 testStubModules = append(testStubModules, "jacoco-stubs")
Paul Duffin74431d52021-04-21 14:10:42 +0100195 }
196
Paul Duffin31fad802021-06-18 18:14:25 +0100197 m := map[*HiddenAPIScope][]string{}
198 m[PublicHiddenAPIScope] = publicStubModules
199 m[SystemHiddenAPIScope] = systemStubModules
200 m[TestHiddenAPIScope] = testStubModules
201 m[CorePlatformHiddenAPIScope] = corePlatformStubModules
Paul Duffin74431d52021-04-21 14:10:42 +0100202 return m
203}
204
205// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
Paul Duffin31fad802021-06-18 18:14:25 +0100206// apiScopeToStubLibModules. It adds them in a well known order and uses a HiddenAPIScope specific
207// tag to identify the source of the dependency.
208func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScopeToStubLibModules map[*HiddenAPIScope][]string) {
Paul Duffin74431d52021-04-21 14:10:42 +0100209 module := ctx.Module()
Paul Duffin31fad802021-06-18 18:14:25 +0100210 for _, apiScope := range hiddenAPIScopes {
211 modules := apiScopeToStubLibModules[apiScope]
212 ctx.AddDependency(module, hiddenAPIStubsDependencyTag{apiScope: apiScope}, modules...)
Paul Duffin74431d52021-04-21 14:10:42 +0100213 }
214}
215
Paul Duffin74431d52021-04-21 14:10:42 +0100216// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
217// available, or reports an error.
Paul Duffin10931582021-04-25 10:13:54 +0100218func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
219 var dexJar android.Path
220 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
221 dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
222 } else if j, ok := module.(UsesLibraryDependency); ok {
223 dexJar = j.DexJarBuildPath()
Paul Duffin74431d52021-04-21 14:10:42 +0100224 } else {
225 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 +0100226 return nil
Paul Duffin74431d52021-04-21 14:10:42 +0100227 }
Paul Duffin10931582021-04-25 10:13:54 +0100228
229 if dexJar == nil {
230 ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
231 }
232 return dexJar
Paul Duffin74431d52021-04-21 14:10:42 +0100233}
234
Paul Duffin74431d52021-04-21 14:10:42 +0100235// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
236//
237// The rule is initialized but not built so that the caller can modify it and select an appropriate
238// name.
Paul Duffin1352f7c2021-05-21 22:18:49 +0100239func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput) *android.RuleBuilder {
Paul Duffin74431d52021-04-21 14:10:42 +0100240 // Singleton rule which applies hiddenapi on all boot class path dex files.
241 rule := android.NewRuleBuilder(pctx, ctx)
242
243 tempPath := tempPathForRestat(ctx, outputPath)
244
Paul Duffinf1b358c2021-05-17 07:38:47 +0100245 // Find the widest API stubs provided by the fragments on which this depends, if any.
246 var dependencyStubDexJars android.Paths
Paul Duffin31fad802021-06-18 18:14:25 +0100247 for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
248 apiScope := hiddenAPIScopes[i]
249 stubsForAPIScope := input.DependencyStubDexJarsByScope[apiScope]
250 if len(stubsForAPIScope) != 0 {
251 dependencyStubDexJars = stubsForAPIScope
Paul Duffinf1b358c2021-05-17 07:38:47 +0100252 break
253 }
254 }
255
Paul Duffin74431d52021-04-21 14:10:42 +0100256 command := rule.Command().
257 Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
258 Text("list").
Paul Duffinf1b358c2021-05-17 07:38:47 +0100259 FlagForEachInput("--dependency-stub-dex=", dependencyStubDexJars).
Paul Duffin74431d52021-04-21 14:10:42 +0100260 FlagForEachInput("--boot-dex=", bootDexJars)
261
Paul Duffin31fad802021-06-18 18:14:25 +0100262 // Iterate over the api scopes in a fixed order.
263 for _, apiScope := range hiddenAPIFlagScopes {
264 // Merge in the stub dex jar paths for this api scope from the fragments on which it depends.
265 // They will be needed to resolve dependencies from this fragment's stubs to classes in the
266 // other fragment's APIs.
267 var paths android.Paths
268 paths = append(paths, input.DependencyStubDexJarsByScope[apiScope]...)
269 paths = append(paths, input.StubDexJarsByScope[apiScope]...)
Paul Duffin74431d52021-04-21 14:10:42 +0100270 if len(paths) > 0 {
Paul Duffin31fad802021-06-18 18:14:25 +0100271 option := apiScope.hiddenAPIListOption
272 command.FlagWithInputList(option+"=", paths, ":")
Paul Duffin74431d52021-04-21 14:10:42 +0100273 }
274 }
275
276 // Add the output path.
277 command.FlagWithOutput("--out-api-flags=", tempPath)
278
279 commitChangeForRestat(rule, tempPath, outputPath)
280 return rule
281}
282
Paul Duffin46169772021-04-14 15:01:56 +0100283// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
284// information obtained from annotations within the source code in order to create the complete set
285// of flags that should be applied to the dex implementation jars on the bootclasspath.
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100286//
287// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
288// of each property reference a plain text file that contains a java signature per line. The flags
289// for each of those signatures will be updated in a property specific way.
290//
291// The Unsupported_packages property contains a list of paths, each of which is a plain text file
292// with one Java package per line. All members of all classes within that package (but not nested
293// packages) will be updated in a property specific way.
Paul Duffin46169772021-04-14 15:01:56 +0100294type HiddenAPIFlagFileProperties struct {
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100295 // Marks each signature in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100296 Unsupported []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100297
298 // Marks each signature in the referenced files as being unsupported because it has been removed.
299 // Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100300 Removed []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100301
302 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= R
303 // and low priority.
Paul Duffin702210b2021-04-08 20:12:41 +0100304 Max_target_r_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100305
306 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= Q.
Paul Duffin702210b2021-04-08 20:12:41 +0100307 Max_target_q []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100308
309 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= P.
Paul Duffin702210b2021-04-08 20:12:41 +0100310 Max_target_p []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100311
312 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= O
313 // and low priority. Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100314 Max_target_o_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100315
316 // Marks each signature in the referenced files as being blocked.
Paul Duffin702210b2021-04-08 20:12:41 +0100317 Blocked []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100318
319 // Marks each signature in every package in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100320 Unsupported_packages []string `android:"path"`
321}
322
Paul Duffine3dc6602021-04-14 09:50:43 +0100323type hiddenAPIFlagFileCategory struct {
Paul Duffin524c82c2021-06-09 14:39:28 +0100324 // PropertyName is the name of the property for this category.
325 PropertyName string
Paul Duffine3dc6602021-04-14 09:50:43 +0100326
Paul Duffincc17bfe2021-04-19 13:21:20 +0100327 // propertyValueReader retrieves the value of the property for this category from the set of
Paul Duffine3dc6602021-04-14 09:50:43 +0100328 // properties.
Paul Duffincc17bfe2021-04-19 13:21:20 +0100329 propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
Paul Duffine3dc6602021-04-14 09:50:43 +0100330
331 // commandMutator adds the appropriate command line options for this category to the supplied
332 // command
333 commandMutator func(command *android.RuleBuilderCommand, path android.Path)
334}
335
Paul Duffin32cf58a2021-05-18 16:32:50 +0100336// The flag file category for removed members of the API.
337//
Paul Duffin524c82c2021-06-09 14:39:28 +0100338// This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
Paul Duffin32cf58a2021-05-18 16:32:50 +0100339// list of removed API members that are generated automatically from the removed.txt files provided
340// by API stubs.
341var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{
342 // See HiddenAPIFlagFileProperties.Removed
Paul Duffin524c82c2021-06-09 14:39:28 +0100343 PropertyName: "removed",
Paul Duffin32cf58a2021-05-18 16:32:50 +0100344 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
345 return properties.Removed
346 },
347 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
348 command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
349 },
350}
351
Paul Duffin524c82c2021-06-09 14:39:28 +0100352var HiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
Paul Duffin46169772021-04-14 15:01:56 +0100353 // See HiddenAPIFlagFileProperties.Unsupported
Paul Duffine3dc6602021-04-14 09:50:43 +0100354 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100355 PropertyName: "unsupported",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100356 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100357 return properties.Unsupported
358 },
359 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
360 command.FlagWithInput("--unsupported ", path)
361 },
362 },
Paul Duffin32cf58a2021-05-18 16:32:50 +0100363 hiddenAPIRemovedFlagFileCategory,
Paul Duffin46169772021-04-14 15:01:56 +0100364 // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100365 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100366 PropertyName: "max_target_r_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100367 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100368 return properties.Max_target_r_low_priority
369 },
370 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
371 command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
372 },
373 },
Paul Duffin46169772021-04-14 15:01:56 +0100374 // See HiddenAPIFlagFileProperties.Max_target_q
Paul Duffine3dc6602021-04-14 09:50:43 +0100375 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100376 PropertyName: "max_target_q",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100377 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100378 return properties.Max_target_q
379 },
380 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
381 command.FlagWithInput("--max-target-q ", path)
382 },
383 },
Paul Duffin46169772021-04-14 15:01:56 +0100384 // See HiddenAPIFlagFileProperties.Max_target_p
Paul Duffine3dc6602021-04-14 09:50:43 +0100385 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100386 PropertyName: "max_target_p",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100387 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100388 return properties.Max_target_p
389 },
390 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
391 command.FlagWithInput("--max-target-p ", path)
392 },
393 },
Paul Duffin46169772021-04-14 15:01:56 +0100394 // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100395 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100396 PropertyName: "max_target_o_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100397 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100398 return properties.Max_target_o_low_priority
399 },
400 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
401 command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
402 },
403 },
Paul Duffin46169772021-04-14 15:01:56 +0100404 // See HiddenAPIFlagFileProperties.Blocked
Paul Duffine3dc6602021-04-14 09:50:43 +0100405 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100406 PropertyName: "blocked",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100407 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100408 return properties.Blocked
409 },
410 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
411 command.FlagWithInput("--blocked ", path)
412 },
413 },
Paul Duffin46169772021-04-14 15:01:56 +0100414 // See HiddenAPIFlagFileProperties.Unsupported_packages
Paul Duffine3dc6602021-04-14 09:50:43 +0100415 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100416 PropertyName: "unsupported_packages",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100417 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100418 return properties.Unsupported_packages
419 },
420 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
421 command.FlagWithInput("--unsupported ", path).Flag("--packages ")
422 },
423 },
Paul Duffin702210b2021-04-08 20:12:41 +0100424}
425
Paul Duffin438eb572021-05-21 16:58:23 +0100426// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
427type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths
428
429// append appends the supplied flags files to the corresponding category in this map.
430func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
Paul Duffin524c82c2021-06-09 14:39:28 +0100431 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +0100432 s[category] = append(s[category], other[category]...)
433 }
434}
435
436// dedup removes duplicates in the flag files, while maintaining the order in which they were
437// appended.
438func (s FlagFilesByCategory) dedup() {
439 for category, paths := range s {
440 s[category] = android.FirstUniquePaths(paths)
441 }
442}
443
Paul Duffinaf99afa2021-05-21 22:18:56 +0100444// HiddenAPIInfo contains information provided by the hidden API processing.
Paul Duffin2fef1362021-04-15 13:32:00 +0100445//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100446// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
447// processing.
448type HiddenAPIInfo struct {
Paul Duffin438eb572021-05-21 16:58:23 +0100449 // FlagFilesByCategory maps from the flag file category to the paths containing information for
450 // that category.
451 FlagFilesByCategory FlagFilesByCategory
Paul Duffin2fef1362021-04-15 13:32:00 +0100452
Paul Duffin31fad802021-06-18 18:14:25 +0100453 // The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes.
454 TransitiveStubDexJarsByScope StubDexJarsByScope
Paul Duffin18cf1972021-05-21 22:46:59 +0100455
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100456 // The output from the hidden API processing needs to be made available to other modules.
457 HiddenAPIFlagOutput
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100458}
Paul Duffin702210b2021-04-08 20:12:41 +0100459
Paul Duffinf1b358c2021-05-17 07:38:47 +0100460func newHiddenAPIInfo() *HiddenAPIInfo {
461 info := HiddenAPIInfo{
Paul Duffin31fad802021-06-18 18:14:25 +0100462 FlagFilesByCategory: FlagFilesByCategory{},
463 TransitiveStubDexJarsByScope: StubDexJarsByScope{},
Paul Duffinf1b358c2021-05-17 07:38:47 +0100464 }
465 return &info
466}
467
468func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragments []android.Module) {
469 // Merge all the information from the fragments. The fragments form a DAG so it is possible that
470 // this will introduce duplicates so they will be resolved after processing all the fragments.
471 for _, fragment := range fragments {
472 if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
473 info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
Paul Duffin31fad802021-06-18 18:14:25 +0100474 i.TransitiveStubDexJarsByScope.append(info.TransitiveStubDexJarsByScope)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100475 }
476 }
477
478 // Dedup and sort paths.
Paul Duffin31fad802021-06-18 18:14:25 +0100479 i.TransitiveStubDexJarsByScope.dedupAndSort()
Paul Duffinf1b358c2021-05-17 07:38:47 +0100480}
481
Paul Duffinaf99afa2021-05-21 22:18:56 +0100482var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
Paul Duffin9b381ef2021-04-08 23:01:37 +0100483
Paul Duffin31fad802021-06-18 18:14:25 +0100484// StubDexJarsByScope maps a *HiddenAPIScope to the paths to stub dex jars appropriate for that
485// scope. See hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
486type StubDexJarsByScope map[*HiddenAPIScope]android.Paths
Paul Duffin1352f7c2021-05-21 22:18:49 +0100487
Paul Duffin31fad802021-06-18 18:14:25 +0100488// append appends the API scope specific stub dex jar args to the corresponding scope in this
Paul Duffin1352f7c2021-05-21 22:18:49 +0100489// map.
Paul Duffin31fad802021-06-18 18:14:25 +0100490func (s StubDexJarsByScope) append(other StubDexJarsByScope) {
491 for _, scope := range hiddenAPIScopes {
492 s[scope] = append(s[scope], other[scope]...)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100493 }
494}
495
496// dedupAndSort removes duplicates in the stub dex jar paths and sorts them into a consistent and
497// deterministic order.
Paul Duffin31fad802021-06-18 18:14:25 +0100498func (s StubDexJarsByScope) dedupAndSort() {
499 for apiScope, paths := range s {
500 s[apiScope] = android.SortedUniquePaths(paths)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100501 }
502}
503
504// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
505// needed for hidden API flag generation.
506type HiddenAPIFlagInput struct {
507 // FlagFilesByCategory contains the flag files that override the initial flags that are derived
508 // from the stub dex files.
509 FlagFilesByCategory FlagFilesByCategory
510
Paul Duffin31fad802021-06-18 18:14:25 +0100511 // StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
Paul Duffin1352f7c2021-05-21 22:18:49 +0100512 // the initial flags for each dex member.
Paul Duffin31fad802021-06-18 18:14:25 +0100513 StubDexJarsByScope StubDexJarsByScope
Paul Duffinf1b358c2021-05-17 07:38:47 +0100514
Paul Duffin31fad802021-06-18 18:14:25 +0100515 // DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
516 // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
Paul Duffinf1b358c2021-05-17 07:38:47 +0100517 // fragment on which this depends.
Paul Duffin31fad802021-06-18 18:14:25 +0100518 DependencyStubDexJarsByScope StubDexJarsByScope
Paul Duffin32cf58a2021-05-18 16:32:50 +0100519
520 // RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
521 // specified in the bootclasspath_fragment's stub_libs and contents properties.
522 RemovedTxtFiles android.Paths
Paul Duffin1352f7c2021-05-21 22:18:49 +0100523}
524
525// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
526func newHiddenAPIFlagInput() HiddenAPIFlagInput {
527 input := HiddenAPIFlagInput{
Paul Duffin31fad802021-06-18 18:14:25 +0100528 FlagFilesByCategory: FlagFilesByCategory{},
529 StubDexJarsByScope: StubDexJarsByScope{},
530 DependencyStubDexJarsByScope: StubDexJarsByScope{},
Paul Duffin1352f7c2021-05-21 22:18:49 +0100531 }
532
533 return input
534}
535
Paul Duffin62370922021-05-23 16:55:37 +0100536// canPerformHiddenAPIProcessing determines whether hidden API processing should be performed.
537//
538// A temporary workaround to avoid existing bootclasspath_fragments that do not provide the
539// appropriate information needed for hidden API processing breaking the build.
540// TODO(b/179354495): Remove this workaround.
541func (i *HiddenAPIFlagInput) canPerformHiddenAPIProcessing(ctx android.ModuleContext, properties bootclasspathFragmentProperties) bool {
542 // Performing hidden API processing without stubs is not supported and it is unlikely to ever be
543 // required as the whole point of adding something to the bootclasspath fragment is to add it to
544 // the bootclasspath in order to be used by something else in the system. Without any stubs it
545 // cannot do that.
Paul Duffin31fad802021-06-18 18:14:25 +0100546 if len(i.StubDexJarsByScope) == 0 {
Paul Duffin62370922021-05-23 16:55:37 +0100547 return false
548 }
549
550 // Hidden API processing is always enabled in tests.
551 if ctx.Config().TestProductVariables != nil {
552 return true
553 }
554
555 // A module that has fragments should have access to the information it needs in order to perform
556 // hidden API processing.
557 if len(properties.Fragments) != 0 {
558 return true
559 }
560
561 // The art bootclasspath fragment does not depend on any other fragments but already supports
562 // hidden API processing.
563 imageName := proptools.String(properties.Image_name)
564 if imageName == "art" {
565 return true
566 }
567
568 // Disable it for everything else.
569 return false
570}
571
Paul Duffin1352f7c2021-05-21 22:18:49 +0100572// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
573// dependencies added in hiddenAPIAddStubLibDependencies.
574//
575// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
576func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
Paul Duffin31fad802021-06-18 18:14:25 +0100577 addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
578 sdkKind := apiScope.sdkKind
579 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100580 if dexJar != nil {
Paul Duffin31fad802021-06-18 18:14:25 +0100581 i.StubDexJarsByScope[apiScope] = append(i.StubDexJarsByScope[apiScope], dexJar)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100582 }
Paul Duffin32cf58a2021-05-18 16:32:50 +0100583
584 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100585 removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
Paul Duffin32cf58a2021-05-18 16:32:50 +0100586 i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
587 }
Paul Duffin1352f7c2021-05-21 22:18:49 +0100588 }
589
590 // If the contents includes any java_sdk_library modules then add them to the stubs.
591 for _, module := range contents {
592 if _, ok := module.(SdkLibraryDependency); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100593 // Add information for every possible API scope needed by hidden API.
594 for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
595 addFromModule(ctx, module, apiScope)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100596 }
597 }
598 }
599
Paul Duffind061d402021-06-07 21:36:01 +0100600 ctx.VisitDirectDeps(func(module android.Module) {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100601 tag := ctx.OtherModuleDependencyTag(module)
602 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100603 apiScope := hiddenAPIStubsTag.apiScope
604 addFromModule(ctx, module, apiScope)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100605 }
606 })
607
608 // Normalize the paths, i.e. remove duplicates and sort.
Paul Duffin31fad802021-06-18 18:14:25 +0100609 i.StubDexJarsByScope.dedupAndSort()
610 i.DependencyStubDexJarsByScope.dedupAndSort()
Paul Duffin32cf58a2021-05-18 16:32:50 +0100611 i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100612}
613
614// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
615// supplied properties and stores them in this struct.
616func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
Paul Duffin524c82c2021-06-09 14:39:28 +0100617 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100618 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
619 i.FlagFilesByCategory[category] = paths
620 }
621}
622
Paul Duffin31fad802021-06-18 18:14:25 +0100623func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByScope {
624 transitive := i.DependencyStubDexJarsByScope
625 transitive.append(i.StubDexJarsByScope)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100626 return transitive
627}
628
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100629// HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
630// bootclasspath_fragment module.
631type HiddenAPIFlagOutput struct {
632 // The path to the generated stub-flags.csv file.
633 StubFlagsPath android.Path
634
635 // The path to the generated annotation-flags.csv file.
636 AnnotationFlagsPath android.Path
637
638 // The path to the generated metadata.csv file.
639 MetadataPath android.Path
640
641 // The path to the generated index.csv file.
642 IndexPath android.Path
643
644 // The path to the generated all-flags.csv file.
645 AllFlagsPath android.Path
646}
647
Paul Duffin5f148ca2021-06-02 17:24:22 +0100648// bootDexJarByModule is a map from base module name (without prebuilt_ prefix) to the boot dex
649// path.
650type bootDexJarByModule map[string]android.Path
651
652// addPath adds the path for a module to the map.
653func (b bootDexJarByModule) addPath(module android.Module, path android.Path) {
654 b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path
655}
656
Paul Duffine5218812021-06-07 13:28:19 +0100657// bootDexJars returns the boot dex jar paths sorted by their keys.
658func (b bootDexJarByModule) bootDexJars() android.Paths {
659 paths := android.Paths{}
660 for _, k := range android.SortedStringKeys(b) {
661 paths = append(paths, b[k])
662 }
663 return paths
664}
665
Paul Duffin7f872162021-06-17 19:33:24 +0100666// bootDexJarsWithoutCoverage returns the boot dex jar paths sorted by their keys without coverage
667// libraries if present.
668func (b bootDexJarByModule) bootDexJarsWithoutCoverage() android.Paths {
669 paths := android.Paths{}
670 for _, k := range android.SortedStringKeys(b) {
671 if k == "jacocoagent" {
672 continue
673 }
674 paths = append(paths, b[k])
675 }
676 return paths
677}
678
Paul Duffine5218812021-06-07 13:28:19 +0100679// HiddenAPIOutput encapsulates the output from the hidden API processing.
680type HiddenAPIOutput struct {
681 HiddenAPIFlagOutput
682
683 // The map from base module name to the path to the encoded boot dex file.
684 EncodedBootDexFilesByModule bootDexJarByModule
685}
686
Paul Duffindfa10832021-05-13 17:31:51 +0100687// pathForValidation creates a path of the same type as the supplied type but with a name of
688// <path>.valid.
689//
690// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
691// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
692func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
693 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
694 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
695}
696
Paul Duffin2fef1362021-04-15 13:32:00 +0100697// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
698// the flags from all the modules, the stub flags, augmented with some additional configuration
699// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100700//
701// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
702// an entry for every single member in the dex implementation jars of the individual modules. Every
703// signature in any of the other files MUST be included in this file.
704//
Paul Duffin537ea3d2021-05-14 10:38:00 +0100705// annotationFlags is the path to the annotation flags file generated from annotation information
706// in each module.
Paul Duffin702210b2021-04-08 20:12:41 +0100707//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100708// hiddenAPIInfo is a struct containing paths to files that augment the information provided by
Paul Duffin537ea3d2021-05-14 10:38:00 +0100709// the annotationFlags.
Paul Duffin32cf58a2021-05-18 16:32:50 +0100710func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string,
Paul Duffind061d402021-06-07 21:36:01 +0100711 outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
Paul Duffin32cf58a2021-05-18 16:32:50 +0100712 flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths, generatedRemovedDexSignatures android.OptionalPath) {
Paul Duffindfa10832021-05-13 17:31:51 +0100713
714 // The file which is used to record that the flags file is valid.
715 var validFile android.WritablePath
716
717 // If there are flag files that have been generated by fragments on which this depends then use
718 // them to validate the flag file generated by the rules created by this method.
Paul Duffin438eb572021-05-21 16:58:23 +0100719 if len(allFlagsPaths) > 0 {
Paul Duffindfa10832021-05-13 17:31:51 +0100720 // The flags file generated by the rule created by this method needs to be validated to ensure
721 // that it is consistent with the flag files generated by the individual fragments.
722
723 validFile = pathForValidation(ctx, outputPath)
724
725 // Create a rule to validate the output from the following rule.
726 rule := android.NewRuleBuilder(pctx, ctx)
727 rule.Command().
728 BuiltTool("verify_overlaps").
729 Input(outputPath).
730 Inputs(allFlagsPaths).
731 // If validation passes then update the file that records that.
732 Text("&& touch").Output(validFile)
733 rule.Build(name+"Validation", desc+" validation")
734 }
735
736 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100737 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100738 rule := android.NewRuleBuilder(pctx, ctx)
739 command := rule.Command().
740 BuiltTool("generate_hiddenapi_lists").
741 FlagWithInput("--csv ", baseFlagsPath).
Paul Duffind061d402021-06-07 21:36:01 +0100742 Inputs(annotationFlagPaths).
Paul Duffin702210b2021-04-08 20:12:41 +0100743 FlagWithOutput("--output ", tempPath)
744
Paul Duffine3dc6602021-04-14 09:50:43 +0100745 // Add the options for the different categories of flag files.
Paul Duffin524c82c2021-06-09 14:39:28 +0100746 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +0100747 paths := flagFilesByCategory[category]
Paul Duffine3dc6602021-04-14 09:50:43 +0100748 for _, path := range paths {
749 category.commandMutator(command, path)
750 }
Paul Duffin702210b2021-04-08 20:12:41 +0100751 }
752
Paul Duffin32cf58a2021-05-18 16:32:50 +0100753 // If available then pass the automatically generated file containing dex signatures of removed
754 // API members to the rule so they can be marked as removed.
755 if generatedRemovedDexSignatures.Valid() {
756 hiddenAPIRemovedFlagFileCategory.commandMutator(command, generatedRemovedDexSignatures.Path())
757 }
758
Paul Duffin702210b2021-04-08 20:12:41 +0100759 commitChangeForRestat(rule, tempPath, outputPath)
760
Paul Duffindfa10832021-05-13 17:31:51 +0100761 if validFile != nil {
762 // Add the file that indicates that the file generated by this is valid.
763 //
764 // This will cause the validation rule above to be run any time that the output of this rule
765 // changes but the validation will run in parallel with other rules that depend on this file.
766 command.Validation(validFile)
767 }
768
Paul Duffin2fef1362021-04-15 13:32:00 +0100769 rule.Build(name, desc)
770}
771
Paul Duffine5218812021-06-07 13:28:19 +0100772// hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the
773// bootclasspath and then encode the flags into the boot dex files.
Paul Duffin2fef1362021-04-15 13:32:00 +0100774//
775// It takes:
776// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
777// * The list of modules that are the contents of the fragment.
778// * The additional manually curated flag files to use.
779//
780// It generates:
781// * stub-flags.csv
782// * annotation-flags.csv
783// * metadata.csv
784// * index.csv
785// * all-flags.csv
Paul Duffine5218812021-06-07 13:28:19 +0100786// * encoded boot dex files
787func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
Paul Duffin2fef1362021-04-15 13:32:00 +0100788 hiddenApiSubDir := "modular-hiddenapi"
789
Paul Duffine5218812021-06-07 13:28:19 +0100790 // Gather information about the boot dex files for the boot libraries provided by this fragment.
791 bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100792
793 // Generate the stub-flags.csv.
Paul Duffin2fef1362021-04-15 13:32:00 +0100794 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
Paul Duffine5218812021-06-07 13:28:19 +0100795 rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input)
Paul Duffin2fef1362021-04-15 13:32:00 +0100796 rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
797
Paul Duffin537ea3d2021-05-14 10:38:00 +0100798 // Extract the classes jars from the contents.
Paul Duffindd5993f2021-06-10 10:18:22 +0100799 classesJars := extractClassesJarsFromModules(contents)
Paul Duffin537ea3d2021-05-14 10:38:00 +0100800
Paul Duffin2fef1362021-04-15 13:32:00 +0100801 // Generate the set of flags from the annotations in the source code.
802 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100803 buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100804
805 // Generate the metadata from the annotations in the source code.
806 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100807 buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100808
Paul Duffin537ea3d2021-05-14 10:38:00 +0100809 // Generate the index file from the CSV files in the classes jars.
Paul Duffin2fef1362021-04-15 13:32:00 +0100810 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100811 buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100812
Paul Duffinaf99afa2021-05-21 22:18:56 +0100813 // 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 +0100814 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
815 // manually combining all the removed.txt files for each API and then converting them to dex
Paul Duffin32cf58a2021-05-18 16:32:50 +0100816 // signatures, see the combined-removed-dex module. This does that automatically by using the
817 // *removed.txt files retrieved from the java_sdk_library modules that are specified in the
818 // stub_libs and contents properties of a bootclasspath_fragment.
819 removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, input.RemovedTxtFiles)
Paul Duffin2fef1362021-04-15 13:32:00 +0100820
821 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
822 // files.
Paul Duffine5218812021-06-07 13:28:19 +0100823 allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
Paul Duffind061d402021-06-07 21:36:01 +0100824 buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
Paul Duffine5218812021-06-07 13:28:19 +0100825
826 // Encode the flags into the boot dex files.
827 encodedBootDexJarsByModule := map[string]android.Path{}
828 outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath
829 for _, name := range android.SortedStringKeys(bootDexInfoByModule) {
830 bootDexInfo := bootDexInfoByModule[name]
831 unencodedDex := bootDexInfo.path
832 encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, outputDir)
833 encodedBootDexJarsByModule[name] = encodedDex
834 }
Paul Duffin2fef1362021-04-15 13:32:00 +0100835
836 // Store the paths in the info for use by other modules and sdk snapshot generation.
Paul Duffine5218812021-06-07 13:28:19 +0100837 output := HiddenAPIOutput{
838 HiddenAPIFlagOutput: HiddenAPIFlagOutput{
839 StubFlagsPath: stubFlagsCSV,
840 AnnotationFlagsPath: annotationFlagsCSV,
841 MetadataPath: metadataCSV,
842 IndexPath: indexCSV,
843 AllFlagsPath: allFlagsCSV,
844 },
845 EncodedBootDexFilesByModule: encodedBootDexJarsByModule,
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100846 }
847 return &output
Paul Duffin702210b2021-04-08 20:12:41 +0100848}
Paul Duffin537ea3d2021-05-14 10:38:00 +0100849
Paul Duffin32cf58a2021-05-18 16:32:50 +0100850func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedTxtFiles android.Paths) android.OptionalPath {
851 if len(removedTxtFiles) == 0 {
852 return android.OptionalPath{}
853 }
854
855 output := android.PathForModuleOut(ctx, "modular-hiddenapi/removed-dex-signatures.txt")
856
857 rule := android.NewRuleBuilder(pctx, ctx)
858 rule.Command().
859 BuiltTool("metalava").
860 Flag("--no-banner").
861 Inputs(removedTxtFiles).
862 FlagWithOutput("--dex-api ", output)
863 rule.Build("modular-hiddenapi-removed-dex-signatures", "modular hiddenapi removed dex signatures")
864 return android.OptionalPathForPath(output)
865}
866
Paul Duffindd5993f2021-06-10 10:18:22 +0100867// extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules.
Paul Duffine5218812021-06-07 13:28:19 +0100868func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
869 bootDexJars := bootDexJarByModule{}
Paul Duffin537ea3d2021-05-14 10:38:00 +0100870 for _, module := range contents {
Paul Duffindd5993f2021-06-10 10:18:22 +0100871 hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
872 if hiddenAPIModule == nil {
873 continue
874 }
Paul Duffine5218812021-06-07 13:28:19 +0100875 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
876 bootDexJars.addPath(module, bootDexJar)
Paul Duffin537ea3d2021-05-14 10:38:00 +0100877 }
878 return bootDexJars
879}
880
Paul Duffindd5993f2021-06-10 10:18:22 +0100881func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Module) hiddenAPIModule {
882 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
883 return hiddenAPIModule
884 } else if _, ok := module.(*DexImport); ok {
885 // Ignore this for the purposes of hidden API processing
886 } else {
887 ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
888 }
889
890 return nil
891}
892
Paul Duffine5218812021-06-07 13:28:19 +0100893// bootDexInfo encapsulates both the path and uncompressDex status retrieved from a hiddenAPIModule.
894type bootDexInfo struct {
895 // The path to the dex jar that has not had hidden API flags encoded into it.
896 path android.Path
897
898 // Indicates whether the dex jar needs uncompressing before encoding.
899 uncompressDex bool
900}
901
902// bootDexInfoByModule is a map from module name (as returned by module.Name()) to the boot dex
903// path (as returned by hiddenAPIModule.bootDexJar()) and the uncompressDex flag.
904type bootDexInfoByModule map[string]bootDexInfo
905
906// bootDexJars returns the boot dex jar paths sorted by their keys.
907func (b bootDexInfoByModule) bootDexJars() android.Paths {
908 paths := android.Paths{}
909 for _, m := range android.SortedStringKeys(b) {
910 paths = append(paths, b[m].path)
911 }
912 return paths
913}
914
915// extractBootDexInfoFromModules extracts the boot dex jar and uncompress dex state from
916// each of the supplied modules which must implement hiddenAPIModule.
917func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android.Module) bootDexInfoByModule {
918 bootDexJarsByModule := bootDexInfoByModule{}
919 for _, module := range contents {
920 hiddenAPIModule := module.(hiddenAPIModule)
921 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
922 bootDexJarsByModule[module.Name()] = bootDexInfo{
923 path: bootDexJar,
924 uncompressDex: *hiddenAPIModule.uncompressDex(),
925 }
926 }
927
928 return bootDexJarsByModule
929}
930
931// retrieveBootDexJarFromHiddenAPIModule retrieves the boot dex jar from the hiddenAPIModule.
932//
933// If the module does not provide a boot dex jar, i.e. the returned boot dex jar is nil, then that
934// create a fake path and either report an error immediately or defer reporting of the error until
935// the path is actually used.
936func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
937 bootDexJar := module.bootDexJar()
938 if bootDexJar == nil {
939 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
940 bootDexJar = fake
941
942 handleMissingDexBootFile(ctx, module, fake)
943 }
944 return bootDexJar
945}
946
Paul Duffindd5993f2021-06-10 10:18:22 +0100947// extractClassesJarsFromModules extracts the class jars from the supplied modules.
948func extractClassesJarsFromModules(contents []android.Module) android.Paths {
Paul Duffin537ea3d2021-05-14 10:38:00 +0100949 classesJars := android.Paths{}
950 for _, module := range contents {
Paul Duffindd5993f2021-06-10 10:18:22 +0100951 classesJars = append(classesJars, retrieveClassesJarsFromModule(module)...)
Paul Duffin537ea3d2021-05-14 10:38:00 +0100952 }
953 return classesJars
954}
Paul Duffin5f148ca2021-06-02 17:24:22 +0100955
Paul Duffindd5993f2021-06-10 10:18:22 +0100956// retrieveClassesJarsFromModule retrieves the classes jars from the supplied module.
957func retrieveClassesJarsFromModule(module android.Module) android.Paths {
958 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
959 return hiddenAPIModule.classesJars()
960 }
961
962 return nil
963}
964
Paul Duffin5f148ca2021-06-02 17:24:22 +0100965// deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
966// Soong but should instead only be reported in ninja if the file is actually built.
967func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
968 // TODO(b/179354495): Remove this workaround when it is unnecessary.
969 // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
970 // create a fake one that will cause a build error only if it is used.
971 if ctx.Config().AlwaysUsePrebuiltSdks() {
972 return true
973 }
974
Paul Duffine5218812021-06-07 13:28:19 +0100975 // Any missing dependency should be allowed.
976 if ctx.Config().AllowMissingDependencies() {
977 return true
978 }
979
Paul Duffin5f148ca2021-06-02 17:24:22 +0100980 // This is called for both platform_bootclasspath and bootclasspath_fragment modules.
981 //
982 // A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
983 // Ideally, a bootclasspath_fragment module should never have a platform variant created for it
984 // but unfortunately, due to b/187910671 it does.
985 //
986 // That causes issues when obtaining a boot dex jar for a prebuilt module as a prebuilt module
987 // used by a bootclasspath_fragment can only provide a boot dex jar when it is part of APEX, i.e.
988 // has an APEX variant not a platform variant.
989 //
990 // There are some other situations when a prebuilt module used by a bootclasspath_fragment cannot
991 // provide a boot dex jar:
992 // 1. If the bootclasspath_fragment is not exported by the prebuilt_apex/apex_set module then it
993 // does not have an APEX variant and only has a platform variant and neither do its content
994 // modules.
995 // 2. Some build configurations, e.g. setting TARGET_BUILD_USE_PREBUILT_SDKS causes all
996 // java_sdk_library_import modules to be treated as preferred and as many of them are not part
997 // of an apex they cannot provide a boot dex jar.
998 //
999 // The first case causes problems when the affected prebuilt modules are preferred but that is an
1000 // invalid configuration and it is ok for it to fail as the work to enable that is not yet
1001 // complete. The second case is used for building targets that do not use boot dex jars and so
1002 // deferring error reporting to ninja is fine as the affected ninja targets should never be built.
1003 // That is handled above.
1004 //
1005 // A platform_bootclasspath module can use libraries from both platform and APEX variants. Unlike
1006 // the bootclasspath_fragment it supports dex_import modules which provides the dex file. So, it
1007 // can obtain a boot dex jar from a prebuilt that is not part of an APEX. However, it is assumed
1008 // that if the library can be part of an APEX then it is the APEX variant that is used.
1009 //
1010 // This check handles the slightly different requirements of the bootclasspath_fragment and
1011 // platform_bootclasspath modules by only deferring error reporting for the platform variant of
1012 // a prebuilt modules that has other variants which are part of an APEX.
1013 //
1014 // TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
1015 if android.IsModulePrebuilt(module) {
1016 if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
1017 apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
1018 if apexInfo.IsForPlatform() {
1019 return true
1020 }
1021 }
1022 }
1023
1024 // A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there
1025 // is no equivalently versioned prebuilt APEX file from which it can be obtained. However,
1026 // versioned bootclasspath modules are processed by Soong so in order to avoid them causing build
1027 // failures missing boot dex jars need to be deferred.
1028 if android.IsModuleInVersionedSdk(ctx.Module()) {
1029 return true
1030 }
1031
1032 return false
1033}
1034
1035// handleMissingDexBootFile will either log a warning or create an error rule to create the fake
1036// file depending on the value returned from deferReportingMissingBootDexJar.
1037func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath) {
1038 if deferReportingMissingBootDexJar(ctx, module) {
1039 // Create an error rule that pretends to create the output file but will actually fail if it
1040 // is run.
1041 ctx.Build(pctx, android.BuildParams{
1042 Rule: android.ErrorRule,
1043 Output: fake,
1044 Args: map[string]string{
1045 "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
1046 },
1047 })
1048 } else {
1049 ctx.ModuleErrorf("module %s does not provide a dex jar", module)
1050 }
1051}
1052
1053// retrieveEncodedBootDexJarFromModule returns a path to the boot dex jar from the supplied module's
1054// DexJarBuildPath() method.
1055//
1056// The returned path will usually be to a dex jar file that has been encoded with hidden API flags.
1057// However, under certain conditions, e.g. errors, or special build configurations it will return
1058// a path to a fake file.
1059func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
1060 bootDexJar := module.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath()
1061 if bootDexJar == nil {
1062 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
1063 bootDexJar = fake
1064
1065 handleMissingDexBootFile(ctx, module, fake)
1066 }
1067 return bootDexJar
1068}
1069
1070// extractEncodedDexJarsFromModules extracts the encoded dex jars from the supplied modules.
1071func extractEncodedDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
1072 encodedDexJarsByModuleName := bootDexJarByModule{}
1073 for _, module := range contents {
1074 path := retrieveEncodedBootDexJarFromModule(ctx, module)
1075 encodedDexJarsByModuleName.addPath(module, path)
1076 }
1077 return encodedDexJarsByModuleName
1078}