blob: e15d9952db8db4ebcc39abb060f24bb821e1af38 [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 Duffin59db6d42021-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 Duffin05bbff92021-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 Duffinb3821fe2021-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 Duffin05bbff92021-06-18 18:14:25 +010047}
48
49// initHiddenAPIScope initializes the scope.
50func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
Paul Duffinb3821fe2021-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 Duffin05bbff92021-06-18 18:14:25 +010075 return apiScope
76}
77
Paul Duffinb3821fe2021-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 Duffin05bbff92021-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 Duffin2cb06b72021-06-21 14:08:08 +0100118 ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
119 name: "module-lib",
120 sdkKind: android.SdkModule,
121 })
Paul Duffin05bbff92021-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 Duffin2cb06b72021-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 Duffin05bbff92021-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 Duffin2cb06b72021-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 Duffin05bbff92021-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 Duffin2cb06b72021-06-21 14:08:08 +0100147 ModuleLibHiddenAPIScope,
Paul Duffin05bbff92021-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 Duffin2cb06b72021-06-21 14:08:08 +0100159 ModuleLibHiddenAPIScope,
Paul Duffin05bbff92021-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 Duffin05bbff92021-06-18 18:14:25 +0100173
174 // The api scope for which this dependency was added.
175 apiScope *HiddenAPIScope
Paul Duffinb3821fe2021-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 Duffinb3821fe2021-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 Duffin05bbff92021-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 Duffin05bbff92021-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 Duffin05bbff92021-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 Duffin05bbff92021-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 Duffin31a68562021-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 Duffinaf193422021-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 Duffin67c1e572021-05-17 07:38:47 +0100306 // Find the widest API stubs provided by the fragments on which this depends, if any.
Paul Duffind05bb8e2021-06-27 20:53:39 +0100307 dependencyStubDexJars := input.DependencyStubDexJarsByScope.StubDexJarsForWidestAPIScope()
Paul Duffinb3821fe2021-05-26 10:16:01 +0100308
309 // Add widest API stubs from the additional dependencies of this, if any.
Paul Duffind05bb8e2021-06-27 20:53:39 +0100310 dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.StubDexJarsForWidestAPIScope()...)
Paul Duffin67c1e572021-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 Duffin67c1e572021-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 Duffinfdb2fb62021-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 Duffin05bbff92021-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 Duffinfb8f07b2021-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 Duffin05bbff92021-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 Duffinaf193422021-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 Duffin31a68562021-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 Duffinc45a86a2021-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 Duffin54c1f082021-05-18 16:32:50 +0100413// The flag file category for removed members of the API.
414//
Paul Duffinc45a86a2021-06-09 14:39:28 +0100415// This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
Paul Duffin54c1f082021-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 Duffinc45a86a2021-06-09 14:39:28 +0100420 PropertyName: "removed",
Paul Duffin54c1f082021-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 Duffinc45a86a2021-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 Duffinc45a86a2021-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 Duffin54c1f082021-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 Duffinc45a86a2021-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 Duffinc45a86a2021-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 Duffinc45a86a2021-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 Duffinc45a86a2021-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 Duffinc45a86a2021-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 Duffinc45a86a2021-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 Duffin9e3b9062021-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 Duffinc45a86a2021-06-09 14:39:28 +0100508 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin9e3b9062021-05-21 16:58:23 +0100509 s[category] = append(s[category], other[category]...)
510 }
511}
512
513// dedup removes duplicates in the flag files, while maintaining the order in which they were
514// appended.
515func (s FlagFilesByCategory) dedup() {
516 for category, paths := range s {
517 s[category] = android.FirstUniquePaths(paths)
518 }
519}
520
Paul Duffin71955b42021-05-21 22:18:56 +0100521// HiddenAPIInfo contains information provided by the hidden API processing.
Paul Duffin2fef1362021-04-15 13:32:00 +0100522//
Paul Duffin71955b42021-05-21 22:18:56 +0100523// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
524// processing.
525type HiddenAPIInfo struct {
Paul Duffin9e3b9062021-05-21 16:58:23 +0100526 // FlagFilesByCategory maps from the flag file category to the paths containing information for
527 // that category.
528 FlagFilesByCategory FlagFilesByCategory
Paul Duffin2fef1362021-04-15 13:32:00 +0100529
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100530 // The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes provided by
531 // this fragment and the fragments on which this depends.
532 TransitiveStubDexJarsByScope StubDexJarsByModule
Paul Duffin6a58cc92021-05-21 22:46:59 +0100533
Paul Duffincad63842021-05-21 16:15:31 +0100534 // The output from the hidden API processing needs to be made available to other modules.
535 HiddenAPIFlagOutput
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100536}
Paul Duffin702210b2021-04-08 20:12:41 +0100537
Paul Duffin67c1e572021-05-17 07:38:47 +0100538func newHiddenAPIInfo() *HiddenAPIInfo {
539 info := HiddenAPIInfo{
Paul Duffin05bbff92021-06-18 18:14:25 +0100540 FlagFilesByCategory: FlagFilesByCategory{},
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100541 TransitiveStubDexJarsByScope: StubDexJarsByModule{},
Paul Duffin67c1e572021-05-17 07:38:47 +0100542 }
543 return &info
544}
545
546func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragments []android.Module) {
547 // Merge all the information from the fragments. The fragments form a DAG so it is possible that
548 // this will introduce duplicates so they will be resolved after processing all the fragments.
549 for _, fragment := range fragments {
550 if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
551 info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100552 i.TransitiveStubDexJarsByScope.addStubDexJarsByModule(info.TransitiveStubDexJarsByScope)
Paul Duffin67c1e572021-05-17 07:38:47 +0100553 }
554 }
Paul Duffin67c1e572021-05-17 07:38:47 +0100555}
556
Paul Duffin71955b42021-05-21 22:18:56 +0100557var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
Paul Duffin9b381ef2021-04-08 23:01:37 +0100558
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100559// ModuleStubDexJars contains the stub dex jars provided by a single module.
560//
561// It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See
562// hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
563type ModuleStubDexJars map[*HiddenAPIScope]android.Path
Paul Duffin5aadef82021-05-21 22:18:49 +0100564
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100565// stubDexJarForWidestAPIScope returns the stub dex jars for the widest API scope provided by this
Paul Duffin5aadef82021-05-21 22:18:49 +0100566// map.
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100567//
568// The relative width of APIs is determined by their order in hiddenAPIScopes.
569func (s ModuleStubDexJars) stubDexJarForWidestAPIScope() android.Path {
Paul Duffinb3821fe2021-05-26 10:16:01 +0100570 for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
571 apiScope := hiddenAPIScopes[i]
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100572 if stubsForAPIScope, ok := s[apiScope]; ok {
Paul Duffinb3821fe2021-05-26 10:16:01 +0100573 return stubsForAPIScope
574 }
575 }
576
577 return nil
578}
579
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100580// StubDexJarsByModule contains the stub dex jars provided by a set of modules.
581//
582// It maps a module name to the path to the stub dex jars provided by that module.
583type StubDexJarsByModule map[string]ModuleStubDexJars
584
585// addStubDexJar adds a stub dex jar path provided by the specified module for the specified scope.
586func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.Module, scope *HiddenAPIScope, stubDexJar android.Path) {
587 name := android.RemoveOptionalPrebuiltPrefix(module.Name())
588 if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule {
589 // Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
590 // java_sdk_library.
591 // TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent.
592 name = "android-non-updatable"
593 } else if name == "legacy.art.module.platform.api" {
594 // Treat legacy.art.module.platform.api as if it was an API scope provided by the
595 // art.module.public.api java_sdk_library which will be the case once the former has been
596 // migrated to a module_lib API.
597 name = "art.module.public.api"
598 } else if name == "legacy.i18n.module.platform.api" {
599 // Treat legacy.i18n.module.platform.api as if it was an API scope provided by the
600 // i18n.module.public.api java_sdk_library which will be the case once the former has been
601 // migrated to a module_lib API.
602 name = "i18n.module.public.api"
603 } else if name == "conscrypt.module.platform.api" {
604 // Treat conscrypt.module.platform.api as if it was an API scope provided by the
605 // conscrypt.module.public.api java_sdk_library which will be the case once the former has been
606 // migrated to a module_lib API.
607 name = "conscrypt.module.public.api"
608 }
609 stubDexJarsByScope := s[name]
610 if stubDexJarsByScope == nil {
611 stubDexJarsByScope = ModuleStubDexJars{}
612 s[name] = stubDexJarsByScope
613 }
614 stubDexJarsByScope[scope] = stubDexJar
615}
616
617// addStubDexJarsByModule adds the stub dex jars in the supplied StubDexJarsByModule to this map.
618func (s StubDexJarsByModule) addStubDexJarsByModule(other StubDexJarsByModule) {
619 for module, stubDexJarsByScope := range other {
620 s[module] = stubDexJarsByScope
621 }
622}
623
624// StubDexJarsForWidestAPIScope returns a list of stub dex jars containing the widest API scope
625// provided by each module.
626//
627// The relative width of APIs is determined by their order in hiddenAPIScopes.
628func (s StubDexJarsByModule) StubDexJarsForWidestAPIScope() android.Paths {
629 stubDexJars := android.Paths{}
630 modules := android.SortedStringKeys(s)
631 for _, module := range modules {
632 stubDexJarsByScope := s[module]
633
634 stubDexJars = append(stubDexJars, stubDexJarsByScope.stubDexJarForWidestAPIScope())
635 }
636
637 return stubDexJars
638}
639
640// StubDexJarsForScope returns a list of stub dex jars containing the stub dex jars provided by each
641// module for the specified scope.
642//
643// If a module does not provide a stub dex jar for the supplied scope then it does not contribute to
644// the returned list.
645func (s StubDexJarsByModule) StubDexJarsForScope(scope *HiddenAPIScope) android.Paths {
646 stubDexJars := android.Paths{}
647 modules := android.SortedStringKeys(s)
648 for _, module := range modules {
649 stubDexJarsByScope := s[module]
650 // Not every module will have the same set of
651 if jars, ok := stubDexJarsByScope[scope]; ok {
652 stubDexJars = append(stubDexJars, jars)
653 }
654 }
655
656 return stubDexJars
657}
658
Paul Duffin5aadef82021-05-21 22:18:49 +0100659// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
660// needed for hidden API flag generation.
661type HiddenAPIFlagInput struct {
662 // FlagFilesByCategory contains the flag files that override the initial flags that are derived
663 // from the stub dex files.
664 FlagFilesByCategory FlagFilesByCategory
665
Paul Duffin05bbff92021-06-18 18:14:25 +0100666 // StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
Paul Duffin5aadef82021-05-21 22:18:49 +0100667 // the initial flags for each dex member.
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100668 StubDexJarsByScope StubDexJarsByModule
Paul Duffin67c1e572021-05-17 07:38:47 +0100669
Paul Duffin05bbff92021-06-18 18:14:25 +0100670 // DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
671 // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
Paul Duffin67c1e572021-05-17 07:38:47 +0100672 // fragment on which this depends.
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100673 DependencyStubDexJarsByScope StubDexJarsByModule
Paul Duffin54c1f082021-05-18 16:32:50 +0100674
Paul Duffinb3821fe2021-05-26 10:16:01 +0100675 // AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to
676 // the ones that are obtained from fragments on which this depends.
677 //
678 // These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope
679 // as there are not propagated transitively to other fragments that depend on this.
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100680 AdditionalStubDexJarsByScope StubDexJarsByModule
Paul Duffinb3821fe2021-05-26 10:16:01 +0100681
Paul Duffin54c1f082021-05-18 16:32:50 +0100682 // RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
683 // specified in the bootclasspath_fragment's stub_libs and contents properties.
684 RemovedTxtFiles android.Paths
Paul Duffin5aadef82021-05-21 22:18:49 +0100685}
686
687// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
688func newHiddenAPIFlagInput() HiddenAPIFlagInput {
689 input := HiddenAPIFlagInput{
Paul Duffin05bbff92021-06-18 18:14:25 +0100690 FlagFilesByCategory: FlagFilesByCategory{},
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100691 StubDexJarsByScope: StubDexJarsByModule{},
692 DependencyStubDexJarsByScope: StubDexJarsByModule{},
693 AdditionalStubDexJarsByScope: StubDexJarsByModule{},
Paul Duffin5aadef82021-05-21 22:18:49 +0100694 }
695
696 return input
697}
698
699// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
700// dependencies added in hiddenAPIAddStubLibDependencies.
701//
702// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
703func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
Paul Duffin05bbff92021-06-18 18:14:25 +0100704 addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
705 sdkKind := apiScope.sdkKind
706 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
Paul Duffin5aadef82021-05-21 22:18:49 +0100707 if dexJar != nil {
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100708 i.StubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
Paul Duffin5aadef82021-05-21 22:18:49 +0100709 }
Paul Duffin54c1f082021-05-18 16:32:50 +0100710
711 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
Paul Duffin05bbff92021-06-18 18:14:25 +0100712 removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
Paul Duffin54c1f082021-05-18 16:32:50 +0100713 i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
714 }
Paul Duffin5aadef82021-05-21 22:18:49 +0100715 }
716
717 // If the contents includes any java_sdk_library modules then add them to the stubs.
718 for _, module := range contents {
719 if _, ok := module.(SdkLibraryDependency); ok {
Paul Duffin05bbff92021-06-18 18:14:25 +0100720 // Add information for every possible API scope needed by hidden API.
721 for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
722 addFromModule(ctx, module, apiScope)
Paul Duffin5aadef82021-05-21 22:18:49 +0100723 }
724 }
725 }
726
Paul Duffin2a999332021-06-07 21:36:01 +0100727 ctx.VisitDirectDeps(func(module android.Module) {
Paul Duffin5aadef82021-05-21 22:18:49 +0100728 tag := ctx.OtherModuleDependencyTag(module)
729 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
Paul Duffin05bbff92021-06-18 18:14:25 +0100730 apiScope := hiddenAPIStubsTag.apiScope
Paul Duffinb3821fe2021-05-26 10:16:01 +0100731 if hiddenAPIStubsTag.fromAdditionalDependency {
732 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind)
733 if dexJar != nil {
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100734 i.AdditionalStubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
Paul Duffinb3821fe2021-05-26 10:16:01 +0100735 }
736 } else {
737 addFromModule(ctx, module, apiScope)
738 }
Paul Duffin5aadef82021-05-21 22:18:49 +0100739 }
740 })
741
742 // Normalize the paths, i.e. remove duplicates and sort.
Paul Duffin54c1f082021-05-18 16:32:50 +0100743 i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
Paul Duffin5aadef82021-05-21 22:18:49 +0100744}
745
746// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
747// supplied properties and stores them in this struct.
748func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
Paul Duffinc45a86a2021-06-09 14:39:28 +0100749 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin5aadef82021-05-21 22:18:49 +0100750 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
751 i.FlagFilesByCategory[category] = paths
752 }
753}
754
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100755func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByModule {
Paul Duffin05bbff92021-06-18 18:14:25 +0100756 transitive := i.DependencyStubDexJarsByScope
Paul Duffinfb8f07b2021-06-27 20:28:29 +0100757 transitive.addStubDexJarsByModule(i.StubDexJarsByScope)
Paul Duffin67c1e572021-05-17 07:38:47 +0100758 return transitive
759}
760
Paul Duffincad63842021-05-21 16:15:31 +0100761// HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
762// bootclasspath_fragment module.
763type HiddenAPIFlagOutput struct {
764 // The path to the generated stub-flags.csv file.
765 StubFlagsPath android.Path
766
767 // The path to the generated annotation-flags.csv file.
768 AnnotationFlagsPath android.Path
769
770 // The path to the generated metadata.csv file.
771 MetadataPath android.Path
772
773 // The path to the generated index.csv file.
774 IndexPath android.Path
775
776 // The path to the generated all-flags.csv file.
777 AllFlagsPath android.Path
778}
779
Paul Duffin3e2db5c2021-06-02 17:24:22 +0100780// bootDexJarByModule is a map from base module name (without prebuilt_ prefix) to the boot dex
781// path.
782type bootDexJarByModule map[string]android.Path
783
784// addPath adds the path for a module to the map.
785func (b bootDexJarByModule) addPath(module android.Module, path android.Path) {
786 b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path
787}
788
Paul Duffinc75bbce2021-06-07 13:28:19 +0100789// bootDexJars returns the boot dex jar paths sorted by their keys.
790func (b bootDexJarByModule) bootDexJars() android.Paths {
791 paths := android.Paths{}
792 for _, k := range android.SortedStringKeys(b) {
793 paths = append(paths, b[k])
794 }
795 return paths
796}
797
Paul Duffin4fd7dc72021-06-17 19:33:24 +0100798// bootDexJarsWithoutCoverage returns the boot dex jar paths sorted by their keys without coverage
799// libraries if present.
800func (b bootDexJarByModule) bootDexJarsWithoutCoverage() android.Paths {
801 paths := android.Paths{}
802 for _, k := range android.SortedStringKeys(b) {
803 if k == "jacocoagent" {
804 continue
805 }
806 paths = append(paths, b[k])
807 }
808 return paths
809}
810
Paul Duffinc75bbce2021-06-07 13:28:19 +0100811// HiddenAPIOutput encapsulates the output from the hidden API processing.
812type HiddenAPIOutput struct {
813 HiddenAPIFlagOutput
814
815 // The map from base module name to the path to the encoded boot dex file.
816 EncodedBootDexFilesByModule bootDexJarByModule
817}
818
Paul Duffindfa10832021-05-13 17:31:51 +0100819// pathForValidation creates a path of the same type as the supplied type but with a name of
820// <path>.valid.
821//
822// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
823// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
824func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
825 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
826 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
827}
828
Paul Duffin2fef1362021-04-15 13:32:00 +0100829// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
830// the flags from all the modules, the stub flags, augmented with some additional configuration
831// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100832//
833// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
834// an entry for every single member in the dex implementation jars of the individual modules. Every
835// signature in any of the other files MUST be included in this file.
836//
Paul Duffin537ea3d2021-05-14 10:38:00 +0100837// annotationFlags is the path to the annotation flags file generated from annotation information
838// in each module.
Paul Duffin702210b2021-04-08 20:12:41 +0100839//
Paul Duffin71955b42021-05-21 22:18:56 +0100840// hiddenAPIInfo is a struct containing paths to files that augment the information provided by
Paul Duffin537ea3d2021-05-14 10:38:00 +0100841// the annotationFlags.
Paul Duffin54c1f082021-05-18 16:32:50 +0100842func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string,
Paul Duffin2a999332021-06-07 21:36:01 +0100843 outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
Paul Duffin54c1f082021-05-18 16:32:50 +0100844 flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths, generatedRemovedDexSignatures android.OptionalPath) {
Paul Duffindfa10832021-05-13 17:31:51 +0100845
Paul Duffindfa10832021-05-13 17:31:51 +0100846 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100847 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100848 rule := android.NewRuleBuilder(pctx, ctx)
849 command := rule.Command().
850 BuiltTool("generate_hiddenapi_lists").
851 FlagWithInput("--csv ", baseFlagsPath).
Paul Duffin2a999332021-06-07 21:36:01 +0100852 Inputs(annotationFlagPaths).
Paul Duffin702210b2021-04-08 20:12:41 +0100853 FlagWithOutput("--output ", tempPath)
854
Paul Duffine3dc6602021-04-14 09:50:43 +0100855 // Add the options for the different categories of flag files.
Paul Duffinc45a86a2021-06-09 14:39:28 +0100856 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin9e3b9062021-05-21 16:58:23 +0100857 paths := flagFilesByCategory[category]
Paul Duffine3dc6602021-04-14 09:50:43 +0100858 for _, path := range paths {
859 category.commandMutator(command, path)
860 }
Paul Duffin702210b2021-04-08 20:12:41 +0100861 }
862
Paul Duffin54c1f082021-05-18 16:32:50 +0100863 // If available then pass the automatically generated file containing dex signatures of removed
864 // API members to the rule so they can be marked as removed.
865 if generatedRemovedDexSignatures.Valid() {
866 hiddenAPIRemovedFlagFileCategory.commandMutator(command, generatedRemovedDexSignatures.Path())
867 }
868
Paul Duffin702210b2021-04-08 20:12:41 +0100869 commitChangeForRestat(rule, tempPath, outputPath)
870
Paul Duffinaf193422021-06-23 23:29:09 +0100871 // If there are flag files that have been generated by fragments on which this depends then use
872 // them to validate the flag file generated by the rules created by this method.
873 if len(allFlagsPaths) > 0 {
874 validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, allFlagsPaths)
875
Paul Duffindfa10832021-05-13 17:31:51 +0100876 // Add the file that indicates that the file generated by this is valid.
877 //
878 // This will cause the validation rule above to be run any time that the output of this rule
879 // changes but the validation will run in parallel with other rules that depend on this file.
880 command.Validation(validFile)
881 }
882
Paul Duffin2fef1362021-04-15 13:32:00 +0100883 rule.Build(name, desc)
884}
885
Paul Duffinaf193422021-06-23 23:29:09 +0100886// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
887// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
888func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string, monolithicFilePath android.WritablePath, modularFilePaths android.Paths) android.WritablePath {
889 // The file which is used to record that the flags file is valid.
890 validFile := pathForValidation(ctx, monolithicFilePath)
891
892 // Create a rule to validate the output from the following rule.
893 rule := android.NewRuleBuilder(pctx, ctx)
894 rule.Command().
895 BuiltTool("verify_overlaps").
896 Input(monolithicFilePath).
897 Inputs(modularFilePaths).
898 // If validation passes then update the file that records that.
899 Text("&& touch").Output(validFile)
900 rule.Build(name+"Validation", desc+" validation")
901
902 return validFile
903}
904
Paul Duffinc75bbce2021-06-07 13:28:19 +0100905// hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the
906// bootclasspath and then encode the flags into the boot dex files.
Paul Duffin2fef1362021-04-15 13:32:00 +0100907//
908// It takes:
909// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
910// * The list of modules that are the contents of the fragment.
911// * The additional manually curated flag files to use.
912//
913// It generates:
914// * stub-flags.csv
915// * annotation-flags.csv
916// * metadata.csv
917// * index.csv
918// * all-flags.csv
Paul Duffinc75bbce2021-06-07 13:28:19 +0100919// * encoded boot dex files
920func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
Paul Duffin2fef1362021-04-15 13:32:00 +0100921 hiddenApiSubDir := "modular-hiddenapi"
922
Paul Duffinc75bbce2021-06-07 13:28:19 +0100923 // Gather information about the boot dex files for the boot libraries provided by this fragment.
924 bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents)
Paul Duffin5aadef82021-05-21 22:18:49 +0100925
926 // Generate the stub-flags.csv.
Paul Duffin2fef1362021-04-15 13:32:00 +0100927 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
Paul Duffinaf193422021-06-23 23:29:09 +0100928 buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
Paul Duffin2fef1362021-04-15 13:32:00 +0100929
Paul Duffin537ea3d2021-05-14 10:38:00 +0100930 // Extract the classes jars from the contents.
Paul Duffin98ea0d42021-06-10 10:18:22 +0100931 classesJars := extractClassesJarsFromModules(contents)
Paul Duffin537ea3d2021-05-14 10:38:00 +0100932
Paul Duffin2fef1362021-04-15 13:32:00 +0100933 // Generate the set of flags from the annotations in the source code.
934 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100935 buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100936
937 // Generate the metadata from the annotations in the source code.
938 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100939 buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100940
Paul Duffin537ea3d2021-05-14 10:38:00 +0100941 // Generate the index file from the CSV files in the classes jars.
Paul Duffin2fef1362021-04-15 13:32:00 +0100942 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
Paul Duffin850e61f2021-05-14 09:58:48 +0100943 buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +0100944
Paul Duffin71955b42021-05-21 22:18:56 +0100945 // 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 +0100946 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
947 // manually combining all the removed.txt files for each API and then converting them to dex
Paul Duffin54c1f082021-05-18 16:32:50 +0100948 // signatures, see the combined-removed-dex module. This does that automatically by using the
949 // *removed.txt files retrieved from the java_sdk_library modules that are specified in the
950 // stub_libs and contents properties of a bootclasspath_fragment.
951 removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, input.RemovedTxtFiles)
Paul Duffin2fef1362021-04-15 13:32:00 +0100952
953 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
954 // files.
Paul Duffinc75bbce2021-06-07 13:28:19 +0100955 allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
Paul Duffin2a999332021-06-07 21:36:01 +0100956 buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
Paul Duffinc75bbce2021-06-07 13:28:19 +0100957
958 // Encode the flags into the boot dex files.
959 encodedBootDexJarsByModule := map[string]android.Path{}
960 outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath
961 for _, name := range android.SortedStringKeys(bootDexInfoByModule) {
962 bootDexInfo := bootDexInfoByModule[name]
963 unencodedDex := bootDexInfo.path
964 encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, outputDir)
965 encodedBootDexJarsByModule[name] = encodedDex
966 }
Paul Duffin2fef1362021-04-15 13:32:00 +0100967
968 // Store the paths in the info for use by other modules and sdk snapshot generation.
Paul Duffinc75bbce2021-06-07 13:28:19 +0100969 output := HiddenAPIOutput{
970 HiddenAPIFlagOutput: HiddenAPIFlagOutput{
971 StubFlagsPath: stubFlagsCSV,
972 AnnotationFlagsPath: annotationFlagsCSV,
973 MetadataPath: metadataCSV,
974 IndexPath: indexCSV,
975 AllFlagsPath: allFlagsCSV,
976 },
977 EncodedBootDexFilesByModule: encodedBootDexJarsByModule,
Paul Duffincad63842021-05-21 16:15:31 +0100978 }
979 return &output
Paul Duffin702210b2021-04-08 20:12:41 +0100980}
Paul Duffin537ea3d2021-05-14 10:38:00 +0100981
Paul Duffin54c1f082021-05-18 16:32:50 +0100982func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedTxtFiles android.Paths) android.OptionalPath {
983 if len(removedTxtFiles) == 0 {
984 return android.OptionalPath{}
985 }
986
987 output := android.PathForModuleOut(ctx, "modular-hiddenapi/removed-dex-signatures.txt")
988
989 rule := android.NewRuleBuilder(pctx, ctx)
990 rule.Command().
991 BuiltTool("metalava").
992 Flag("--no-banner").
993 Inputs(removedTxtFiles).
994 FlagWithOutput("--dex-api ", output)
995 rule.Build("modular-hiddenapi-removed-dex-signatures", "modular hiddenapi removed dex signatures")
996 return android.OptionalPathForPath(output)
997}
998
Paul Duffin98ea0d42021-06-10 10:18:22 +0100999// extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules.
Paul Duffinc75bbce2021-06-07 13:28:19 +01001000func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
1001 bootDexJars := bootDexJarByModule{}
Paul Duffin537ea3d2021-05-14 10:38:00 +01001002 for _, module := range contents {
Paul Duffin98ea0d42021-06-10 10:18:22 +01001003 hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
1004 if hiddenAPIModule == nil {
1005 continue
1006 }
Paul Duffinc75bbce2021-06-07 13:28:19 +01001007 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
1008 bootDexJars.addPath(module, bootDexJar)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001009 }
1010 return bootDexJars
1011}
1012
Paul Duffin98ea0d42021-06-10 10:18:22 +01001013func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Module) hiddenAPIModule {
1014 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
1015 return hiddenAPIModule
1016 } else if _, ok := module.(*DexImport); ok {
1017 // Ignore this for the purposes of hidden API processing
1018 } else {
1019 ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
1020 }
1021
1022 return nil
1023}
1024
Paul Duffinc75bbce2021-06-07 13:28:19 +01001025// bootDexInfo encapsulates both the path and uncompressDex status retrieved from a hiddenAPIModule.
1026type bootDexInfo struct {
1027 // The path to the dex jar that has not had hidden API flags encoded into it.
1028 path android.Path
1029
1030 // Indicates whether the dex jar needs uncompressing before encoding.
1031 uncompressDex bool
1032}
1033
1034// bootDexInfoByModule is a map from module name (as returned by module.Name()) to the boot dex
1035// path (as returned by hiddenAPIModule.bootDexJar()) and the uncompressDex flag.
1036type bootDexInfoByModule map[string]bootDexInfo
1037
1038// bootDexJars returns the boot dex jar paths sorted by their keys.
1039func (b bootDexInfoByModule) bootDexJars() android.Paths {
1040 paths := android.Paths{}
1041 for _, m := range android.SortedStringKeys(b) {
1042 paths = append(paths, b[m].path)
1043 }
1044 return paths
1045}
1046
1047// extractBootDexInfoFromModules extracts the boot dex jar and uncompress dex state from
1048// each of the supplied modules which must implement hiddenAPIModule.
1049func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android.Module) bootDexInfoByModule {
1050 bootDexJarsByModule := bootDexInfoByModule{}
1051 for _, module := range contents {
1052 hiddenAPIModule := module.(hiddenAPIModule)
1053 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
1054 bootDexJarsByModule[module.Name()] = bootDexInfo{
1055 path: bootDexJar,
1056 uncompressDex: *hiddenAPIModule.uncompressDex(),
1057 }
1058 }
1059
1060 return bootDexJarsByModule
1061}
1062
1063// retrieveBootDexJarFromHiddenAPIModule retrieves the boot dex jar from the hiddenAPIModule.
1064//
1065// If the module does not provide a boot dex jar, i.e. the returned boot dex jar is nil, then that
1066// create a fake path and either report an error immediately or defer reporting of the error until
1067// the path is actually used.
1068func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
1069 bootDexJar := module.bootDexJar()
1070 if bootDexJar == nil {
1071 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
1072 bootDexJar = fake
1073
1074 handleMissingDexBootFile(ctx, module, fake)
1075 }
1076 return bootDexJar
1077}
1078
Paul Duffin98ea0d42021-06-10 10:18:22 +01001079// extractClassesJarsFromModules extracts the class jars from the supplied modules.
1080func extractClassesJarsFromModules(contents []android.Module) android.Paths {
Paul Duffin537ea3d2021-05-14 10:38:00 +01001081 classesJars := android.Paths{}
1082 for _, module := range contents {
Paul Duffin98ea0d42021-06-10 10:18:22 +01001083 classesJars = append(classesJars, retrieveClassesJarsFromModule(module)...)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001084 }
1085 return classesJars
1086}
Paul Duffin3e2db5c2021-06-02 17:24:22 +01001087
Paul Duffin98ea0d42021-06-10 10:18:22 +01001088// retrieveClassesJarsFromModule retrieves the classes jars from the supplied module.
1089func retrieveClassesJarsFromModule(module android.Module) android.Paths {
1090 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
1091 return hiddenAPIModule.classesJars()
1092 }
1093
1094 return nil
1095}
1096
Paul Duffin3e2db5c2021-06-02 17:24:22 +01001097// deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
1098// Soong but should instead only be reported in ninja if the file is actually built.
1099func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
1100 // TODO(b/179354495): Remove this workaround when it is unnecessary.
1101 // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
1102 // create a fake one that will cause a build error only if it is used.
1103 if ctx.Config().AlwaysUsePrebuiltSdks() {
1104 return true
1105 }
1106
Paul Duffinc75bbce2021-06-07 13:28:19 +01001107 // Any missing dependency should be allowed.
1108 if ctx.Config().AllowMissingDependencies() {
1109 return true
1110 }
1111
Paul Duffin3e2db5c2021-06-02 17:24:22 +01001112 // This is called for both platform_bootclasspath and bootclasspath_fragment modules.
1113 //
1114 // A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
1115 // Ideally, a bootclasspath_fragment module should never have a platform variant created for it
1116 // but unfortunately, due to b/187910671 it does.
1117 //
1118 // That causes issues when obtaining a boot dex jar for a prebuilt module as a prebuilt module
1119 // used by a bootclasspath_fragment can only provide a boot dex jar when it is part of APEX, i.e.
1120 // has an APEX variant not a platform variant.
1121 //
1122 // There are some other situations when a prebuilt module used by a bootclasspath_fragment cannot
1123 // provide a boot dex jar:
1124 // 1. If the bootclasspath_fragment is not exported by the prebuilt_apex/apex_set module then it
1125 // does not have an APEX variant and only has a platform variant and neither do its content
1126 // modules.
1127 // 2. Some build configurations, e.g. setting TARGET_BUILD_USE_PREBUILT_SDKS causes all
1128 // java_sdk_library_import modules to be treated as preferred and as many of them are not part
1129 // of an apex they cannot provide a boot dex jar.
1130 //
1131 // The first case causes problems when the affected prebuilt modules are preferred but that is an
1132 // invalid configuration and it is ok for it to fail as the work to enable that is not yet
1133 // complete. The second case is used for building targets that do not use boot dex jars and so
1134 // deferring error reporting to ninja is fine as the affected ninja targets should never be built.
1135 // That is handled above.
1136 //
1137 // A platform_bootclasspath module can use libraries from both platform and APEX variants. Unlike
1138 // the bootclasspath_fragment it supports dex_import modules which provides the dex file. So, it
1139 // can obtain a boot dex jar from a prebuilt that is not part of an APEX. However, it is assumed
1140 // that if the library can be part of an APEX then it is the APEX variant that is used.
1141 //
1142 // This check handles the slightly different requirements of the bootclasspath_fragment and
1143 // platform_bootclasspath modules by only deferring error reporting for the platform variant of
1144 // a prebuilt modules that has other variants which are part of an APEX.
1145 //
1146 // TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
1147 if android.IsModulePrebuilt(module) {
1148 if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
1149 apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
1150 if apexInfo.IsForPlatform() {
1151 return true
1152 }
1153 }
1154 }
1155
1156 // A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there
1157 // is no equivalently versioned prebuilt APEX file from which it can be obtained. However,
1158 // versioned bootclasspath modules are processed by Soong so in order to avoid them causing build
1159 // failures missing boot dex jars need to be deferred.
1160 if android.IsModuleInVersionedSdk(ctx.Module()) {
1161 return true
1162 }
1163
1164 return false
1165}
1166
1167// handleMissingDexBootFile will either log a warning or create an error rule to create the fake
1168// file depending on the value returned from deferReportingMissingBootDexJar.
1169func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath) {
1170 if deferReportingMissingBootDexJar(ctx, module) {
1171 // Create an error rule that pretends to create the output file but will actually fail if it
1172 // is run.
1173 ctx.Build(pctx, android.BuildParams{
1174 Rule: android.ErrorRule,
1175 Output: fake,
1176 Args: map[string]string{
1177 "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
1178 },
1179 })
1180 } else {
1181 ctx.ModuleErrorf("module %s does not provide a dex jar", module)
1182 }
1183}
1184
1185// retrieveEncodedBootDexJarFromModule returns a path to the boot dex jar from the supplied module's
1186// DexJarBuildPath() method.
1187//
1188// The returned path will usually be to a dex jar file that has been encoded with hidden API flags.
1189// However, under certain conditions, e.g. errors, or special build configurations it will return
1190// a path to a fake file.
1191func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
1192 bootDexJar := module.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath()
1193 if bootDexJar == nil {
1194 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
1195 bootDexJar = fake
1196
1197 handleMissingDexBootFile(ctx, module, fake)
1198 }
1199 return bootDexJar
1200}
1201
1202// extractEncodedDexJarsFromModules extracts the encoded dex jars from the supplied modules.
1203func extractEncodedDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
1204 encodedDexJarsByModuleName := bootDexJarByModule{}
1205 for _, module := range contents {
1206 path := retrieveEncodedBootDexJarFromModule(ctx, module)
1207 encodedDexJarsByModuleName.addPath(module, path)
1208 }
1209 return encodedDexJarsByModuleName
1210}