blob: a8e0a22e53f7d7aedbd0bfc18d2bf7a1b71fe260 [file] [log] [blame]
Colin Cross2207f872021-03-24 12:39:08 -07001// Copyright 2021 Google Inc. All rights reserved.
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 (
18 "fmt"
Anton Hansson86758ac2021-11-03 14:44:12 +000019 "path/filepath"
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +020020 "regexp"
Colin Cross2207f872021-03-24 12:39:08 -070021 "strings"
22
23 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
26 "android/soong/java/config"
27 "android/soong/remoteexec"
28)
29
Pedro Loureirocc203502021-10-04 17:24:00 +000030// The values allowed for Droidstubs' Api_levels_sdk_type
Cole Faust051fa912022-10-05 12:45:42 -070031var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
Pedro Loureirocc203502021-10-04 17:24:00 +000032
Jihoon Kang6592e872023-12-19 01:13:16 +000033type StubsType int
34
35const (
36 Everything StubsType = iota
37 Runtime
38 Exportable
Jihoon Kang78f89142023-12-27 01:40:29 +000039 Unavailable
Jihoon Kang6592e872023-12-19 01:13:16 +000040)
41
42func (s StubsType) String() string {
43 switch s {
44 case Everything:
45 return "everything"
46 case Runtime:
47 return "runtime"
48 case Exportable:
49 return "exportable"
50 default:
51 return ""
52 }
53}
54
Jihoon Kang5d701272024-02-15 21:53:49 +000055func StringToStubsType(s string) StubsType {
56 switch strings.ToLower(s) {
57 case Everything.String():
58 return Everything
59 case Runtime.String():
60 return Runtime
61 case Exportable.String():
62 return Exportable
63 default:
64 return Unavailable
65 }
66}
67
Colin Cross2207f872021-03-24 12:39:08 -070068func init() {
69 RegisterStubsBuildComponents(android.InitRegistrationContext)
70}
71
72func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
73 ctx.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
74
75 ctx.RegisterModuleType("droidstubs", DroidstubsFactory)
76 ctx.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
77
78 ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
79}
80
Jihoon Kangee113282024-01-23 00:16:41 +000081type stubsArtifacts struct {
82 nullabilityWarningsFile android.WritablePath
83 annotationsZip android.WritablePath
84 apiVersionsXml android.WritablePath
85 metadataZip android.WritablePath
86 metadataDir android.WritablePath
87}
88
Colin Cross2207f872021-03-24 12:39:08 -070089// Droidstubs
Colin Cross2207f872021-03-24 12:39:08 -070090type Droidstubs struct {
91 Javadoc
Spandan Das2cc80ba2023-10-27 17:21:52 +000092 embeddableInModuleAndImport
Colin Cross2207f872021-03-24 12:39:08 -070093
Jihoon Kangee113282024-01-23 00:16:41 +000094 properties DroidstubsProperties
95 apiFile android.Path
96 removedApiFile android.Path
Colin Cross2207f872021-03-24 12:39:08 -070097
98 checkCurrentApiTimestamp android.WritablePath
99 updateCurrentApiTimestamp android.WritablePath
100 checkLastReleasedApiTimestamp android.WritablePath
101 apiLintTimestamp android.WritablePath
102 apiLintReport android.WritablePath
103
104 checkNullabilityWarningsTimestamp android.WritablePath
105
Jihoon Kangee113282024-01-23 00:16:41 +0000106 everythingArtifacts stubsArtifacts
107 exportableArtifacts stubsArtifacts
Jihoon Kang3c89f042023-12-19 02:40:22 +0000108
Jihoon Kangee113282024-01-23 00:16:41 +0000109 exportableApiFile android.WritablePath
110 exportableRemovedApiFile android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -0700111}
112
113type DroidstubsProperties struct {
114 // The generated public API filename by Metalava, defaults to <module>_api.txt
115 Api_filename *string
116
117 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
118 Removed_api_filename *string
119
Colin Cross2207f872021-03-24 12:39:08 -0700120 Check_api struct {
121 Last_released ApiToCheck
122
123 Current ApiToCheck
124
125 Api_lint struct {
126 Enabled *bool
127
128 // If set, performs api_lint on any new APIs not found in the given signature file
129 New_since *string `android:"path"`
130
131 // If not blank, path to the baseline txt file for approved API lint violations.
132 Baseline_file *string `android:"path"`
133 }
134 }
135
136 // user can specify the version of previous released API file in order to do compatibility check.
137 Previous_api *string `android:"path"`
138
139 // is set to true, Metalava will allow framework SDK to contain annotations.
140 Annotations_enabled *bool
141
142 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
143 Merge_annotations_dirs []string
144
145 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
146 Merge_inclusion_annotations_dirs []string
147
148 // a file containing a list of classes to do nullability validation for.
149 Validate_nullability_from_list *string
150
151 // a file containing expected warnings produced by validation of nullability annotations.
152 Check_nullability_warnings *string
153
154 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
155 Create_doc_stubs *bool
156
157 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
158 // Has no effect if create_doc_stubs: true.
159 Output_javadoc_comments *bool
160
161 // if set to false then do not write out stubs. Defaults to true.
162 //
163 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
164 Generate_stubs *bool
165
166 // if set to true, provides a hint to the build system that this rule uses a lot of memory,
Liz Kammer170dd722023-10-16 15:08:39 -0400167 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700168 High_mem *bool
169
satayev783195c2021-06-23 21:49:57 +0100170 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700171 Api_levels_annotations_enabled *bool
172
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000173 // Apply the api levels database created by this module rather than generating one in this droidstubs.
174 Api_levels_module *string
175
Colin Cross2207f872021-03-24 12:39:08 -0700176 // the dirs which Metalava extracts API levels annotations from.
177 Api_levels_annotations_dirs []string
178
Cole Faust051fa912022-10-05 12:45:42 -0700179 // the sdk kind which Metalava extracts API levels annotations from. Supports 'public', 'system', 'module-lib' and 'system-server'; defaults to public.
satayev783195c2021-06-23 21:49:57 +0100180 Api_levels_sdk_type *string
181
Colin Cross2207f872021-03-24 12:39:08 -0700182 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
183 Api_levels_jar_filename *string
184
185 // if set to true, collect the values used by the Dev tools and
186 // write them in files packaged with the SDK. Defaults to false.
187 Write_sdk_values *bool
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200188
189 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
190 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
191 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000192
193 // API surface of this module. If set, the module contributes to an API surface.
194 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
195 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000196
197 // a list of aconfig_declarations module names that the stubs generated in this module
198 // depend on.
199 Aconfig_declarations []string
Colin Cross2207f872021-03-24 12:39:08 -0700200}
201
Anton Hansson52609322021-05-05 10:36:05 +0100202// Used by xsd_config
203type ApiFilePath interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000204 ApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100205}
206
207type ApiStubsSrcProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000208 StubsSrcJar(StubsType) (android.Path, error)
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000209}
210
Anton Hansson52609322021-05-05 10:36:05 +0100211// Provider of information about API stubs, used by java_sdk_library.
212type ApiStubsProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000213 AnnotationsZip(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100214 ApiFilePath
Jihoon Kangee113282024-01-23 00:16:41 +0000215 RemovedApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100216
217 ApiStubsSrcProvider
218}
219
Jihoon Kang063ec002023-06-28 01:16:23 +0000220type currentApiTimestampProvider interface {
221 CurrentApiTimestamp() android.Path
222}
223
Jihoon Kang3c89f042023-12-19 02:40:22 +0000224type annotationFlagsParams struct {
225 migratingNullability bool
226 validatingNullability bool
227 nullabilityWarningsFile android.WritablePath
228 annotationsZip android.WritablePath
229}
230type stubsCommandParams struct {
231 srcJarDir android.ModuleOutPath
232 stubsDir android.OptionalPath
233 stubsSrcJar android.WritablePath
234 metadataZip android.WritablePath
235 metadataDir android.WritablePath
236 apiVersionsXml android.WritablePath
237 nullabilityWarningsFile android.WritablePath
238 annotationsZip android.WritablePath
239 stubConfig stubsCommandConfigParams
240}
241type stubsCommandConfigParams struct {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000242 stubsType StubsType
243 javaVersion javaVersion
244 deps deps
245 checkApi bool
246 generateStubs bool
247 doApiLint bool
248 doCheckReleased bool
249 writeSdkValues bool
250 migratingNullability bool
251 validatingNullability bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000252}
253
Colin Cross2207f872021-03-24 12:39:08 -0700254// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
255// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
256// a droiddoc module to generate documentation.
257func DroidstubsFactory() android.Module {
258 module := &Droidstubs{}
259
260 module.AddProperties(&module.properties,
261 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000262 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700263
264 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000265
266 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
267 module.createApiContribution(ctx)
268 })
Colin Cross2207f872021-03-24 12:39:08 -0700269 return module
270}
271
272// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
273// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
274// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
275// module when symbols needed by the source files are provided by java_library_host modules.
276func DroidstubsHostFactory() android.Module {
277 module := &Droidstubs{}
278
279 module.AddProperties(&module.properties,
280 &module.Javadoc.properties)
281
282 InitDroiddocModule(module, android.HostSupported)
283 return module
284}
285
Jihoon Kang246690a2024-02-01 21:55:01 +0000286func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000287 switch stubsType {
288 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000289 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000290 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000291 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000292 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000293 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000294 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000295 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000296}
297
Jihoon Kang246690a2024-02-01 21:55:01 +0000298func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000299 switch stubsType {
300 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000301 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000302 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000303 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000304 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000305 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000306 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000307 if ret == nil && err == nil {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000308 err = fmt.Errorf("api file is null for the stub type %s", stubsType.String())
Jihoon Kang246690a2024-02-01 21:55:01 +0000309 }
310 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000311}
312
Jihoon Kang246690a2024-02-01 21:55:01 +0000313func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000314 switch stubsType {
315 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000316 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000317 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000318 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000319 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000320 ret, err = nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000321 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000322 if ret == nil && err == nil {
323 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
324 }
325 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000326}
327
Jihoon Kang246690a2024-02-01 21:55:01 +0000328func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000329 switch stubsType {
330 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000331 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000332 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000333 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000334 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000335 if ret == nil && err == nil {
336 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
337 }
338 return ret, err
339}
340
341func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
342 switch stubsType {
343 case Everything:
344 ret, err = d.removedApiFile, nil
345 case Exportable:
346 ret, err = d.exportableRemovedApiFile, nil
347 default:
348 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
349 }
350 if ret == nil && err == nil {
351 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
352 }
353 return ret, err
354}
355
356func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
357 switch stubsType {
358 case Everything:
359 ret, err = d.stubsSrcJar, nil
360 case Exportable:
361 ret, err = d.exportableStubsSrcJar, nil
362 default:
363 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
364 }
365 if ret == nil && err == nil {
366 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
367 }
368 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000369}
370
Jihoon Kang063ec002023-06-28 01:16:23 +0000371func (d *Droidstubs) CurrentApiTimestamp() android.Path {
372 return d.checkCurrentApiTimestamp
373}
374
Colin Cross2207f872021-03-24 12:39:08 -0700375var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
376var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
377var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000378var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000379var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700380
381func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
382 d.Javadoc.addDeps(ctx)
383
384 if len(d.properties.Merge_annotations_dirs) != 0 {
385 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
386 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
387 }
388 }
389
390 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
391 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
392 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
393 }
394 }
395
396 if len(d.properties.Api_levels_annotations_dirs) != 0 {
397 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
398 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
399 }
400 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000401
Jihoon Kang6592e872023-12-19 01:13:16 +0000402 if len(d.properties.Aconfig_declarations) != 0 {
403 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
404 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
405 }
406 }
407
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000408 if d.properties.Api_levels_module != nil {
409 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
410 }
Colin Cross2207f872021-03-24 12:39:08 -0700411}
412
Jihoon Kang3c89f042023-12-19 02:40:22 +0000413func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
414 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
415}
416
417func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000418
Jihoon Kang36c3d962024-03-14 17:28:44 +0000419 apiFileName := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
420 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), apiFileName)
421 cmd.FlagWithOutput("--api ", uncheckedApiFile)
422 if checkApi || String(d.properties.Api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000423 if stubsType == Everything {
424 d.apiFile = uncheckedApiFile
425 } else if stubsType == Exportable {
426 d.exportableApiFile = uncheckedApiFile
427 }
Colin Cross2207f872021-03-24 12:39:08 -0700428 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000429 if stubsType == Everything {
430 // If check api is disabled then make the source file available for export.
431 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
432 } else if stubsType == Exportable {
433 d.exportableApiFile = uncheckedApiFile
434 }
Colin Cross2207f872021-03-24 12:39:08 -0700435 }
436
Jihoon Kang36c3d962024-03-14 17:28:44 +0000437 removedApiFileName := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
438 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), removedApiFileName)
439 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000440 if checkApi || String(d.properties.Removed_api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000441 if stubsType == Everything {
442 d.removedApiFile = uncheckedRemovedFile
443 } else if stubsType == Exportable {
444 d.exportableRemovedApiFile = uncheckedRemovedFile
445 }
Colin Cross2207f872021-03-24 12:39:08 -0700446 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000447 if stubsType == Everything {
448 // If check api is disabled then make the source removed api file available for export.
449 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
450 } else if stubsType == Exportable {
451 d.exportableRemovedApiFile = uncheckedRemovedFile
452 }
Colin Cross2207f872021-03-24 12:39:08 -0700453 }
454
Colin Cross2207f872021-03-24 12:39:08 -0700455 if stubsDir.Valid() {
456 if Bool(d.properties.Create_doc_stubs) {
457 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
458 } else {
459 cmd.FlagWithArg("--stubs ", stubsDir.String())
460 if !Bool(d.properties.Output_javadoc_comments) {
461 cmd.Flag("--exclude-documentation-from-stubs")
462 }
463 }
464 }
465}
466
Jihoon Kang3c89f042023-12-19 02:40:22 +0000467func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000468 if Bool(d.properties.Annotations_enabled) {
469 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100470
Jihoon Kanga11d6792024-03-05 16:12:20 +0000471 if params.migratingNullability {
Jihoon Kang5623e542024-01-31 23:27:26 +0000472 previousApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Previous_api)})
473 cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000474 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000475
Jihoon Kanga11d6792024-03-05 16:12:20 +0000476 if s := String(d.properties.Validate_nullability_from_list); s != "" {
477 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
478 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000479
Jihoon Kanga11d6792024-03-05 16:12:20 +0000480 if params.validatingNullability {
481 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
482 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000483
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000484 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000485
Jihoon Kanga11d6792024-03-05 16:12:20 +0000486 if len(d.properties.Merge_annotations_dirs) != 0 {
487 d.mergeAnnoDirFlags(ctx, cmd)
488 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000489
Jihoon Kanga11d6792024-03-05 16:12:20 +0000490 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700491 }
Colin Cross2207f872021-03-24 12:39:08 -0700492}
493
494func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
495 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
496 if t, ok := m.(*ExportedDroiddocDir); ok {
497 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
498 } else {
499 ctx.PropertyErrorf("merge_annotations_dirs",
500 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
501 }
502 })
503}
504
505func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
506 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
507 if t, ok := m.(*ExportedDroiddocDir); ok {
508 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
509 } else {
510 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
511 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
512 }
513 })
514}
515
Jihoon Kanga11d6792024-03-05 16:12:20 +0000516func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000517 var apiVersions android.Path
Jihoon Kanga11d6792024-03-05 16:12:20 +0000518 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000519 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000520 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000521 } else {
522 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
523 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000524 if stubsType == Everything {
525 apiVersions = s.everythingArtifacts.apiVersionsXml
526 } else if stubsType == Exportable {
527 apiVersions = s.exportableArtifacts.apiVersionsXml
528 } else {
Jihoon Kangd40c5912024-03-05 16:12:20 +0000529 ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
Jihoon Kangd9a06942024-01-26 01:49:20 +0000530 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000531 } else {
532 ctx.PropertyErrorf("api_levels_module",
533 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
534 }
535 })
Colin Cross2207f872021-03-24 12:39:08 -0700536 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000537 if apiVersions != nil {
538 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
539 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
540 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
541 }
542}
Colin Cross2207f872021-03-24 12:39:08 -0700543
Paul Duffin5a195f42024-05-01 12:52:35 +0100544// AndroidPlusUpdatableJar is the name of some extra jars added into `module-lib` and
545// `system-server` directories that contain all the APIs provided by the platform and updatable
546// modules because the `android.jar` files do not. See b/337836752.
547const AndroidPlusUpdatableJar = "android-plus-updatable.jar"
548
Jihoon Kang3c89f042023-12-19 02:40:22 +0000549func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700550 if len(d.properties.Api_levels_annotations_dirs) == 0 {
551 ctx.PropertyErrorf("api_levels_annotations_dirs",
552 "has to be non-empty if api levels annotations was enabled!")
553 }
554
Jihoon Kang3c89f042023-12-19 02:40:22 +0000555 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700556
557 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
558
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100559 // TODO: Avoid the duplication of API surfaces, reuse apiScope.
560 // Add all relevant --android-jar-pattern patterns for Metalava.
561 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
562 // an actual file present on disk (in the order the patterns were passed). For system APIs for
563 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
564 // for older releases. Similarly, module-lib falls back to system API.
565 var sdkDirs []string
Paul Duffin92efc612024-05-02 17:18:05 +0100566 apiLevelsSdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public")
567 switch apiLevelsSdkType {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100568 case "system-server":
569 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
570 case "module-lib":
571 sdkDirs = []string{"module-lib", "system", "public"}
572 case "system":
573 sdkDirs = []string{"system", "public"}
574 case "public":
575 sdkDirs = []string{"public"}
576 default:
577 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
578 return
579 }
580
Paul Duffin92efc612024-05-02 17:18:05 +0100581 // Construct a pattern to match the appropriate extensions that should be included in the
582 // generated api-versions.xml file.
583 //
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100584 // Use the first item in the sdkDirs array as that is the sdk type for the target API levels
585 // being generated but has the advantage over `Api_levels_sdk_type` as it has been validated.
Paul Duffin92efc612024-05-02 17:18:05 +0100586 // The exception is for system-server which needs to include module-lib and system-server. That
587 // is because while system-server extends module-lib the system-server extension directory only
588 // contains service-* modules which provide system-server APIs it does not list the modules which
589 // only provide a module-lib, so they have to be included separately.
590 extensionSurfacesPattern := sdkDirs[0]
591 if apiLevelsSdkType == "system-server" {
592 // Take the first two items in sdkDirs, which are system-server and module-lib, and construct
593 // a pattern that will match either.
594 extensionSurfacesPattern = strings.Join(sdkDirs[0:2], "|")
595 }
596 extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/(%s)/.*\.jar`, extensionSurfacesPattern)
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100597
satayev783195c2021-06-23 21:49:57 +0100598 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200599 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700600 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
601 if t, ok := m.(*ExportedDroiddocDir); ok {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100602 extRegex := regexp.MustCompile(t.dir.String() + extensionsPattern)
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200603
604 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
605 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700606 for _, dep := range t.deps {
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100607 // Check to see if it matches an extension first.
608 depBase := dep.Base()
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200609 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
610 if extensions_dir == "" {
611 extensions_dir = t.dir.String() + "/extensions"
612 }
613 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100614 } else if depBase == filename {
615 // Check to see if it matches a dessert release for an SDK, e.g. Android, Car, Wear, etc..
Colin Cross5f6ffc72021-03-29 21:54:45 -0700616 cmd.Implicit(dep)
Paul Duffin5a195f42024-05-01 12:52:35 +0100617 } else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil {
618 // The output api-versions.xml has been requested to include information on SDK
619 // extensions. That means it also needs to include
620 // so
621 // The module-lib and system-server directories should use `android-plus-updatable.jar`
622 // instead of `android.jar`. See AndroidPlusUpdatableJar for more information.
623 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100624 } else if filename != "android.jar" && depBase == "android.jar" {
Colin Cross5f6ffc72021-03-29 21:54:45 -0700625 // Metalava implicitly searches these patterns:
626 // prebuilts/tools/common/api-versions/android-%/android.jar
627 // prebuilts/sdk/%/public/android.jar
628 // Add android.jar files from the api_levels_annotations_dirs directories to try
629 // to satisfy these patterns. If Metalava can't find a match for an API level
630 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700631 cmd.Implicit(dep)
632 }
633 }
satayev783195c2021-06-23 21:49:57 +0100634
635 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700636 } else {
637 ctx.PropertyErrorf("api_levels_annotations_dirs",
638 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
639 }
640 })
satayev783195c2021-06-23 21:49:57 +0100641
Paul Duffin5a195f42024-05-01 12:52:35 +0100642 // Generate the list of --android-jar-pattern options. The order matters so the first one which
643 // matches will be the one that is used for a specific api level..
Pedro Loureirocc203502021-10-04 17:24:00 +0000644 for _, sdkDir := range sdkDirs {
645 for _, dir := range dirs {
Paul Duffin5a195f42024-05-01 12:52:35 +0100646 addPattern := func(jarFilename string) {
647 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, jarFilename))
648 }
649
650 if sdkDir == "module-lib" || sdkDir == "system-server" {
651 // The module-lib and system-server android.jars do not include the updatable modules (as
652 // doing so in the source would introduce dependency cycles and the prebuilts have to
653 // match the sources). So, instead an additional `android-plus-updatable.jar` will be used
654 // that does include the updatable modules and this pattern will match that. This pattern
655 // is added in addition to the following pattern to decouple this change from the change
656 // to add the `android-plus-updatable.jar`.
657 addPattern(AndroidPlusUpdatableJar)
658 }
659
660 addPattern(filename)
Pedro Loureirocc203502021-10-04 17:24:00 +0000661 }
satayev783195c2021-06-23 21:49:57 +0100662 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200663
664 if d.properties.Extensions_info_file != nil {
665 if extensions_dir == "" {
666 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
667 }
668 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
669 cmd.Implicit(info_file)
670 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
671 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
672 }
Colin Cross2207f872021-03-24 12:39:08 -0700673}
674
Jihoon Kang472f73f2024-03-28 20:59:29 +0000675func (d *Droidstubs) apiCompatibilityFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType) {
676 if len(d.Javadoc.properties.Out) > 0 {
677 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
678 }
679
Jihoon Kang5623e542024-01-31 23:27:26 +0000680 apiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Api_file)})
681 removedApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Removed_api_file)})
Jihoon Kang472f73f2024-03-28 20:59:29 +0000682
Jihoon Kang5623e542024-01-31 23:27:26 +0000683 cmd.FlagForEachInput("--check-compatibility:api:released ", apiFiles)
684 cmd.FlagForEachInput("--check-compatibility:removed:released ", removedApiFiles)
Jihoon Kang472f73f2024-03-28 20:59:29 +0000685
686 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
687 if baselineFile.Valid() {
688 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
689 }
690}
691
Colin Crosse52c2ac2022-03-28 17:03:35 -0700692func metalavaUseRbe(ctx android.ModuleContext) bool {
693 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
694}
695
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000696func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
697 srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700698 rule.Command().Text("rm -rf").Flag(homeDir.String())
699 rule.Command().Text("mkdir -p").Flag(homeDir.String())
700
Anton Hansson556e8142021-06-04 16:20:25 +0100701 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700702 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
703
Colin Crosse52c2ac2022-03-28 17:03:35 -0700704 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700705 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700706 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000707 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
708 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700709 labels := map[string]string{"type": "tool", "name": "metalava"}
710 // TODO: metalava pool rejects these jobs
711 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
712 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000713 Labels: labels,
714 ExecStrategy: execStrategy,
715 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
716 Platform: map[string]string{remoteexec.PoolKey: pool},
717 Compare: compare,
718 NumLocalRuns: 1,
719 NumRemoteRuns: 1,
720 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700721 })
Colin Cross2207f872021-03-24 12:39:08 -0700722 }
723
Colin Cross6aa5c402021-03-24 12:28:50 -0700724 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700725 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400726 Flag(config.MetalavaAddOpens).
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000727 FlagWithArg("--java-source ", params.javaVersion.String()).
728 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, fmt.Sprintf("%s.metalava.rsp", params.stubsType.String())), srcs).
Colin Cross2207f872021-03-24 12:39:08 -0700729 FlagWithInput("@", srcJarList)
730
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100731 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
732 // years, so it is unlikely to change any time soon.
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000733 combinedPaths := append(([]android.Path)(nil), params.deps.bootClasspath.Paths()...)
734 combinedPaths = append(combinedPaths, params.deps.classpath.Paths()...)
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100735 if len(combinedPaths) > 0 {
736 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700737 }
738
Liz Kammere09e20e2023-10-16 15:07:54 -0400739 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000740
Colin Cross2207f872021-03-24 12:39:08 -0700741 return cmd
742}
743
Jihoon Kang3c89f042023-12-19 02:40:22 +0000744// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
745// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
746// property is defined, apply transformations and only revert the flagged apis that are not
747// enabled via release configurations and are not specified in aconfig_declarations
Jihoon Kang5d701272024-02-15 21:53:49 +0000748func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000749
750 if len(aconfigFlagsPaths) == 0 {
751 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
752 return
753 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000754
755 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
756 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
757
758 var filterArgs string
759 switch stubsType {
760 // No flagged apis specific flags need to be passed to metalava when generating
761 // everything stubs
762 case Everything:
763 return
764
765 case Runtime:
766 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
767
768 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000769 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
770 // the flagged apis that have read_write permissions are exposed on top of the enabled
771 // and read_only apis. This is to support local override of flag values at runtime.
772 if ctx.Config().ReleaseExportRuntimeApis() {
773 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
774 } else {
775 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
776 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000777 }
778
779 ctx.Build(pctx, android.BuildParams{
780 Rule: gatherReleasedFlaggedApisRule,
781 Inputs: aconfigFlagsPaths,
782 Output: releasedFlaggedApisFile,
783 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
784 Args: map[string]string{
785 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
786 "filter_args": filterArgs,
787 },
788 })
789
790 ctx.Build(pctx, android.BuildParams{
791 Rule: generateMetalavaRevertAnnotationsRule,
792 Input: releasedFlaggedApisFile,
793 Output: revertAnnotationsFile,
794 Description: fmt.Sprintf("%s revert annotations", stubsType),
795 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000796
797 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000798}
799
Jihoon Kang3c89f042023-12-19 02:40:22 +0000800func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
801 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700802 if BoolDefault(d.properties.High_mem, false) {
803 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
804 rule.HighMem()
805 }
806
Jihoon Kang3c89f042023-12-19 02:40:22 +0000807 if params.stubConfig.generateStubs {
808 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
809 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700810 }
811
Jihoon Kang3c89f042023-12-19 02:40:22 +0000812 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700813
Jihoon Kang3c89f042023-12-19 02:40:22 +0000814 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000815 cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig)
Colin Cross2207f872021-03-24 12:39:08 -0700816 cmd.Implicits(d.Javadoc.implicits)
817
Jihoon Kang3c89f042023-12-19 02:40:22 +0000818 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700819
Jihoon Kang3c89f042023-12-19 02:40:22 +0000820 if params.stubConfig.writeSdkValues {
821 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
822 }
823
824 annotationParams := annotationFlagsParams{
825 migratingNullability: params.stubConfig.migratingNullability,
826 validatingNullability: params.stubConfig.validatingNullability,
827 nullabilityWarningsFile: params.nullabilityWarningsFile,
828 annotationsZip: params.annotationsZip,
829 }
830
Jihoon Kanga11d6792024-03-05 16:12:20 +0000831 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700832 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000833 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700834
Jihoon Kang472f73f2024-03-28 20:59:29 +0000835 if params.stubConfig.doCheckReleased {
836 d.apiCompatibilityFlags(ctx, cmd, params.stubConfig.stubsType)
837 }
838
Colin Crossbc139922021-03-25 18:33:16 -0700839 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700840
Colin Cross2207f872021-03-24 12:39:08 -0700841 for _, o := range d.Javadoc.properties.Out {
842 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
843 }
844
Jihoon Kang3c89f042023-12-19 02:40:22 +0000845 return cmd
846}
Colin Cross2207f872021-03-24 12:39:08 -0700847
Jihoon Kang3c89f042023-12-19 02:40:22 +0000848// Sandbox rule for generating the everything stubs and other artifacts
849func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
850 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
851 rule := android.NewRuleBuilder(pctx, ctx)
852 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
853 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
854 SandboxInputs()
855
856 var stubsDir android.OptionalPath
857 if params.generateStubs {
858 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
859 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
860 }
861
862 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000863 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
864 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000865 }
866
Jihoon Kanga11d6792024-03-05 16:12:20 +0000867 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000868 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000869 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000870 }
Jihoon Kangee113282024-01-23 00:16:41 +0000871 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000872 }
Jihoon Kanga11d6792024-03-05 16:12:20 +0000873 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +0000874 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000875 }
876
877 commonCmdParams := stubsCommandParams{
878 srcJarDir: srcJarDir,
879 stubsDir: stubsDir,
880 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000881 metadataDir: d.everythingArtifacts.metadataDir,
882 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
883 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
884 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000885 stubConfig: params,
886 }
887
888 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
889
890 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
891
892 if params.generateStubs {
893 rule.Command().
894 BuiltTool("soong_zip").
895 Flag("-write_if_changed").
896 Flag("-jar").
897 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
898 FlagWithArg("-C ", stubsDir.String()).
899 FlagWithArg("-D ", stubsDir.String())
900 }
901
902 if params.writeSdkValues {
903 rule.Command().
904 BuiltTool("soong_zip").
905 Flag("-write_if_changed").
906 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000907 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
908 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
909 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000910 }
911
912 // TODO: We don't really need two separate API files, but this is a reminiscence of how
913 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
914 if params.doApiLint {
915 rule.Command().Text("touch").Output(d.apiLintTimestamp)
916 }
917 if params.doCheckReleased {
918 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
919 }
920
921 // TODO(b/183630617): rewrapper doesn't support restat rules
922 if !metalavaUseRbe(ctx) {
923 rule.Restat()
924 }
925
926 zipSyncCleanupCmd(rule, srcJarDir)
927
928 rule.Build("metalava", "metalava merged")
929}
930
931// Sandbox rule for generating the everything artifacts that are not run by
932// default but only run based on the module configurations
933func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700934
935 // Add API lint options.
Paul Duffinbaf34782024-05-28 17:27:22 +0100936 treatDocumentationIssuesAsErrors := false
Jihoon Kang3c89f042023-12-19 02:40:22 +0000937 if doApiLint {
Jihoon Kang5623e542024-01-31 23:27:26 +0000938 var newSince android.Paths
939 if d.properties.Check_api.Api_lint.New_since != nil {
940 newSince = android.PathsForModuleSrc(ctx, []string{proptools.String(d.properties.Check_api.Api_lint.New_since)})
941 }
Paul Duffin0a71d732024-04-22 13:22:56 +0100942 cmd.Flag("--api-lint")
943 cmd.FlagForEachInput("--api-lint-previous-api ", newSince)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000944 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700945 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
946
Colin Cross0d532412021-03-25 09:38:45 -0700947 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700948 if d.Name() != "android.car-system-stubs-docs" &&
949 d.Name() != "android.car-stubs-docs" {
Paul Duffinbaf34782024-05-28 17:27:22 +0100950 treatDocumentationIssuesAsErrors = true
Colin Cross2207f872021-03-24 12:39:08 -0700951 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
952 }
953
954 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000955 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
956 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700957
958 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700959 //
960 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
961 // message and metalava's one?
962 msg := `$'` + // Enclose with $' ... '
963 `************************************************************\n` +
964 `Your API changes are triggering API Lint warnings or errors.\n` +
965 `To make these errors go away, fix the code according to the\n` +
966 `error and/or warning messages above.\n` +
967 `\n` +
968 `If it is not possible to do so, there are workarounds:\n` +
969 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000970 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
971 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700972
973 if baselineFile.Valid() {
974 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
975 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
976
977 msg += fmt.Sprintf(``+
978 `2. You can update the baseline by executing the following\n`+
979 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700980 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
981 ` "%s" \\\n`+
982 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700983 ` To submit the revised baseline.txt to the main Android\n`+
984 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
985 } else {
986 msg += fmt.Sprintf(``+
987 `2. You can add a baseline file of existing lint failures\n`+
988 ` to the build rule of %s.\n`, d.Name())
989 }
990 // Note the message ends with a ' (single quote), to close the $' ... ' .
991 msg += `************************************************************\n'`
992
993 cmd.FlagWithArg("--error-message:api-lint ", msg)
994 }
995
Paul Duffinbaf34782024-05-28 17:27:22 +0100996 if !treatDocumentationIssuesAsErrors {
Paul Duffinb679bdd2024-06-10 14:29:41 +0100997 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffinbaf34782024-05-28 17:27:22 +0100998 }
999
Colin Cross2207f872021-03-24 12:39:08 -07001000 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001001 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -07001002 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001003 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001004 if baselineFile.Valid() {
Jihoon Kang472f73f2024-03-28 20:59:29 +00001005 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001006 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
1007 }
Colin Cross2207f872021-03-24 12:39:08 -07001008 // Note this string includes quote ($' ... '), which decodes the "\n"s.
1009 msg := `$'\n******************************\n` +
1010 `You have tried to change the API from what has been previously released in\n` +
1011 `an SDK. Please fix the errors listed above.\n` +
1012 `******************************\n'`
1013
1014 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1015 }
1016
Paul Duffin10a23c22023-08-11 22:47:31 +01001017 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1018 // Pass the current API file into metalava so it can use it as the basis for determining how to
1019 // generate the output signature files (both api and removed).
1020 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1021 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1022 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001023}
Paul Duffin10a23c22023-08-11 22:47:31 +01001024
Paul Duffinb679bdd2024-06-10 14:29:41 +01001025// HIDDEN_DOCUMENTATION_ISSUES is the set of documentation related issues that should always be
1026// hidden as they are very noisy and provide little value.
1027var HIDDEN_DOCUMENTATION_ISSUES = []string{
1028 "Deprecated",
1029 "IntDef",
1030 "Nullable",
1031}
1032
1033func treatDocumentationIssuesAsWarningErrorWhenNew(cmd *android.RuleBuilderCommand) {
1034 // Treat documentation issues as warnings, but error when new.
1035 cmd.Flag("--error-when-new-category").Flag("Documentation")
1036
1037 // Hide some documentation issues that generated a lot of noise for little benefit.
1038 cmd.FlagForEachArg("--hide ", HIDDEN_DOCUMENTATION_ISSUES)
1039}
1040
Jihoon Kang3c89f042023-12-19 02:40:22 +00001041// Sandbox rule for generating exportable stubs and other artifacts
1042func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1043 optionalCmdParams := stubsCommandParams{
1044 stubConfig: params,
1045 }
1046
Jihoon Kang246690a2024-02-01 21:55:01 +00001047 if params.generateStubs {
1048 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1049 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1050 }
1051
Jihoon Kang3c89f042023-12-19 02:40:22 +00001052 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001053 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1054 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1055 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1056 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001057 }
1058
Jihoon Kanga11d6792024-03-05 16:12:20 +00001059 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001060 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001061 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1062 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001063 }
Jihoon Kangee113282024-01-23 00:16:41 +00001064 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1065 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001066 }
Jihoon Kanga11d6792024-03-05 16:12:20 +00001067 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +00001068 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1069 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001070 }
1071
1072 if params.checkApi || String(d.properties.Api_filename) != "" {
1073 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1074 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1075 }
1076
1077 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1078 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1079 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1080 }
1081
1082 d.optionalStubCmd(ctx, optionalCmdParams)
1083}
1084
1085func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1086
1087 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1088 rule := android.NewRuleBuilder(pctx, ctx)
1089 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1090 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1091 SandboxInputs()
1092
1093 if params.stubConfig.generateStubs {
1094 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1095 }
1096
1097 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1098
Jihoon Kang5d701272024-02-15 21:53:49 +00001099 generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001100
1101 if params.stubConfig.doApiLint {
1102 // Pass the lint baseline file as an input to resolve the lint errors.
1103 // The exportable stubs generation does not update the lint baseline file.
1104 // Lint baseline file update is handled by the everything stubs
1105 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1106 if baselineFile.Valid() {
1107 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1108 }
1109 }
1110
Paul Duffin71527b72024-05-31 13:30:32 +01001111 // Treat documentation issues as warnings, but error when new.
Paul Duffinb679bdd2024-06-10 14:29:41 +01001112 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffin71527b72024-05-31 13:30:32 +01001113
Jihoon Kang3c89f042023-12-19 02:40:22 +00001114 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001115 rule.Command().
1116 BuiltTool("soong_zip").
1117 Flag("-write_if_changed").
1118 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001119 FlagWithOutput("-o ", params.stubsSrcJar).
1120 FlagWithArg("-C ", params.stubsDir.String()).
1121 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001122 }
1123
Jihoon Kang3c89f042023-12-19 02:40:22 +00001124 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001125 rule.Command().
1126 BuiltTool("soong_zip").
1127 Flag("-write_if_changed").
1128 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001129 FlagWithOutput("-o ", params.metadataZip).
1130 FlagWithArg("-C ", params.metadataDir.String()).
1131 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001132 }
1133
Colin Cross6aa5c402021-03-24 12:28:50 -07001134 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001135 if !metalavaUseRbe(ctx) {
1136 rule.Restat()
1137 }
Colin Cross2207f872021-03-24 12:39:08 -07001138
Jihoon Kang3c89f042023-12-19 02:40:22 +00001139 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001140
Jihoon Kang3c89f042023-12-19 02:40:22 +00001141 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1142}
1143
1144func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1145 deps := d.Javadoc.collectDeps(ctx)
1146
1147 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1148 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1149
1150 // Add options for the other optional tasks: API-lint and check-released.
1151 // We generate separate timestamp files for them.
1152 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1153 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1154
1155 writeSdkValues := Bool(d.properties.Write_sdk_values)
1156
1157 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1158
1159 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1160 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1161 String(d.properties.Validate_nullability_from_list) != "")
1162
1163 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1164 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1165
1166 stubCmdParams := stubsCommandConfigParams{
Jihoon Kanga11d6792024-03-05 16:12:20 +00001167 javaVersion: javaVersion,
1168 deps: deps,
1169 checkApi: checkApi,
1170 generateStubs: generateStubs,
1171 doApiLint: doApiLint,
1172 doCheckReleased: doCheckReleased,
1173 writeSdkValues: writeSdkValues,
1174 migratingNullability: migratingNullability,
1175 validatingNullability: validatingNullability,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001176 }
1177 stubCmdParams.stubsType = Everything
1178 // Create default (i.e. "everything" stubs) rule for metalava
1179 d.everythingStubCmd(ctx, stubCmdParams)
1180
Jihoon Kangd40c5912024-03-05 16:12:20 +00001181 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001182 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1183 // strips all flagged apis to generate the "exportable" stubs
1184 stubCmdParams.stubsType = Exportable
1185 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001186
Paul Duffine7a86642022-08-16 15:43:20 +00001187 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1188
1189 if len(d.Javadoc.properties.Out) > 0 {
1190 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1191 }
1192
1193 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1194 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1195 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1196
1197 if baselineFile.Valid() {
1198 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1199 }
1200
Jihoon Kang3c89f042023-12-19 02:40:22 +00001201 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001202
1203 rule := android.NewRuleBuilder(pctx, ctx)
1204
1205 // Diff command line.
1206 // -F matches the closest "opening" line, such as "package android {"
1207 // and " public class Intent {".
1208 diff := `diff -u -F '{ *$'`
1209
1210 rule.Command().Text("( true")
1211 rule.Command().
1212 Text(diff).
1213 Input(apiFile).Input(d.apiFile)
1214
1215 rule.Command().
1216 Text(diff).
1217 Input(removedApiFile).Input(d.removedApiFile)
1218
1219 msg := fmt.Sprintf(`\n******************************\n`+
1220 `You have tried to change the API from what has been previously approved.\n\n`+
1221 `To make these errors go away, you have two choices:\n`+
1222 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1223 ` to the new methods, etc. shown in the above diff.\n\n`+
1224 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1225 ` m %s-update-current-api\n\n`+
1226 ` To submit the revised current.txt to the main Android repository,\n`+
1227 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001228 `If your build failed due to stub validation, you can resolve the errors with\n`+
1229 `either of the two choices above and try re-building the target.\n`+
1230 `If the mismatch between the stubs and the current.txt is intended,\n`+
1231 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001232 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1233 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001234 `******************************\n`, ctx.ModuleName())
1235
1236 rule.Command().
1237 Text("touch").Output(d.checkCurrentApiTimestamp).
1238 Text(") || (").
1239 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1240 Text("; exit 38").
1241 Text(")")
1242
1243 rule.Build("metalavaCurrentApiCheck", "check current API")
1244
Jihoon Kang3c89f042023-12-19 02:40:22 +00001245 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001246
1247 // update API rule
1248 rule = android.NewRuleBuilder(pctx, ctx)
1249
1250 rule.Command().Text("( true")
1251
1252 rule.Command().
1253 Text("cp").Flag("-f").
1254 Input(d.apiFile).Flag(apiFile.String())
1255
1256 rule.Command().
1257 Text("cp").Flag("-f").
1258 Input(d.removedApiFile).Flag(removedApiFile.String())
1259
1260 msg = "failed to update public API"
1261
1262 rule.Command().
1263 Text("touch").Output(d.updateCurrentApiTimestamp).
1264 Text(") || (").
1265 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1266 Text("; exit 38").
1267 Text(")")
1268
1269 rule.Build("metalavaCurrentApiUpdate", "update current API")
1270 }
1271
Colin Cross2207f872021-03-24 12:39:08 -07001272 if String(d.properties.Check_nullability_warnings) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001273 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001274 ctx.PropertyErrorf("check_nullability_warnings",
1275 "Cannot specify check_nullability_warnings unless validating nullability")
1276 }
1277
1278 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1279
Jihoon Kang3c89f042023-12-19 02:40:22 +00001280 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001281
1282 msg := fmt.Sprintf(`\n******************************\n`+
1283 `The warnings encountered during nullability annotation validation did\n`+
1284 `not match the checked in file of expected warnings. The diffs are shown\n`+
1285 `above. You have two options:\n`+
1286 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1287 ` 2. Update the file of expected warnings by running:\n`+
1288 ` cp %s %s\n`+
1289 ` and submitting the updated file as part of your change.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001290 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001291
1292 rule := android.NewRuleBuilder(pctx, ctx)
1293
1294 rule.Command().
1295 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001296 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001297 Text("&&").
1298 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1299 Text(") || (").
1300 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1301 Text("; exit 38").
1302 Text(")")
1303
1304 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1305 }
mrziwang39e68ff2024-07-01 16:35:32 -07001306
1307 d.setOutputFiles(ctx)
1308}
1309
1310// This method sets the outputFiles property, which is used to set the
1311// OutputFilesProvider later.
1312// Droidstubs' tag supports specifying with the stubs type.
1313// While supporting the pre-existing tags, it also supports tags with
1314// the stubs type prefix. Some examples are shown below:
1315// {.annotations.zip} - pre-existing behavior. Returns the path to the
1316// annotation zip.
1317// {.exportable} - Returns the path to the exportable stubs src jar.
1318// {.exportable.annotations.zip} - Returns the path to the exportable
1319// annotations zip file.
1320// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
1321// xml file. For unsupported combinations, the default everything output file
1322// is returned.
1323func (d *Droidstubs) setOutputFiles(ctx android.ModuleContext) {
1324 tagToOutputFileFunc := map[string]func(StubsType) (android.Path, error){
1325 "": d.StubsSrcJar,
1326 ".docs.zip": d.DocZip,
1327 ".api.txt": d.ApiFilePath,
1328 android.DefaultDistTag: d.ApiFilePath,
1329 ".removed-api.txt": d.RemovedApiFilePath,
1330 ".annotations.zip": d.AnnotationsZip,
1331 ".api_versions.xml": d.ApiVersionsXmlFilePath,
1332 }
1333 stubsTypeToPrefix := map[StubsType]string{
1334 Everything: "",
1335 Exportable: ".exportable",
1336 }
1337 for _, tag := range android.SortedKeys(tagToOutputFileFunc) {
1338 for _, stubType := range android.SortedKeys(stubsTypeToPrefix) {
1339 tagWithPrefix := stubsTypeToPrefix[stubType] + tag
1340 outputFile, err := tagToOutputFileFunc[tag](stubType)
1341 if err == nil {
1342 ctx.SetOutputFiles(android.Paths{outputFile}, tagWithPrefix)
1343 }
1344 }
1345 }
Colin Cross2207f872021-03-24 12:39:08 -07001346}
1347
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001348func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1349 api_file := d.properties.Check_api.Current.Api_file
1350 api_surface := d.properties.Api_surface
1351
1352 props := struct {
1353 Name *string
1354 Api_surface *string
1355 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001356 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001357 }{}
1358
1359 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1360 props.Api_surface = api_surface
1361 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001362 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001363
1364 ctx.CreateModule(ApiContributionFactory, &props)
1365}
1366
Spandan Das0b555e32022-11-28 18:48:51 +00001367// TODO (b/262014796): Export the API contributions of CorePlatformApi
1368// A map to populate the api surface of a droidstub from a substring appearing in its name
1369// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1370// use a strict naming convention
1371var (
1372 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
Paul Duffin2ced2eb2024-05-01 13:13:51 +01001373 // public is commented out since the core libraries use public in their java_sdk_library names
Spandan Das0b555e32022-11-28 18:48:51 +00001374 "intracore": android.SdkIntraCore,
1375 "intra.core": android.SdkIntraCore,
1376 "system_server": android.SdkSystemServer,
1377 "system-server": android.SdkSystemServer,
1378 "system": android.SdkSystem,
1379 "module_lib": android.SdkModule,
1380 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001381 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001382 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001383 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001384 }
1385)
1386
Colin Cross2207f872021-03-24 12:39:08 -07001387func StubsDefaultsFactory() android.Module {
1388 module := &DocDefaults{}
1389
1390 module.AddProperties(
1391 &JavadocProperties{},
1392 &DroidstubsProperties{},
1393 )
1394
1395 android.InitDefaultsModule(module)
1396
1397 return module
1398}
1399
1400var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1401
1402type PrebuiltStubsSourcesProperties struct {
1403 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001404
1405 // Name of the source soong module that gets shadowed by this prebuilt
1406 // If unspecified, follows the naming convention that the source module of
1407 // the prebuilt is Name() without "prebuilt_" prefix
1408 Source_module_name *string
1409
1410 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1411 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1412 // (without any prebuilt_ prefix)
1413 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1414}
1415
1416func (j *PrebuiltStubsSources) BaseModuleName() string {
1417 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1418}
1419
1420func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1421 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001422}
1423
1424type PrebuiltStubsSources struct {
1425 android.ModuleBase
1426 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001427 embeddableInModuleAndImport
1428
Colin Cross2207f872021-03-24 12:39:08 -07001429 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001430
1431 properties PrebuiltStubsSourcesProperties
1432
kgui67007242022-01-25 13:50:25 +08001433 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001434}
1435
Jihoon Kangee113282024-01-23 00:16:41 +00001436func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1437 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001438}
1439
1440func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001441 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001442 ctx.PropertyErrorf("srcs", "must only specify one directory path or srcjar, contains %d paths", len(p.properties.Srcs))
Colin Cross2207f872021-03-24 12:39:08 -07001443 return
1444 }
1445
Anton Hansson86758ac2021-11-03 14:44:12 +00001446 src := p.properties.Srcs[0]
1447 if filepath.Ext(src) == ".srcjar" {
1448 // This is a srcjar. We can use it directly.
1449 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1450 } else {
1451 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001452
Anton Hansson86758ac2021-11-03 14:44:12 +00001453 // This is a directory. Glob the contents just in case the directory does not exist.
1454 srcGlob := src + "/**/*"
1455 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001456
Anton Hansson86758ac2021-11-03 14:44:12 +00001457 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1458 // the path components are invalid it won't in this case because no components
1459 // are specified and the module directory must exist in order to get this far.
1460 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001461
Anton Hansson86758ac2021-11-03 14:44:12 +00001462 rule := android.NewRuleBuilder(pctx, ctx)
1463 rule.Command().
1464 BuiltTool("soong_zip").
1465 Flag("-write_if_changed").
1466 Flag("-jar").
1467 FlagWithOutput("-o ", outPath).
1468 FlagWithArg("-C ", srcDir.String()).
1469 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1470 rule.Restat()
1471 rule.Build("zip src", "Create srcjar from prebuilt source")
1472 p.stubsSrcJar = outPath
1473 }
mrziwangaa2a2b62024-07-01 12:09:20 -07001474
1475 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, "")
1476 // prebuilt droidstubs does not output "exportable" stubs.
1477 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1478 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, ".exportable")
Colin Cross2207f872021-03-24 12:39:08 -07001479}
1480
1481func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1482 return &p.prebuilt
1483}
1484
1485func (p *PrebuiltStubsSources) Name() string {
1486 return p.prebuilt.Name(p.ModuleBase.Name())
1487}
1488
1489// prebuilt_stubs_sources imports a set of java source files as if they were
1490// generated by droidstubs.
1491//
1492// By default, a prebuilt_stubs_sources has a single variant that expects a
1493// set of `.java` files generated by droidstubs.
1494//
1495// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1496// for host modules.
1497//
1498// Intended only for use by sdk snapshots.
1499func PrebuiltStubsSourcesFactory() android.Module {
1500 module := &PrebuiltStubsSources{}
1501
1502 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001503 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001504
1505 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001506 InitDroiddocModule(module, android.HostAndDeviceSupported)
1507 return module
1508}