blob: 365005835ca383f4729c5080f4a6da7cc139e9ac [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"
Spandan Das64c9e0c2023-12-20 20:13:34 +000022 "android/soong/dexpreopt"
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +010023
Paul Duffin9b381ef2021-04-08 23:01:37 +010024 "github.com/google/blueprint"
Paul Duffinc6bb7cf2021-04-08 17:49:27 +010025)
26
27// Contains support for processing hiddenAPI in a modular fashion.
28
Paul Duffin31fad802021-06-18 18:14:25 +010029// HiddenAPIScope encapsulates all the information that the hidden API processing needs about API
30// scopes, i.e. what is called android.SdkKind and apiScope. It does not just use those as they do
31// not provide the information needed by hidden API processing.
32type HiddenAPIScope struct {
33 // The name of the scope, used for debug purposes.
34 name string
35
36 // The corresponding android.SdkKind, used for retrieving paths from java_sdk_library* modules.
37 sdkKind android.SdkKind
38
39 // The option needed to passed to "hiddenapi list".
40 hiddenAPIListOption string
Paul Duffin5cca7c42021-05-26 10:16:01 +010041
Jihoon Kang244d42a2023-10-06 16:54:58 +000042 // The names of the source stub library modules that contain the API provided by the platform,
Paul Duffin5cca7c42021-05-26 10:16:01 +010043 // i.e. by modules that are not in an APEX.
44 nonUpdatableSourceModule string
45
Jihoon Kang244d42a2023-10-06 16:54:58 +000046 // The names of from-text stub library modules that contain the API provided by the platform,
47 // i.e. by modules that are not in an APEX.
48 nonUpdatableFromTextModule string
49
Paul Duffin5cca7c42021-05-26 10:16:01 +010050 // The names of the prebuilt stub library modules that contain the API provided by the platform,
51 // i.e. by modules that are not in an APEX.
52 nonUpdatablePrebuiltModule string
Paul Duffin31fad802021-06-18 18:14:25 +010053}
54
55// initHiddenAPIScope initializes the scope.
56func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
Paul Duffin5cca7c42021-05-26 10:16:01 +010057 sdkKind := apiScope.sdkKind
58 // The platform does not provide a core platform API.
59 if sdkKind != android.SdkCorePlatform {
60 kindAsString := sdkKind.String()
61 var insert string
62 if sdkKind == android.SdkPublic {
63 insert = ""
64 } else {
65 insert = "." + strings.ReplaceAll(kindAsString, "-", "_")
66 }
67
68 nonUpdatableModule := "android-non-updatable"
69
70 // Construct the name of the android-non-updatable source module for this scope.
71 apiScope.nonUpdatableSourceModule = fmt.Sprintf("%s.stubs%s", nonUpdatableModule, insert)
72
73 prebuiltModuleName := func(name string, kind string) string {
74 return fmt.Sprintf("sdk_%s_current_%s", kind, name)
75 }
76
77 // Construct the name of the android-non-updatable prebuilt module for this scope.
78 apiScope.nonUpdatablePrebuiltModule = prebuiltModuleName(nonUpdatableModule, kindAsString)
79 }
80
Paul Duffin31fad802021-06-18 18:14:25 +010081 return apiScope
82}
83
Paul Duffin5cca7c42021-05-26 10:16:01 +010084// android-non-updatable takes the name of a module and returns a possibly scope specific name of
85// the module.
86func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, name string) string {
87 // The android-non-updatable is not a java_sdk_library but there are separate stub libraries for
88 // each scope.
89 // TODO(b/192067200): Remove special handling of android-non-updatable.
90 if name == "android-non-updatable" {
91 if ctx.Config().AlwaysUsePrebuiltSdks() {
92 return l.nonUpdatablePrebuiltModule
93 } else {
Jihoon Kang244d42a2023-10-06 16:54:58 +000094 if l.nonUpdatableFromTextModule != "" && ctx.Config().BuildFromTextStub() {
95 return l.nonUpdatableFromTextModule
96 }
Paul Duffin5cca7c42021-05-26 10:16:01 +010097 return l.nonUpdatableSourceModule
98 }
99 } else {
100 // Assume that the module is either a java_sdk_library (or equivalent) and so will provide
101 // separate stub jars for each scope or is a java_library (or equivalent) in which case it will
102 // have the same stub jar for each scope.
103 return name
104 }
105}
106
Paul Duffin31fad802021-06-18 18:14:25 +0100107func (l *HiddenAPIScope) String() string {
108 return fmt.Sprintf("HiddenAPIScope{%s}", l.name)
109}
110
111var (
112 PublicHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
113 name: "public",
114 sdkKind: android.SdkPublic,
115 hiddenAPIListOption: "--public-stub-classpath",
116 })
117 SystemHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
118 name: "system",
119 sdkKind: android.SdkSystem,
120 hiddenAPIListOption: "--system-stub-classpath",
121 })
122 TestHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
123 name: "test",
124 sdkKind: android.SdkTest,
125 hiddenAPIListOption: "--test-stub-classpath",
126 })
Paul Duffinb51db2e2021-06-21 14:08:08 +0100127 ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
Jihoon Kang244d42a2023-10-06 16:54:58 +0000128 name: "module-lib",
129 sdkKind: android.SdkModule,
130 nonUpdatableFromTextModule: "android-non-updatable.stubs.test_module_lib",
Paul Duffinb51db2e2021-06-21 14:08:08 +0100131 })
Paul Duffin31fad802021-06-18 18:14:25 +0100132 CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
133 name: "core-platform",
134 sdkKind: android.SdkCorePlatform,
135 hiddenAPIListOption: "--core-platform-stub-classpath",
136 })
137
138 // hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
139 // API processing.
140 //
141 // These are roughly in order from narrowest API surface to widest. Widest means the API stubs
142 // with the biggest API surface, e.g. test is wider than system is wider than public.
143 //
Paul Duffinb51db2e2021-06-21 14:08:08 +0100144 // Core platform is considered wider than system/module-lib because those modules that provide
145 // core platform APIs either do not have any system/module-lib APIs at all, or if they do it is
146 // because the core platform API is being converted to system/module-lib APIs. In either case the
147 // system/module-lib APIs are subsets of the core platform API.
Paul Duffin31fad802021-06-18 18:14:25 +0100148 //
149 // 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 +0100150 // is neither wider or narrower than the module-lib or core platform APIs. However, this works
151 // well enough at the moment.
Paul Duffin31fad802021-06-18 18:14:25 +0100152 // TODO(b/191644675): Correctly reflect the sub/superset relationships between APIs.
153 hiddenAPIScopes = []*HiddenAPIScope{
154 PublicHiddenAPIScope,
155 SystemHiddenAPIScope,
156 TestHiddenAPIScope,
Paul Duffinb51db2e2021-06-21 14:08:08 +0100157 ModuleLibHiddenAPIScope,
Paul Duffin31fad802021-06-18 18:14:25 +0100158 CorePlatformHiddenAPIScope,
159 }
160
161 // The HiddenAPIScope instances that are supported by a java_sdk_library.
162 //
163 // CorePlatformHiddenAPIScope is not used as the java_sdk_library does not have special support
164 // for core_platform API, instead it is implemented as a customized form of PublicHiddenAPIScope.
165 hiddenAPISdkLibrarySupportedScopes = []*HiddenAPIScope{
166 PublicHiddenAPIScope,
167 SystemHiddenAPIScope,
168 TestHiddenAPIScope,
Paul Duffinb51db2e2021-06-21 14:08:08 +0100169 ModuleLibHiddenAPIScope,
Paul Duffin31fad802021-06-18 18:14:25 +0100170 }
171
172 // The HiddenAPIScope instances that are supported by the `hiddenapi list`.
173 hiddenAPIFlagScopes = []*HiddenAPIScope{
174 PublicHiddenAPIScope,
175 SystemHiddenAPIScope,
176 TestHiddenAPIScope,
177 CorePlatformHiddenAPIScope,
178 }
179)
180
Paul Duffin74431d52021-04-21 14:10:42 +0100181type hiddenAPIStubsDependencyTag struct {
182 blueprint.BaseDependencyTag
Paul Duffin31fad802021-06-18 18:14:25 +0100183
184 // The api scope for which this dependency was added.
185 apiScope *HiddenAPIScope
Paul Duffin5cca7c42021-05-26 10:16:01 +0100186
187 // Indicates that the dependency is not for an API provided by the current bootclasspath fragment
188 // but is an additional API provided by a module that is not part of the current bootclasspath
189 // fragment.
190 fromAdditionalDependency bool
Paul Duffin74431d52021-04-21 14:10:42 +0100191}
192
193func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
194}
195
196func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
197 return false
198}
199
Paul Duffin976b0e52021-04-27 23:20:26 +0100200func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
Paul Duffin5cca7c42021-05-26 10:16:01 +0100201 // Do not add additional dependencies to the sdk.
202 if b.fromAdditionalDependency {
203 return nil
204 }
205
Paul Duffin976b0e52021-04-27 23:20:26 +0100206 // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
207 // property, otherwise treat if it was specified in the java_header_libs property.
208 if javaSdkLibrarySdkMemberType.IsInstance(child) {
209 return javaSdkLibrarySdkMemberType
210 }
211
212 return javaHeaderLibsSdkMemberType
213}
214
215func (b hiddenAPIStubsDependencyTag) ExportMember() bool {
216 // Export the module added via this dependency tag from the sdk.
217 return true
218}
219
Paul Duffin74431d52021-04-21 14:10:42 +0100220// Avoid having to make stubs content explicitly visible to dependent modules.
221//
222// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
223// with proper dependencies.
224// TODO(b/177892522): Remove this and add needed visibility.
225func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
226}
227
228var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
229var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
230var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
Paul Duffinf7b3d0d2021-09-02 14:29:21 +0100231var _ android.SdkMemberDependencyTag = hiddenAPIStubsDependencyTag{}
Paul Duffin74431d52021-04-21 14:10:42 +0100232
Paul Duffin74431d52021-04-21 14:10:42 +0100233// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
234// needed to produce the hidden API monolithic stub flags file.
Paul Duffin31fad802021-06-18 18:14:25 +0100235func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*HiddenAPIScope][]string {
Paul Duffin74431d52021-04-21 14:10:42 +0100236 var publicStubModules []string
237 var systemStubModules []string
238 var testStubModules []string
239 var corePlatformStubModules []string
240
241 if config.AlwaysUsePrebuiltSdks() {
242 // Build configuration mandates using prebuilt stub modules
243 publicStubModules = append(publicStubModules, "sdk_public_current_android")
244 systemStubModules = append(systemStubModules, "sdk_system_current_android")
245 testStubModules = append(testStubModules, "sdk_test_current_android")
246 } else {
247 // Use stub modules built from source
Jihoon Kangbd093452023-12-26 19:08:01 +0000248 if config.ReleaseHiddenApiExportableStubs() {
249 publicStubModules = append(publicStubModules, android.SdkPublic.DefaultExportableJavaLibraryName())
250 systemStubModules = append(systemStubModules, android.SdkSystem.DefaultExportableJavaLibraryName())
251 testStubModules = append(testStubModules, android.SdkTest.DefaultExportableJavaLibraryName())
252 } else {
253 publicStubModules = append(publicStubModules, android.SdkPublic.DefaultJavaLibraryName())
254 systemStubModules = append(systemStubModules, android.SdkSystem.DefaultJavaLibraryName())
255 testStubModules = append(testStubModules, android.SdkTest.DefaultJavaLibraryName())
256 }
Paul Duffin74431d52021-04-21 14:10:42 +0100257 }
258 // We do not have prebuilts of the core platform api yet
Jihoon Kangbd093452023-12-26 19:08:01 +0000259 if config.ReleaseHiddenApiExportableStubs() {
260 corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs.exportable")
261 } else {
262 corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
263 }
Paul Duffin74431d52021-04-21 14:10:42 +0100264
265 // Allow products to define their own stubs for custom product jars that apps can use.
266 publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
267 systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
268 testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
269 if config.IsEnvTrue("EMMA_INSTRUMENT") {
Paul Duffin098c8782021-05-14 10:45:25 +0100270 // Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
271 // allows everyone access but it is needed to ensure consistent flags between the
272 // bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
Paul Duffin74431d52021-04-21 14:10:42 +0100273 publicStubModules = append(publicStubModules, "jacoco-stubs")
Paul Duffin098c8782021-05-14 10:45:25 +0100274 systemStubModules = append(systemStubModules, "jacoco-stubs")
275 testStubModules = append(testStubModules, "jacoco-stubs")
Paul Duffin74431d52021-04-21 14:10:42 +0100276 }
277
Paul Duffin31fad802021-06-18 18:14:25 +0100278 m := map[*HiddenAPIScope][]string{}
279 m[PublicHiddenAPIScope] = publicStubModules
280 m[SystemHiddenAPIScope] = systemStubModules
281 m[TestHiddenAPIScope] = testStubModules
282 m[CorePlatformHiddenAPIScope] = corePlatformStubModules
Paul Duffin74431d52021-04-21 14:10:42 +0100283 return m
284}
285
286// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
Paul Duffin31fad802021-06-18 18:14:25 +0100287// apiScopeToStubLibModules. It adds them in a well known order and uses a HiddenAPIScope specific
288// tag to identify the source of the dependency.
289func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScopeToStubLibModules map[*HiddenAPIScope][]string) {
Paul Duffin74431d52021-04-21 14:10:42 +0100290 module := ctx.Module()
Paul Duffin31fad802021-06-18 18:14:25 +0100291 for _, apiScope := range hiddenAPIScopes {
292 modules := apiScopeToStubLibModules[apiScope]
293 ctx.AddDependency(module, hiddenAPIStubsDependencyTag{apiScope: apiScope}, modules...)
Paul Duffin74431d52021-04-21 14:10:42 +0100294 }
295}
296
Paul Duffin74431d52021-04-21 14:10:42 +0100297// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
298// available, or reports an error.
Paul Duffin10931582021-04-25 10:13:54 +0100299func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +0100300 var dexJar OptionalDexJarPath
Jihoon Kang98e9ac62024-09-25 23:42:30 +0000301 if sdkLibrary, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
Jihoon Kangbd093452023-12-26 19:08:01 +0000302 if ctx.Config().ReleaseHiddenApiExportableStubs() {
Jihoon Kang98e9ac62024-09-25 23:42:30 +0000303 dexJar = sdkLibrary.ExportableStubDexJarPaths[kind]
Jihoon Kangbd093452023-12-26 19:08:01 +0000304 } else {
Jihoon Kang98e9ac62024-09-25 23:42:30 +0000305 dexJar = sdkLibrary.EverythingStubDexJarPaths[kind]
Jihoon Kangbd093452023-12-26 19:08:01 +0000306 }
Paul Duffin10931582021-04-25 10:13:54 +0100307 } else if j, ok := module.(UsesLibraryDependency); ok {
Spandan Das59a4a2b2024-01-09 21:35:56 +0000308 dexJar = j.DexJarBuildPath(ctx)
Paul Duffin74431d52021-04-21 14:10:42 +0100309 } else {
310 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 +0100311 return nil
Paul Duffin74431d52021-04-21 14:10:42 +0100312 }
Paul Duffin10931582021-04-25 10:13:54 +0100313
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +0100314 if !dexJar.Valid() {
315 ctx.ModuleErrorf("dependency %s does not provide a dex jar: %s", module, dexJar.InvalidReason())
316 return nil
Paul Duffin10931582021-04-25 10:13:54 +0100317 }
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +0100318 return dexJar.Path()
Paul Duffin74431d52021-04-21 14:10:42 +0100319}
320
Paul Duffinbd88c882022-04-07 23:32:19 +0100321// HIDDENAPI_STUB_FLAGS_IMPL_FLAGS is the set of flags that identify implementation only signatures,
322// i.e. those signatures that are not part of any API (including the hidden API).
323var HIDDENAPI_STUB_FLAGS_IMPL_FLAGS = []string{}
324
325var HIDDENAPI_FLAGS_CSV_IMPL_FLAGS = []string{"blocked"}
326
Paul Duffin4539a372021-06-23 23:20:43 +0100327// buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
Paul Duffin74431d52021-04-21 14:10:42 +0100328//
329// The rule is initialized but not built so that the caller can modify it and select an appropriate
330// name.
Paul Duffin67b9d612021-07-21 17:38:47 +0100331func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput, stubFlagSubsets SignatureCsvSubsets) {
Paul Duffin74431d52021-04-21 14:10:42 +0100332 // Singleton rule which applies hiddenapi on all boot class path dex files.
333 rule := android.NewRuleBuilder(pctx, ctx)
334
335 tempPath := tempPathForRestat(ctx, outputPath)
336
Paul Duffinf1b358c2021-05-17 07:38:47 +0100337 // Find the widest API stubs provided by the fragments on which this depends, if any.
Paul Duffind2b1e0c2021-06-27 20:53:39 +0100338 dependencyStubDexJars := input.DependencyStubDexJarsByScope.StubDexJarsForWidestAPIScope()
Paul Duffin5cca7c42021-05-26 10:16:01 +0100339
340 // Add widest API stubs from the additional dependencies of this, if any.
Paul Duffind2b1e0c2021-06-27 20:53:39 +0100341 dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.StubDexJarsForWidestAPIScope()...)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100342
Paul Duffin74431d52021-04-21 14:10:42 +0100343 command := rule.Command().
344 Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
345 Text("list").
Paul Duffinf1b358c2021-05-17 07:38:47 +0100346 FlagForEachInput("--dependency-stub-dex=", dependencyStubDexJars).
Paul Duffin74431d52021-04-21 14:10:42 +0100347 FlagForEachInput("--boot-dex=", bootDexJars)
348
Paul Duffin156b5d32021-06-24 23:06:52 +0100349 // If no module stub flags paths are provided then this must be being called for a
350 // bootclasspath_fragment and not the whole platform_bootclasspath.
Paul Duffin67b9d612021-07-21 17:38:47 +0100351 if stubFlagSubsets == nil {
Paul Duffin156b5d32021-06-24 23:06:52 +0100352 // This is being run on a fragment of the bootclasspath.
353 command.Flag("--fragment")
354 }
355
Paul Duffin31fad802021-06-18 18:14:25 +0100356 // Iterate over the api scopes in a fixed order.
357 for _, apiScope := range hiddenAPIFlagScopes {
358 // Merge in the stub dex jar paths for this api scope from the fragments on which it depends.
359 // They will be needed to resolve dependencies from this fragment's stubs to classes in the
360 // other fragment's APIs.
361 var paths android.Paths
Paul Duffin280a31a2021-06-27 20:28:29 +0100362 paths = append(paths, input.DependencyStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
363 paths = append(paths, input.AdditionalStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
364 paths = append(paths, input.StubDexJarsByScope.StubDexJarsForScope(apiScope)...)
Paul Duffin74431d52021-04-21 14:10:42 +0100365 if len(paths) > 0 {
Paul Duffin31fad802021-06-18 18:14:25 +0100366 option := apiScope.hiddenAPIListOption
367 command.FlagWithInputList(option+"=", paths, ":")
Paul Duffin74431d52021-04-21 14:10:42 +0100368 }
369 }
370
371 // Add the output path.
372 command.FlagWithOutput("--out-api-flags=", tempPath)
373
Paul Duffin2e880972021-06-23 23:29:09 +0100374 // If there are stub flag files that have been generated by fragments on which this depends then
375 // use them to validate the stub flag file generated by the rules created by this method.
Alyssa Ketpreechasawat7daf2782023-11-01 13:58:39 +0000376 if !ctx.Config().DisableVerifyOverlaps() && len(stubFlagSubsets) > 0 {
Paul Duffinbd88c882022-04-07 23:32:19 +0100377 validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets,
378 HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
Paul Duffin2e880972021-06-23 23:29:09 +0100379
380 // Add the file that indicates that the file generated by this is valid.
381 //
382 // This will cause the validation rule above to be run any time that the output of this rule
383 // changes but the validation will run in parallel with other rules that depend on this file.
384 command.Validation(validFile)
385 }
386
Paul Duffin74431d52021-04-21 14:10:42 +0100387 commitChangeForRestat(rule, tempPath, outputPath)
Paul Duffin4539a372021-06-23 23:20:43 +0100388
389 rule.Build(name, desc)
Paul Duffin74431d52021-04-21 14:10:42 +0100390}
391
Paul Duffin46169772021-04-14 15:01:56 +0100392// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
393// information obtained from annotations within the source code in order to create the complete set
394// of flags that should be applied to the dex implementation jars on the bootclasspath.
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100395//
396// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
397// of each property reference a plain text file that contains a java signature per line. The flags
398// for each of those signatures will be updated in a property specific way.
399//
400// The Unsupported_packages property contains a list of paths, each of which is a plain text file
401// with one Java package per line. All members of all classes within that package (but not nested
402// packages) will be updated in a property specific way.
Paul Duffin46169772021-04-14 15:01:56 +0100403type HiddenAPIFlagFileProperties struct {
Paul Duffin9b61abb2022-07-27 16:16:54 +0000404 Hidden_api struct {
405 // Marks each signature in the referenced files as being unsupported.
406 Unsupported []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100407
Paul Duffin9b61abb2022-07-27 16:16:54 +0000408 // Marks each signature in the referenced files as being unsupported because it has been
409 // removed. Any conflicts with other flags are ignored.
410 Removed []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100411
Paul Duffin9b61abb2022-07-27 16:16:54 +0000412 // Marks each signature in the referenced files as being supported only for
413 // targetSdkVersion <= R and low priority.
414 Max_target_r_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100415
Paul Duffin9b61abb2022-07-27 16:16:54 +0000416 // Marks each signature in the referenced files as being supported only for
417 // targetSdkVersion <= Q.
418 Max_target_q []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100419
Paul Duffin9b61abb2022-07-27 16:16:54 +0000420 // Marks each signature in the referenced files as being supported only for
421 // targetSdkVersion <= P.
422 Max_target_p []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100423
Paul Duffin9b61abb2022-07-27 16:16:54 +0000424 // Marks each signature in the referenced files as being supported only for
425 // targetSdkVersion <= O
426 // and low priority. Any conflicts with other flags are ignored.
427 Max_target_o_low_priority []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100428
Paul Duffin9b61abb2022-07-27 16:16:54 +0000429 // Marks each signature in the referenced files as being blocked.
430 Blocked []string `android:"path"`
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100431
Paul Duffin9b61abb2022-07-27 16:16:54 +0000432 // Marks each signature in every package in the referenced files as being unsupported.
433 Unsupported_packages []string `android:"path"`
434 }
Paul Duffin702210b2021-04-08 20:12:41 +0100435}
436
Cole Faust22e8abc2024-01-23 17:52:13 -0800437type hiddenAPIFlagFileCategory int
Paul Duffine3dc6602021-04-14 09:50:43 +0100438
Cole Faust22e8abc2024-01-23 17:52:13 -0800439const (
440 // The flag file category for removed members of the API.
441 //
442 // This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
443 // list of removed API members that are generated automatically from the removed.txt files provided
444 // by API stubs.
445 hiddenAPIFlagFileCategoryRemoved hiddenAPIFlagFileCategory = iota
446 hiddenAPIFlagFileCategoryUnsupported
447 hiddenAPIFlagFileCategoryMaxTargetRLowPriority
448 hiddenAPIFlagFileCategoryMaxTargetQ
449 hiddenAPIFlagFileCategoryMaxTargetP
450 hiddenAPIFlagFileCategoryMaxTargetOLowPriority
451 hiddenAPIFlagFileCategoryBlocked
452 hiddenAPIFlagFileCategoryUnsupportedPackages
453)
Paul Duffine3dc6602021-04-14 09:50:43 +0100454
Cole Faust22e8abc2024-01-23 17:52:13 -0800455func (c hiddenAPIFlagFileCategory) PropertyName() string {
456 switch c {
457 case hiddenAPIFlagFileCategoryRemoved:
458 return "removed"
459 case hiddenAPIFlagFileCategoryUnsupported:
460 return "unsupported"
461 case hiddenAPIFlagFileCategoryMaxTargetRLowPriority:
462 return "max_target_r_low_priority"
463 case hiddenAPIFlagFileCategoryMaxTargetQ:
464 return "max_target_q"
465 case hiddenAPIFlagFileCategoryMaxTargetP:
466 return "max_target_p"
467 case hiddenAPIFlagFileCategoryMaxTargetOLowPriority:
468 return "max_target_o_low_priority"
469 case hiddenAPIFlagFileCategoryBlocked:
470 return "blocked"
471 case hiddenAPIFlagFileCategoryUnsupportedPackages:
472 return "unsupported_packages"
473 default:
474 panic(fmt.Sprintf("Unknown hidden api flag file category type: %d", c))
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000475 }
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000476}
477
Cole Faust22e8abc2024-01-23 17:52:13 -0800478// propertyValueReader retrieves the value of the property for this category from the set of properties.
479func (c hiddenAPIFlagFileCategory) propertyValueReader(properties *HiddenAPIFlagFileProperties) []string {
480 switch c {
481 case hiddenAPIFlagFileCategoryRemoved:
482 return properties.Hidden_api.Removed
483 case hiddenAPIFlagFileCategoryUnsupported:
484 return properties.Hidden_api.Unsupported
485 case hiddenAPIFlagFileCategoryMaxTargetRLowPriority:
486 return properties.Hidden_api.Max_target_r_low_priority
487 case hiddenAPIFlagFileCategoryMaxTargetQ:
488 return properties.Hidden_api.Max_target_q
489 case hiddenAPIFlagFileCategoryMaxTargetP:
490 return properties.Hidden_api.Max_target_p
491 case hiddenAPIFlagFileCategoryMaxTargetOLowPriority:
492 return properties.Hidden_api.Max_target_o_low_priority
493 case hiddenAPIFlagFileCategoryBlocked:
494 return properties.Hidden_api.Blocked
495 case hiddenAPIFlagFileCategoryUnsupportedPackages:
496 return properties.Hidden_api.Unsupported_packages
497 default:
498 panic(fmt.Sprintf("Unknown hidden api flag file category type: %d", c))
499 }
500}
501
502// commandMutator adds the appropriate command line options for this category to the supplied command
503func (c hiddenAPIFlagFileCategory) commandMutator(command *android.RuleBuilderCommand, path android.Path) {
504 switch c {
505 case hiddenAPIFlagFileCategoryRemoved:
506 command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
507 case hiddenAPIFlagFileCategoryUnsupported:
508 command.FlagWithInput("--unsupported ", path)
509 case hiddenAPIFlagFileCategoryMaxTargetRLowPriority:
510 command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
511 case hiddenAPIFlagFileCategoryMaxTargetQ:
512 command.FlagWithInput("--max-target-q ", path)
513 case hiddenAPIFlagFileCategoryMaxTargetP:
514 command.FlagWithInput("--max-target-p ", path)
515 case hiddenAPIFlagFileCategoryMaxTargetOLowPriority:
516 command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
517 case hiddenAPIFlagFileCategoryBlocked:
518 command.FlagWithInput("--blocked ", path)
519 case hiddenAPIFlagFileCategoryUnsupportedPackages:
520 command.FlagWithInput("--unsupported ", path).Flag("--packages ")
521 default:
522 panic(fmt.Sprintf("Unknown hidden api flag file category type: %d", c))
523 }
524}
525
526type hiddenAPIFlagFileCategories []hiddenAPIFlagFileCategory
527
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000528var HiddenAPIFlagFileCategories = hiddenAPIFlagFileCategories{
Paul Duffin46169772021-04-14 15:01:56 +0100529 // See HiddenAPIFlagFileProperties.Unsupported
Cole Faust22e8abc2024-01-23 17:52:13 -0800530 hiddenAPIFlagFileCategoryUnsupported,
531 // See HiddenAPIFlagFileProperties.Removed
532 hiddenAPIFlagFileCategoryRemoved,
Paul Duffin46169772021-04-14 15:01:56 +0100533 // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
Cole Faust22e8abc2024-01-23 17:52:13 -0800534 hiddenAPIFlagFileCategoryMaxTargetRLowPriority,
Paul Duffin46169772021-04-14 15:01:56 +0100535 // See HiddenAPIFlagFileProperties.Max_target_q
Cole Faust22e8abc2024-01-23 17:52:13 -0800536 hiddenAPIFlagFileCategoryMaxTargetQ,
Paul Duffin46169772021-04-14 15:01:56 +0100537 // See HiddenAPIFlagFileProperties.Max_target_p
Cole Faust22e8abc2024-01-23 17:52:13 -0800538 hiddenAPIFlagFileCategoryMaxTargetP,
Paul Duffin46169772021-04-14 15:01:56 +0100539 // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
Cole Faust22e8abc2024-01-23 17:52:13 -0800540 hiddenAPIFlagFileCategoryMaxTargetOLowPriority,
Paul Duffin46169772021-04-14 15:01:56 +0100541 // See HiddenAPIFlagFileProperties.Blocked
Cole Faust22e8abc2024-01-23 17:52:13 -0800542 hiddenAPIFlagFileCategoryBlocked,
Paul Duffin46169772021-04-14 15:01:56 +0100543 // See HiddenAPIFlagFileProperties.Unsupported_packages
Cole Faust22e8abc2024-01-23 17:52:13 -0800544 hiddenAPIFlagFileCategoryUnsupportedPackages,
Paul Duffin702210b2021-04-08 20:12:41 +0100545}
546
Paul Duffin438eb572021-05-21 16:58:23 +0100547// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
Cole Faust22e8abc2024-01-23 17:52:13 -0800548type FlagFilesByCategory map[hiddenAPIFlagFileCategory]android.Paths
Paul Duffin438eb572021-05-21 16:58:23 +0100549
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000550// append the supplied flags files to the corresponding category in this map.
Paul Duffin438eb572021-05-21 16:58:23 +0100551func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
Paul Duffin524c82c2021-06-09 14:39:28 +0100552 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +0100553 s[category] = append(s[category], other[category]...)
554 }
555}
556
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000557// sort the paths for each category in this map.
558func (s FlagFilesByCategory) sort() {
559 for category, value := range s {
560 s[category] = android.SortedUniquePaths(value)
561 }
562}
563
Paul Duffinaf99afa2021-05-21 22:18:56 +0100564// HiddenAPIInfo contains information provided by the hidden API processing.
Paul Duffin2fef1362021-04-15 13:32:00 +0100565//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100566// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
567// processing.
568type HiddenAPIInfo struct {
Paul Duffin438eb572021-05-21 16:58:23 +0100569 // FlagFilesByCategory maps from the flag file category to the paths containing information for
570 // that category.
571 FlagFilesByCategory FlagFilesByCategory
Paul Duffin2fef1362021-04-15 13:32:00 +0100572
Paul Duffin280a31a2021-06-27 20:28:29 +0100573 // The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes provided by
574 // this fragment and the fragments on which this depends.
575 TransitiveStubDexJarsByScope StubDexJarsByModule
Paul Duffin18cf1972021-05-21 22:46:59 +0100576
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100577 // The output from the hidden API processing needs to be made available to other modules.
578 HiddenAPIFlagOutput
Paul Duffinc6bb7cf2021-04-08 17:49:27 +0100579}
Paul Duffin702210b2021-04-08 20:12:41 +0100580
Paul Duffinf1b358c2021-05-17 07:38:47 +0100581func newHiddenAPIInfo() *HiddenAPIInfo {
582 info := HiddenAPIInfo{
Paul Duffin31fad802021-06-18 18:14:25 +0100583 FlagFilesByCategory: FlagFilesByCategory{},
Paul Duffin280a31a2021-06-27 20:28:29 +0100584 TransitiveStubDexJarsByScope: StubDexJarsByModule{},
Paul Duffinf1b358c2021-05-17 07:38:47 +0100585 }
586 return &info
587}
588
589func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragments []android.Module) {
590 // Merge all the information from the fragments. The fragments form a DAG so it is possible that
591 // this will introduce duplicates so they will be resolved after processing all the fragments.
592 for _, fragment := range fragments {
Colin Cross313aa542023-12-13 13:47:44 -0800593 if info, ok := android.OtherModuleProvider(ctx, fragment, HiddenAPIInfoProvider); ok {
Paul Duffin280a31a2021-06-27 20:28:29 +0100594 i.TransitiveStubDexJarsByScope.addStubDexJarsByModule(info.TransitiveStubDexJarsByScope)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100595 }
596 }
Paul Duffinf1b358c2021-05-17 07:38:47 +0100597}
598
Paul Duffin191be3a2021-08-10 16:14:16 +0100599// StubFlagSubset returns a SignatureCsvSubset that contains a path to a filtered-stub-flags.csv
600// file and a path to a signature-patterns.csv file that defines a subset of the monolithic stub
601// flags file, i.e. out/soong/hiddenapi/hiddenapi-stub-flags.txt, against which it will be compared.
Paul Duffin67b9d612021-07-21 17:38:47 +0100602func (i *HiddenAPIInfo) StubFlagSubset() SignatureCsvSubset {
Paul Duffin191be3a2021-08-10 16:14:16 +0100603 return SignatureCsvSubset{i.FilteredStubFlagsPath, i.SignaturePatternsPath}
Paul Duffin67b9d612021-07-21 17:38:47 +0100604}
605
Paul Duffin191be3a2021-08-10 16:14:16 +0100606// FlagSubset returns a SignatureCsvSubset that contains a path to a filtered-flags.csv file and a
Paul Duffin67b9d612021-07-21 17:38:47 +0100607// path to a signature-patterns.csv file that defines a subset of the monolithic flags file, i.e.
608// out/soong/hiddenapi/hiddenapi-flags.csv, against which it will be compared.
609func (i *HiddenAPIInfo) FlagSubset() SignatureCsvSubset {
Paul Duffin191be3a2021-08-10 16:14:16 +0100610 return SignatureCsvSubset{i.FilteredFlagsPath, i.SignaturePatternsPath}
Paul Duffin67b9d612021-07-21 17:38:47 +0100611}
612
Colin Crossbc7d76c2023-12-12 16:39:03 -0800613var HiddenAPIInfoProvider = blueprint.NewProvider[HiddenAPIInfo]()
Paul Duffin9b381ef2021-04-08 23:01:37 +0100614
Paul Duffin887efdd2022-09-14 16:37:12 +0100615// HiddenAPIInfoForSdk contains information provided by the hidden API processing for use
616// by the sdk snapshot.
617//
618// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
619// processing.
620type HiddenAPIInfoForSdk struct {
621 // FlagFilesByCategory maps from the flag file category to the paths containing information for
622 // that category.
623 FlagFilesByCategory FlagFilesByCategory
624
625 // The output from the hidden API processing needs to be made available to other modules.
626 HiddenAPIFlagOutput
627}
628
629// Provides hidden API info for the sdk snapshot.
Colin Crossbc7d76c2023-12-12 16:39:03 -0800630var HiddenAPIInfoForSdkProvider = blueprint.NewProvider[HiddenAPIInfoForSdk]()
Paul Duffin887efdd2022-09-14 16:37:12 +0100631
Paul Duffin280a31a2021-06-27 20:28:29 +0100632// ModuleStubDexJars contains the stub dex jars provided by a single module.
633//
634// It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See
635// hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
636type ModuleStubDexJars map[*HiddenAPIScope]android.Path
Paul Duffin1352f7c2021-05-21 22:18:49 +0100637
Paul Duffin280a31a2021-06-27 20:28:29 +0100638// stubDexJarForWidestAPIScope returns the stub dex jars for the widest API scope provided by this
Paul Duffin1352f7c2021-05-21 22:18:49 +0100639// map.
Paul Duffin280a31a2021-06-27 20:28:29 +0100640//
641// The relative width of APIs is determined by their order in hiddenAPIScopes.
642func (s ModuleStubDexJars) stubDexJarForWidestAPIScope() android.Path {
Paul Duffin5cca7c42021-05-26 10:16:01 +0100643 for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
644 apiScope := hiddenAPIScopes[i]
Paul Duffin280a31a2021-06-27 20:28:29 +0100645 if stubsForAPIScope, ok := s[apiScope]; ok {
Paul Duffin5cca7c42021-05-26 10:16:01 +0100646 return stubsForAPIScope
647 }
648 }
649
650 return nil
651}
652
Paul Duffin280a31a2021-06-27 20:28:29 +0100653// StubDexJarsByModule contains the stub dex jars provided by a set of modules.
654//
655// It maps a module name to the path to the stub dex jars provided by that module.
656type StubDexJarsByModule map[string]ModuleStubDexJars
657
658// addStubDexJar adds a stub dex jar path provided by the specified module for the specified scope.
659func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.Module, scope *HiddenAPIScope, stubDexJar android.Path) {
660 name := android.RemoveOptionalPrebuiltPrefix(module.Name())
Paul Duffin3f0290e2021-06-30 18:25:36 +0100661
662 // Each named module provides one dex jar for each scope. However, in some cases different API
663 // versions of a single classes are provided by separate modules. e.g. the core platform
664 // version of java.lang.Object is provided by the legacy.art.module.platform.api module but the
665 // public version is provided by the art.module.public.api module. In those cases it is necessary
666 // to treat all those modules as they were the same name, otherwise it will result in multiple
667 // definitions of a single class being passed to hidden API processing which will cause an error.
Jihoon Kang244d42a2023-10-06 16:54:58 +0000668 if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule || name == scope.nonUpdatableFromTextModule {
Paul Duffin280a31a2021-06-27 20:28:29 +0100669 // Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
670 // java_sdk_library.
671 // TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent.
672 name = "android-non-updatable"
673 } else if name == "legacy.art.module.platform.api" {
674 // Treat legacy.art.module.platform.api as if it was an API scope provided by the
675 // art.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 = "art.module.public.api"
678 } else if name == "legacy.i18n.module.platform.api" {
679 // Treat legacy.i18n.module.platform.api as if it was an API scope provided by the
680 // i18n.module.public.api java_sdk_library which will be the case once the former has been
681 // migrated to a module_lib API.
682 name = "i18n.module.public.api"
683 } else if name == "conscrypt.module.platform.api" {
684 // Treat conscrypt.module.platform.api as if it was an API scope provided by the
685 // conscrypt.module.public.api java_sdk_library which will be the case once the former has been
686 // migrated to a module_lib API.
687 name = "conscrypt.module.public.api"
Paul Duffin3f0290e2021-06-30 18:25:36 +0100688 } else if d, ok := module.(SdkLibraryComponentDependency); ok {
689 sdkLibraryName := d.SdkLibraryName()
690 if sdkLibraryName != nil {
691 // The module is a component of a java_sdk_library so use the name of the java_sdk_library.
692 // e.g. if this module is `foo.system.stubs` and is part of the `foo` java_sdk_library then
693 // use `foo` as the name.
694 name = *sdkLibraryName
695 }
Paul Duffin280a31a2021-06-27 20:28:29 +0100696 }
697 stubDexJarsByScope := s[name]
698 if stubDexJarsByScope == nil {
699 stubDexJarsByScope = ModuleStubDexJars{}
700 s[name] = stubDexJarsByScope
701 }
702 stubDexJarsByScope[scope] = stubDexJar
703}
704
705// addStubDexJarsByModule adds the stub dex jars in the supplied StubDexJarsByModule to this map.
706func (s StubDexJarsByModule) addStubDexJarsByModule(other StubDexJarsByModule) {
707 for module, stubDexJarsByScope := range other {
708 s[module] = stubDexJarsByScope
709 }
710}
711
712// StubDexJarsForWidestAPIScope returns a list of stub dex jars containing the widest API scope
713// provided by each module.
714//
715// The relative width of APIs is determined by their order in hiddenAPIScopes.
716func (s StubDexJarsByModule) StubDexJarsForWidestAPIScope() android.Paths {
717 stubDexJars := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -0800718 modules := android.SortedKeys(s)
Paul Duffin280a31a2021-06-27 20:28:29 +0100719 for _, module := range modules {
720 stubDexJarsByScope := s[module]
721
722 stubDexJars = append(stubDexJars, stubDexJarsByScope.stubDexJarForWidestAPIScope())
723 }
724
725 return stubDexJars
726}
727
728// StubDexJarsForScope returns a list of stub dex jars containing the stub dex jars provided by each
729// module for the specified scope.
730//
731// If a module does not provide a stub dex jar for the supplied scope then it does not contribute to
732// the returned list.
733func (s StubDexJarsByModule) StubDexJarsForScope(scope *HiddenAPIScope) android.Paths {
734 stubDexJars := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -0800735 modules := android.SortedKeys(s)
Paul Duffin280a31a2021-06-27 20:28:29 +0100736 for _, module := range modules {
737 stubDexJarsByScope := s[module]
738 // Not every module will have the same set of
739 if jars, ok := stubDexJarsByScope[scope]; ok {
740 stubDexJars = append(stubDexJars, jars)
741 }
742 }
743
744 return stubDexJars
745}
746
Paul Duffin1e9e9382022-07-27 15:55:06 +0000747type HiddenAPIPropertyInfo struct {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100748 // FlagFilesByCategory contains the flag files that override the initial flags that are derived
749 // from the stub dex files.
750 FlagFilesByCategory FlagFilesByCategory
751
Paul Duffin1e9e9382022-07-27 15:55:06 +0000752 // See HiddenAPIFlagFileProperties.Package_prefixes
753 PackagePrefixes []string
754
755 // See HiddenAPIFlagFileProperties.Single_packages
756 SinglePackages []string
757
758 // See HiddenAPIFlagFileProperties.Split_packages
759 SplitPackages []string
760}
761
Colin Crossbc7d76c2023-12-12 16:39:03 -0800762var hiddenAPIPropertyInfoProvider = blueprint.NewProvider[HiddenAPIPropertyInfo]()
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000763
Paul Duffin1e9e9382022-07-27 15:55:06 +0000764// newHiddenAPIPropertyInfo creates a new initialized HiddenAPIPropertyInfo struct.
765func newHiddenAPIPropertyInfo() HiddenAPIPropertyInfo {
766 return HiddenAPIPropertyInfo{
767 FlagFilesByCategory: FlagFilesByCategory{},
768 }
769}
770
771// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
772// supplied properties and stores them in this struct.
773func (i *HiddenAPIPropertyInfo) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
774 for _, category := range HiddenAPIFlagFileCategories {
775 paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
776 i.FlagFilesByCategory[category] = paths
777 }
778}
779
780// extractPackageRulesFromProperties extracts the package rules that are specified in the supplied
781// properties and stores them in this struct.
782func (i *HiddenAPIPropertyInfo) extractPackageRulesFromProperties(p *HiddenAPIPackageProperties) {
783 i.PackagePrefixes = p.Hidden_api.Package_prefixes
784 i.SinglePackages = p.Hidden_api.Single_packages
785 i.SplitPackages = p.Hidden_api.Split_packages
786}
787
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000788func (i *HiddenAPIPropertyInfo) gatherPropertyInfo(ctx android.ModuleContext, contents []android.Module) {
789 for _, module := range contents {
Colin Cross313aa542023-12-13 13:47:44 -0800790 if info, ok := android.OtherModuleProvider(ctx, module, hiddenAPIPropertyInfoProvider); ok {
Paul Duffin3f1ae0b2022-07-27 16:27:42 +0000791 i.FlagFilesByCategory.append(info.FlagFilesByCategory)
792 i.PackagePrefixes = append(i.PackagePrefixes, info.PackagePrefixes...)
793 i.SinglePackages = append(i.SinglePackages, info.SinglePackages...)
794 i.SplitPackages = append(i.SplitPackages, info.SplitPackages...)
795 }
796 }
797
798 // Dedup and sort the information to ensure consistent builds.
799 i.FlagFilesByCategory.sort()
800 i.PackagePrefixes = android.SortedUniqueStrings(i.PackagePrefixes)
801 i.SinglePackages = android.SortedUniqueStrings(i.SinglePackages)
802 i.SplitPackages = android.SortedUniqueStrings(i.SplitPackages)
803}
804
Paul Duffin1e9e9382022-07-27 15:55:06 +0000805// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
806// needed for hidden API flag generation.
807type HiddenAPIFlagInput struct {
808 HiddenAPIPropertyInfo
809
Paul Duffin31fad802021-06-18 18:14:25 +0100810 // StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
Paul Duffin1352f7c2021-05-21 22:18:49 +0100811 // the initial flags for each dex member.
Paul Duffin280a31a2021-06-27 20:28:29 +0100812 StubDexJarsByScope StubDexJarsByModule
Paul Duffinf1b358c2021-05-17 07:38:47 +0100813
Paul Duffin31fad802021-06-18 18:14:25 +0100814 // DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
815 // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
Paul Duffinf1b358c2021-05-17 07:38:47 +0100816 // fragment on which this depends.
Paul Duffin280a31a2021-06-27 20:28:29 +0100817 DependencyStubDexJarsByScope StubDexJarsByModule
Paul Duffin32cf58a2021-05-18 16:32:50 +0100818
Paul Duffin5cca7c42021-05-26 10:16:01 +0100819 // AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to
820 // the ones that are obtained from fragments on which this depends.
821 //
822 // These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope
823 // as there are not propagated transitively to other fragments that depend on this.
Paul Duffin280a31a2021-06-27 20:28:29 +0100824 AdditionalStubDexJarsByScope StubDexJarsByModule
Paul Duffin5cca7c42021-05-26 10:16:01 +0100825
Paul Duffin32cf58a2021-05-18 16:32:50 +0100826 // RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
827 // specified in the bootclasspath_fragment's stub_libs and contents properties.
828 RemovedTxtFiles android.Paths
Paul Duffin1352f7c2021-05-21 22:18:49 +0100829}
830
Paul Duffin1e9e9382022-07-27 15:55:06 +0000831// newHiddenAPIFlagInput creates a new initialized HiddenAPIFlagInput struct.
Paul Duffin1352f7c2021-05-21 22:18:49 +0100832func newHiddenAPIFlagInput() HiddenAPIFlagInput {
833 input := HiddenAPIFlagInput{
Paul Duffin1e9e9382022-07-27 15:55:06 +0000834 HiddenAPIPropertyInfo: newHiddenAPIPropertyInfo(),
Paul Duffin280a31a2021-06-27 20:28:29 +0100835 StubDexJarsByScope: StubDexJarsByModule{},
836 DependencyStubDexJarsByScope: StubDexJarsByModule{},
837 AdditionalStubDexJarsByScope: StubDexJarsByModule{},
Paul Duffin1352f7c2021-05-21 22:18:49 +0100838 }
839
840 return input
841}
842
843// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
844// dependencies added in hiddenAPIAddStubLibDependencies.
845//
846// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
847func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
Paul Duffin31fad802021-06-18 18:14:25 +0100848 addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
849 sdkKind := apiScope.sdkKind
850 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100851 if dexJar != nil {
Paul Duffin280a31a2021-06-27 20:28:29 +0100852 i.StubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100853 }
Paul Duffin32cf58a2021-05-18 16:32:50 +0100854
Jihoon Kang98e9ac62024-09-25 23:42:30 +0000855 if sdkLibrary, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
856 removedTxtFile := sdkLibrary.RemovedTxtFiles[sdkKind]
Paul Duffin32cf58a2021-05-18 16:32:50 +0100857 i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
858 }
Paul Duffin1352f7c2021-05-21 22:18:49 +0100859 }
860
861 // If the contents includes any java_sdk_library modules then add them to the stubs.
862 for _, module := range contents {
Jihoon Kang98e9ac62024-09-25 23:42:30 +0000863 if _, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100864 // Add information for every possible API scope needed by hidden API.
865 for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
866 addFromModule(ctx, module, apiScope)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100867 }
868 }
869 }
870
Paul Duffind061d402021-06-07 21:36:01 +0100871 ctx.VisitDirectDeps(func(module android.Module) {
Paul Duffin1352f7c2021-05-21 22:18:49 +0100872 tag := ctx.OtherModuleDependencyTag(module)
873 if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
Paul Duffin31fad802021-06-18 18:14:25 +0100874 apiScope := hiddenAPIStubsTag.apiScope
Paul Duffin5cca7c42021-05-26 10:16:01 +0100875 if hiddenAPIStubsTag.fromAdditionalDependency {
876 dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind)
877 if dexJar != nil {
Paul Duffin280a31a2021-06-27 20:28:29 +0100878 i.AdditionalStubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
Paul Duffin5cca7c42021-05-26 10:16:01 +0100879 }
880 } else {
881 addFromModule(ctx, module, apiScope)
882 }
Paul Duffin1352f7c2021-05-21 22:18:49 +0100883 }
884 })
885
886 // Normalize the paths, i.e. remove duplicates and sort.
Paul Duffin32cf58a2021-05-18 16:32:50 +0100887 i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
Paul Duffin1352f7c2021-05-21 22:18:49 +0100888}
889
Paul Duffin280a31a2021-06-27 20:28:29 +0100890func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByModule {
Paul Duffin31fad802021-06-18 18:14:25 +0100891 transitive := i.DependencyStubDexJarsByScope
Paul Duffin280a31a2021-06-27 20:28:29 +0100892 transitive.addStubDexJarsByModule(i.StubDexJarsByScope)
Paul Duffinf1b358c2021-05-17 07:38:47 +0100893 return transitive
894}
895
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100896// HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
897// bootclasspath_fragment module.
898type HiddenAPIFlagOutput struct {
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100899 // The path to the generated annotation-flags.csv file.
900 AnnotationFlagsPath android.Path
901
902 // The path to the generated metadata.csv file.
903 MetadataPath android.Path
904
905 // The path to the generated index.csv file.
906 IndexPath android.Path
907
Paul Duffin191be3a2021-08-10 16:14:16 +0100908 // The path to the generated stub-flags.csv file.
909 StubFlagsPath android.Path
910
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100911 // The path to the generated all-flags.csv file.
912 AllFlagsPath android.Path
Paul Duffin67b9d612021-07-21 17:38:47 +0100913
914 // The path to the generated signature-patterns.txt file which defines the subset of the
915 // monolithic hidden API files provided in this.
916 SignaturePatternsPath android.Path
Paul Duffin191be3a2021-08-10 16:14:16 +0100917
918 // The path to the generated filtered-stub-flags.csv file.
919 FilteredStubFlagsPath android.Path
920
921 // The path to the generated filtered-flags.csv file.
922 FilteredFlagsPath android.Path
Paul Duffin1e6f5c42021-05-21 16:15:31 +0100923}
924
Paul Duffin5f148ca2021-06-02 17:24:22 +0100925// bootDexJarByModule is a map from base module name (without prebuilt_ prefix) to the boot dex
926// path.
927type bootDexJarByModule map[string]android.Path
928
929// addPath adds the path for a module to the map.
930func (b bootDexJarByModule) addPath(module android.Module, path android.Path) {
931 b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path
932}
933
Paul Duffine5218812021-06-07 13:28:19 +0100934// bootDexJars returns the boot dex jar paths sorted by their keys.
935func (b bootDexJarByModule) bootDexJars() android.Paths {
936 paths := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -0800937 for _, k := range android.SortedKeys(b) {
Paul Duffine5218812021-06-07 13:28:19 +0100938 paths = append(paths, b[k])
939 }
940 return paths
941}
942
Paul Duffin7f872162021-06-17 19:33:24 +0100943// bootDexJarsWithoutCoverage returns the boot dex jar paths sorted by their keys without coverage
944// libraries if present.
945func (b bootDexJarByModule) bootDexJarsWithoutCoverage() android.Paths {
946 paths := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -0800947 for _, k := range android.SortedKeys(b) {
Paul Duffin7f872162021-06-17 19:33:24 +0100948 if k == "jacocoagent" {
949 continue
950 }
951 paths = append(paths, b[k])
952 }
953 return paths
954}
955
Paul Duffine5218812021-06-07 13:28:19 +0100956// HiddenAPIOutput encapsulates the output from the hidden API processing.
957type HiddenAPIOutput struct {
958 HiddenAPIFlagOutput
959
960 // The map from base module name to the path to the encoded boot dex file.
Spandan Das5be63332023-12-13 00:06:32 +0000961 // This field is not available in prebuilt apexes
Paul Duffine5218812021-06-07 13:28:19 +0100962 EncodedBootDexFilesByModule bootDexJarByModule
963}
964
Paul Duffindfa10832021-05-13 17:31:51 +0100965// pathForValidation creates a path of the same type as the supplied type but with a name of
966// <path>.valid.
967//
968// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
969// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
970func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
971 extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
972 return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
973}
974
Paul Duffin2fef1362021-04-15 13:32:00 +0100975// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
976// the flags from all the modules, the stub flags, augmented with some additional configuration
977// files.
Paul Duffin702210b2021-04-08 20:12:41 +0100978//
979// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
980// an entry for every single member in the dex implementation jars of the individual modules. Every
981// signature in any of the other files MUST be included in this file.
982//
Paul Duffin537ea3d2021-05-14 10:38:00 +0100983// annotationFlags is the path to the annotation flags file generated from annotation information
984// in each module.
Paul Duffin702210b2021-04-08 20:12:41 +0100985//
Paul Duffinaf99afa2021-05-21 22:18:56 +0100986// hiddenAPIInfo is a struct containing paths to files that augment the information provided by
Paul Duffin537ea3d2021-05-14 10:38:00 +0100987// the annotationFlags.
Paul Duffin32cf58a2021-05-18 16:32:50 +0100988func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string,
Paul Duffind061d402021-06-07 21:36:01 +0100989 outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
Paul Duffin67b9d612021-07-21 17:38:47 +0100990 flagFilesByCategory FlagFilesByCategory, flagSubsets SignatureCsvSubsets, generatedRemovedDexSignatures android.OptionalPath) {
Paul Duffindfa10832021-05-13 17:31:51 +0100991
Paul Duffindfa10832021-05-13 17:31:51 +0100992 // Create the rule that will generate the flag files.
Paul Duffind3c15132021-04-21 22:12:35 +0100993 tempPath := tempPathForRestat(ctx, outputPath)
Paul Duffin702210b2021-04-08 20:12:41 +0100994 rule := android.NewRuleBuilder(pctx, ctx)
995 command := rule.Command().
996 BuiltTool("generate_hiddenapi_lists").
997 FlagWithInput("--csv ", baseFlagsPath).
Paul Duffind061d402021-06-07 21:36:01 +0100998 Inputs(annotationFlagPaths).
Paul Duffin702210b2021-04-08 20:12:41 +0100999 FlagWithOutput("--output ", tempPath)
1000
Paul Duffine3dc6602021-04-14 09:50:43 +01001001 // Add the options for the different categories of flag files.
Paul Duffin524c82c2021-06-09 14:39:28 +01001002 for _, category := range HiddenAPIFlagFileCategories {
Paul Duffin438eb572021-05-21 16:58:23 +01001003 paths := flagFilesByCategory[category]
Paul Duffine3dc6602021-04-14 09:50:43 +01001004 for _, path := range paths {
1005 category.commandMutator(command, path)
1006 }
Paul Duffin702210b2021-04-08 20:12:41 +01001007 }
1008
Paul Duffin32cf58a2021-05-18 16:32:50 +01001009 // If available then pass the automatically generated file containing dex signatures of removed
1010 // API members to the rule so they can be marked as removed.
1011 if generatedRemovedDexSignatures.Valid() {
Cole Faust22e8abc2024-01-23 17:52:13 -08001012 hiddenAPIFlagFileCategoryRemoved.commandMutator(command, generatedRemovedDexSignatures.Path())
Paul Duffin32cf58a2021-05-18 16:32:50 +01001013 }
1014
Paul Duffin702210b2021-04-08 20:12:41 +01001015 commitChangeForRestat(rule, tempPath, outputPath)
1016
Paul Duffin2e880972021-06-23 23:29:09 +01001017 // If there are flag files that have been generated by fragments on which this depends then use
1018 // them to validate the flag file generated by the rules created by this method.
Alyssa Ketpreechasawat7daf2782023-11-01 13:58:39 +00001019 if !ctx.Config().DisableVerifyOverlaps() && len(flagSubsets) > 0 {
Paul Duffinbd88c882022-04-07 23:32:19 +01001020 validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets,
1021 HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
Paul Duffin2e880972021-06-23 23:29:09 +01001022
Paul Duffindfa10832021-05-13 17:31:51 +01001023 // Add the file that indicates that the file generated by this is valid.
1024 //
1025 // This will cause the validation rule above to be run any time that the output of this rule
1026 // changes but the validation will run in parallel with other rules that depend on this file.
1027 command.Validation(validFile)
1028 }
1029
Paul Duffin2fef1362021-04-15 13:32:00 +01001030 rule.Build(name, desc)
1031}
1032
Paul Duffin67b9d612021-07-21 17:38:47 +01001033// SignatureCsvSubset describes a subset of a monolithic flags file, i.e. either
1034// out/soong/hiddenapi/hiddenapi-stub-flags.txt or out/soong/hiddenapi/hiddenapi-flags.csv
1035type SignatureCsvSubset struct {
1036 // The path to the CSV file containing hidden API flags.
1037 //
1038 // It has the dex member signature as the first column, with flags, one per column, in the
1039 // subsequent columns.
1040 CsvFile android.Path
1041
1042 // The path to the CSV file containing the signature patterns.
1043 //
1044 // It is a single column CSV file with the column containing a signature pattern.
1045 SignaturePatternsFile android.Path
1046}
1047
1048type SignatureCsvSubsets []SignatureCsvSubset
1049
1050func (s SignatureCsvSubsets) RelativeToTop() []string {
1051 result := []string{}
1052 for _, subset := range s {
1053 result = append(result, fmt.Sprintf("%s:%s", subset.CsvFile.RelativeToTop(), subset.SignaturePatternsFile.RelativeToTop()))
1054 }
1055 return result
1056}
1057
1058// buildRuleSignaturePatternsFile creates a rule to generate a file containing the set of signature
1059// patterns that will select a subset of the monolithic flags.
Paul Duffin846beb72022-03-15 17:45:57 +00001060func buildRuleSignaturePatternsFile(
1061 ctx android.ModuleContext, flagsPath android.Path,
Paul Duffin1938dba2022-07-26 23:53:00 +00001062 splitPackages []string, packagePrefixes []string, singlePackages []string,
1063 suffix string) android.Path {
1064 hiddenApiSubDir := "modular-hiddenapi" + suffix
1065
1066 patternsFile := android.PathForModuleOut(ctx, hiddenApiSubDir, "signature-patterns.csv")
Paul Duffin67b9d612021-07-21 17:38:47 +01001067 // Create a rule to validate the output from the following rule.
1068 rule := android.NewRuleBuilder(pctx, ctx)
Paul Duffin1e18e982021-08-03 15:42:27 +01001069
1070 // Quote any * in the packages to avoid them being expanded by the shell.
1071 quotedSplitPackages := []string{}
1072 for _, pkg := range splitPackages {
1073 quotedSplitPackages = append(quotedSplitPackages, strings.ReplaceAll(pkg, "*", "\\*"))
1074 }
1075
Paul Duffin67b9d612021-07-21 17:38:47 +01001076 rule.Command().
1077 BuiltTool("signature_patterns").
1078 FlagWithInput("--flags ", flagsPath).
Paul Duffin1e18e982021-08-03 15:42:27 +01001079 FlagForEachArg("--split-package ", quotedSplitPackages).
1080 FlagForEachArg("--package-prefix ", packagePrefixes).
Paul Duffin846beb72022-03-15 17:45:57 +00001081 FlagForEachArg("--single-package ", singlePackages).
Paul Duffin67b9d612021-07-21 17:38:47 +01001082 FlagWithOutput("--output ", patternsFile)
Paul Duffin1938dba2022-07-26 23:53:00 +00001083 rule.Build("hiddenAPISignaturePatterns"+suffix, "hidden API signature patterns"+suffix)
Paul Duffin67b9d612021-07-21 17:38:47 +01001084
1085 return patternsFile
1086}
1087
Paul Duffinbd88c882022-04-07 23:32:19 +01001088// buildRuleRemoveSignaturesWithImplementationFlags creates a rule that will remove signatures from
1089// the input flags file which have only the implementation flags, i.e. are not part of an API.
1090//
1091// The implementationFlags specifies the set of default flags that identifies the signature of a
1092// private, implementation only, member. Signatures that match those flags are removed from the
1093// flags as they are implementation only.
1094//
1095// This is used to remove implementation only signatures from the signature files that are persisted
1096// in the sdk snapshot as the sdk snapshots should not include implementation details. The
1097// signatures generated by this method will be compared by the buildRuleValidateOverlappingCsvFiles
1098// method which treats any missing signatures as if they were implementation only signatures.
1099func buildRuleRemoveSignaturesWithImplementationFlags(ctx android.BuilderContext,
1100 name string, desc string, inputPath android.Path, filteredPath android.WritablePath,
1101 implementationFlags []string) {
1102
Paul Duffin280bae62021-07-20 18:03:53 +01001103 rule := android.NewRuleBuilder(pctx, ctx)
Paul Duffinbd88c882022-04-07 23:32:19 +01001104 implementationFlagPattern := ""
1105 for _, implementationFlag := range implementationFlags {
1106 implementationFlagPattern = implementationFlagPattern + "," + implementationFlag
1107 }
Paul Duffin280bae62021-07-20 18:03:53 +01001108 rule.Command().
Paul Duffinbd88c882022-04-07 23:32:19 +01001109 Text(`grep -vE "^[^,]+` + implementationFlagPattern + `$"`).Input(inputPath).
1110 Text(">").Output(filteredPath).
Paul Duffin280bae62021-07-20 18:03:53 +01001111 // Grep's exit code depends on whether it finds anything. It is 0 (build success) when it finds
1112 // something and 1 (build failure) when it does not and 2 (when it encounters an error).
1113 // However, while it is unlikely it is not an error if this does not find any matches. The
1114 // following will only run if the grep does not find something and in that case it will treat
1115 // an exit code of 1 as success and anything else as failure.
1116 Text("|| test $? -eq 1")
1117 rule.Build(name, desc)
1118}
1119
Paul Duffin2e880972021-06-23 23:29:09 +01001120// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
1121// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
Paul Duffinbd88c882022-04-07 23:32:19 +01001122//
1123// The implementationFlags specifies the set of default flags that identifies the signature of a
1124// private, implementation only, member. A signature which is present in a monolithic flags subset
1125// defined by SignatureCsvSubset but which is not present in the flags file from the corresponding
1126// module is assumed to be an implementation only member and so must have these flags.
1127func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string,
1128 monolithicFilePath android.WritablePath, csvSubsets SignatureCsvSubsets,
1129 implementationFlags []string) android.WritablePath {
Paul Duffin2e880972021-06-23 23:29:09 +01001130 // The file which is used to record that the flags file is valid.
1131 validFile := pathForValidation(ctx, monolithicFilePath)
1132
1133 // Create a rule to validate the output from the following rule.
1134 rule := android.NewRuleBuilder(pctx, ctx)
Paul Duffin67b9d612021-07-21 17:38:47 +01001135 command := rule.Command().
Paul Duffin2e880972021-06-23 23:29:09 +01001136 BuiltTool("verify_overlaps").
Paul Duffin0c12b782022-04-08 00:28:11 +01001137 FlagWithInput("--monolithic-flags ", monolithicFilePath)
Paul Duffin67b9d612021-07-21 17:38:47 +01001138
1139 for _, subset := range csvSubsets {
1140 command.
Paul Duffin0c12b782022-04-08 00:28:11 +01001141 Flag("--module-flags ").
Paul Duffin67b9d612021-07-21 17:38:47 +01001142 Textf("%s:%s", subset.CsvFile, subset.SignaturePatternsFile).
1143 Implicit(subset.CsvFile).Implicit(subset.SignaturePatternsFile)
1144 }
1145
Paul Duffinbd88c882022-04-07 23:32:19 +01001146 for _, implementationFlag := range implementationFlags {
1147 command.FlagWithArg("--implementation-flag ", implementationFlag)
1148 }
1149
Paul Duffin67b9d612021-07-21 17:38:47 +01001150 // If validation passes then update the file that records that.
1151 command.Text("&& touch").Output(validFile)
Paul Duffin2e880972021-06-23 23:29:09 +01001152 rule.Build(name+"Validation", desc+" validation")
1153
1154 return validFile
1155}
1156
Paul Duffinaf705182022-09-14 11:47:34 +01001157// hiddenAPIFlagRulesForBootclasspathFragment will generate all the flags for a fragment of the
1158// bootclasspath.
Paul Duffin2fef1362021-04-15 13:32:00 +01001159//
1160// It takes:
1161// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
1162// * The list of modules that are the contents of the fragment.
1163// * The additional manually curated flag files to use.
1164//
1165// It generates:
1166// * stub-flags.csv
1167// * annotation-flags.csv
1168// * metadata.csv
1169// * index.csv
1170// * all-flags.csv
Paul Duffin1938dba2022-07-26 23:53:00 +00001171func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.Module, input HiddenAPIFlagInput, suffix string) HiddenAPIFlagOutput {
1172 hiddenApiSubDir := "modular-hiddenapi" + suffix
Paul Duffin2fef1362021-04-15 13:32:00 +01001173
Paul Duffin1352f7c2021-05-21 22:18:49 +01001174 // Generate the stub-flags.csv.
Paul Duffin2fef1362021-04-15 13:32:00 +01001175 stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001176 buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile"+suffix, "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
Paul Duffin2fef1362021-04-15 13:32:00 +01001177
Paul Duffin537ea3d2021-05-14 10:38:00 +01001178 // Extract the classes jars from the contents.
Paul Duffindd5993f2021-06-10 10:18:22 +01001179 classesJars := extractClassesJarsFromModules(contents)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001180
Paul Duffin2fef1362021-04-15 13:32:00 +01001181 // Generate the set of flags from the annotations in the source code.
1182 annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001183 buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags"+suffix, classesJars, stubFlagsCSV, annotationFlagsCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +01001184
1185 // Generate the metadata from the annotations in the source code.
1186 metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001187 buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata"+suffix, classesJars, stubFlagsCSV, metadataCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +01001188
Paul Duffin537ea3d2021-05-14 10:38:00 +01001189 // Generate the index file from the CSV files in the classes jars.
Paul Duffin2fef1362021-04-15 13:32:00 +01001190 indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001191 buildRuleToGenerateIndex(ctx, "modular hiddenapi index"+suffix, classesJars, indexCSV)
Paul Duffin2fef1362021-04-15 13:32:00 +01001192
Paul Duffinaf99afa2021-05-21 22:18:56 +01001193 // 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 +01001194 // containing dex signatures of all the removed APIs. In the monolithic files that is done by
1195 // manually combining all the removed.txt files for each API and then converting them to dex
Paul Duffin32cf58a2021-05-18 16:32:50 +01001196 // signatures, see the combined-removed-dex module. This does that automatically by using the
1197 // *removed.txt files retrieved from the java_sdk_library modules that are specified in the
1198 // stub_libs and contents properties of a bootclasspath_fragment.
Paul Duffin1938dba2022-07-26 23:53:00 +00001199 removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, suffix, input.RemovedTxtFiles)
Paul Duffin2fef1362021-04-15 13:32:00 +01001200
1201 // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
1202 // files.
Paul Duffine5218812021-06-07 13:28:19 +01001203 allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001204 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 +01001205
Paul Duffin280bae62021-07-20 18:03:53 +01001206 // Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be
1207 // compared against the monolithic stub flags.
1208 filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001209 buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags"+suffix,
1210 "modular hiddenapi filtered stub flags"+suffix, stubFlagsCSV, filteredStubFlagsCSV,
Paul Duffinbd88c882022-04-07 23:32:19 +01001211 HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
Paul Duffin280bae62021-07-20 18:03:53 +01001212
1213 // Generate the filtered-flags.csv file which contains the filtered flags that will be compared
1214 // against the monolithic flags.
1215 filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv")
Paul Duffin1938dba2022-07-26 23:53:00 +00001216 buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags"+suffix,
1217 "modular hiddenapi filtered flags"+suffix, allFlagsCSV, filteredFlagsCSV,
Paul Duffinbd88c882022-04-07 23:32:19 +01001218 HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
Paul Duffin280bae62021-07-20 18:03:53 +01001219
Paul Duffin2fef1362021-04-15 13:32:00 +01001220 // Store the paths in the info for use by other modules and sdk snapshot generation.
Paul Duffinaf705182022-09-14 11:47:34 +01001221 return HiddenAPIFlagOutput{
1222 AnnotationFlagsPath: annotationFlagsCSV,
1223 MetadataPath: metadataCSV,
1224 IndexPath: indexCSV,
1225 StubFlagsPath: stubFlagsCSV,
1226 AllFlagsPath: allFlagsCSV,
1227 FilteredStubFlagsPath: filteredStubFlagsCSV,
1228 FilteredFlagsPath: filteredFlagsCSV,
Paul Duffin1e6f5c42021-05-21 16:15:31 +01001229 }
Paul Duffinaf705182022-09-14 11:47:34 +01001230}
1231
1232// hiddenAPIEncodeRulesForBootclasspathFragment generates rules to encode hidden API flags into the
1233// dex jars in bootDexInfoByModule.
1234func hiddenAPIEncodeRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, allFlagsCSV android.Path) bootDexJarByModule {
1235 // Encode the flags into the boot dex files.
1236 encodedBootDexJarsByModule := bootDexJarByModule{}
1237 outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath
Cole Faust18994c72023-02-28 16:02:16 -08001238 for _, name := range android.SortedKeys(bootDexInfoByModule) {
Paul Duffinaf705182022-09-14 11:47:34 +01001239 bootDexInfo := bootDexInfoByModule[name]
1240 unencodedDex := bootDexInfo.path
1241 encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, bootDexInfo.minSdkVersion, outputDir)
1242 encodedBootDexJarsByModule[name] = encodedDex
1243 }
1244 return encodedBootDexJarsByModule
Paul Duffin702210b2021-04-08 20:12:41 +01001245}
Paul Duffin537ea3d2021-05-14 10:38:00 +01001246
Paul Duffin1938dba2022-07-26 23:53:00 +00001247func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix string, removedTxtFiles android.Paths) android.OptionalPath {
Paul Duffin32cf58a2021-05-18 16:32:50 +01001248 if len(removedTxtFiles) == 0 {
1249 return android.OptionalPath{}
1250 }
1251
Paul Duffin1938dba2022-07-26 23:53:00 +00001252 output := android.PathForModuleOut(ctx, "module-hiddenapi"+suffix, "removed-dex-signatures.txt")
Paul Duffin32cf58a2021-05-18 16:32:50 +01001253
1254 rule := android.NewRuleBuilder(pctx, ctx)
1255 rule.Command().
1256 BuiltTool("metalava").
Paul Duffin78ed7f32024-06-28 00:13:29 +01001257 Text("signature-to-dex").
Paul Duffin32cf58a2021-05-18 16:32:50 +01001258 Inputs(removedTxtFiles).
Paul Duffin78ed7f32024-06-28 00:13:29 +01001259 FlagWithOutput("--out ", output)
Paul Duffin1938dba2022-07-26 23:53:00 +00001260 rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix)
Paul Duffin32cf58a2021-05-18 16:32:50 +01001261 return android.OptionalPathForPath(output)
1262}
1263
Paul Duffindd5993f2021-06-10 10:18:22 +01001264// extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules.
Spandan Das64c9e0c2023-12-20 20:13:34 +00001265// This information can come from two mechanisms
1266// 1. New: Direct deps to _selected_ apexes. The apexes contain a ApexExportsInfo
1267// 2. Legacy: An edge to java_sdk_library(_import) module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
1268// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
Paul Duffine5218812021-06-07 13:28:19 +01001269func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
1270 bootDexJars := bootDexJarByModule{}
Spandan Das64c9e0c2023-12-20 20:13:34 +00001271
1272 apexNameToApexExportsInfoMap := getApexNameToApexExportsInfoMap(ctx)
1273 // For ART and mainline module jars, query apexNameToApexExportsInfoMap to get the dex file
1274 apexJars := dexpreopt.GetGlobalConfig(ctx).ArtApexJars.AppendList(&dexpreopt.GetGlobalConfig(ctx).ApexBootJars)
1275 for i := 0; i < apexJars.Len(); i++ {
1276 if dex, found := apexNameToApexExportsInfoMap.javaLibraryDexPathOnHost(ctx, apexJars.Apex(i), apexJars.Jar(i)); found {
1277 bootDexJars[apexJars.Jar(i)] = dex
1278 }
1279 }
1280
1281 // TODO - b/308174306: Drop the legacy mechanism
Paul Duffin537ea3d2021-05-14 10:38:00 +01001282 for _, module := range contents {
Spandan Das64c9e0c2023-12-20 20:13:34 +00001283 if _, exists := bootDexJars[android.RemoveOptionalPrebuiltPrefix(module.Name())]; exists {
1284 continue
1285 }
Paul Duffindd5993f2021-06-10 10:18:22 +01001286 hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
1287 if hiddenAPIModule == nil {
1288 continue
1289 }
Paul Duffine5218812021-06-07 13:28:19 +01001290 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
1291 bootDexJars.addPath(module, bootDexJar)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001292 }
1293 return bootDexJars
1294}
1295
Paul Duffindd5993f2021-06-10 10:18:22 +01001296func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Module) hiddenAPIModule {
1297 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
1298 return hiddenAPIModule
1299 } else if _, ok := module.(*DexImport); ok {
1300 // Ignore this for the purposes of hidden API processing
1301 } else {
1302 ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
1303 }
1304
1305 return nil
1306}
1307
Paul Duffine5218812021-06-07 13:28:19 +01001308// bootDexInfo encapsulates both the path and uncompressDex status retrieved from a hiddenAPIModule.
1309type bootDexInfo struct {
1310 // The path to the dex jar that has not had hidden API flags encoded into it.
1311 path android.Path
1312
1313 // Indicates whether the dex jar needs uncompressing before encoding.
1314 uncompressDex bool
Paul Duffin09817d62022-04-28 17:45:11 +01001315
1316 // The minimum sdk version that the dex jar will be used on.
Spandan Das8c9ae7e2023-03-03 21:20:36 +00001317 minSdkVersion android.ApiLevel
Paul Duffine5218812021-06-07 13:28:19 +01001318}
1319
1320// bootDexInfoByModule is a map from module name (as returned by module.Name()) to the boot dex
1321// path (as returned by hiddenAPIModule.bootDexJar()) and the uncompressDex flag.
1322type bootDexInfoByModule map[string]bootDexInfo
1323
1324// bootDexJars returns the boot dex jar paths sorted by their keys.
1325func (b bootDexInfoByModule) bootDexJars() android.Paths {
1326 paths := android.Paths{}
Cole Faust18994c72023-02-28 16:02:16 -08001327 for _, m := range android.SortedKeys(b) {
Paul Duffine5218812021-06-07 13:28:19 +01001328 paths = append(paths, b[m].path)
1329 }
1330 return paths
1331}
1332
1333// extractBootDexInfoFromModules extracts the boot dex jar and uncompress dex state from
1334// each of the supplied modules which must implement hiddenAPIModule.
1335func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android.Module) bootDexInfoByModule {
1336 bootDexJarsByModule := bootDexInfoByModule{}
1337 for _, module := range contents {
1338 hiddenAPIModule := module.(hiddenAPIModule)
1339 bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
1340 bootDexJarsByModule[module.Name()] = bootDexInfo{
1341 path: bootDexJar,
1342 uncompressDex: *hiddenAPIModule.uncompressDex(),
Paul Duffin09817d62022-04-28 17:45:11 +01001343 minSdkVersion: hiddenAPIModule.MinSdkVersion(ctx),
Paul Duffine5218812021-06-07 13:28:19 +01001344 }
1345 }
1346
1347 return bootDexJarsByModule
1348}
1349
1350// retrieveBootDexJarFromHiddenAPIModule retrieves the boot dex jar from the hiddenAPIModule.
1351//
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001352// If the module does not provide a boot dex jar, i.e. the returned boot dex jar is unset or
1353// invalid, then create a fake path and either report an error immediately or defer reporting of the
1354// error until the path is actually used.
Paul Duffine5218812021-06-07 13:28:19 +01001355func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
Spandan Das3a392012024-01-17 18:26:27 +00001356 bootDexJar := module.bootDexJar(ctx)
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001357 if !bootDexJar.Valid() {
Paul Duffine5218812021-06-07 13:28:19 +01001358 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001359 handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
1360 return fake
Paul Duffine5218812021-06-07 13:28:19 +01001361 }
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001362 return bootDexJar.Path()
Paul Duffine5218812021-06-07 13:28:19 +01001363}
1364
Paul Duffindd5993f2021-06-10 10:18:22 +01001365// extractClassesJarsFromModules extracts the class jars from the supplied modules.
1366func extractClassesJarsFromModules(contents []android.Module) android.Paths {
Paul Duffin537ea3d2021-05-14 10:38:00 +01001367 classesJars := android.Paths{}
1368 for _, module := range contents {
Paul Duffindd5993f2021-06-10 10:18:22 +01001369 classesJars = append(classesJars, retrieveClassesJarsFromModule(module)...)
Paul Duffin537ea3d2021-05-14 10:38:00 +01001370 }
1371 return classesJars
1372}
Paul Duffin5f148ca2021-06-02 17:24:22 +01001373
Paul Duffindd5993f2021-06-10 10:18:22 +01001374// retrieveClassesJarsFromModule retrieves the classes jars from the supplied module.
1375func retrieveClassesJarsFromModule(module android.Module) android.Paths {
1376 if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
1377 return hiddenAPIModule.classesJars()
1378 }
1379
1380 return nil
1381}
1382
Paul Duffin5f148ca2021-06-02 17:24:22 +01001383// deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
1384// Soong but should instead only be reported in ninja if the file is actually built.
1385func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
Paul Duffine5218812021-06-07 13:28:19 +01001386 // Any missing dependency should be allowed.
1387 if ctx.Config().AllowMissingDependencies() {
1388 return true
1389 }
1390
Paul Duffin5f148ca2021-06-02 17:24:22 +01001391 // This is called for both platform_bootclasspath and bootclasspath_fragment modules.
1392 //
1393 // A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
1394 // Ideally, a bootclasspath_fragment module should never have a platform variant created for it
1395 // but unfortunately, due to b/187910671 it does.
1396 //
1397 // That causes issues when obtaining a boot dex jar for a prebuilt module as a prebuilt module
1398 // used by a bootclasspath_fragment can only provide a boot dex jar when it is part of APEX, i.e.
1399 // has an APEX variant not a platform variant.
1400 //
1401 // There are some other situations when a prebuilt module used by a bootclasspath_fragment cannot
1402 // provide a boot dex jar:
1403 // 1. If the bootclasspath_fragment is not exported by the prebuilt_apex/apex_set module then it
1404 // does not have an APEX variant and only has a platform variant and neither do its content
1405 // modules.
1406 // 2. Some build configurations, e.g. setting TARGET_BUILD_USE_PREBUILT_SDKS causes all
1407 // java_sdk_library_import modules to be treated as preferred and as many of them are not part
1408 // of an apex they cannot provide a boot dex jar.
1409 //
1410 // The first case causes problems when the affected prebuilt modules are preferred but that is an
1411 // invalid configuration and it is ok for it to fail as the work to enable that is not yet
1412 // complete. The second case is used for building targets that do not use boot dex jars and so
1413 // deferring error reporting to ninja is fine as the affected ninja targets should never be built.
1414 // That is handled above.
1415 //
1416 // A platform_bootclasspath module can use libraries from both platform and APEX variants. Unlike
1417 // the bootclasspath_fragment it supports dex_import modules which provides the dex file. So, it
1418 // can obtain a boot dex jar from a prebuilt that is not part of an APEX. However, it is assumed
1419 // that if the library can be part of an APEX then it is the APEX variant that is used.
1420 //
1421 // This check handles the slightly different requirements of the bootclasspath_fragment and
1422 // platform_bootclasspath modules by only deferring error reporting for the platform variant of
1423 // a prebuilt modules that has other variants which are part of an APEX.
1424 //
1425 // TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
1426 if android.IsModulePrebuilt(module) {
Paul Duffinef083c92021-06-29 13:36:34 +01001427 // An inactive source module can still contribute to the APEX but an inactive prebuilt module
1428 // should not contribute to anything. So, rather than have a missing dex jar cause a Soong
1429 // failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly
1430 // built Ninja should never use the dex jar file.
Cole Fausta963b942024-04-11 17:43:00 -07001431 if !isActiveModule(ctx, module) {
Paul Duffinef083c92021-06-29 13:36:34 +01001432 return true
1433 }
1434
Paul Duffin5f148ca2021-06-02 17:24:22 +01001435 if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
Colin Cross313aa542023-12-13 13:47:44 -08001436 apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
Paul Duffin5f148ca2021-06-02 17:24:22 +01001437 if apexInfo.IsForPlatform() {
1438 return true
1439 }
1440 }
1441 }
1442
Paul Duffin5f148ca2021-06-02 17:24:22 +01001443 return false
1444}
1445
1446// handleMissingDexBootFile will either log a warning or create an error rule to create the fake
1447// file depending on the value returned from deferReportingMissingBootDexJar.
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001448func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath, reason string) {
Paul Duffin5f148ca2021-06-02 17:24:22 +01001449 if deferReportingMissingBootDexJar(ctx, module) {
1450 // Create an error rule that pretends to create the output file but will actually fail if it
1451 // is run.
1452 ctx.Build(pctx, android.BuildParams{
1453 Rule: android.ErrorRule,
1454 Output: fake,
1455 Args: map[string]string{
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001456 "error": fmt.Sprintf("missing boot dex jar dependency for %s: %s", module, reason),
Paul Duffin5f148ca2021-06-02 17:24:22 +01001457 },
1458 })
1459 } else {
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001460 ctx.ModuleErrorf("module %s does not provide a dex jar: %s", module, reason)
Paul Duffin5f148ca2021-06-02 17:24:22 +01001461 }
1462}
1463
1464// retrieveEncodedBootDexJarFromModule returns a path to the boot dex jar from the supplied module's
1465// DexJarBuildPath() method.
1466//
1467// The returned path will usually be to a dex jar file that has been encoded with hidden API flags.
1468// However, under certain conditions, e.g. errors, or special build configurations it will return
1469// a path to a fake file.
1470func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
Spandan Das59a4a2b2024-01-09 21:35:56 +00001471 bootDexJar := module.(interface {
1472 DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
1473 }).DexJarBuildPath(ctx)
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001474 if !bootDexJar.Valid() {
Paul Duffin5f148ca2021-06-02 17:24:22 +01001475 fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001476 handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
1477 return fake
Paul Duffin5f148ca2021-06-02 17:24:22 +01001478 }
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001479 return bootDexJar.Path()
Paul Duffin5f148ca2021-06-02 17:24:22 +01001480}