blob: 81be33dd1bec22fefed893544c1ea119a2b745a2 [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"
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +010022
Paul Duffin9b381ef2021-04-08 23:01:37 +010023 "github.com/google/blueprint"
Paul Duffinc6bb7cf2021-04-08 17:49:27 +010024)
25
26// Contains support for processing hiddenAPI in a modular fashion.
27
Paul Duffin31fad802021-06-18 18:14:25 +010028// HiddenAPIScope encapsulates all the information that the hidden API processing needs about API
29// scopes, i.e. what is called android.SdkKind and apiScope. It does not just use those as they do
30// not provide the information needed by hidden API processing.
31type HiddenAPIScope struct {
32 // The name of the scope, used for debug purposes.
33 name string
34
35 // The corresponding android.SdkKind, used for retrieving paths from java_sdk_library* modules.
36 sdkKind android.SdkKind
37
38 // The option needed to passed to "hiddenapi list".
39 hiddenAPIListOption string
Paul Duffin5cca7c42021-05-26 10:16:01 +010040
Jihoon Kang244d42a2023-10-06 16:54:58 +000041 // The names of the source stub library modules that contain the API provided by the platform,
Paul Duffin5cca7c42021-05-26 10:16:01 +010042 // i.e. by modules that are not in an APEX.
43 nonUpdatableSourceModule string
44
Jihoon Kang244d42a2023-10-06 16:54:58 +000045 // The names of from-text stub library modules that contain the API provided by the platform,
46 // i.e. by modules that are not in an APEX.
47 nonUpdatableFromTextModule string
48
Paul Duffin5cca7c42021-05-26 10:16:01 +010049 // The names of the prebuilt stub library modules that contain the API provided by the platform,
50 // i.e. by modules that are not in an APEX.
51 nonUpdatablePrebuiltModule string
Paul Duffin31fad802021-06-18 18:14:25 +010052}
53
54// initHiddenAPIScope initializes the scope.
55func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
Paul Duffin5cca7c42021-05-26 10:16:01 +010056 sdkKind := apiScope.sdkKind
57 // The platform does not provide a core platform API.
58 if sdkKind != android.SdkCorePlatform {
59 kindAsString := sdkKind.String()
60 var insert string
61 if sdkKind == android.SdkPublic {
62 insert = ""
63 } else {
64 insert = "." + strings.ReplaceAll(kindAsString, "-", "_")
65 }
66
67 nonUpdatableModule := "android-non-updatable"
68
69 // Construct the name of the android-non-updatable source module for this scope.
70 apiScope.nonUpdatableSourceModule = fmt.Sprintf("%s.stubs%s", nonUpdatableModule, insert)
71
72 prebuiltModuleName := func(name string, kind string) string {
73 return fmt.Sprintf("sdk_%s_current_%s", kind, name)
74 }
75
76 // Construct the name of the android-non-updatable prebuilt module for this scope.
77 apiScope.nonUpdatablePrebuiltModule = prebuiltModuleName(nonUpdatableModule, kindAsString)
78 }
79
Paul Duffin31fad802021-06-18 18:14:25 +010080 return apiScope
81}
82
Paul Duffin5cca7c42021-05-26 10:16:01 +010083// android-non-updatable takes the name of a module and returns a possibly scope specific name of
84// the module.
85func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, name string) string {
86 // The android-non-updatable is not a java_sdk_library but there are separate stub libraries for
87 // each scope.
88 // TODO(b/192067200): Remove special handling of android-non-updatable.
89 if name == "android-non-updatable" {
90 if ctx.Config().AlwaysUsePrebuiltSdks() {
91 return l.nonUpdatablePrebuiltModule
92 } else {
Jihoon Kang244d42a2023-10-06 16:54:58 +000093 if l.nonUpdatableFromTextModule != "" && ctx.Config().BuildFromTextStub() {
94 return l.nonUpdatableFromTextModule
95 }
Paul Duffin5cca7c42021-05-26 10:16:01 +010096 return l.nonUpdatableSourceModule
97 }
98 } else {
99 // Assume that the module is either a java_sdk_library (or equivalent) and so will provide
100 // separate stub jars for each scope or is a java_library (or equivalent) in which case it will
101 // have the same stub jar for each scope.
102 return name
103 }
104}
105
Paul Duffin31fad802021-06-18 18:14:25 +0100106func (l *HiddenAPIScope) String() string {
107 return fmt.Sprintf("HiddenAPIScope{%s}", l.name)
108}
109
110var (
111 PublicHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
112 name: "public",
113 sdkKind: android.SdkPublic,
114 hiddenAPIListOption: "--public-stub-classpath",
115 })
116 SystemHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
117 name: "system",
118 sdkKind: android.SdkSystem,
119 hiddenAPIListOption: "--system-stub-classpath",
120 })
121 TestHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
122 name: "test",
123 sdkKind: android.SdkTest,
124 hiddenAPIListOption: "--test-stub-classpath",
125 })
Paul Duffinb51db2e2021-06-21 14:08:08 +0100126 ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
Jihoon Kang244d42a2023-10-06 16:54:58 +0000127 name: "module-lib",
128 sdkKind: android.SdkModule,
129 nonUpdatableFromTextModule: "android-non-updatable.stubs.test_module_lib",
Paul Duffinb51db2e2021-06-21 14:08:08 +0100130 })
Paul Duffin31fad802021-06-18 18:14:25 +0100131 CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
132 name: "core-platform",
133 sdkKind: android.SdkCorePlatform,
134 hiddenAPIListOption: "--core-platform-stub-classpath",
135 })
136
137 // hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
138 // API processing.
139 //
140 // These are roughly in order from narrowest API surface to widest. Widest means the API stubs
141 // with the biggest API surface, e.g. test is wider than system is wider than public.
142 //
Paul Duffinb51db2e2021-06-21 14:08:08 +0100143 // Core platform is considered wider than system/module-lib because those modules that provide
144 // core platform APIs either do not have any system/module-lib APIs at all, or if they do it is
145 // because the core platform API is being converted to system/module-lib APIs. In either case the
146 // system/module-lib APIs are subsets of the core platform API.
Paul Duffin31fad802021-06-18 18:14:25 +0100147 //
148 // 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 +0100149 // is neither wider or narrower than the module-lib or core platform APIs. However, this works
150 // well enough at the moment.
Paul Duffin31fad802021-06-18 18:14:25 +0100151 // TODO(b/191644675): Correctly reflect the sub/superset relationships between APIs.
152 hiddenAPIScopes = []*HiddenAPIScope{
153 PublicHiddenAPIScope,
154 SystemHiddenAPIScope,
155 TestHiddenAPIScope,
Paul Duffinb51db2e2021-06-21 14:08:08 +0100156 ModuleLibHiddenAPIScope,
Paul Duffin31fad802021-06-18 18:14:25 +0100157 CorePlatformHiddenAPIScope,
158 }
159
160 // The HiddenAPIScope instances that are supported by a java_sdk_library.
161 //
162 // CorePlatformHiddenAPIScope is not used as the java_sdk_library does not have special support
163 // for core_platform API, instead it is implemented as a customized form of PublicHiddenAPIScope.
164 hiddenAPISdkLibrarySupportedScopes = []*HiddenAPIScope{
165 PublicHiddenAPIScope,
166 SystemHiddenAPIScope,
167 TestHiddenAPIScope,
Paul Duffinb51db2e2021-06-21 14:08:08 +0100168 ModuleLibHiddenAPIScope,
Paul Duffin31fad802021-06-18 18:14:25 +0100169 }
170
171 // The HiddenAPIScope instances that are supported by the `hiddenapi list`.
172 hiddenAPIFlagScopes = []*HiddenAPIScope{
173 PublicHiddenAPIScope,
174 SystemHiddenAPIScope,
175 TestHiddenAPIScope,
176 CorePlatformHiddenAPIScope,
177 }
178)
179
Paul Duffin74431d52021-04-21 14:10:42 +0100180type hiddenAPIStubsDependencyTag struct {
181 blueprint.BaseDependencyTag
Paul Duffin31fad802021-06-18 18:14:25 +0100182
183 // The api scope for which this dependency was added.
184 apiScope *HiddenAPIScope
Paul Duffin5cca7c42021-05-26 10:16:01 +0100185
186 // Indicates that the dependency is not for an API provided by the current bootclasspath fragment
187 // but is an additional API provided by a module that is not part of the current bootclasspath
188 // fragment.
189 fromAdditionalDependency bool
Paul Duffin74431d52021-04-21 14:10:42 +0100190}
191
192func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
193}
194
195func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
196 return false
197}
198
Paul Duffin976b0e52021-04-27 23:20:26 +0100199func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
Paul Duffin5cca7c42021-05-26 10:16:01 +0100200 // Do not add additional dependencies to the sdk.
201 if b.fromAdditionalDependency {
202 return nil
203 }
204
Paul Duffin976b0e52021-04-27 23:20:26 +0100205 // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
206 // property, otherwise treat if it was specified in the java_header_libs property.
207 if javaSdkLibrarySdkMemberType.IsInstance(child) {
208 return javaSdkLibrarySdkMemberType
209 }
210
211 return javaHeaderLibsSdkMemberType
212}
213
214func (b hiddenAPIStubsDependencyTag) ExportMember() bool {
215 // Export the module added via this dependency tag from the sdk.
216 return true
217}
218
Paul Duffin74431d52021-04-21 14:10:42 +0100219// Avoid having to make stubs content explicitly visible to dependent modules.
220//
221// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
222// with proper dependencies.
223// TODO(b/177892522): Remove this and add needed visibility.
224func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
225}
226
227var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
228var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
229var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
Paul Duffinf7b3d0d2021-09-02 14:29:21 +0100230var _ android.SdkMemberDependencyTag = hiddenAPIStubsDependencyTag{}
Paul Duffin74431d52021-04-21 14:10:42 +0100231
Paul Duffin74431d52021-04-21 14:10:42 +0100232// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
233// needed to produce the hidden API monolithic stub flags file.
Paul Duffin31fad802021-06-18 18:14:25 +0100234func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*HiddenAPIScope][]string {
Paul Duffin74431d52021-04-21 14:10:42 +0100235 var publicStubModules []string
236 var systemStubModules []string
237 var testStubModules []string
238 var corePlatformStubModules []string
239
240 if config.AlwaysUsePrebuiltSdks() {
241 // Build configuration mandates using prebuilt stub modules
242 publicStubModules = append(publicStubModules, "sdk_public_current_android")
243 systemStubModules = append(systemStubModules, "sdk_system_current_android")
244 testStubModules = append(testStubModules, "sdk_test_current_android")
245 } else {
246 // Use stub modules built from source
Jihoon Kang91c83952023-05-30 19:12:28 +0000247 publicStubModules = append(publicStubModules, android.SdkPublic.DefaultJavaLibraryName())
248 systemStubModules = append(systemStubModules, android.SdkSystem.DefaultJavaLibraryName())
249 testStubModules = append(testStubModules, android.SdkTest.DefaultJavaLibraryName())
Paul Duffin74431d52021-04-21 14:10:42 +0100250 }
251 // We do not have prebuilts of the core platform api yet
Jihoon Kang91c83952023-05-30 19:12:28 +0000252 corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
Paul Duffin74431d52021-04-21 14:10:42 +0100253
254 // Allow products to define their own stubs for custom product jars that apps can use.
255 publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
256 systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
257 testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
258 if config.IsEnvTrue("EMMA_INSTRUMENT") {
Paul Duffin098c8782021-05-14 10:45:25 +0100259 // Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
260 // allows everyone access but it is needed to ensure consistent flags between the
261 // bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
Paul Duffin74431d52021-04-21 14:10:42 +0100262 publicStubModules = append(publicStubModules, "jacoco-stubs")
Paul Duffin098c8782021-05-14 10:45:25 +0100263 systemStubModules = append(systemStubModules, "jacoco-stubs")
264 testStubModules = append(testStubModules, "jacoco-stubs")
Paul Duffin74431d52021-04-21 14:10:42 +0100265 }
266
Paul Duffin31fad802021-06-18 18:14:25 +0100267 m := map[*HiddenAPIScope][]string{}
268 m[PublicHiddenAPIScope] = publicStubModules
269 m[SystemHiddenAPIScope] = systemStubModules
270 m[TestHiddenAPIScope] = testStubModules
271 m[CorePlatformHiddenAPIScope] = corePlatformStubModules
Paul Duffin74431d52021-04-21 14:10:42 +0100272 return m
273}
274
275// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
Paul Duffin31fad802021-06-18 18:14:25 +0100276// apiScopeToStubLibModules. It adds them in a well known order and uses a HiddenAPIScope specific
277// tag to identify the source of the dependency.
278func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScopeToStubLibModules map[*HiddenAPIScope][]string) {
Paul Duffin74431d52021-04-21 14:10:42 +0100279 module := ctx.Module()
Paul Duffin31fad802021-06-18 18:14:25 +0100280 for _, apiScope := range hiddenAPIScopes {
281 modules := apiScopeToStubLibModules[apiScope]
282 ctx.AddDependency(module, hiddenAPIStubsDependencyTag{apiScope: apiScope}, modules...)
Paul Duffin74431d52021-04-21 14:10:42 +0100283 }
284}
285
Paul Duffin74431d52021-04-21 14:10:42 +0100286// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
287// available, or reports an error.
Paul Duffin10931582021-04-25 10:13:54 +0100288func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +0100289 var dexJar OptionalDexJarPath
Paul Duffin10931582021-04-25 10:13:54 +0100290 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
291 dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
292 } else if j, ok := module.(UsesLibraryDependency); ok {
293 dexJar = j.DexJarBuildPath()
Paul Duffin74431d52021-04-21 14:10:42 +0100294 } else {
295 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 +0100296 return nil
Paul Duffin74431d52021-04-21 14:10:42 +0100297 }
Paul Duffin10931582021-04-25 10:13:54 +0100298
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +0100299 if !dexJar.Valid() {
300 ctx.ModuleErrorf("dependency %s does not provide a dex jar: %s", module, dexJar.InvalidReason())
301 return nil
Paul Duffin10931582021-04-25 10:13:54 +0100302 }
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +0100303 return dexJar.Path()
Paul Duffin74431d52021-04-21 14:10:42 +0100304}
305
Paul Duffinbd88c882022-04-07 23:32:19 +0100306// HIDDENAPI_STUB_FLAGS_IMPL_FLAGS is the set of flags that identify implementation only signatures,
307// i.e. those signatures that are not part of any API (including the hidden API).
308var HIDDENAPI_STUB_FLAGS_IMPL_FLAGS = []string{}
309
310var HIDDENAPI_FLAGS_CSV_IMPL_FLAGS = []string{"blocked"}
311
Paul Duffin4539a372021-06-23 23:20:43 +0100312// buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
Paul Duffin74431d52021-04-21 14:10:42 +0100313//
314// The rule is initialized but not built so that the caller can modify it and select an appropriate
315// name.
Paul Duffin67b9d612021-07-21 17:38:47 +0100316func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput, stubFlagSubsets SignatureCsvSubsets) {
Paul Duffin74431d52021-04-21 14:10:42 +0100317 // Singleton rule which applies hiddenapi on all boot class path dex files.
318 rule := android.NewRuleBuilder(pctx, ctx)
319
320 tempPath := tempPathForRestat(ctx, outputPath)
321
Paul Duffinf1b358c2021-05-17 07:38:47 +0100322 // Find the widest API stubs provided by the fragments on which this depends, if any.
Paul Duffind2b1e0c2021-06-27 20:53:39 +0100323 dependencyStubDexJars := input.DependencyStubDexJarsByScope.StubDexJarsForWidestAPIScope()
Paul Duffin5cca7c42021-05-26 10:16:01 +0100324
325 // Add widest API stubs from the additional dependencies of this, if any.
Paul Duffind2b1e0c2021-06-27 20:53:39 +0100326 dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.StubDexJarsForWidestAPIScope()...)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100327
Paul Duffin74431d52021-04-21 14:10:42 +0100328 command := rule.Command().
329 Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
330 Text("list").
Paul Duffinf1b358c2021-05-17 07:38:47 +0100331 FlagForEachInput("--dependency-stub-dex=", dependencyStubDexJars).
Paul Duffin74431d52021-04-21 14:10:42 +0100332 FlagForEachInput("--boot-dex=", bootDexJars)
333
Paul Duffin156b5d32021-06-24 23:06:52 +0100334 // If no module stub flags paths are provided then this must be being called for a
335 // bootclasspath_fragment and not the whole platform_bootclasspath.
Paul Duffin67b9d612021-07-21 17:38:47 +0100336 if stubFlagSubsets == nil {
Paul Duffin156b5d32021-06-24 23:06:52 +0100337 // This is being run on a fragment of the bootclasspath.
338 command.Flag("--fragment")
339 }
340
Paul Duffin31fad802021-06-18 18:14:25 +0100341 // Iterate over the api scopes in a fixed order.
342 for _, apiScope := range hiddenAPIFlagScopes {
343 // Merge in the stub dex jar paths for this api scope from the fragments on which it depends.
344 // They will be needed to resolve dependencies from this fragment's stubs to classes in the
345 // other fragment's APIs.
346 var paths android.Paths
Paul Duffin280a31a2021-06-27 20:28:29 +0100347 paths = append(paths, input.DependencyStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
348 paths = append(paths, input.AdditionalStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
349 paths = append(paths, input.StubDexJarsByScope.StubDexJarsForScope(apiScope)...)
Paul Duffin74431d52021-04-21 14:10:42 +0100350 if len(paths) > 0 {
Paul Duffin31fad802021-06-18 18:14:25 +0100351 option := apiScope.hiddenAPIListOption
352 command.FlagWithInputList(option+"=", paths, ":")
Paul Duffin74431d52021-04-21 14:10:42 +0100353 }
354 }
355
356 // Add the output path.
357 command.FlagWithOutput("--out-api-flags=", tempPath)
358
Paul Duffin2e880972021-06-23 23:29:09 +0100359 // If there are stub flag files that have been generated by fragments on which this depends then
360 // use them to validate the stub flag file generated by the rules created by this method.
Paul Duffin67b9d612021-07-21 17:38:47 +0100361 if len(stubFlagSubsets) > 0 {
Paul Duffinbd88c882022-04-07 23:32:19 +0100362 validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets,
363 HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
Paul Duffin2e880972021-06-23 23:29:09 +0100364
365 // Add the file that indicates that the file generated by this is valid.
366 //
367 // This will cause the validation rule above to be run any time that the output of this rule
368 // changes but the validation will run in parallel with other rules that depend on this file.
369 command.Validation(validFile)
370 }
371
Paul Duffin74431d52021-04-21 14:10:42 +0100372 commitChangeForRestat(rule, tempPath, outputPath)
Paul Duffin4539a372021-06-23 23:20:43 +0100373
374 rule.Build(name, desc)
Paul Duffin74431d52021-04-21 14:10:42 +0100375}
376
Paul Duffin46169772021-04-14 15:01:56 +0100377// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
378// information obtained from annotations within the source code in order to create the complete set
379// of flags that should be applied to the dex implementation jars on the bootclasspath.
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100380//
381// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
382// of each property reference a plain text file that contains a java signature per line. The flags
383// for each of those signatures will be updated in a property specific way.
384//
385// The Unsupported_packages property contains a list of paths, each of which is a plain text file
386// with one Java package per line. All members of all classes within that package (but not nested
387// packages) will be updated in a property specific way.
Paul Duffin46169772021-04-14 15:01:56 +0100388type HiddenAPIFlagFileProperties struct {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000389 Hidden_api struct {
390 // Marks each signature in the referenced files as being unsupported.
391 Unsupported []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100392
Paul Duffin9b61abb2022-07-27 16:16:54 +0000393 // Marks each signature in the referenced files as being unsupported because it has been
394 // removed. Any conflicts with other flags are ignored.
395 Removed []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100396
Paul Duffin9b61abb2022-07-27 16:16:54 +0000397 // Marks each signature in the referenced files as being supported only for
398 // targetSdkVersion <= R and low priority.
399 Max_target_r_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100400
Paul Duffin9b61abb2022-07-27 16:16:54 +0000401 // Marks each signature in the referenced files as being supported only for
402 // targetSdkVersion <= Q.
403 Max_target_q []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100404
Paul Duffin9b61abb2022-07-27 16:16:54 +0000405 // Marks each signature in the referenced files as being supported only for
406 // targetSdkVersion <= P.
407 Max_target_p []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100408
Paul Duffin9b61abb2022-07-27 16:16:54 +0000409 // Marks each signature in the referenced files as being supported only for
410 // targetSdkVersion <= O
411 // and low priority. Any conflicts with other flags are ignored.
412 Max_target_o_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100413
Paul Duffin9b61abb2022-07-27 16:16:54 +0000414 // Marks each signature in the referenced files as being blocked.
415 Blocked []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100416
Paul Duffin9b61abb2022-07-27 16:16:54 +0000417 // Marks each signature in every package in the referenced files as being unsupported.
418 Unsupported_packages []string `android:"path"`
419 }
Paul Duffin702210b2021-04-08 20:12:41 +0100420}
421
Paul Duffine3dc6602021-04-14 09:50:43 +0100422type hiddenAPIFlagFileCategory struct {
Paul Duffin524c82c2021-06-09 14:39:28 +0100423 // PropertyName is the name of the property for this category.
424 PropertyName string
Paul Duffine3dc6602021-04-14 09:50:43 +0100425
Paul Duffincc17bfe2021-04-19 13:21:20 +0100426 // propertyValueReader retrieves the value of the property for this category from the set of
Paul Duffine3dc6602021-04-14 09:50:43 +0100427 // properties.
Paul Duffincc17bfe2021-04-19 13:21:20 +0100428 propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
Paul Duffine3dc6602021-04-14 09:50:43 +0100429
430 // commandMutator adds the appropriate command line options for this category to the supplied
431 // command
432 commandMutator func(command *android.RuleBuilderCommand, path android.Path)
433}
434
Paul Duffin32cf58a2021-05-18 16:32:50 +0100435// The flag file category for removed members of the API.
436//
Paul Duffin524c82c2021-06-09 14:39:28 +0100437// This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
Paul Duffin32cf58a2021-05-18 16:32:50 +0100438// list of removed API members that are generated automatically from the removed.txt files provided
439// by API stubs.
440var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{
441 // See HiddenAPIFlagFileProperties.Removed
Paul Duffin524c82c2021-06-09 14:39:28 +0100442 PropertyName: "removed",
Paul Duffin32cf58a2021-05-18 16:32:50 +0100443 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000444 return properties.Hidden_api.Removed
Paul Duffin32cf58a2021-05-18 16:32:50 +0100445 },
446 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
447 command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
448 },
449}
450
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000451type hiddenAPIFlagFileCategories []*hiddenAPIFlagFileCategory
452
453func (c hiddenAPIFlagFileCategories) byProperty(name string) *hiddenAPIFlagFileCategory {
454 for _, category := range c {
455 if category.PropertyName == name {
456 return category
457 }
458 }
459 panic(fmt.Errorf("no category exists with property name %q in %v", name, c))
460}
461
462var HiddenAPIFlagFileCategories = hiddenAPIFlagFileCategories{
Paul Duffin46169772021-04-14 15:01:56 +0100463 // See HiddenAPIFlagFileProperties.Unsupported
Paul Duffine3dc6602021-04-14 09:50:43 +0100464 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100465 PropertyName: "unsupported",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100466 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000467 return properties.Hidden_api.Unsupported
Paul Duffine3dc6602021-04-14 09:50:43 +0100468 },
469 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
470 command.FlagWithInput("--unsupported ", path)
471 },
472 },
Paul Duffin32cf58a2021-05-18 16:32:50 +0100473 hiddenAPIRemovedFlagFileCategory,
Paul Duffin46169772021-04-14 15:01:56 +0100474 // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100475 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100476 PropertyName: "max_target_r_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100477 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000478 return properties.Hidden_api.Max_target_r_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100479 },
480 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
481 command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
482 },
483 },
Paul Duffin46169772021-04-14 15:01:56 +0100484 // See HiddenAPIFlagFileProperties.Max_target_q
Paul Duffine3dc6602021-04-14 09:50:43 +0100485 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100486 PropertyName: "max_target_q",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100487 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000488 return properties.Hidden_api.Max_target_q
Paul Duffine3dc6602021-04-14 09:50:43 +0100489 },
490 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
491 command.FlagWithInput("--max-target-q ", path)
492 },
493 },
Paul Duffin46169772021-04-14 15:01:56 +0100494 // See HiddenAPIFlagFileProperties.Max_target_p
Paul Duffine3dc6602021-04-14 09:50:43 +0100495 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100496 PropertyName: "max_target_p",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100497 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000498 return properties.Hidden_api.Max_target_p
Paul Duffine3dc6602021-04-14 09:50:43 +0100499 },
500 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
501 command.FlagWithInput("--max-target-p ", path)
502 },
503 },
Paul Duffin46169772021-04-14 15:01:56 +0100504 // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100505 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100506 PropertyName: "max_target_o_low_priority",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100507 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000508 return properties.Hidden_api.Max_target_o_low_priority
Paul Duffine3dc6602021-04-14 09:50:43 +0100509 },
510 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
511 command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
512 },
513 },
Paul Duffin46169772021-04-14 15:01:56 +0100514 // See HiddenAPIFlagFileProperties.Blocked
Paul Duffine3dc6602021-04-14 09:50:43 +0100515 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100516 PropertyName: "blocked",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100517 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000518 return properties.Hidden_api.Blocked
Paul Duffine3dc6602021-04-14 09:50:43 +0100519 },
520 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
521 command.FlagWithInput("--blocked ", path)
522 },
523 },
Paul Duffin46169772021-04-14 15:01:56 +0100524 // See HiddenAPIFlagFileProperties.Unsupported_packages
Paul Duffine3dc6602021-04-14 09:50:43 +0100525 {
Paul Duffin524c82c2021-06-09 14:39:28 +0100526 PropertyName: "unsupported_packages",
Paul Duffincc17bfe2021-04-19 13:21:20 +0100527 propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000528 return properties.Hidden_api.Unsupported_packages
Paul Duffine3dc6602021-04-14 09:50:43 +0100529 },
530 commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
531 command.FlagWithInput("--unsupported ", path).Flag("--packages ")
532 },
533 },
Paul Duffin702210b2021-04-08 20:12:41 +0100534}
535
Paul Duffin438eb572021-05-21 16:58:23 +0100536// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
537type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths
538
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000539// append the supplied flags files to the corresponding category in this map.
Paul Duffin438eb572021-05-21 16:58:23 +0100540func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
Paul Duffin524c82c2021-06-09 14:39:28 +0100541 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +0100542 s[category] = append(s[category], other[category]...)
543 }
544}
545
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000546// sort the paths for each category in this map.
547func (s FlagFilesByCategory) sort() {
548 for category, value := range s {
549 s[category] = android.SortedUniquePaths(value)
550 }
551}
552
Paul Duffinaf99afa2021-05-21 22:18:56 +0100553// HiddenAPIInfo contains information provided by the hidden API processing.
Paul Duffin2fef1362021-04-15 13:32:00 +0100554//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100555// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
556// processing.
557type HiddenAPIInfo struct {
Paul Duffin438eb572021-05-21 16:58:23 +0100558 // FlagFilesByCategory maps from the flag file category to the paths containing information for
559 // that category.
560 FlagFilesByCategory FlagFilesByCategory
Paul Duffin2fef1362021-04-15 13:32:00 +0100561
Paul Duffin280a31a2021-06-27 20:28:29 +0100562 // The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes provided by
563 // this fragment and the fragments on which this depends.
564 TransitiveStubDexJarsByScope StubDexJarsByModule
Paul Duffin18cf1972021-05-21 22:46:59 +0100565
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100566 // The output from the hidden API processing needs to be made available to other modules.
567 HiddenAPIFlagOutput
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100568}
Paul Duffin702210b2021-04-08 20:12:41 +0100569
Paul Duffinf1b358c2021-05-17 07:38:47 +0100570func newHiddenAPIInfo() *HiddenAPIInfo {
571 info := HiddenAPIInfo{
Paul Duffin31fad802021-06-18 18:14:25 +0100572 FlagFilesByCategory: FlagFilesByCategory{},
Paul Duffin280a31a2021-06-27 20:28:29 +0100573 TransitiveStubDexJarsByScope: StubDexJarsByModule{},
Paul Duffinf1b358c2021-05-17 07:38:47 +0100574 }
575 return &info
576}
577
578func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragments []android.Module) {
579 // Merge all the information from the fragments. The fragments form a DAG so it is possible that
580 // this will introduce duplicates so they will be resolved after processing all the fragments.
581 for _, fragment := range fragments {
582 if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
583 info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
Paul Duffin280a31a2021-06-27 20:28:29 +0100584 i.TransitiveStubDexJarsByScope.addStubDexJarsByModule(info.TransitiveStubDexJarsByScope)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100585 }
586 }
Paul Duffinf1b358c2021-05-17 07:38:47 +0100587}
588
Paul Duffin191be3a2021-08-10 16:14:16 +0100589// StubFlagSubset returns a SignatureCsvSubset that contains a path to a filtered-stub-flags.csv
590// file and a path to a signature-patterns.csv file that defines a subset of the monolithic stub
591// flags file, i.e. out/soong/hiddenapi/hiddenapi-stub-flags.txt, against which it will be compared.
Paul Duffin67b9d612021-07-21 17:38:47 +0100592func (i *HiddenAPIInfo) StubFlagSubset() SignatureCsvSubset {
Paul Duffin191be3a2021-08-10 16:14:16 +0100593 return SignatureCsvSubset{i.FilteredStubFlagsPath, i.SignaturePatternsPath}
Paul Duffin67b9d612021-07-21 17:38:47 +0100594}
595
Paul Duffin191be3a2021-08-10 16:14:16 +0100596// FlagSubset returns a SignatureCsvSubset that contains a path to a filtered-flags.csv file and a
Paul Duffin67b9d612021-07-21 17:38:47 +0100597// path to a signature-patterns.csv file that defines a subset of the monolithic flags file, i.e.
598// out/soong/hiddenapi/hiddenapi-flags.csv, against which it will be compared.
599func (i *HiddenAPIInfo) FlagSubset() SignatureCsvSubset {
Paul Duffin191be3a2021-08-10 16:14:16 +0100600 return SignatureCsvSubset{i.FilteredFlagsPath, i.SignaturePatternsPath}
Paul Duffin67b9d612021-07-21 17:38:47 +0100601}
602
Paul Duffinaf99afa2021-05-21 22:18:56 +0100603var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
Paul Duffin9b381ef2021-04-08 23:01:37 +0100604
Paul Duffin887efdd2022-09-14 16:37:12 +0100605// HiddenAPIInfoForSdk contains information provided by the hidden API processing for use
606// by the sdk snapshot.
607//
608// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
609// processing.
610type HiddenAPIInfoForSdk struct {
611 // FlagFilesByCategory maps from the flag file category to the paths containing information for
612 // that category.
613 FlagFilesByCategory FlagFilesByCategory
614
615 // The output from the hidden API processing needs to be made available to other modules.
616 HiddenAPIFlagOutput
617}
618
619// Provides hidden API info for the sdk snapshot.
620var HiddenAPIInfoForSdkProvider = blueprint.NewProvider(HiddenAPIInfoForSdk{})
621
Paul Duffin280a31a2021-06-27 20:28:29 +0100622// ModuleStubDexJars contains the stub dex jars provided by a single module.
623//
624// It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See
625// hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
626type ModuleStubDexJars map[*HiddenAPIScope]android.Path
Paul Duffin1352f7c2021-05-21 22:18:49 +0100627
Paul Duffin280a31a2021-06-27 20:28:29 +0100628// stubDexJarForWidestAPIScope returns the stub dex jars for the widest API scope provided by this
Paul Duffin1352f7c2021-05-21 22:18:49 +0100629// map.
Paul Duffin280a31a2021-06-27 20:28:29 +0100630//
631// The relative width of APIs is determined by their order in hiddenAPIScopes.
632func (s ModuleStubDexJars) stubDexJarForWidestAPIScope() android.Path {
Paul Duffin5cca7c42021-05-26 10:16:01 +0100633 for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
634 apiScope := hiddenAPIScopes[i]
Paul Duffin280a31a2021-06-27 20:28:29 +0100635 if stubsForAPIScope, ok := s[apiScope]; ok {
Paul Duffin5cca7c42021-05-26 10:16:01 +0100636 return stubsForAPIScope
637 }
638 }
639
640 return nil
641}
642
Paul Duffin280a31a2021-06-27 20:28:29 +0100643// StubDexJarsByModule contains the stub dex jars provided by a set of modules.
644//
645// It maps a module name to the path to the stub dex jars provided by that module.
646type StubDexJarsByModule map[string]ModuleStubDexJars
647
648// addStubDexJar adds a stub dex jar path provided by the specified module for the specified scope.
649func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.Module, scope *HiddenAPIScope, stubDexJar android.Path) {
650 name := android.RemoveOptionalPrebuiltPrefix(module.Name())
Paul Duffin3f0290e2021-06-30 18:25:36 +0100651
652 // Each named module provides one dex jar for each scope. However, in some cases different API
653 // versions of a single classes are provided by separate modules. e.g. the core platform
654 // version of java.lang.Object is provided by the legacy.art.module.platform.api module but the
655 // public version is provided by the art.module.public.api module. In those cases it is necessary
656 // to treat all those modules as they were the same name, otherwise it will result in multiple
657 // definitions of a single class being passed to hidden API processing which will cause an error.
Jihoon Kang244d42a2023-10-06 16:54:58 +0000658 if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule || name == scope.nonUpdatableFromTextModule {
Paul Duffin280a31a2021-06-27 20:28:29 +0100659 // Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
660 // java_sdk_library.
661 // TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent.
662 name = "android-non-updatable"
663 } else if name == "legacy.art.module.platform.api" {
664 // Treat legacy.art.module.platform.api as if it was an API scope provided by the
665 // art.module.public.api java_sdk_library which will be the case once the former has been
666 // migrated to a module_lib API.
667 name = "art.module.public.api"
668 } else if name == "legacy.i18n.module.platform.api" {
669 // Treat legacy.i18n.module.platform.api as if it was an API scope provided by the
670 // i18n.module.public.api java_sdk_library which will be the case once the former has been
671 // migrated to a module_lib API.
672 name = "i18n.module.public.api"
673 } else if name == "conscrypt.module.platform.api" {
674 // Treat conscrypt.module.platform.api as if it was an API scope provided by the
675 // conscrypt.module.public.api java_sdk_library which will be the case once the former has been
676 // migrated to a module_lib API.
677 name = "conscrypt.module.public.api"
Paul Duffin3f0290e2021-06-30 18:25:36 +0100678 } else if d, ok := module.(SdkLibraryComponentDependency); ok {
679 sdkLibraryName := d.SdkLibraryName()
680 if sdkLibraryName != nil {
681 // The module is a component of a java_sdk_library so use the name of the java_sdk_library.
682 // e.g. if this module is `foo.system.stubs` and is part of the `foo` java_sdk_library then
683 // use `foo` as the name.
684 name = *sdkLibraryName
685 }
Paul Duffin280a31a2021-06-27 20:28:29 +0100686 }
687 stubDexJarsByScope := s[name]
688 if stubDexJarsByScope == nil {
689 stubDexJarsByScope = ModuleStubDexJars{}
690 s[name] = stubDexJarsByScope
691 }
692 stubDexJarsByScope[scope] = stubDexJar
693}
694
695// addStubDexJarsByModule adds the stub dex jars in the supplied StubDexJarsByModule to this map.
696func (s StubDexJarsByModule) addStubDexJarsByModule(other StubDexJarsByModule) {
697 for module, stubDexJarsByScope := range other {
698 s[module] = stubDexJarsByScope
699 }
700}
701
702// StubDexJarsForWidestAPIScope returns a list of stub dex jars containing the widest API scope
703// provided by each module.
704//
705// The relative width of APIs is determined by their order in hiddenAPIScopes.
706func (s StubDexJarsByModule) StubDexJarsForWidestAPIScope() android.Paths {
707 stubDexJars := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -0800708 modules := android.SortedKeys(s)
Paul Duffin280a31a2021-06-27 20:28:29 +0100709 for _, module := range modules {
710 stubDexJarsByScope := s[module]
711
712 stubDexJars = append(stubDexJars, stubDexJarsByScope.stubDexJarForWidestAPIScope())
713 }
714
715 return stubDexJars
716}
717
718// StubDexJarsForScope returns a list of stub dex jars containing the stub dex jars provided by each
719// module for the specified scope.
720//
721// If a module does not provide a stub dex jar for the supplied scope then it does not contribute to
722// the returned list.
723func (s StubDexJarsByModule) StubDexJarsForScope(scope *HiddenAPIScope) android.Paths {
724 stubDexJars := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -0800725 modules := android.SortedKeys(s)
Paul Duffin280a31a2021-06-27 20:28:29 +0100726 for _, module := range modules {
727 stubDexJarsByScope := s[module]
728 // Not every module will have the same set of
729 if jars, ok := stubDexJarsByScope[scope]; ok {
730 stubDexJars = append(stubDexJars, jars)
731 }
732 }
733
734 return stubDexJars
735}
736
Paul Duffin1e9e9382022-07-27 15:55:06 +0000737type HiddenAPIPropertyInfo struct {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100738 // FlagFilesByCategory contains the flag files that override the initial flags that are derived
739 // from the stub dex files.
740 FlagFilesByCategory FlagFilesByCategory
741
Paul Duffin1e9e9382022-07-27 15:55:06 +0000742 // See HiddenAPIFlagFileProperties.Package_prefixes
743 PackagePrefixes []string
744
745 // See HiddenAPIFlagFileProperties.Single_packages
746 SinglePackages []string
747
748 // See HiddenAPIFlagFileProperties.Split_packages
749 SplitPackages []string
750}
751
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000752var hiddenAPIPropertyInfoProvider = blueprint.NewProvider(HiddenAPIPropertyInfo{})
753
Paul Duffin1e9e9382022-07-27 15:55:06 +0000754// newHiddenAPIPropertyInfo creates a new initialized HiddenAPIPropertyInfo struct.
755func newHiddenAPIPropertyInfo() HiddenAPIPropertyInfo {
756 return HiddenAPIPropertyInfo{
757 FlagFilesByCategory: FlagFilesByCategory{},
758 }
759}
760
761// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
762// supplied properties and stores them in this struct.
763func (i *HiddenAPIPropertyInfo) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
764 for _, category := range HiddenAPIFlagFileCategories {
765 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
766 i.FlagFilesByCategory[category] = paths
767 }
768}
769
770// extractPackageRulesFromProperties extracts the package rules that are specified in the supplied
771// properties and stores them in this struct.
772func (i *HiddenAPIPropertyInfo) extractPackageRulesFromProperties(p *HiddenAPIPackageProperties) {
773 i.PackagePrefixes = p.Hidden_api.Package_prefixes
774 i.SinglePackages = p.Hidden_api.Single_packages
775 i.SplitPackages = p.Hidden_api.Split_packages
776}
777
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000778func (i *HiddenAPIPropertyInfo) gatherPropertyInfo(ctx android.ModuleContext, contents []android.Module) {
779 for _, module := range contents {
780 if ctx.OtherModuleHasProvider(module, hiddenAPIPropertyInfoProvider) {
781 info := ctx.OtherModuleProvider(module, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo)
782 i.FlagFilesByCategory.append(info.FlagFilesByCategory)
783 i.PackagePrefixes = append(i.PackagePrefixes, info.PackagePrefixes...)
784 i.SinglePackages = append(i.SinglePackages, info.SinglePackages...)
785 i.SplitPackages = append(i.SplitPackages, info.SplitPackages...)
786 }
787 }
788
789 // Dedup and sort the information to ensure consistent builds.
790 i.FlagFilesByCategory.sort()
791 i.PackagePrefixes = android.SortedUniqueStrings(i.PackagePrefixes)
792 i.SinglePackages = android.SortedUniqueStrings(i.SinglePackages)
793 i.SplitPackages = android.SortedUniqueStrings(i.SplitPackages)
794}
795
Paul Duffin1e9e9382022-07-27 15:55:06 +0000796// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
797// needed for hidden API flag generation.
798type HiddenAPIFlagInput struct {
799 HiddenAPIPropertyInfo
800
Paul Duffin31fad802021-06-18 18:14:25 +0100801 // StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
Paul Duffin1352f7c2021-05-21 22:18:49 +0100802 // the initial flags for each dex member.
Paul Duffin280a31a2021-06-27 20:28:29 +0100803 StubDexJarsByScope StubDexJarsByModule
Paul Duffinf1b358c2021-05-17 07:38:47 +0100804
Paul Duffin31fad802021-06-18 18:14:25 +0100805 // DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
806 // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
Paul Duffinf1b358c2021-05-17 07:38:47 +0100807 // fragment on which this depends.
Paul Duffin280a31a2021-06-27 20:28:29 +0100808 DependencyStubDexJarsByScope StubDexJarsByModule
Paul Duffin32cf58a2021-05-18 16:32:50 +0100809
Paul Duffin5cca7c42021-05-26 10:16:01 +0100810 // AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to
811 // the ones that are obtained from fragments on which this depends.
812 //
813 // These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope
814 // as there are not propagated transitively to other fragments that depend on this.
Paul Duffin280a31a2021-06-27 20:28:29 +0100815 AdditionalStubDexJarsByScope StubDexJarsByModule
Paul Duffin5cca7c42021-05-26 10:16:01 +0100816
Paul Duffin32cf58a2021-05-18 16:32:50 +0100817 // RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
818 // specified in the bootclasspath_fragment's stub_libs and contents properties.
819 RemovedTxtFiles android.Paths
Paul Duffin1352f7c2021-05-21 22:18:49 +0100820}
821
Paul Duffin1e9e9382022-07-27 15:55:06 +0000822// newHiddenAPIFlagInput creates a new initialized HiddenAPIFlagInput struct.
Paul Duffin1352f7c2021-05-21 22:18:49 +0100823func newHiddenAPIFlagInput() HiddenAPIFlagInput {
824 input := HiddenAPIFlagInput{
Paul Duffin1e9e9382022-07-27 15:55:06 +0000825 HiddenAPIPropertyInfo: newHiddenAPIPropertyInfo(),
Paul Duffin280a31a2021-06-27 20:28:29 +0100826 StubDexJarsByScope: StubDexJarsByModule{},
827 DependencyStubDexJarsByScope: StubDexJarsByModule{},
828 AdditionalStubDexJarsByScope: StubDexJarsByModule{},
Paul Duffin1352f7c2021-05-21 22:18:49 +0100829 }
830
831 return input
832}
833
834// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
835// dependencies added in hiddenAPIAddStubLibDependencies.
836//
837// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
838func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
Paul Duffin31fad802021-06-18 18:14:25 +0100839 addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
840 sdkKind := apiScope.sdkKind
841 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100842 if dexJar != nil {
Paul Duffin280a31a2021-06-27 20:28:29 +0100843 i.StubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100844 }
Paul Duffin32cf58a2021-05-18 16:32:50 +0100845
846 if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100847 removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
Paul Duffin32cf58a2021-05-18 16:32:50 +0100848 i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
849 }
Paul Duffin1352f7c2021-05-21 22:18:49 +0100850 }
851
852 // If the contents includes any java_sdk_library modules then add them to the stubs.
853 for _, module := range contents {
854 if _, ok := module.(SdkLibraryDependency); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100855 // Add information for every possible API scope needed by hidden API.
856 for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
857 addFromModule(ctx, module, apiScope)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100858 }
859 }
860 }
861
Paul Duffind061d402021-06-07 21:36:01 +0100862 ctx.VisitDirectDeps(func(module android.Module) {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100863 tag := ctx.OtherModuleDependencyTag(module)
864 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100865 apiScope := hiddenAPIStubsTag.apiScope
Paul Duffin5cca7c42021-05-26 10:16:01 +0100866 if hiddenAPIStubsTag.fromAdditionalDependency {
867 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind)
868 if dexJar != nil {
Paul Duffin280a31a2021-06-27 20:28:29 +0100869 i.AdditionalStubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
Paul Duffin5cca7c42021-05-26 10:16:01 +0100870 }
871 } else {
872 addFromModule(ctx, module, apiScope)
873 }
Paul Duffin1352f7c2021-05-21 22:18:49 +0100874 }
875 })
876
877 // Normalize the paths, i.e. remove duplicates and sort.
Paul Duffin32cf58a2021-05-18 16:32:50 +0100878 i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100879}
880
Paul Duffin280a31a2021-06-27 20:28:29 +0100881func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByModule {
Paul Duffin31fad802021-06-18 18:14:25 +0100882 transitive := i.DependencyStubDexJarsByScope
Paul Duffin280a31a2021-06-27 20:28:29 +0100883 transitive.addStubDexJarsByModule(i.StubDexJarsByScope)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100884 return transitive
885}
886
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100887// HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
888// bootclasspath_fragment module.
889type HiddenAPIFlagOutput struct {
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100890 // The path to the generated annotation-flags.csv file.
891 AnnotationFlagsPath android.Path
892
893 // The path to the generated metadata.csv file.
894 MetadataPath android.Path
895
896 // The path to the generated index.csv file.
897 IndexPath android.Path
898
Paul Duffin191be3a2021-08-10 16:14:16 +0100899 // The path to the generated stub-flags.csv file.
900 StubFlagsPath android.Path
901
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100902 // The path to the generated all-flags.csv file.
903 AllFlagsPath android.Path
Paul Duffin67b9d612021-07-21 17:38:47 +0100904
905 // The path to the generated signature-patterns.txt file which defines the subset of the
906 // monolithic hidden API files provided in this.
907 SignaturePatternsPath android.Path
Paul Duffin191be3a2021-08-10 16:14:16 +0100908
909 // The path to the generated filtered-stub-flags.csv file.
910 FilteredStubFlagsPath android.Path
911
912 // The path to the generated filtered-flags.csv file.
913 FilteredFlagsPath android.Path
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100914}
915
Paul Duffin5f148ca2021-06-02 17:24:22 +0100916// bootDexJarByModule is a map from base module name (without prebuilt_ prefix) to the boot dex
917// path.
918type bootDexJarByModule map[string]android.Path
919
920// addPath adds the path for a module to the map.
921func (b bootDexJarByModule) addPath(module android.Module, path android.Path) {
922 b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path
923}
924
Paul Duffine5218812021-06-07 13:28:19 +0100925// bootDexJars returns the boot dex jar paths sorted by their keys.
926func (b bootDexJarByModule) bootDexJars() android.Paths {
927 paths := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -0800928 for _, k := range android.SortedKeys(b) {
Paul Duffine5218812021-06-07 13:28:19 +0100929 paths = append(paths, b[k])
930 }
931 return paths
932}
933
Paul Duffin7f872162021-06-17 19:33:24 +0100934// bootDexJarsWithoutCoverage returns the boot dex jar paths sorted by their keys without coverage
935// libraries if present.
936func (b bootDexJarByModule) bootDexJarsWithoutCoverage() android.Paths {
937 paths := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -0800938 for _, k := range android.SortedKeys(b) {
Paul Duffin7f872162021-06-17 19:33:24 +0100939 if k == "jacocoagent" {
940 continue
941 }
942 paths = append(paths, b[k])
943 }
944 return paths
945}
946
Paul Duffine5218812021-06-07 13:28:19 +0100947// HiddenAPIOutput encapsulates the output from the hidden API processing.
948type HiddenAPIOutput struct {
949 HiddenAPIFlagOutput
950
951 // The map from base module name to the path to the encoded boot dex file.
952 EncodedBootDexFilesByModule bootDexJarByModule
953}
954
Paul Duffindfa10832021-05-13 17:31:51 +0100955// pathForValidation creates a path of the same type as the supplied type but with a name of
956// <path>.valid.
957//
958// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
959// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
960func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
961 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
962 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
963}
964
Paul Duffin2fef1362021-04-15 13:32:00 +0100965// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
966// the flags from all the modules, the stub flags, augmented with some additional configuration
967// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100968//
969// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
970// an entry for every single member in the dex implementation jars of the individual modules. Every
971// signature in any of the other files MUST be included in this file.
972//
Paul Duffin537ea3d2021-05-14 10:38:00 +0100973// annotationFlags is the path to the annotation flags file generated from annotation information
974// in each module.
Paul Duffin702210b2021-04-08 20:12:41 +0100975//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100976// hiddenAPIInfo is a struct containing paths to files that augment the information provided by
Paul Duffin537ea3d2021-05-14 10:38:00 +0100977// the annotationFlags.
Paul Duffin32cf58a2021-05-18 16:32:50 +0100978func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string,
Paul Duffind061d402021-06-07 21:36:01 +0100979 outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
Paul Duffin67b9d612021-07-21 17:38:47 +0100980 flagFilesByCategory FlagFilesByCategory, flagSubsets SignatureCsvSubsets, generatedRemovedDexSignatures android.OptionalPath) {
Paul Duffindfa10832021-05-13 17:31:51 +0100981
Paul Duffindfa10832021-05-13 17:31:51 +0100982 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100983 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100984 rule := android.NewRuleBuilder(pctx, ctx)
985 command := rule.Command().
986 BuiltTool("generate_hiddenapi_lists").
987 FlagWithInput("--csv ", baseFlagsPath).
Paul Duffind061d402021-06-07 21:36:01 +0100988 Inputs(annotationFlagPaths).
Paul Duffin702210b2021-04-08 20:12:41 +0100989 FlagWithOutput("--output ", tempPath)
990
Paul Duffine3dc6602021-04-14 09:50:43 +0100991 // Add the options for the different categories of flag files.
Paul Duffin524c82c2021-06-09 14:39:28 +0100992 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +0100993 paths := flagFilesByCategory[category]
Paul Duffine3dc6602021-04-14 09:50:43 +0100994 for _, path := range paths {
995 category.commandMutator(command, path)
996 }
Paul Duffin702210b2021-04-08 20:12:41 +0100997 }
998
Paul Duffin32cf58a2021-05-18 16:32:50 +0100999 // If available then pass the automatically generated file containing dex signatures of removed
1000 // API members to the rule so they can be marked as removed.
1001 if generatedRemovedDexSignatures.Valid() {
1002 hiddenAPIRemovedFlagFileCategory.commandMutator(command, generatedRemovedDexSignatures.Path())
1003 }
1004
Paul Duffin702210b2021-04-08 20:12:41 +01001005 commitChangeForRestat(rule, tempPath, outputPath)
1006
Paul Duffin2e880972021-06-23 23:29:09 +01001007 // If there are flag files that have been generated by fragments on which this depends then use
1008 // them to validate the flag file generated by the rules created by this method.
Paul Duffin67b9d612021-07-21 17:38:47 +01001009 if len(flagSubsets) > 0 {
Paul Duffinbd88c882022-04-07 23:32:19 +01001010 validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets,
1011 HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
Paul Duffin2e880972021-06-23 23:29:09 +01001012
Paul Duffindfa10832021-05-13 17:31:51 +01001013 // Add the file that indicates that the file generated by this is valid.
1014 //
1015 // This will cause the validation rule above to be run any time that the output of this rule
1016 // changes but the validation will run in parallel with other rules that depend on this file.
1017 command.Validation(validFile)
1018 }
1019
Paul Duffin2fef1362021-04-15 13:32:00 +01001020 rule.Build(name, desc)
1021}
1022
Paul Duffin67b9d612021-07-21 17:38:47 +01001023// SignatureCsvSubset describes a subset of a monolithic flags file, i.e. either
1024// out/soong/hiddenapi/hiddenapi-stub-flags.txt or out/soong/hiddenapi/hiddenapi-flags.csv
1025type SignatureCsvSubset struct {
1026 // The path to the CSV file containing hidden API flags.
1027 //
1028 // It has the dex member signature as the first column, with flags, one per column, in the
1029 // subsequent columns.
1030 CsvFile android.Path
1031
1032 // The path to the CSV file containing the signature patterns.
1033 //
1034 // It is a single column CSV file with the column containing a signature pattern.
1035 SignaturePatternsFile android.Path
1036}
1037
1038type SignatureCsvSubsets []SignatureCsvSubset
1039
1040func (s SignatureCsvSubsets) RelativeToTop() []string {
1041 result := []string{}
1042 for _, subset := range s {
1043 result = append(result, fmt.Sprintf("%s:%s", subset.CsvFile.RelativeToTop(), subset.SignaturePatternsFile.RelativeToTop()))
1044 }
1045 return result
1046}
1047
1048// buildRuleSignaturePatternsFile creates a rule to generate a file containing the set of signature
1049// patterns that will select a subset of the monolithic flags.
Paul Duffin846beb72022-03-15 17:45:57 +00001050func buildRuleSignaturePatternsFile(
1051 ctx android.ModuleContext, flagsPath android.Path,
Paul Duffin1938dba2022-07-26 23:53:00 +00001052 splitPackages []string, packagePrefixes []string, singlePackages []string,
1053 suffix string) android.Path {
1054 hiddenApiSubDir := "modular-hiddenapi" + suffix
1055
1056 patternsFile := android.PathForModuleOut(ctx, hiddenApiSubDir, "signature-patterns.csv")
Paul Duffin67b9d612021-07-21 17:38:47 +01001057 // Create a rule to validate the output from the following rule.
1058 rule := android.NewRuleBuilder(pctx, ctx)
Paul Duffin1e18e982021-08-03 15:42:27 +01001059
1060 // Quote any * in the packages to avoid them being expanded by the shell.
1061 quotedSplitPackages := []string{}
1062 for _, pkg := range splitPackages {
1063 quotedSplitPackages = append(quotedSplitPackages, strings.ReplaceAll(pkg, "*", "\\*"))
1064 }
1065
Paul Duffin67b9d612021-07-21 17:38:47 +01001066 rule.Command().
1067 BuiltTool("signature_patterns").
1068 FlagWithInput("--flags ", flagsPath).
Paul Duffin1e18e982021-08-03 15:42:27 +01001069 FlagForEachArg("--split-package ", quotedSplitPackages).
1070 FlagForEachArg("--package-prefix ", packagePrefixes).
Paul Duffin846beb72022-03-15 17:45:57 +00001071 FlagForEachArg("--single-package ", singlePackages).
Paul Duffin67b9d612021-07-21 17:38:47 +01001072 FlagWithOutput("--output ", patternsFile)
Paul Duffin1938dba2022-07-26 23:53:00 +00001073 rule.Build("hiddenAPISignaturePatterns"+suffix, "hidden API signature patterns"+suffix)
Paul Duffin67b9d612021-07-21 17:38:47 +01001074
1075 return patternsFile
1076}
1077
Paul Duffinbd88c882022-04-07 23:32:19 +01001078// buildRuleRemoveSignaturesWithImplementationFlags creates a rule that will remove signatures from
1079// the input flags file which have only the implementation flags, i.e. are not part of an API.
1080//
1081// The implementationFlags specifies the set of default flags that identifies the signature of a
1082// private, implementation only, member. Signatures that match those flags are removed from the
1083// flags as they are implementation only.
1084//
1085// This is used to remove implementation only signatures from the signature files that are persisted
1086// in the sdk snapshot as the sdk snapshots should not include implementation details. The
1087// signatures generated by this method will be compared by the buildRuleValidateOverlappingCsvFiles
1088// method which treats any missing signatures as if they were implementation only signatures.
1089func buildRuleRemoveSignaturesWithImplementationFlags(ctx android.BuilderContext,
1090 name string, desc string, inputPath android.Path, filteredPath android.WritablePath,
1091 implementationFlags []string) {
1092
Paul Duffin280bae62021-07-20 18:03:53 +01001093 rule := android.NewRuleBuilder(pctx, ctx)
Paul Duffinbd88c882022-04-07 23:32:19 +01001094 implementationFlagPattern := ""
1095 for _, implementationFlag := range implementationFlags {
1096 implementationFlagPattern = implementationFlagPattern + "," + implementationFlag
1097 }
Paul Duffin280bae62021-07-20 18:03:53 +01001098 rule.Command().
Paul Duffinbd88c882022-04-07 23:32:19 +01001099 Text(`grep -vE "^[^,]+` + implementationFlagPattern + `$"`).Input(inputPath).
1100 Text(">").Output(filteredPath).
Paul Duffin280bae62021-07-20 18:03:53 +01001101 // Grep's exit code depends on whether it finds anything. It is 0 (build success) when it finds
1102 // something and 1 (build failure) when it does not and 2 (when it encounters an error).
1103 // However, while it is unlikely it is not an error if this does not find any matches. The
1104 // following will only run if the grep does not find something and in that case it will treat
1105 // an exit code of 1 as success and anything else as failure.
1106 Text("|| test $? -eq 1")
1107 rule.Build(name, desc)
1108}
1109
Paul Duffin2e880972021-06-23 23:29:09 +01001110// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
1111// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
Paul Duffinbd88c882022-04-07 23:32:19 +01001112//
1113// The implementationFlags specifies the set of default flags that identifies the signature of a
1114// private, implementation only, member. A signature which is present in a monolithic flags subset
1115// defined by SignatureCsvSubset but which is not present in the flags file from the corresponding
1116// module is assumed to be an implementation only member and so must have these flags.
1117func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string,
1118 monolithicFilePath android.WritablePath, csvSubsets SignatureCsvSubsets,
1119 implementationFlags []string) android.WritablePath {
Paul Duffin2e880972021-06-23 23:29:09 +01001120 // The file which is used to record that the flags file is valid.
1121 validFile := pathForValidation(ctx, monolithicFilePath)
1122
1123 // Create a rule to validate the output from the following rule.
1124 rule := android.NewRuleBuilder(pctx, ctx)
Paul Duffin67b9d612021-07-21 17:38:47 +01001125 command := rule.Command().
Paul Duffin2e880972021-06-23 23:29:09 +01001126 BuiltTool("verify_overlaps").
Paul Duffin0c12b782022-04-08 00:28:11 +01001127 FlagWithInput("--monolithic-flags ", monolithicFilePath)
Paul Duffin67b9d612021-07-21 17:38:47 +01001128
1129 for _, subset := range csvSubsets {
1130 command.
Paul Duffin0c12b782022-04-08 00:28:11 +01001131 Flag("--module-flags ").
Paul Duffin67b9d612021-07-21 17:38:47 +01001132 Textf("%s:%s", subset.CsvFile, subset.SignaturePatternsFile).
1133 Implicit(subset.CsvFile).Implicit(subset.SignaturePatternsFile)
1134 }
1135
Paul Duffinbd88c882022-04-07 23:32:19 +01001136 for _, implementationFlag := range implementationFlags {
1137 command.FlagWithArg("--implementation-flag ", implementationFlag)
1138 }
1139
Paul Duffin67b9d612021-07-21 17:38:47 +01001140 // If validation passes then update the file that records that.
1141 command.Text("&& touch").Output(validFile)
Paul Duffin2e880972021-06-23 23:29:09 +01001142 rule.Build(name+"Validation", desc+" validation")
1143
1144 return validFile
1145}
1146
Paul Duffinaf705182022-09-14 11:47:34 +01001147// hiddenAPIFlagRulesForBootclasspathFragment will generate all the flags for a fragment of the
1148// bootclasspath.
Paul Duffin2fef1362021-04-15 13:32:00 +01001149//
1150// It takes:
1151// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
1152// * The list of modules that are the contents of the fragment.
1153// * The additional manually curated flag files to use.
1154//
1155// It generates:
1156// * stub-flags.csv
1157// * annotation-flags.csv
1158// * metadata.csv
1159// * index.csv
1160// * all-flags.csv
Paul Duffin1938dba2022-07-26 23:53:00 +00001161func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.Module, input HiddenAPIFlagInput, suffix string) HiddenAPIFlagOutput {
1162 hiddenApiSubDir := "modular-hiddenapi" + suffix
Paul Duffin2fef1362021-04-15 13:32:00 +01001163
Paul Duffin1352f7c2021-05-21 22:18:49 +01001164 // Generate the stub-flags.csv.
Paul Duffin2fef1362021-04-15 13:32:00 +01001165 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001166 buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile"+suffix, "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
Paul Duffin2fef1362021-04-15 13:32:00 +01001167
Paul Duffin537ea3d2021-05-14 10:38:00 +01001168 // Extract the classes jars from the contents.
Paul Duffindd5993f2021-06-10 10:18:22 +01001169 classesJars := extractClassesJarsFromModules(contents)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001170
Paul Duffin2fef1362021-04-15 13:32:00 +01001171 // Generate the set of flags from the annotations in the source code.
1172 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001173 buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags"+suffix, classesJars, stubFlagsCSV, annotationFlagsCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +01001174
1175 // Generate the metadata from the annotations in the source code.
1176 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001177 buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata"+suffix, classesJars, stubFlagsCSV, metadataCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +01001178
Paul Duffin537ea3d2021-05-14 10:38:00 +01001179 // Generate the index file from the CSV files in the classes jars.
Paul Duffin2fef1362021-04-15 13:32:00 +01001180 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001181 buildRuleToGenerateIndex(ctx, "modular hiddenapi index"+suffix, classesJars, indexCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +01001182
Paul Duffinaf99afa2021-05-21 22:18:56 +01001183 // 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 +01001184 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
1185 // manually combining all the removed.txt files for each API and then converting them to dex
Paul Duffin32cf58a2021-05-18 16:32:50 +01001186 // signatures, see the combined-removed-dex module. This does that automatically by using the
1187 // *removed.txt files retrieved from the java_sdk_library modules that are specified in the
1188 // stub_libs and contents properties of a bootclasspath_fragment.
Paul Duffin1938dba2022-07-26 23:53:00 +00001189 removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, suffix, input.RemovedTxtFiles)
Paul Duffin2fef1362021-04-15 13:32:00 +01001190
1191 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
1192 // files.
Paul Duffine5218812021-06-07 13:28:19 +01001193 allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001194 buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags"+suffix, "modular hiddenapi all flags"+suffix, allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
Paul Duffine5218812021-06-07 13:28:19 +01001195
Paul Duffin280bae62021-07-20 18:03:53 +01001196 // Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be
1197 // compared against the monolithic stub flags.
1198 filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001199 buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags"+suffix,
1200 "modular hiddenapi filtered stub flags"+suffix, stubFlagsCSV, filteredStubFlagsCSV,
Paul Duffinbd88c882022-04-07 23:32:19 +01001201 HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
Paul Duffin280bae62021-07-20 18:03:53 +01001202
1203 // Generate the filtered-flags.csv file which contains the filtered flags that will be compared
1204 // against the monolithic flags.
1205 filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001206 buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags"+suffix,
1207 "modular hiddenapi filtered flags"+suffix, allFlagsCSV, filteredFlagsCSV,
Paul Duffinbd88c882022-04-07 23:32:19 +01001208 HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
Paul Duffin280bae62021-07-20 18:03:53 +01001209
Paul Duffin2fef1362021-04-15 13:32:00 +01001210 // Store the paths in the info for use by other modules and sdk snapshot generation.
Paul Duffinaf705182022-09-14 11:47:34 +01001211 return HiddenAPIFlagOutput{
1212 AnnotationFlagsPath: annotationFlagsCSV,
1213 MetadataPath: metadataCSV,
1214 IndexPath: indexCSV,
1215 StubFlagsPath: stubFlagsCSV,
1216 AllFlagsPath: allFlagsCSV,
1217 FilteredStubFlagsPath: filteredStubFlagsCSV,
1218 FilteredFlagsPath: filteredFlagsCSV,
Paul Duffin1e6f5c42021-05-21 16:15:31 +01001219 }
Paul Duffinaf705182022-09-14 11:47:34 +01001220}
1221
1222// hiddenAPIEncodeRulesForBootclasspathFragment generates rules to encode hidden API flags into the
1223// dex jars in bootDexInfoByModule.
1224func hiddenAPIEncodeRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, allFlagsCSV android.Path) bootDexJarByModule {
1225 // Encode the flags into the boot dex files.
1226 encodedBootDexJarsByModule := bootDexJarByModule{}
1227 outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath
Cole Faust18994c72023-02-28 16:02:16 -08001228 for _, name := range android.SortedKeys(bootDexInfoByModule) {
Paul Duffinaf705182022-09-14 11:47:34 +01001229 bootDexInfo := bootDexInfoByModule[name]
1230 unencodedDex := bootDexInfo.path
1231 encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, bootDexInfo.minSdkVersion, outputDir)
1232 encodedBootDexJarsByModule[name] = encodedDex
1233 }
1234 return encodedBootDexJarsByModule
Paul Duffin702210b2021-04-08 20:12:41 +01001235}
Paul Duffin537ea3d2021-05-14 10:38:00 +01001236
Paul Duffin1938dba2022-07-26 23:53:00 +00001237func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix string, removedTxtFiles android.Paths) android.OptionalPath {
Paul Duffin32cf58a2021-05-18 16:32:50 +01001238 if len(removedTxtFiles) == 0 {
1239 return android.OptionalPath{}
1240 }
1241
Paul Duffin1938dba2022-07-26 23:53:00 +00001242 output := android.PathForModuleOut(ctx, "module-hiddenapi"+suffix, "removed-dex-signatures.txt")
Paul Duffin32cf58a2021-05-18 16:32:50 +01001243
1244 rule := android.NewRuleBuilder(pctx, ctx)
1245 rule.Command().
1246 BuiltTool("metalava").
Paul Duffin32cf58a2021-05-18 16:32:50 +01001247 Inputs(removedTxtFiles).
1248 FlagWithOutput("--dex-api ", output)
Paul Duffin1938dba2022-07-26 23:53:00 +00001249 rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix)
Paul Duffin32cf58a2021-05-18 16:32:50 +01001250 return android.OptionalPathForPath(output)
1251}
1252
Paul Duffindd5993f2021-06-10 10:18:22 +01001253// extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules.
Paul Duffine5218812021-06-07 13:28:19 +01001254func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
1255 bootDexJars := bootDexJarByModule{}
Paul Duffin537ea3d2021-05-14 10:38:00 +01001256 for _, module := range contents {
Paul Duffindd5993f2021-06-10 10:18:22 +01001257 hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
1258 if hiddenAPIModule == nil {
1259 continue
1260 }
Paul Duffine5218812021-06-07 13:28:19 +01001261 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
1262 bootDexJars.addPath(module, bootDexJar)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001263 }
1264 return bootDexJars
1265}
1266
Paul Duffindd5993f2021-06-10 10:18:22 +01001267func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Module) hiddenAPIModule {
1268 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
1269 return hiddenAPIModule
1270 } else if _, ok := module.(*DexImport); ok {
1271 // Ignore this for the purposes of hidden API processing
1272 } else {
1273 ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
1274 }
1275
1276 return nil
1277}
1278
Paul Duffine5218812021-06-07 13:28:19 +01001279// bootDexInfo encapsulates both the path and uncompressDex status retrieved from a hiddenAPIModule.
1280type bootDexInfo struct {
1281 // The path to the dex jar that has not had hidden API flags encoded into it.
1282 path android.Path
1283
1284 // Indicates whether the dex jar needs uncompressing before encoding.
1285 uncompressDex bool
Paul Duffin09817d62022-04-28 17:45:11 +01001286
1287 // The minimum sdk version that the dex jar will be used on.
Spandan Das8c9ae7e2023-03-03 21:20:36 +00001288 minSdkVersion android.ApiLevel
Paul Duffine5218812021-06-07 13:28:19 +01001289}
1290
1291// bootDexInfoByModule is a map from module name (as returned by module.Name()) to the boot dex
1292// path (as returned by hiddenAPIModule.bootDexJar()) and the uncompressDex flag.
1293type bootDexInfoByModule map[string]bootDexInfo
1294
1295// bootDexJars returns the boot dex jar paths sorted by their keys.
1296func (b bootDexInfoByModule) bootDexJars() android.Paths {
1297 paths := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -08001298 for _, m := range android.SortedKeys(b) {
Paul Duffine5218812021-06-07 13:28:19 +01001299 paths = append(paths, b[m].path)
1300 }
1301 return paths
1302}
1303
1304// extractBootDexInfoFromModules extracts the boot dex jar and uncompress dex state from
1305// each of the supplied modules which must implement hiddenAPIModule.
1306func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android.Module) bootDexInfoByModule {
1307 bootDexJarsByModule := bootDexInfoByModule{}
1308 for _, module := range contents {
1309 hiddenAPIModule := module.(hiddenAPIModule)
1310 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
1311 bootDexJarsByModule[module.Name()] = bootDexInfo{
1312 path: bootDexJar,
1313 uncompressDex: *hiddenAPIModule.uncompressDex(),
Paul Duffin09817d62022-04-28 17:45:11 +01001314 minSdkVersion: hiddenAPIModule.MinSdkVersion(ctx),
Paul Duffine5218812021-06-07 13:28:19 +01001315 }
1316 }
1317
1318 return bootDexJarsByModule
1319}
1320
1321// retrieveBootDexJarFromHiddenAPIModule retrieves the boot dex jar from the hiddenAPIModule.
1322//
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001323// If the module does not provide a boot dex jar, i.e. the returned boot dex jar is unset or
1324// invalid, then create a fake path and either report an error immediately or defer reporting of the
1325// error until the path is actually used.
Paul Duffine5218812021-06-07 13:28:19 +01001326func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
1327 bootDexJar := module.bootDexJar()
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001328 if !bootDexJar.Valid() {
Paul Duffine5218812021-06-07 13:28:19 +01001329 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001330 handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
1331 return fake
Paul Duffine5218812021-06-07 13:28:19 +01001332 }
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001333 return bootDexJar.Path()
Paul Duffine5218812021-06-07 13:28:19 +01001334}
1335
Paul Duffindd5993f2021-06-10 10:18:22 +01001336// extractClassesJarsFromModules extracts the class jars from the supplied modules.
1337func extractClassesJarsFromModules(contents []android.Module) android.Paths {
Paul Duffin537ea3d2021-05-14 10:38:00 +01001338 classesJars := android.Paths{}
1339 for _, module := range contents {
Paul Duffindd5993f2021-06-10 10:18:22 +01001340 classesJars = append(classesJars, retrieveClassesJarsFromModule(module)...)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001341 }
1342 return classesJars
1343}
Paul Duffin5f148ca2021-06-02 17:24:22 +01001344
Paul Duffindd5993f2021-06-10 10:18:22 +01001345// retrieveClassesJarsFromModule retrieves the classes jars from the supplied module.
1346func retrieveClassesJarsFromModule(module android.Module) android.Paths {
1347 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
1348 return hiddenAPIModule.classesJars()
1349 }
1350
1351 return nil
1352}
1353
Paul Duffin5f148ca2021-06-02 17:24:22 +01001354// deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
1355// Soong but should instead only be reported in ninja if the file is actually built.
1356func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
Paul Duffine5218812021-06-07 13:28:19 +01001357 // Any missing dependency should be allowed.
1358 if ctx.Config().AllowMissingDependencies() {
1359 return true
1360 }
1361
Paul Duffin5f148ca2021-06-02 17:24:22 +01001362 // This is called for both platform_bootclasspath and bootclasspath_fragment modules.
1363 //
1364 // A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
1365 // Ideally, a bootclasspath_fragment module should never have a platform variant created for it
1366 // but unfortunately, due to b/187910671 it does.
1367 //
1368 // That causes issues when obtaining a boot dex jar for a prebuilt module as a prebuilt module
1369 // used by a bootclasspath_fragment can only provide a boot dex jar when it is part of APEX, i.e.
1370 // has an APEX variant not a platform variant.
1371 //
1372 // There are some other situations when a prebuilt module used by a bootclasspath_fragment cannot
1373 // provide a boot dex jar:
1374 // 1. If the bootclasspath_fragment is not exported by the prebuilt_apex/apex_set module then it
1375 // does not have an APEX variant and only has a platform variant and neither do its content
1376 // modules.
1377 // 2. Some build configurations, e.g. setting TARGET_BUILD_USE_PREBUILT_SDKS causes all
1378 // java_sdk_library_import modules to be treated as preferred and as many of them are not part
1379 // of an apex they cannot provide a boot dex jar.
1380 //
1381 // The first case causes problems when the affected prebuilt modules are preferred but that is an
1382 // invalid configuration and it is ok for it to fail as the work to enable that is not yet
1383 // complete. The second case is used for building targets that do not use boot dex jars and so
1384 // deferring error reporting to ninja is fine as the affected ninja targets should never be built.
1385 // That is handled above.
1386 //
1387 // A platform_bootclasspath module can use libraries from both platform and APEX variants. Unlike
1388 // the bootclasspath_fragment it supports dex_import modules which provides the dex file. So, it
1389 // can obtain a boot dex jar from a prebuilt that is not part of an APEX. However, it is assumed
1390 // that if the library can be part of an APEX then it is the APEX variant that is used.
1391 //
1392 // This check handles the slightly different requirements of the bootclasspath_fragment and
1393 // platform_bootclasspath modules by only deferring error reporting for the platform variant of
1394 // a prebuilt modules that has other variants which are part of an APEX.
1395 //
1396 // TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
1397 if android.IsModulePrebuilt(module) {
Paul Duffinef083c92021-06-29 13:36:34 +01001398 // An inactive source module can still contribute to the APEX but an inactive prebuilt module
1399 // should not contribute to anything. So, rather than have a missing dex jar cause a Soong
1400 // failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly
1401 // built Ninja should never use the dex jar file.
1402 if !isActiveModule(module) {
1403 return true
1404 }
1405
Paul Duffin5f148ca2021-06-02 17:24:22 +01001406 if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
1407 apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
1408 if apexInfo.IsForPlatform() {
1409 return true
1410 }
1411 }
1412 }
1413
Paul Duffin5f148ca2021-06-02 17:24:22 +01001414 return false
1415}
1416
1417// handleMissingDexBootFile will either log a warning or create an error rule to create the fake
1418// file depending on the value returned from deferReportingMissingBootDexJar.
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001419func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath, reason string) {
Paul Duffin5f148ca2021-06-02 17:24:22 +01001420 if deferReportingMissingBootDexJar(ctx, module) {
1421 // Create an error rule that pretends to create the output file but will actually fail if it
1422 // is run.
1423 ctx.Build(pctx, android.BuildParams{
1424 Rule: android.ErrorRule,
1425 Output: fake,
1426 Args: map[string]string{
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001427 "error": fmt.Sprintf("missing boot dex jar dependency for %s: %s", module, reason),
Paul Duffin5f148ca2021-06-02 17:24:22 +01001428 },
1429 })
1430 } else {
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001431 ctx.ModuleErrorf("module %s does not provide a dex jar: %s", module, reason)
Paul Duffin5f148ca2021-06-02 17:24:22 +01001432 }
1433}
1434
1435// retrieveEncodedBootDexJarFromModule returns a path to the boot dex jar from the supplied module's
1436// DexJarBuildPath() method.
1437//
1438// The returned path will usually be to a dex jar file that has been encoded with hidden API flags.
1439// However, under certain conditions, e.g. errors, or special build configurations it will return
1440// a path to a fake file.
1441func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001442 bootDexJar := module.(interface{ DexJarBuildPath() OptionalDexJarPath }).DexJarBuildPath()
1443 if !bootDexJar.Valid() {
Paul Duffin5f148ca2021-06-02 17:24:22 +01001444 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001445 handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
1446 return fake
Paul Duffin5f148ca2021-06-02 17:24:22 +01001447 }
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001448 return bootDexJar.Path()
Paul Duffin5f148ca2021-06-02 17:24:22 +01001449}
1450
1451// extractEncodedDexJarsFromModules extracts the encoded dex jars from the supplied modules.
1452func extractEncodedDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
1453 encodedDexJarsByModuleName := bootDexJarByModule{}
1454 for _, module := range contents {
1455 path := retrieveEncodedBootDexJarFromModule(ctx, module)
1456 encodedDexJarsByModuleName.addPath(module, path)
1457 }
1458 return encodedDexJarsByModuleName
1459}