blob: 86ab8253e82ee264d5b8635274eb267e510754fe [file] [log] [blame]
Paul Duffinc6bb7cf2021-04-08 17:49:27 +01001// Copyright (C) 2021 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
Paul Duffin7487a7a2021-05-19 09:36:09 +010018 "fmt"
Paul Duffindfa10832021-05-13 17:31:51 +010019 "strings"
20
Paul Duffinc6bb7cf2021-04-08 17:49:27 +010021 "android/soong/android"
Paul Duffin9b381ef2021-04-08 23:01:37 +010022 "github.com/google/blueprint"
Paul Duffinc6bb7cf2021-04-08 17:49:27 +010023)
24
25// Contains support for processing hiddenAPI in a modular fashion.
26
Paul Duffin31fad802021-06-18 18:14:25 +010027// HiddenAPIScope encapsulates all the information that the hidden API processing needs about API
28// scopes, i.e. what is called android.SdkKind and apiScope. It does not just use those as they do
29// not provide the information needed by hidden API processing.
30type HiddenAPIScope struct {
31 // The name of the scope, used for debug purposes.
32 name string
33
34 // The corresponding android.SdkKind, used for retrieving paths from java_sdk_library* modules.
35 sdkKind android.SdkKind
36
37 // The option needed to passed to "hiddenapi list".
38 hiddenAPIListOption string
Paul Duffin5cca7c42021-05-26 10:16:01 +010039
40 // The name sof the source stub library modules that contain the API provided by the platform,
41 // i.e. by modules that are not in an APEX.
42 nonUpdatableSourceModule string
43
44 // The names of the prebuilt stub library modules that contain the API provided by the platform,
45 // i.e. by modules that are not in an APEX.
46 nonUpdatablePrebuiltModule string
Paul Duffin31fad802021-06-18 18:14:25 +010047}
48
49// initHiddenAPIScope initializes the scope.
50func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
Paul Duffin5cca7c42021-05-26 10:16:01 +010051 sdkKind := apiScope.sdkKind
52 // The platform does not provide a core platform API.
53 if sdkKind != android.SdkCorePlatform {
54 kindAsString := sdkKind.String()
55 var insert string
56 if sdkKind == android.SdkPublic {
57 insert = ""
58 } else {
59 insert = "." + strings.ReplaceAll(kindAsString, "-", "_")
60 }
61
62 nonUpdatableModule := "android-non-updatable"
63
64 // Construct the name of the android-non-updatable source module for this scope.
65 apiScope.nonUpdatableSourceModule = fmt.Sprintf("%s.stubs%s", nonUpdatableModule, insert)
66
67 prebuiltModuleName := func(name string, kind string) string {
68 return fmt.Sprintf("sdk_%s_current_%s", kind, name)
69 }
70
71 // Construct the name of the android-non-updatable prebuilt module for this scope.
72 apiScope.nonUpdatablePrebuiltModule = prebuiltModuleName(nonUpdatableModule, kindAsString)
73 }
74
Paul Duffin31fad802021-06-18 18:14:25 +010075 return apiScope
76}
77
Paul Duffin5cca7c42021-05-26 10:16:01 +010078// android-non-updatable takes the name of a module and returns a possibly scope specific name of
79// the module.
80func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, name string) string {
81 // The android-non-updatable is not a java_sdk_library but there are separate stub libraries for
82 // each scope.
83 // TODO(b/192067200): Remove special handling of android-non-updatable.
84 if name == "android-non-updatable" {
85 if ctx.Config().AlwaysUsePrebuiltSdks() {
86 return l.nonUpdatablePrebuiltModule
87 } else {
88 return l.nonUpdatableSourceModule
89 }
90 } else {
91 // Assume that the module is either a java_sdk_library (or equivalent) and so will provide
92 // separate stub jars for each scope or is a java_library (or equivalent) in which case it will
93 // have the same stub jar for each scope.
94 return name
95 }
96}
97
Paul Duffin31fad802021-06-18 18:14:25 +010098func (l *HiddenAPIScope) String() string {
99 return fmt.Sprintf("HiddenAPIScope{%s}", l.name)
100}
101
102var (
103 PublicHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
104 name: "public",
105 sdkKind: android.SdkPublic,
106 hiddenAPIListOption: "--public-stub-classpath",
107 })
108 SystemHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
109 name: "system",
110 sdkKind: android.SdkSystem,
111 hiddenAPIListOption: "--system-stub-classpath",
112 })
113 TestHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
114 name: "test",
115 sdkKind: android.SdkTest,
116 hiddenAPIListOption: "--test-stub-classpath",
117 })
Paul Duffinb51db2e2021-06-21 14:08:08 +0100118 ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
119 name: "module-lib",
120 sdkKind: android.SdkModule,
121 })
Paul Duffin31fad802021-06-18 18:14:25 +0100122 CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
123 name: "core-platform",
124 sdkKind: android.SdkCorePlatform,
125 hiddenAPIListOption: "--core-platform-stub-classpath",
126 })
127
128 // hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
129 // API processing.
130 //
131 // These are roughly in order from narrowest API surface to widest. Widest means the API stubs
132 // with the biggest API surface, e.g. test is wider than system is wider than public.
133 //
Paul Duffinb51db2e2021-06-21 14:08:08 +0100134 // Core platform is considered wider than system/module-lib because those modules that provide
135 // core platform APIs either do not have any system/module-lib APIs at all, or if they do it is
136 // because the core platform API is being converted to system/module-lib APIs. In either case the
137 // system/module-lib APIs are subsets of the core platform API.
Paul Duffin31fad802021-06-18 18:14:25 +0100138 //
139 // 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 +0100140 // is neither wider or narrower than the module-lib or core platform APIs. However, this works
141 // well enough at the moment.
Paul Duffin31fad802021-06-18 18:14:25 +0100142 // TODO(b/191644675): Correctly reflect the sub/superset relationships between APIs.
143 hiddenAPIScopes = []*HiddenAPIScope{
144 PublicHiddenAPIScope,
145 SystemHiddenAPIScope,
146 TestHiddenAPIScope,
Paul Duffinb51db2e2021-06-21 14:08:08 +0100147 ModuleLibHiddenAPIScope,
Paul Duffin31fad802021-06-18 18:14:25 +0100148 CorePlatformHiddenAPIScope,
149 }
150
151 // The HiddenAPIScope instances that are supported by a java_sdk_library.
152 //
153 // CorePlatformHiddenAPIScope is not used as the java_sdk_library does not have special support
154 // for core_platform API, instead it is implemented as a customized form of PublicHiddenAPIScope.
155 hiddenAPISdkLibrarySupportedScopes = []*HiddenAPIScope{
156 PublicHiddenAPIScope,
157 SystemHiddenAPIScope,
158 TestHiddenAPIScope,
Paul Duffinb51db2e2021-06-21 14:08:08 +0100159 ModuleLibHiddenAPIScope,
Paul Duffin31fad802021-06-18 18:14:25 +0100160 }
161
162 // The HiddenAPIScope instances that are supported by the `hiddenapi list`.
163 hiddenAPIFlagScopes = []*HiddenAPIScope{
164 PublicHiddenAPIScope,
165 SystemHiddenAPIScope,
166 TestHiddenAPIScope,
167 CorePlatformHiddenAPIScope,
168 }
169)
170
Paul Duffin74431d52021-04-21 14:10:42 +0100171type hiddenAPIStubsDependencyTag struct {
172 blueprint.BaseDependencyTag
Paul Duffin31fad802021-06-18 18:14:25 +0100173
174 // The api scope for which this dependency was added.
175 apiScope *HiddenAPIScope
Paul Duffin5cca7c42021-05-26 10:16:01 +0100176
177 // Indicates that the dependency is not for an API provided by the current bootclasspath fragment
178 // but is an additional API provided by a module that is not part of the current bootclasspath
179 // fragment.
180 fromAdditionalDependency bool
Paul Duffin74431d52021-04-21 14:10:42 +0100181}
182
183func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
184}
185
186func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
187 return false
188}
189
Paul Duffin976b0e52021-04-27 23:20:26 +0100190func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
Paul Duffin5cca7c42021-05-26 10:16:01 +0100191 // Do not add additional dependencies to the sdk.
192 if b.fromAdditionalDependency {
193 return nil
194 }
195
Paul Duffin976b0e52021-04-27 23:20:26 +0100196 // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
197 // property, otherwise treat if it was specified in the java_header_libs property.
198 if javaSdkLibrarySdkMemberType.IsInstance(child) {
199 return javaSdkLibrarySdkMemberType
200 }
201
202 return javaHeaderLibsSdkMemberType
203}
204
205func (b hiddenAPIStubsDependencyTag) ExportMember() bool {
206 // Export the module added via this dependency tag from the sdk.
207 return true
208}
209
Paul Duffin74431d52021-04-21 14:10:42 +0100210// Avoid having to make stubs content explicitly visible to dependent modules.
211//
212// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
213// with proper dependencies.
214// TODO(b/177892522): Remove this and add needed visibility.
215func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
216}
217
218var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
219var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
220var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
Paul Duffin976b0e52021-04-27 23:20:26 +0100221var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
Paul Duffin74431d52021-04-21 14:10:42 +0100222
Paul Duffin74431d52021-04-21 14:10:42 +0100223// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
224// needed to produce the hidden API monolithic stub flags file.
Paul Duffin31fad802021-06-18 18:14:25 +0100225func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*HiddenAPIScope][]string {
Paul Duffin74431d52021-04-21 14:10:42 +0100226 var publicStubModules []string
227 var systemStubModules []string
228 var testStubModules []string
229 var corePlatformStubModules []string
230
231 if config.AlwaysUsePrebuiltSdks() {
232 // Build configuration mandates using prebuilt stub modules
233 publicStubModules = append(publicStubModules, "sdk_public_current_android")
234 systemStubModules = append(systemStubModules, "sdk_system_current_android")
235 testStubModules = append(testStubModules, "sdk_test_current_android")
236 } else {
237 // Use stub modules built from source
238 publicStubModules = append(publicStubModules, "android_stubs_current")
239 systemStubModules = append(systemStubModules, "android_system_stubs_current")
240 testStubModules = append(testStubModules, "android_test_stubs_current")
241 }
242 // We do not have prebuilts of the core platform api yet
243 corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
244
245 // Allow products to define their own stubs for custom product jars that apps can use.
246 publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
247 systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
248 testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
249 if config.IsEnvTrue("EMMA_INSTRUMENT") {
Paul Duffin098c8782021-05-14 10:45:25 +0100250 // Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
251 // allows everyone access but it is needed to ensure consistent flags between the
252 // bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
Paul Duffin74431d52021-04-21 14:10:42 +0100253 publicStubModules = append(publicStubModules, "jacoco-stubs")
Paul Duffin098c8782021-05-14 10:45:25 +0100254 systemStubModules = append(systemStubModules, "jacoco-stubs")
255 testStubModules = append(testStubModules, "jacoco-stubs")
Paul Duffin74431d52021-04-21 14:10:42 +0100256 }
257
Paul Duffin31fad802021-06-18 18:14:25 +0100258 m := map[*HiddenAPIScope][]string{}
259 m[PublicHiddenAPIScope] = publicStubModules
260 m[SystemHiddenAPIScope] = systemStubModules
261 m[TestHiddenAPIScope] = testStubModules
262 m[CorePlatformHiddenAPIScope] = corePlatformStubModules
Paul Duffin74431d52021-04-21 14:10:42 +0100263 return m
264}
265
266// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
Paul Duffin31fad802021-06-18 18:14:25 +0100267// apiScopeToStubLibModules. It adds them in a well known order and uses a HiddenAPIScope specific
268// tag to identify the source of the dependency.
269func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScopeToStubLibModules map[*HiddenAPIScope][]string) {
Paul Duffin74431d52021-04-21 14:10:42 +0100270 module := ctx.Module()
Paul Duffin31fad802021-06-18 18:14:25 +0100271 for _, apiScope := range hiddenAPIScopes {
272 modules := apiScopeToStubLibModules[apiScope]
273 ctx.AddDependency(module, hiddenAPIStubsDependencyTag{apiScope: apiScope}, modules...)
Paul Duffin74431d52021-04-21 14:10:42 +0100274 }
275}
276
Paul Duffin74431d52021-04-21 14:10:42 +0100277// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
278// available, or reports an error.
Paul Duffin10931582021-04-25 10:13:54 +0100279func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
280 var dexJar android.Path
281 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
282 dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
283 } else if j, ok := module.(UsesLibraryDependency); ok {
284 dexJar = j.DexJarBuildPath()
Paul Duffin74431d52021-04-21 14:10:42 +0100285 } else {
286 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 +0100287 return nil
Paul Duffin74431d52021-04-21 14:10:42 +0100288 }
Paul Duffin10931582021-04-25 10:13:54 +0100289
290 if dexJar == nil {
291 ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
292 }
293 return dexJar
Paul Duffin74431d52021-04-21 14:10:42 +0100294}
295
Paul Duffin4539a372021-06-23 23:20:43 +0100296// buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
Paul Duffin74431d52021-04-21 14:10:42 +0100297//
298// The rule is initialized but not built so that the caller can modify it and select an appropriate
299// name.
Paul Duffin2e880972021-06-23 23:29:09 +0100300func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput, moduleStubFlagsPaths android.Paths) {
Paul Duffin74431d52021-04-21 14:10:42 +0100301 // Singleton rule which applies hiddenapi on all boot class path dex files.
302 rule := android.NewRuleBuilder(pctx, ctx)
303
304 tempPath := tempPathForRestat(ctx, outputPath)
305
Paul Duffinf1b358c2021-05-17 07:38:47 +0100306 // Find the widest API stubs provided by the fragments on which this depends, if any.
Paul Duffind2b1e0c2021-06-27 20:53:39 +0100307 dependencyStubDexJars := input.DependencyStubDexJarsByScope.StubDexJarsForWidestAPIScope()
Paul Duffin5cca7c42021-05-26 10:16:01 +0100308
309 // Add widest API stubs from the additional dependencies of this, if any.
Paul Duffind2b1e0c2021-06-27 20:53:39 +0100310 dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.StubDexJarsForWidestAPIScope()...)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100311
Paul Duffin74431d52021-04-21 14:10:42 +0100312 command := rule.Command().
313 Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
314 Text("list").
Paul Duffinf1b358c2021-05-17 07:38:47 +0100315 FlagForEachInput("--dependency-stub-dex=", dependencyStubDexJars).
Paul Duffin74431d52021-04-21 14:10:42 +0100316 FlagForEachInput("--boot-dex=", bootDexJars)
317
Paul Duffin156b5d32021-06-24 23:06:52 +0100318 // If no module stub flags paths are provided then this must be being called for a
319 // bootclasspath_fragment and not the whole platform_bootclasspath.
320 if moduleStubFlagsPaths == nil {
321 // This is being run on a fragment of the bootclasspath.
322 command.Flag("--fragment")
323 }
324
Paul Duffin31fad802021-06-18 18:14:25 +0100325 // Iterate over the api scopes in a fixed order.
326 for _, apiScope := range hiddenAPIFlagScopes {
327 // Merge in the stub dex jar paths for this api scope from the fragments on which it depends.
328 // They will be needed to resolve dependencies from this fragment's stubs to classes in the
329 // other fragment's APIs.
330 var paths android.Paths
Paul Duffin280a31a2021-06-27 20:28:29 +0100331 paths = append(paths, input.DependencyStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
332 paths = append(paths, input.AdditionalStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
333 paths = append(paths, input.StubDexJarsByScope.StubDexJarsForScope(apiScope)...)
Paul Duffin74431d52021-04-21 14:10:42 +0100334 if len(paths) > 0 {
Paul Duffin31fad802021-06-18 18:14:25 +0100335 option := apiScope.hiddenAPIListOption
336 command.FlagWithInputList(option+"=", paths, ":")
Paul Duffin74431d52021-04-21 14:10:42 +0100337 }
338 }
339
340 // Add the output path.
341 command.FlagWithOutput("--out-api-flags=", tempPath)
342
Paul Duffin2e880972021-06-23 23:29:09 +0100343 // If there are stub flag files that have been generated by fragments on which this depends then
344 // use them to validate the stub flag file generated by the rules created by this method.
345 if len(moduleStubFlagsPaths) > 0 {
346 validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, moduleStubFlagsPaths)
347
348 // Add the file that indicates that the file generated by this is valid.
349 //
350 // This will cause the validation rule above to be run any time that the output of this rule
351 // changes but the validation will run in parallel with other rules that depend on this file.
352 command.Validation(validFile)
353 }
354
Paul Duffin74431d52021-04-21 14:10:42 +0100355 commitChangeForRestat(rule, tempPath, outputPath)
Paul Duffin4539a372021-06-23 23:20:43 +0100356
357 rule.Build(name, desc)
Paul Duffin74431d52021-04-21 14:10:42 +0100358}
359
Paul Duffin46169772021-04-14 15:01:56 +0100360// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
361// information obtained from annotations within the source code in order to create the complete set
362// of flags that should be applied to the dex implementation jars on the bootclasspath.
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100363//
364// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
365// of each property reference a plain text file that contains a java signature per line. The flags
366// for each of those signatures will be updated in a property specific way.
367//
368// The Unsupported_packages property contains a list of paths, each of which is a plain text file
369// with one Java package per line. All members of all classes within that package (but not nested
370// packages) will be updated in a property specific way.
Paul Duffin46169772021-04-14 15:01:56 +0100371type HiddenAPIFlagFileProperties struct {
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100372 // Marks each signature in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100373 Unsupported []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100374
375 // Marks each signature in the referenced files as being unsupported because it has been removed.
376 // Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100377 Removed []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100378
379 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= R
380 // and low priority.
Paul Duffin702210b2021-04-08 20:12:41 +0100381 Max_target_r_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100382
383 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= Q.
Paul Duffin702210b2021-04-08 20:12:41 +0100384 Max_target_q []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100385
386 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= P.
Paul Duffin702210b2021-04-08 20:12:41 +0100387 Max_target_p []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100388
389 // Marks each signature in the referenced files as being supported only for targetSdkVersion <= O
390 // and low priority. Any conflicts with other flags are ignored.
Paul Duffin702210b2021-04-08 20:12:41 +0100391 Max_target_o_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100392
393 // Marks each signature in the referenced files as being blocked.
Paul Duffin702210b2021-04-08 20:12:41 +0100394 Blocked []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100395
396 // Marks each signature in every package in the referenced files as being unsupported.
Paul Duffin702210b2021-04-08 20:12:41 +0100397 Unsupported_packages []string `android:"path"`
398}
399
Paul Duffine3dc6602021-04-14 09:50:43 +0100400type hiddenAPIFlagFileCategory struct {
Paul Duffin524c82c2021-06-09 14:39:28 +0100401 // PropertyName is the name of the property for this category.
402 PropertyName string
Paul Duffine3dc6602021-04-14 09:50:43 +0100403
Paul Duffincc17bfe2021-04-19 13:21:20 +0100404 // propertyValueReader retrieves the value of the property for this category from the set of
Paul Duffine3dc6602021-04-14 09:50:43 +0100405 // properties.
Paul Duffincc17bfe2021-04-19 13:21:20 +0100406 propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
Paul Duffine3dc6602021-04-14 09:50:43 +0100407
408 // commandMutator adds the appropriate command line options for this category to the supplied
409 // command
410 commandMutator func(command *android.RuleBuilderCommand, path android.Path)
411}
412
Paul Duffin32cf58a2021-05-18 16:32:50 +0100413// The flag file category for removed members of the API.
414//
Paul Duffin524c82c2021-06-09 14:39:28 +0100415// This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
Paul Duffin32cf58a2021-05-18 16:32:50 +0100416// list of removed API members that are generated automatically from the removed.txt files provided
417// by API stubs.
418var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{
419 // See HiddenAPIFlagFileProperties.Removed
Paul Duffin524c82c2021-06-09 14:39:28 +0100420 PropertyName: "removed",
Paul Duffin32cf58a2021-05-18 16:32:50 +0100421 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
422 return properties.Removed
423 },
424 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
425 command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
426 },
427}
428
Paul Duffin524c82c2021-06-09 14:39:28 +0100429var HiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
Paul Duffin46169772021-04-14 15:01:56 +0100430 // See HiddenAPIFlagFileProperties.Unsupported
Paul Duffine3dc6602021-04-14 09:50:43 +0100431 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100432 PropertyName: "unsupported",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100433 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100434 return properties.Unsupported
435 },
436 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
437 command.FlagWithInput("--unsupported ", path)
438 },
439 },
Paul Duffin32cf58a2021-05-18 16:32:50 +0100440 hiddenAPIRemovedFlagFileCategory,
Paul Duffin46169772021-04-14 15:01:56 +0100441 // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100442 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100443 PropertyName: "max_target_r_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100444 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100445 return properties.Max_target_r_low_priority
446 },
447 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
448 command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
449 },
450 },
Paul Duffin46169772021-04-14 15:01:56 +0100451 // See HiddenAPIFlagFileProperties.Max_target_q
Paul Duffine3dc6602021-04-14 09:50:43 +0100452 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100453 PropertyName: "max_target_q",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100454 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100455 return properties.Max_target_q
456 },
457 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
458 command.FlagWithInput("--max-target-q ", path)
459 },
460 },
Paul Duffin46169772021-04-14 15:01:56 +0100461 // See HiddenAPIFlagFileProperties.Max_target_p
Paul Duffine3dc6602021-04-14 09:50:43 +0100462 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100463 PropertyName: "max_target_p",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100464 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100465 return properties.Max_target_p
466 },
467 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
468 command.FlagWithInput("--max-target-p ", path)
469 },
470 },
Paul Duffin46169772021-04-14 15:01:56 +0100471 // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100472 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100473 PropertyName: "max_target_o_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100474 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100475 return properties.Max_target_o_low_priority
476 },
477 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
478 command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
479 },
480 },
Paul Duffin46169772021-04-14 15:01:56 +0100481 // See HiddenAPIFlagFileProperties.Blocked
Paul Duffine3dc6602021-04-14 09:50:43 +0100482 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100483 PropertyName: "blocked",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100484 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100485 return properties.Blocked
486 },
487 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
488 command.FlagWithInput("--blocked ", path)
489 },
490 },
Paul Duffin46169772021-04-14 15:01:56 +0100491 // See HiddenAPIFlagFileProperties.Unsupported_packages
Paul Duffine3dc6602021-04-14 09:50:43 +0100492 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100493 PropertyName: "unsupported_packages",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100494 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffine3dc6602021-04-14 09:50:43 +0100495 return properties.Unsupported_packages
496 },
497 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
498 command.FlagWithInput("--unsupported ", path).Flag("--packages ")
499 },
500 },
Paul Duffin702210b2021-04-08 20:12:41 +0100501}
502
Paul Duffin438eb572021-05-21 16:58:23 +0100503// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
504type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths
505
506// append appends the supplied flags files to the corresponding category in this map.
507func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
Paul Duffin524c82c2021-06-09 14:39:28 +0100508 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +0100509 s[category] = append(s[category], other[category]...)
510 }
511}
512
Paul Duffinaf99afa2021-05-21 22:18:56 +0100513// HiddenAPIInfo contains information provided by the hidden API processing.
Paul Duffin2fef1362021-04-15 13:32:00 +0100514//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100515// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
516// processing.
517type HiddenAPIInfo struct {
Paul Duffin438eb572021-05-21 16:58:23 +0100518 // FlagFilesByCategory maps from the flag file category to the paths containing information for
519 // that category.
520 FlagFilesByCategory FlagFilesByCategory
Paul Duffin2fef1362021-04-15 13:32:00 +0100521
Paul Duffin280a31a2021-06-27 20:28:29 +0100522 // The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes provided by
523 // this fragment and the fragments on which this depends.
524 TransitiveStubDexJarsByScope StubDexJarsByModule
Paul Duffin18cf1972021-05-21 22:46:59 +0100525
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100526 // The output from the hidden API processing needs to be made available to other modules.
527 HiddenAPIFlagOutput
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100528}
Paul Duffin702210b2021-04-08 20:12:41 +0100529
Paul Duffinf1b358c2021-05-17 07:38:47 +0100530func newHiddenAPIInfo() *HiddenAPIInfo {
531 info := HiddenAPIInfo{
Paul Duffin31fad802021-06-18 18:14:25 +0100532 FlagFilesByCategory: FlagFilesByCategory{},
Paul Duffin280a31a2021-06-27 20:28:29 +0100533 TransitiveStubDexJarsByScope: StubDexJarsByModule{},
Paul Duffinf1b358c2021-05-17 07:38:47 +0100534 }
535 return &info
536}
537
538func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragments []android.Module) {
539 // Merge all the information from the fragments. The fragments form a DAG so it is possible that
540 // this will introduce duplicates so they will be resolved after processing all the fragments.
541 for _, fragment := range fragments {
542 if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
543 info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
Paul Duffin280a31a2021-06-27 20:28:29 +0100544 i.TransitiveStubDexJarsByScope.addStubDexJarsByModule(info.TransitiveStubDexJarsByScope)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100545 }
546 }
Paul Duffinf1b358c2021-05-17 07:38:47 +0100547}
548
Paul Duffinaf99afa2021-05-21 22:18:56 +0100549var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
Paul Duffin9b381ef2021-04-08 23:01:37 +0100550
Paul Duffin280a31a2021-06-27 20:28:29 +0100551// ModuleStubDexJars contains the stub dex jars provided by a single module.
552//
553// It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See
554// hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
555type ModuleStubDexJars map[*HiddenAPIScope]android.Path
Paul Duffin1352f7c2021-05-21 22:18:49 +0100556
Paul Duffin280a31a2021-06-27 20:28:29 +0100557// stubDexJarForWidestAPIScope returns the stub dex jars for the widest API scope provided by this
Paul Duffin1352f7c2021-05-21 22:18:49 +0100558// map.
Paul Duffin280a31a2021-06-27 20:28:29 +0100559//
560// The relative width of APIs is determined by their order in hiddenAPIScopes.
561func (s ModuleStubDexJars) stubDexJarForWidestAPIScope() android.Path {
Paul Duffin5cca7c42021-05-26 10:16:01 +0100562 for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
563 apiScope := hiddenAPIScopes[i]
Paul Duffin280a31a2021-06-27 20:28:29 +0100564 if stubsForAPIScope, ok := s[apiScope]; ok {
Paul Duffin5cca7c42021-05-26 10:16:01 +0100565 return stubsForAPIScope
566 }
567 }
568
569 return nil
570}
571
Paul Duffin280a31a2021-06-27 20:28:29 +0100572// StubDexJarsByModule contains the stub dex jars provided by a set of modules.
573//
574// It maps a module name to the path to the stub dex jars provided by that module.
575type StubDexJarsByModule map[string]ModuleStubDexJars
576
577// addStubDexJar adds a stub dex jar path provided by the specified module for the specified scope.
578func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.Module, scope *HiddenAPIScope, stubDexJar android.Path) {
579 name := android.RemoveOptionalPrebuiltPrefix(module.Name())
Paul Duffin3f0290e2021-06-30 18:25:36 +0100580
581 // Each named module provides one dex jar for each scope. However, in some cases different API
582 // versions of a single classes are provided by separate modules. e.g. the core platform
583 // version of java.lang.Object is provided by the legacy.art.module.platform.api module but the
584 // public version is provided by the art.module.public.api module. In those cases it is necessary
585 // to treat all those modules as they were the same name, otherwise it will result in multiple
586 // definitions of a single class being passed to hidden API processing which will cause an error.
Paul Duffin280a31a2021-06-27 20:28:29 +0100587 if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule {
588 // Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
589 // java_sdk_library.
590 // TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent.
591 name = "android-non-updatable"
592 } else if name == "legacy.art.module.platform.api" {
593 // Treat legacy.art.module.platform.api as if it was an API scope provided by the
594 // art.module.public.api java_sdk_library which will be the case once the former has been
595 // migrated to a module_lib API.
596 name = "art.module.public.api"
597 } else if name == "legacy.i18n.module.platform.api" {
598 // Treat legacy.i18n.module.platform.api as if it was an API scope provided by the
599 // i18n.module.public.api java_sdk_library which will be the case once the former has been
600 // migrated to a module_lib API.
601 name = "i18n.module.public.api"
602 } else if name == "conscrypt.module.platform.api" {
603 // Treat conscrypt.module.platform.api as if it was an API scope provided by the
604 // conscrypt.module.public.api java_sdk_library which will be the case once the former has been
605 // migrated to a module_lib API.
606 name = "conscrypt.module.public.api"
Paul Duffin3f0290e2021-06-30 18:25:36 +0100607 } else if d, ok := module.(SdkLibraryComponentDependency); ok {
608 sdkLibraryName := d.SdkLibraryName()
609 if sdkLibraryName != nil {
610 // The module is a component of a java_sdk_library so use the name of the java_sdk_library.
611 // e.g. if this module is `foo.system.stubs` and is part of the `foo` java_sdk_library then
612 // use `foo` as the name.
613 name = *sdkLibraryName
614 }
Paul Duffin280a31a2021-06-27 20:28:29 +0100615 }
616 stubDexJarsByScope := s[name]
617 if stubDexJarsByScope == nil {
618 stubDexJarsByScope = ModuleStubDexJars{}
619 s[name] = stubDexJarsByScope
620 }
621 stubDexJarsByScope[scope] = stubDexJar
622}
623
624// addStubDexJarsByModule adds the stub dex jars in the supplied StubDexJarsByModule to this map.
625func (s StubDexJarsByModule) addStubDexJarsByModule(other StubDexJarsByModule) {
626 for module, stubDexJarsByScope := range other {
627 s[module] = stubDexJarsByScope
628 }
629}
630
631// StubDexJarsForWidestAPIScope returns a list of stub dex jars containing the widest API scope
632// provided by each module.
633//
634// The relative width of APIs is determined by their order in hiddenAPIScopes.
635func (s StubDexJarsByModule) StubDexJarsForWidestAPIScope() android.Paths {
636 stubDexJars := android.Paths{}
637 modules := android.SortedStringKeys(s)
638 for _, module := range modules {
639 stubDexJarsByScope := s[module]
640
641 stubDexJars = append(stubDexJars, stubDexJarsByScope.stubDexJarForWidestAPIScope())
642 }
643
644 return stubDexJars
645}
646
647// StubDexJarsForScope returns a list of stub dex jars containing the stub dex jars provided by each
648// module for the specified scope.
649//
650// If a module does not provide a stub dex jar for the supplied scope then it does not contribute to
651// the returned list.
652func (s StubDexJarsByModule) StubDexJarsForScope(scope *HiddenAPIScope) android.Paths {
653 stubDexJars := android.Paths{}
654 modules := android.SortedStringKeys(s)
655 for _, module := range modules {
656 stubDexJarsByScope := s[module]
657 // Not every module will have the same set of
658 if jars, ok := stubDexJarsByScope[scope]; ok {
659 stubDexJars = append(stubDexJars, jars)
660 }
661 }
662
663 return stubDexJars
664}
665
Paul Duffin1352f7c2021-05-21 22:18:49 +0100666// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
667// needed for hidden API flag generation.
668type HiddenAPIFlagInput struct {
669 // FlagFilesByCategory contains the flag files that override the initial flags that are derived
670 // from the stub dex files.
671 FlagFilesByCategory FlagFilesByCategory
672
Paul Duffin31fad802021-06-18 18:14:25 +0100673 // StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
Paul Duffin1352f7c2021-05-21 22:18:49 +0100674 // the initial flags for each dex member.
Paul Duffin280a31a2021-06-27 20:28:29 +0100675 StubDexJarsByScope StubDexJarsByModule
Paul Duffinf1b358c2021-05-17 07:38:47 +0100676
Paul Duffin31fad802021-06-18 18:14:25 +0100677 // DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
678 // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
Paul Duffinf1b358c2021-05-17 07:38:47 +0100679 // fragment on which this depends.
Paul Duffin280a31a2021-06-27 20:28:29 +0100680 DependencyStubDexJarsByScope StubDexJarsByModule
Paul Duffin32cf58a2021-05-18 16:32:50 +0100681
Paul Duffin5cca7c42021-05-26 10:16:01 +0100682 // AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to
683 // the ones that are obtained from fragments on which this depends.
684 //
685 // These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope
686 // as there are not propagated transitively to other fragments that depend on this.
Paul Duffin280a31a2021-06-27 20:28:29 +0100687 AdditionalStubDexJarsByScope StubDexJarsByModule
Paul Duffin5cca7c42021-05-26 10:16:01 +0100688
Paul Duffin32cf58a2021-05-18 16:32:50 +0100689 // RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
690 // specified in the bootclasspath_fragment's stub_libs and contents properties.
691 RemovedTxtFiles android.Paths
Paul Duffin1352f7c2021-05-21 22:18:49 +0100692}
693
694// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
695func newHiddenAPIFlagInput() HiddenAPIFlagInput {
696 input := HiddenAPIFlagInput{
Paul Duffin31fad802021-06-18 18:14:25 +0100697 FlagFilesByCategory: FlagFilesByCategory{},
Paul Duffin280a31a2021-06-27 20:28:29 +0100698 StubDexJarsByScope: StubDexJarsByModule{},
699 DependencyStubDexJarsByScope: StubDexJarsByModule{},
700 AdditionalStubDexJarsByScope: StubDexJarsByModule{},
Paul Duffin1352f7c2021-05-21 22:18:49 +0100701 }
702
703 return input
704}
705
706// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
707// dependencies added in hiddenAPIAddStubLibDependencies.
708//
709// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
710func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
Paul Duffin31fad802021-06-18 18:14:25 +0100711 addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
712 sdkKind := apiScope.sdkKind
713 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100714 if dexJar != nil {
Paul Duffin280a31a2021-06-27 20:28:29 +0100715 i.StubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100716 }
Paul Duffin32cf58a2021-05-18 16:32:50 +0100717
718 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100719 removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
Paul Duffin32cf58a2021-05-18 16:32:50 +0100720 i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
721 }
Paul Duffin1352f7c2021-05-21 22:18:49 +0100722 }
723
724 // If the contents includes any java_sdk_library modules then add them to the stubs.
725 for _, module := range contents {
726 if _, ok := module.(SdkLibraryDependency); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100727 // Add information for every possible API scope needed by hidden API.
728 for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
729 addFromModule(ctx, module, apiScope)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100730 }
731 }
732 }
733
Paul Duffind061d402021-06-07 21:36:01 +0100734 ctx.VisitDirectDeps(func(module android.Module) {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100735 tag := ctx.OtherModuleDependencyTag(module)
736 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100737 apiScope := hiddenAPIStubsTag.apiScope
Paul Duffin5cca7c42021-05-26 10:16:01 +0100738 if hiddenAPIStubsTag.fromAdditionalDependency {
739 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind)
740 if dexJar != nil {
Paul Duffin280a31a2021-06-27 20:28:29 +0100741 i.AdditionalStubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
Paul Duffin5cca7c42021-05-26 10:16:01 +0100742 }
743 } else {
744 addFromModule(ctx, module, apiScope)
745 }
Paul Duffin1352f7c2021-05-21 22:18:49 +0100746 }
747 })
748
749 // Normalize the paths, i.e. remove duplicates and sort.
Paul Duffin32cf58a2021-05-18 16:32:50 +0100750 i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100751}
752
753// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
754// supplied properties and stores them in this struct.
755func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
Paul Duffin524c82c2021-06-09 14:39:28 +0100756 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100757 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
758 i.FlagFilesByCategory[category] = paths
759 }
760}
761
Paul Duffin280a31a2021-06-27 20:28:29 +0100762func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByModule {
Paul Duffin31fad802021-06-18 18:14:25 +0100763 transitive := i.DependencyStubDexJarsByScope
Paul Duffin280a31a2021-06-27 20:28:29 +0100764 transitive.addStubDexJarsByModule(i.StubDexJarsByScope)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100765 return transitive
766}
767
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100768// HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
769// bootclasspath_fragment module.
770type HiddenAPIFlagOutput struct {
771 // The path to the generated stub-flags.csv file.
772 StubFlagsPath android.Path
773
774 // The path to the generated annotation-flags.csv file.
775 AnnotationFlagsPath android.Path
776
777 // The path to the generated metadata.csv file.
778 MetadataPath android.Path
779
780 // The path to the generated index.csv file.
781 IndexPath android.Path
782
783 // The path to the generated all-flags.csv file.
784 AllFlagsPath android.Path
785}
786
Paul Duffin5f148ca2021-06-02 17:24:22 +0100787// bootDexJarByModule is a map from base module name (without prebuilt_ prefix) to the boot dex
788// path.
789type bootDexJarByModule map[string]android.Path
790
791// addPath adds the path for a module to the map.
792func (b bootDexJarByModule) addPath(module android.Module, path android.Path) {
793 b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path
794}
795
Paul Duffine5218812021-06-07 13:28:19 +0100796// bootDexJars returns the boot dex jar paths sorted by their keys.
797func (b bootDexJarByModule) bootDexJars() android.Paths {
798 paths := android.Paths{}
799 for _, k := range android.SortedStringKeys(b) {
800 paths = append(paths, b[k])
801 }
802 return paths
803}
804
Paul Duffin7f872162021-06-17 19:33:24 +0100805// bootDexJarsWithoutCoverage returns the boot dex jar paths sorted by their keys without coverage
806// libraries if present.
807func (b bootDexJarByModule) bootDexJarsWithoutCoverage() android.Paths {
808 paths := android.Paths{}
809 for _, k := range android.SortedStringKeys(b) {
810 if k == "jacocoagent" {
811 continue
812 }
813 paths = append(paths, b[k])
814 }
815 return paths
816}
817
Paul Duffine5218812021-06-07 13:28:19 +0100818// HiddenAPIOutput encapsulates the output from the hidden API processing.
819type HiddenAPIOutput struct {
820 HiddenAPIFlagOutput
821
822 // The map from base module name to the path to the encoded boot dex file.
823 EncodedBootDexFilesByModule bootDexJarByModule
824}
825
Paul Duffindfa10832021-05-13 17:31:51 +0100826// pathForValidation creates a path of the same type as the supplied type but with a name of
827// <path>.valid.
828//
829// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
830// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
831func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
832 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
833 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
834}
835
Paul Duffin2fef1362021-04-15 13:32:00 +0100836// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
837// the flags from all the modules, the stub flags, augmented with some additional configuration
838// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100839//
840// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
841// an entry for every single member in the dex implementation jars of the individual modules. Every
842// signature in any of the other files MUST be included in this file.
843//
Paul Duffin537ea3d2021-05-14 10:38:00 +0100844// annotationFlags is the path to the annotation flags file generated from annotation information
845// in each module.
Paul Duffin702210b2021-04-08 20:12:41 +0100846//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100847// hiddenAPIInfo is a struct containing paths to files that augment the information provided by
Paul Duffin537ea3d2021-05-14 10:38:00 +0100848// the annotationFlags.
Paul Duffin32cf58a2021-05-18 16:32:50 +0100849func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string,
Paul Duffind061d402021-06-07 21:36:01 +0100850 outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
Paul Duffin32cf58a2021-05-18 16:32:50 +0100851 flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths, generatedRemovedDexSignatures android.OptionalPath) {
Paul Duffindfa10832021-05-13 17:31:51 +0100852
Paul Duffindfa10832021-05-13 17:31:51 +0100853 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100854 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100855 rule := android.NewRuleBuilder(pctx, ctx)
856 command := rule.Command().
857 BuiltTool("generate_hiddenapi_lists").
858 FlagWithInput("--csv ", baseFlagsPath).
Paul Duffind061d402021-06-07 21:36:01 +0100859 Inputs(annotationFlagPaths).
Paul Duffin702210b2021-04-08 20:12:41 +0100860 FlagWithOutput("--output ", tempPath)
861
Paul Duffine3dc6602021-04-14 09:50:43 +0100862 // Add the options for the different categories of flag files.
Paul Duffin524c82c2021-06-09 14:39:28 +0100863 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +0100864 paths := flagFilesByCategory[category]
Paul Duffine3dc6602021-04-14 09:50:43 +0100865 for _, path := range paths {
866 category.commandMutator(command, path)
867 }
Paul Duffin702210b2021-04-08 20:12:41 +0100868 }
869
Paul Duffin32cf58a2021-05-18 16:32:50 +0100870 // If available then pass the automatically generated file containing dex signatures of removed
871 // API members to the rule so they can be marked as removed.
872 if generatedRemovedDexSignatures.Valid() {
873 hiddenAPIRemovedFlagFileCategory.commandMutator(command, generatedRemovedDexSignatures.Path())
874 }
875
Paul Duffin702210b2021-04-08 20:12:41 +0100876 commitChangeForRestat(rule, tempPath, outputPath)
877
Paul Duffin2e880972021-06-23 23:29:09 +0100878 // If there are flag files that have been generated by fragments on which this depends then use
879 // them to validate the flag file generated by the rules created by this method.
880 if len(allFlagsPaths) > 0 {
881 validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, allFlagsPaths)
882
Paul Duffindfa10832021-05-13 17:31:51 +0100883 // Add the file that indicates that the file generated by this is valid.
884 //
885 // This will cause the validation rule above to be run any time that the output of this rule
886 // changes but the validation will run in parallel with other rules that depend on this file.
887 command.Validation(validFile)
888 }
889
Paul Duffin2fef1362021-04-15 13:32:00 +0100890 rule.Build(name, desc)
891}
892
Paul Duffin2e880972021-06-23 23:29:09 +0100893// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
894// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
895func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string, monolithicFilePath android.WritablePath, modularFilePaths android.Paths) android.WritablePath {
896 // The file which is used to record that the flags file is valid.
897 validFile := pathForValidation(ctx, monolithicFilePath)
898
899 // Create a rule to validate the output from the following rule.
900 rule := android.NewRuleBuilder(pctx, ctx)
901 rule.Command().
902 BuiltTool("verify_overlaps").
903 Input(monolithicFilePath).
904 Inputs(modularFilePaths).
905 // If validation passes then update the file that records that.
906 Text("&& touch").Output(validFile)
907 rule.Build(name+"Validation", desc+" validation")
908
909 return validFile
910}
911
Paul Duffine5218812021-06-07 13:28:19 +0100912// hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the
913// bootclasspath and then encode the flags into the boot dex files.
Paul Duffin2fef1362021-04-15 13:32:00 +0100914//
915// It takes:
916// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
917// * The list of modules that are the contents of the fragment.
918// * The additional manually curated flag files to use.
919//
920// It generates:
921// * stub-flags.csv
922// * annotation-flags.csv
923// * metadata.csv
924// * index.csv
925// * all-flags.csv
Paul Duffine5218812021-06-07 13:28:19 +0100926// * encoded boot dex files
927func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
Paul Duffin2fef1362021-04-15 13:32:00 +0100928 hiddenApiSubDir := "modular-hiddenapi"
929
Paul Duffine5218812021-06-07 13:28:19 +0100930 // Gather information about the boot dex files for the boot libraries provided by this fragment.
931 bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100932
933 // Generate the stub-flags.csv.
Paul Duffin2fef1362021-04-15 13:32:00 +0100934 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
Paul Duffin2e880972021-06-23 23:29:09 +0100935 buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
Paul Duffin2fef1362021-04-15 13:32:00 +0100936
Paul Duffin537ea3d2021-05-14 10:38:00 +0100937 // Extract the classes jars from the contents.
Paul Duffindd5993f2021-06-10 10:18:22 +0100938 classesJars := extractClassesJarsFromModules(contents)
Paul Duffin537ea3d2021-05-14 10:38:00 +0100939
Paul Duffin2fef1362021-04-15 13:32:00 +0100940 // Generate the set of flags from the annotations in the source code.
941 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100942 buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100943
944 // Generate the metadata from the annotations in the source code.
945 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100946 buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100947
Paul Duffin537ea3d2021-05-14 10:38:00 +0100948 // Generate the index file from the CSV files in the classes jars.
Paul Duffin2fef1362021-04-15 13:32:00 +0100949 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100950 buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100951
Paul Duffinaf99afa2021-05-21 22:18:56 +0100952 // 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 +0100953 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
954 // manually combining all the removed.txt files for each API and then converting them to dex
Paul Duffin32cf58a2021-05-18 16:32:50 +0100955 // signatures, see the combined-removed-dex module. This does that automatically by using the
956 // *removed.txt files retrieved from the java_sdk_library modules that are specified in the
957 // stub_libs and contents properties of a bootclasspath_fragment.
958 removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, input.RemovedTxtFiles)
Paul Duffin2fef1362021-04-15 13:32:00 +0100959
960 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
961 // files.
Paul Duffine5218812021-06-07 13:28:19 +0100962 allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
Paul Duffind061d402021-06-07 21:36:01 +0100963 buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
Paul Duffine5218812021-06-07 13:28:19 +0100964
965 // Encode the flags into the boot dex files.
966 encodedBootDexJarsByModule := map[string]android.Path{}
967 outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath
968 for _, name := range android.SortedStringKeys(bootDexInfoByModule) {
969 bootDexInfo := bootDexInfoByModule[name]
970 unencodedDex := bootDexInfo.path
971 encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, outputDir)
972 encodedBootDexJarsByModule[name] = encodedDex
973 }
Paul Duffin2fef1362021-04-15 13:32:00 +0100974
975 // Store the paths in the info for use by other modules and sdk snapshot generation.
Paul Duffine5218812021-06-07 13:28:19 +0100976 output := HiddenAPIOutput{
977 HiddenAPIFlagOutput: HiddenAPIFlagOutput{
978 StubFlagsPath: stubFlagsCSV,
979 AnnotationFlagsPath: annotationFlagsCSV,
980 MetadataPath: metadataCSV,
981 IndexPath: indexCSV,
982 AllFlagsPath: allFlagsCSV,
983 },
984 EncodedBootDexFilesByModule: encodedBootDexJarsByModule,
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100985 }
986 return &output
Paul Duffin702210b2021-04-08 20:12:41 +0100987}
Paul Duffin537ea3d2021-05-14 10:38:00 +0100988
Paul Duffin32cf58a2021-05-18 16:32:50 +0100989func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedTxtFiles android.Paths) android.OptionalPath {
990 if len(removedTxtFiles) == 0 {
991 return android.OptionalPath{}
992 }
993
994 output := android.PathForModuleOut(ctx, "modular-hiddenapi/removed-dex-signatures.txt")
995
996 rule := android.NewRuleBuilder(pctx, ctx)
997 rule.Command().
998 BuiltTool("metalava").
999 Flag("--no-banner").
1000 Inputs(removedTxtFiles).
1001 FlagWithOutput("--dex-api ", output)
1002 rule.Build("modular-hiddenapi-removed-dex-signatures", "modular hiddenapi removed dex signatures")
1003 return android.OptionalPathForPath(output)
1004}
1005
Paul Duffindd5993f2021-06-10 10:18:22 +01001006// extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules.
Paul Duffine5218812021-06-07 13:28:19 +01001007func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
1008 bootDexJars := bootDexJarByModule{}
Paul Duffin537ea3d2021-05-14 10:38:00 +01001009 for _, module := range contents {
Paul Duffindd5993f2021-06-10 10:18:22 +01001010 hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
1011 if hiddenAPIModule == nil {
1012 continue
1013 }
Paul Duffine5218812021-06-07 13:28:19 +01001014 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
1015 bootDexJars.addPath(module, bootDexJar)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001016 }
1017 return bootDexJars
1018}
1019
Paul Duffindd5993f2021-06-10 10:18:22 +01001020func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Module) hiddenAPIModule {
1021 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
1022 return hiddenAPIModule
1023 } else if _, ok := module.(*DexImport); ok {
1024 // Ignore this for the purposes of hidden API processing
1025 } else {
1026 ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
1027 }
1028
1029 return nil
1030}
1031
Paul Duffine5218812021-06-07 13:28:19 +01001032// bootDexInfo encapsulates both the path and uncompressDex status retrieved from a hiddenAPIModule.
1033type bootDexInfo struct {
1034 // The path to the dex jar that has not had hidden API flags encoded into it.
1035 path android.Path
1036
1037 // Indicates whether the dex jar needs uncompressing before encoding.
1038 uncompressDex bool
1039}
1040
1041// bootDexInfoByModule is a map from module name (as returned by module.Name()) to the boot dex
1042// path (as returned by hiddenAPIModule.bootDexJar()) and the uncompressDex flag.
1043type bootDexInfoByModule map[string]bootDexInfo
1044
1045// bootDexJars returns the boot dex jar paths sorted by their keys.
1046func (b bootDexInfoByModule) bootDexJars() android.Paths {
1047 paths := android.Paths{}
1048 for _, m := range android.SortedStringKeys(b) {
1049 paths = append(paths, b[m].path)
1050 }
1051 return paths
1052}
1053
1054// extractBootDexInfoFromModules extracts the boot dex jar and uncompress dex state from
1055// each of the supplied modules which must implement hiddenAPIModule.
1056func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android.Module) bootDexInfoByModule {
1057 bootDexJarsByModule := bootDexInfoByModule{}
1058 for _, module := range contents {
1059 hiddenAPIModule := module.(hiddenAPIModule)
1060 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
1061 bootDexJarsByModule[module.Name()] = bootDexInfo{
1062 path: bootDexJar,
1063 uncompressDex: *hiddenAPIModule.uncompressDex(),
1064 }
1065 }
1066
1067 return bootDexJarsByModule
1068}
1069
1070// retrieveBootDexJarFromHiddenAPIModule retrieves the boot dex jar from the hiddenAPIModule.
1071//
1072// If the module does not provide a boot dex jar, i.e. the returned boot dex jar is nil, then that
1073// create a fake path and either report an error immediately or defer reporting of the error until
1074// the path is actually used.
1075func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
1076 bootDexJar := module.bootDexJar()
1077 if bootDexJar == nil {
1078 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
1079 bootDexJar = fake
1080
1081 handleMissingDexBootFile(ctx, module, fake)
1082 }
1083 return bootDexJar
1084}
1085
Paul Duffindd5993f2021-06-10 10:18:22 +01001086// extractClassesJarsFromModules extracts the class jars from the supplied modules.
1087func extractClassesJarsFromModules(contents []android.Module) android.Paths {
Paul Duffin537ea3d2021-05-14 10:38:00 +01001088 classesJars := android.Paths{}
1089 for _, module := range contents {
Paul Duffindd5993f2021-06-10 10:18:22 +01001090 classesJars = append(classesJars, retrieveClassesJarsFromModule(module)...)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001091 }
1092 return classesJars
1093}
Paul Duffin5f148ca2021-06-02 17:24:22 +01001094
Paul Duffindd5993f2021-06-10 10:18:22 +01001095// retrieveClassesJarsFromModule retrieves the classes jars from the supplied module.
1096func retrieveClassesJarsFromModule(module android.Module) android.Paths {
1097 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
1098 return hiddenAPIModule.classesJars()
1099 }
1100
1101 return nil
1102}
1103
Paul Duffin5f148ca2021-06-02 17:24:22 +01001104// deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
1105// Soong but should instead only be reported in ninja if the file is actually built.
1106func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
1107 // TODO(b/179354495): Remove this workaround when it is unnecessary.
1108 // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
1109 // create a fake one that will cause a build error only if it is used.
1110 if ctx.Config().AlwaysUsePrebuiltSdks() {
1111 return true
1112 }
1113
Paul Duffine5218812021-06-07 13:28:19 +01001114 // Any missing dependency should be allowed.
1115 if ctx.Config().AllowMissingDependencies() {
1116 return true
1117 }
1118
Paul Duffinef083c92021-06-29 13:36:34 +01001119 // A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there
1120 // is no equivalently versioned prebuilt APEX file from which it can be obtained. However,
1121 // versioned bootclasspath modules are processed by Soong so in order to avoid them causing build
1122 // failures missing boot dex jars need to be deferred.
1123 if android.IsModuleInVersionedSdk(ctx.Module()) {
1124 return true
1125 }
1126
Paul Duffin5f148ca2021-06-02 17:24:22 +01001127 // This is called for both platform_bootclasspath and bootclasspath_fragment modules.
1128 //
1129 // A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
1130 // Ideally, a bootclasspath_fragment module should never have a platform variant created for it
1131 // but unfortunately, due to b/187910671 it does.
1132 //
1133 // That causes issues when obtaining a boot dex jar for a prebuilt module as a prebuilt module
1134 // used by a bootclasspath_fragment can only provide a boot dex jar when it is part of APEX, i.e.
1135 // has an APEX variant not a platform variant.
1136 //
1137 // There are some other situations when a prebuilt module used by a bootclasspath_fragment cannot
1138 // provide a boot dex jar:
1139 // 1. If the bootclasspath_fragment is not exported by the prebuilt_apex/apex_set module then it
1140 // does not have an APEX variant and only has a platform variant and neither do its content
1141 // modules.
1142 // 2. Some build configurations, e.g. setting TARGET_BUILD_USE_PREBUILT_SDKS causes all
1143 // java_sdk_library_import modules to be treated as preferred and as many of them are not part
1144 // of an apex they cannot provide a boot dex jar.
1145 //
1146 // The first case causes problems when the affected prebuilt modules are preferred but that is an
1147 // invalid configuration and it is ok for it to fail as the work to enable that is not yet
1148 // complete. The second case is used for building targets that do not use boot dex jars and so
1149 // deferring error reporting to ninja is fine as the affected ninja targets should never be built.
1150 // That is handled above.
1151 //
1152 // A platform_bootclasspath module can use libraries from both platform and APEX variants. Unlike
1153 // the bootclasspath_fragment it supports dex_import modules which provides the dex file. So, it
1154 // can obtain a boot dex jar from a prebuilt that is not part of an APEX. However, it is assumed
1155 // that if the library can be part of an APEX then it is the APEX variant that is used.
1156 //
1157 // This check handles the slightly different requirements of the bootclasspath_fragment and
1158 // platform_bootclasspath modules by only deferring error reporting for the platform variant of
1159 // a prebuilt modules that has other variants which are part of an APEX.
1160 //
1161 // TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
1162 if android.IsModulePrebuilt(module) {
Paul Duffinef083c92021-06-29 13:36:34 +01001163 // An inactive source module can still contribute to the APEX but an inactive prebuilt module
1164 // should not contribute to anything. So, rather than have a missing dex jar cause a Soong
1165 // failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly
1166 // built Ninja should never use the dex jar file.
1167 if !isActiveModule(module) {
1168 return true
1169 }
1170
Paul Duffin5f148ca2021-06-02 17:24:22 +01001171 if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
1172 apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
1173 if apexInfo.IsForPlatform() {
1174 return true
1175 }
1176 }
1177 }
1178
Paul Duffin5f148ca2021-06-02 17:24:22 +01001179 return false
1180}
1181
1182// handleMissingDexBootFile will either log a warning or create an error rule to create the fake
1183// file depending on the value returned from deferReportingMissingBootDexJar.
1184func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath) {
1185 if deferReportingMissingBootDexJar(ctx, module) {
1186 // Create an error rule that pretends to create the output file but will actually fail if it
1187 // is run.
1188 ctx.Build(pctx, android.BuildParams{
1189 Rule: android.ErrorRule,
1190 Output: fake,
1191 Args: map[string]string{
1192 "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
1193 },
1194 })
1195 } else {
1196 ctx.ModuleErrorf("module %s does not provide a dex jar", module)
1197 }
1198}
1199
1200// retrieveEncodedBootDexJarFromModule returns a path to the boot dex jar from the supplied module's
1201// DexJarBuildPath() method.
1202//
1203// The returned path will usually be to a dex jar file that has been encoded with hidden API flags.
1204// However, under certain conditions, e.g. errors, or special build configurations it will return
1205// a path to a fake file.
1206func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
1207 bootDexJar := module.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath()
1208 if bootDexJar == nil {
1209 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
1210 bootDexJar = fake
1211
1212 handleMissingDexBootFile(ctx, module, fake)
1213 }
1214 return bootDexJar
1215}
1216
1217// extractEncodedDexJarsFromModules extracts the encoded dex jars from the supplied modules.
1218func extractEncodedDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
1219 encodedDexJarsByModuleName := bootDexJarByModule{}
1220 for _, module := range contents {
1221 path := retrieveEncodedBootDexJarFromModule(ctx, module)
1222 encodedDexJarsByModuleName.addPath(module, path)
1223 }
1224 return encodedDexJarsByModuleName
1225}