blob: f8af017804137a342a4d4b543c2eb49409a78624 [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
Paul Duffin27819362024-07-22 21:03:50 +0100200
201 // List of hard coded filegroups containing Metalava config files that are passed to every
202 // Metalava invocation that this module performs. See addMetalavaConfigFilesToCmd.
203 ConfigFiles []string `android:"path" blueprint:"mutated"`
Colin Cross2207f872021-03-24 12:39:08 -0700204}
205
Anton Hansson52609322021-05-05 10:36:05 +0100206// Used by xsd_config
207type ApiFilePath interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000208 ApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100209}
210
211type ApiStubsSrcProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000212 StubsSrcJar(StubsType) (android.Path, error)
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000213}
214
Anton Hansson52609322021-05-05 10:36:05 +0100215// Provider of information about API stubs, used by java_sdk_library.
216type ApiStubsProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000217 AnnotationsZip(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100218 ApiFilePath
Jihoon Kangee113282024-01-23 00:16:41 +0000219 RemovedApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100220
221 ApiStubsSrcProvider
222}
223
Jihoon Kang063ec002023-06-28 01:16:23 +0000224type currentApiTimestampProvider interface {
225 CurrentApiTimestamp() android.Path
226}
227
Jihoon Kang3c89f042023-12-19 02:40:22 +0000228type annotationFlagsParams struct {
229 migratingNullability bool
230 validatingNullability bool
231 nullabilityWarningsFile android.WritablePath
232 annotationsZip android.WritablePath
233}
234type stubsCommandParams struct {
235 srcJarDir android.ModuleOutPath
236 stubsDir android.OptionalPath
237 stubsSrcJar android.WritablePath
238 metadataZip android.WritablePath
239 metadataDir android.WritablePath
240 apiVersionsXml android.WritablePath
241 nullabilityWarningsFile android.WritablePath
242 annotationsZip android.WritablePath
243 stubConfig stubsCommandConfigParams
244}
245type stubsCommandConfigParams struct {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000246 stubsType StubsType
247 javaVersion javaVersion
248 deps deps
249 checkApi bool
250 generateStubs bool
251 doApiLint bool
252 doCheckReleased bool
253 writeSdkValues bool
254 migratingNullability bool
255 validatingNullability bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000256}
257
Colin Cross2207f872021-03-24 12:39:08 -0700258// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
259// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
260// a droiddoc module to generate documentation.
261func DroidstubsFactory() android.Module {
262 module := &Droidstubs{}
263
264 module.AddProperties(&module.properties,
265 &module.Javadoc.properties)
Paul Duffin27819362024-07-22 21:03:50 +0100266 module.properties.ConfigFiles = getMetalavaConfigFilegroupReference()
Spandan Das2cc80ba2023-10-27 17:21:52 +0000267 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700268
269 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000270
271 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
272 module.createApiContribution(ctx)
273 })
Colin Cross2207f872021-03-24 12:39:08 -0700274 return module
275}
276
277// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
278// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
279// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
280// module when symbols needed by the source files are provided by java_library_host modules.
281func DroidstubsHostFactory() android.Module {
282 module := &Droidstubs{}
283
284 module.AddProperties(&module.properties,
285 &module.Javadoc.properties)
286
Paul Duffin27819362024-07-22 21:03:50 +0100287 module.properties.ConfigFiles = getMetalavaConfigFilegroupReference()
Colin Cross2207f872021-03-24 12:39:08 -0700288 InitDroiddocModule(module, android.HostSupported)
289 return module
290}
291
Jihoon Kang246690a2024-02-01 21:55:01 +0000292func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000293 switch stubsType {
294 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000295 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000296 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000297 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000298 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000299 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000300 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000301 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000302}
303
Jihoon Kang246690a2024-02-01 21:55:01 +0000304func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000305 switch stubsType {
306 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000307 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000308 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000309 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000310 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000311 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000312 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000313 if ret == nil && err == nil {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000314 err = fmt.Errorf("api file is null for the stub type %s", stubsType.String())
Jihoon Kang246690a2024-02-01 21:55:01 +0000315 }
316 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000317}
318
Jihoon Kang246690a2024-02-01 21:55:01 +0000319func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000320 switch stubsType {
321 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000322 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000323 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000324 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000325 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000326 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 +0000327 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000328 if ret == nil && err == nil {
329 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
330 }
331 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000332}
333
Jihoon Kang246690a2024-02-01 21:55:01 +0000334func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000335 switch stubsType {
336 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000337 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000338 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000339 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000340 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000341 if ret == nil && err == nil {
342 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
343 }
344 return ret, err
345}
346
347func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
348 switch stubsType {
349 case Everything:
350 ret, err = d.removedApiFile, nil
351 case Exportable:
352 ret, err = d.exportableRemovedApiFile, nil
353 default:
354 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
355 }
356 if ret == nil && err == nil {
357 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
358 }
359 return ret, err
360}
361
362func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
363 switch stubsType {
364 case Everything:
365 ret, err = d.stubsSrcJar, nil
366 case Exportable:
367 ret, err = d.exportableStubsSrcJar, nil
368 default:
369 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
370 }
371 if ret == nil && err == nil {
372 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
373 }
374 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000375}
376
Jihoon Kang063ec002023-06-28 01:16:23 +0000377func (d *Droidstubs) CurrentApiTimestamp() android.Path {
378 return d.checkCurrentApiTimestamp
379}
380
Colin Cross2207f872021-03-24 12:39:08 -0700381var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
382var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
383var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000384var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000385var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700386
387func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
388 d.Javadoc.addDeps(ctx)
389
390 if len(d.properties.Merge_annotations_dirs) != 0 {
391 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
392 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
393 }
394 }
395
396 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
397 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
398 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
399 }
400 }
401
402 if len(d.properties.Api_levels_annotations_dirs) != 0 {
403 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
404 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
405 }
406 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000407
Jihoon Kang6592e872023-12-19 01:13:16 +0000408 if len(d.properties.Aconfig_declarations) != 0 {
409 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
410 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
411 }
412 }
413
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000414 if d.properties.Api_levels_module != nil {
415 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
416 }
Colin Cross2207f872021-03-24 12:39:08 -0700417}
418
Jihoon Kang3c89f042023-12-19 02:40:22 +0000419func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
420 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
421}
422
423func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000424
Jihoon Kang36c3d962024-03-14 17:28:44 +0000425 apiFileName := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
426 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), apiFileName)
427 cmd.FlagWithOutput("--api ", uncheckedApiFile)
428 if checkApi || String(d.properties.Api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000429 if stubsType == Everything {
430 d.apiFile = uncheckedApiFile
431 } else if stubsType == Exportable {
432 d.exportableApiFile = uncheckedApiFile
433 }
Colin Cross2207f872021-03-24 12:39:08 -0700434 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000435 if stubsType == Everything {
436 // If check api is disabled then make the source file available for export.
437 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
438 } else if stubsType == Exportable {
439 d.exportableApiFile = uncheckedApiFile
440 }
Colin Cross2207f872021-03-24 12:39:08 -0700441 }
442
Jihoon Kang36c3d962024-03-14 17:28:44 +0000443 removedApiFileName := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
444 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), removedApiFileName)
445 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000446 if checkApi || String(d.properties.Removed_api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000447 if stubsType == Everything {
448 d.removedApiFile = uncheckedRemovedFile
449 } else if stubsType == Exportable {
450 d.exportableRemovedApiFile = uncheckedRemovedFile
451 }
Colin Cross2207f872021-03-24 12:39:08 -0700452 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000453 if stubsType == Everything {
454 // If check api is disabled then make the source removed api file available for export.
455 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
456 } else if stubsType == Exportable {
457 d.exportableRemovedApiFile = uncheckedRemovedFile
458 }
Colin Cross2207f872021-03-24 12:39:08 -0700459 }
460
Colin Cross2207f872021-03-24 12:39:08 -0700461 if stubsDir.Valid() {
462 if Bool(d.properties.Create_doc_stubs) {
463 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
464 } else {
465 cmd.FlagWithArg("--stubs ", stubsDir.String())
466 if !Bool(d.properties.Output_javadoc_comments) {
467 cmd.Flag("--exclude-documentation-from-stubs")
468 }
469 }
470 }
471}
472
Jihoon Kang3c89f042023-12-19 02:40:22 +0000473func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000474 if Bool(d.properties.Annotations_enabled) {
475 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100476
Jihoon Kanga11d6792024-03-05 16:12:20 +0000477 if params.migratingNullability {
Jihoon Kang5623e542024-01-31 23:27:26 +0000478 previousApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Previous_api)})
479 cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000480 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000481
Jihoon Kanga11d6792024-03-05 16:12:20 +0000482 if s := String(d.properties.Validate_nullability_from_list); s != "" {
483 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
484 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000485
Jihoon Kanga11d6792024-03-05 16:12:20 +0000486 if params.validatingNullability {
487 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
488 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000489
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000490 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000491
Jihoon Kanga11d6792024-03-05 16:12:20 +0000492 if len(d.properties.Merge_annotations_dirs) != 0 {
493 d.mergeAnnoDirFlags(ctx, cmd)
494 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000495
Jihoon Kanga11d6792024-03-05 16:12:20 +0000496 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700497 }
Colin Cross2207f872021-03-24 12:39:08 -0700498}
499
500func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
501 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
502 if t, ok := m.(*ExportedDroiddocDir); ok {
503 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
504 } else {
505 ctx.PropertyErrorf("merge_annotations_dirs",
506 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
507 }
508 })
509}
510
511func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
512 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
513 if t, ok := m.(*ExportedDroiddocDir); ok {
514 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
515 } else {
516 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
517 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
518 }
519 })
520}
521
Jihoon Kanga11d6792024-03-05 16:12:20 +0000522func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000523 var apiVersions android.Path
Jihoon Kanga11d6792024-03-05 16:12:20 +0000524 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000525 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000526 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000527 } else {
528 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
529 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000530 if stubsType == Everything {
531 apiVersions = s.everythingArtifacts.apiVersionsXml
532 } else if stubsType == Exportable {
533 apiVersions = s.exportableArtifacts.apiVersionsXml
534 } else {
Jihoon Kangd40c5912024-03-05 16:12:20 +0000535 ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
Jihoon Kangd9a06942024-01-26 01:49:20 +0000536 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000537 } else {
538 ctx.PropertyErrorf("api_levels_module",
539 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
540 }
541 })
Colin Cross2207f872021-03-24 12:39:08 -0700542 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000543 if apiVersions != nil {
544 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
545 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
546 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
547 }
548}
Colin Cross2207f872021-03-24 12:39:08 -0700549
Paul Duffin5a195f42024-05-01 12:52:35 +0100550// AndroidPlusUpdatableJar is the name of some extra jars added into `module-lib` and
551// `system-server` directories that contain all the APIs provided by the platform and updatable
552// modules because the `android.jar` files do not. See b/337836752.
553const AndroidPlusUpdatableJar = "android-plus-updatable.jar"
554
Jihoon Kang3c89f042023-12-19 02:40:22 +0000555func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700556 if len(d.properties.Api_levels_annotations_dirs) == 0 {
557 ctx.PropertyErrorf("api_levels_annotations_dirs",
558 "has to be non-empty if api levels annotations was enabled!")
559 }
560
Jihoon Kang3c89f042023-12-19 02:40:22 +0000561 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700562
563 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
564
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100565 // TODO: Avoid the duplication of API surfaces, reuse apiScope.
566 // Add all relevant --android-jar-pattern patterns for Metalava.
567 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
568 // an actual file present on disk (in the order the patterns were passed). For system APIs for
569 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
570 // for older releases. Similarly, module-lib falls back to system API.
571 var sdkDirs []string
Paul Duffin92efc612024-05-02 17:18:05 +0100572 apiLevelsSdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public")
573 switch apiLevelsSdkType {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100574 case "system-server":
575 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
576 case "module-lib":
577 sdkDirs = []string{"module-lib", "system", "public"}
578 case "system":
579 sdkDirs = []string{"system", "public"}
580 case "public":
581 sdkDirs = []string{"public"}
582 default:
583 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
584 return
585 }
586
Paul Duffin92efc612024-05-02 17:18:05 +0100587 // Construct a pattern to match the appropriate extensions that should be included in the
588 // generated api-versions.xml file.
589 //
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100590 // Use the first item in the sdkDirs array as that is the sdk type for the target API levels
591 // being generated but has the advantage over `Api_levels_sdk_type` as it has been validated.
Paul Duffin92efc612024-05-02 17:18:05 +0100592 // The exception is for system-server which needs to include module-lib and system-server. That
593 // is because while system-server extends module-lib the system-server extension directory only
594 // contains service-* modules which provide system-server APIs it does not list the modules which
595 // only provide a module-lib, so they have to be included separately.
596 extensionSurfacesPattern := sdkDirs[0]
597 if apiLevelsSdkType == "system-server" {
598 // Take the first two items in sdkDirs, which are system-server and module-lib, and construct
599 // a pattern that will match either.
600 extensionSurfacesPattern = strings.Join(sdkDirs[0:2], "|")
601 }
602 extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/(%s)/.*\.jar`, extensionSurfacesPattern)
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100603
satayev783195c2021-06-23 21:49:57 +0100604 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200605 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700606 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
607 if t, ok := m.(*ExportedDroiddocDir); ok {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100608 extRegex := regexp.MustCompile(t.dir.String() + extensionsPattern)
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200609
610 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
611 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700612 for _, dep := range t.deps {
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100613 // Check to see if it matches an extension first.
614 depBase := dep.Base()
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200615 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
616 if extensions_dir == "" {
617 extensions_dir = t.dir.String() + "/extensions"
618 }
619 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100620 } else if depBase == filename {
621 // 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 -0700622 cmd.Implicit(dep)
Paul Duffin5a195f42024-05-01 12:52:35 +0100623 } else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil {
624 // The output api-versions.xml has been requested to include information on SDK
Paul Duffinee5e0932025-01-15 18:00:35 +0000625 // extensions, i.e. updatable Apis. That means it also needs to include the history of
626 // those updatable APIs. Usually, they would be included in the `android.jar` file but
627 // unfortunately, the `module-lib` and `system-server` cannot as it would lead to build
628 // cycles. So, the module-lib and system-server directories contain an
629 // `android-plus-updatable.jar` that should be used instead of `android.jar`. See
630 // AndroidPlusUpdatableJar for more information.
Paul Duffin5a195f42024-05-01 12:52:35 +0100631 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100632 } else if filename != "android.jar" && depBase == "android.jar" {
Colin Cross5f6ffc72021-03-29 21:54:45 -0700633 // Metalava implicitly searches these patterns:
Paul Duffin4c9d3052025-01-07 16:03:10 +0000634 // prebuilts/tools/common/api-versions/android-{version:level}/android.jar
635 // prebuilts/sdk/{version:level}/public/android.jar
Colin Cross5f6ffc72021-03-29 21:54:45 -0700636 // Add android.jar files from the api_levels_annotations_dirs directories to try
637 // to satisfy these patterns. If Metalava can't find a match for an API level
638 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700639 cmd.Implicit(dep)
640 }
641 }
satayev783195c2021-06-23 21:49:57 +0100642
643 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700644 } else {
645 ctx.PropertyErrorf("api_levels_annotations_dirs",
646 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
647 }
648 })
satayev783195c2021-06-23 21:49:57 +0100649
Paul Duffin5a195f42024-05-01 12:52:35 +0100650 // Generate the list of --android-jar-pattern options. The order matters so the first one which
Paul Duffin4c9d3052025-01-07 16:03:10 +0000651 // matches will be the one that is used for a specific api level.
Pedro Loureirocc203502021-10-04 17:24:00 +0000652 for _, sdkDir := range sdkDirs {
653 for _, dir := range dirs {
Paul Duffin5a195f42024-05-01 12:52:35 +0100654 addPattern := func(jarFilename string) {
Paul Duffin4c9d3052025-01-07 16:03:10 +0000655 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/{version:level}/%s/%s", dir, sdkDir, jarFilename))
Paul Duffin5a195f42024-05-01 12:52:35 +0100656 }
657
658 if sdkDir == "module-lib" || sdkDir == "system-server" {
659 // The module-lib and system-server android.jars do not include the updatable modules (as
660 // doing so in the source would introduce dependency cycles and the prebuilts have to
661 // match the sources). So, instead an additional `android-plus-updatable.jar` will be used
662 // that does include the updatable modules and this pattern will match that. This pattern
663 // is added in addition to the following pattern to decouple this change from the change
664 // to add the `android-plus-updatable.jar`.
665 addPattern(AndroidPlusUpdatableJar)
666 }
667
668 addPattern(filename)
Pedro Loureirocc203502021-10-04 17:24:00 +0000669 }
satayev783195c2021-06-23 21:49:57 +0100670 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200671
672 if d.properties.Extensions_info_file != nil {
673 if extensions_dir == "" {
674 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
675 }
676 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
677 cmd.Implicit(info_file)
678 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
679 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
680 }
Colin Cross2207f872021-03-24 12:39:08 -0700681}
682
Jihoon Kang472f73f2024-03-28 20:59:29 +0000683func (d *Droidstubs) apiCompatibilityFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType) {
684 if len(d.Javadoc.properties.Out) > 0 {
685 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
686 }
687
Jihoon Kang5623e542024-01-31 23:27:26 +0000688 apiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Api_file)})
689 removedApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Removed_api_file)})
Jihoon Kang472f73f2024-03-28 20:59:29 +0000690
Jihoon Kang5623e542024-01-31 23:27:26 +0000691 cmd.FlagForEachInput("--check-compatibility:api:released ", apiFiles)
692 cmd.FlagForEachInput("--check-compatibility:removed:released ", removedApiFiles)
Jihoon Kang472f73f2024-03-28 20:59:29 +0000693
694 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
695 if baselineFile.Valid() {
696 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
697 }
698}
699
Colin Crosse52c2ac2022-03-28 17:03:35 -0700700func metalavaUseRbe(ctx android.ModuleContext) bool {
701 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
702}
703
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000704func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
Paul Duffin27819362024-07-22 21:03:50 +0100705 srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams, configFiles android.Paths) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700706 rule.Command().Text("rm -rf").Flag(homeDir.String())
707 rule.Command().Text("mkdir -p").Flag(homeDir.String())
708
Anton Hansson556e8142021-06-04 16:20:25 +0100709 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700710 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
711
Colin Crosse52c2ac2022-03-28 17:03:35 -0700712 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700713 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700714 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000715 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
716 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700717 labels := map[string]string{"type": "tool", "name": "metalava"}
718 // TODO: metalava pool rejects these jobs
719 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
720 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000721 Labels: labels,
722 ExecStrategy: execStrategy,
723 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
724 Platform: map[string]string{remoteexec.PoolKey: pool},
725 Compare: compare,
726 NumLocalRuns: 1,
727 NumRemoteRuns: 1,
728 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700729 })
Colin Cross2207f872021-03-24 12:39:08 -0700730 }
731
Colin Cross6aa5c402021-03-24 12:28:50 -0700732 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700733 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400734 Flag(config.MetalavaAddOpens).
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000735 FlagWithArg("--java-source ", params.javaVersion.String()).
736 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, fmt.Sprintf("%s.metalava.rsp", params.stubsType.String())), srcs).
Colin Cross2207f872021-03-24 12:39:08 -0700737 FlagWithInput("@", srcJarList)
738
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100739 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
740 // years, so it is unlikely to change any time soon.
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000741 combinedPaths := append(([]android.Path)(nil), params.deps.bootClasspath.Paths()...)
742 combinedPaths = append(combinedPaths, params.deps.classpath.Paths()...)
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100743 if len(combinedPaths) > 0 {
744 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700745 }
746
Liz Kammere09e20e2023-10-16 15:07:54 -0400747 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000748
Paul Duffin27819362024-07-22 21:03:50 +0100749 addMetalavaConfigFilesToCmd(cmd, configFiles)
750
Colin Cross2207f872021-03-24 12:39:08 -0700751 return cmd
752}
753
Paul Duffin27819362024-07-22 21:03:50 +0100754// MetalavaConfigFilegroup is the name of the filegroup in build/soong/java/metalava that lists
755// the configuration files to pass to Metalava.
756const MetalavaConfigFilegroup = "metalava-config-files"
757
758// Get a reference to the MetalavaConfigFilegroup suitable for use in a property.
759func getMetalavaConfigFilegroupReference() []string {
760 return []string{":" + MetalavaConfigFilegroup}
761}
762
763// addMetalavaConfigFilesToCmd adds --config-file options to use the config files list in the
764// MetalavaConfigFilegroup filegroup.
765func addMetalavaConfigFilesToCmd(cmd *android.RuleBuilderCommand, configFiles android.Paths) {
766 cmd.FlagForEachInput("--config-file ", configFiles)
767}
768
Jihoon Kang3c89f042023-12-19 02:40:22 +0000769// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
770// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
771// property is defined, apply transformations and only revert the flagged apis that are not
772// enabled via release configurations and are not specified in aconfig_declarations
Jihoon Kang5d701272024-02-15 21:53:49 +0000773func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
Jihoon Kang6592e872023-12-19 01:13:16 +0000774 var filterArgs string
775 switch stubsType {
776 // No flagged apis specific flags need to be passed to metalava when generating
777 // everything stubs
778 case Everything:
779 return
780
781 case Runtime:
782 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
783
784 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000785 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
786 // the flagged apis that have read_write permissions are exposed on top of the enabled
787 // and read_only apis. This is to support local override of flag values at runtime.
788 if ctx.Config().ReleaseExportRuntimeApis() {
789 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
790 } else {
791 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
792 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000793 }
794
Jihoon Kangf1e0ff02024-11-20 21:10:40 +0000795 if len(aconfigFlagsPaths) == 0 {
796 // This argument should not be added for "everything" stubs
797 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
798 return
799 }
800
801 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
802 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
803
Jihoon Kang6592e872023-12-19 01:13:16 +0000804 ctx.Build(pctx, android.BuildParams{
805 Rule: gatherReleasedFlaggedApisRule,
806 Inputs: aconfigFlagsPaths,
807 Output: releasedFlaggedApisFile,
808 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
809 Args: map[string]string{
810 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
811 "filter_args": filterArgs,
812 },
813 })
814
815 ctx.Build(pctx, android.BuildParams{
816 Rule: generateMetalavaRevertAnnotationsRule,
817 Input: releasedFlaggedApisFile,
818 Output: revertAnnotationsFile,
819 Description: fmt.Sprintf("%s revert annotations", stubsType),
820 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000821
822 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000823}
824
Jihoon Kang3c89f042023-12-19 02:40:22 +0000825func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
826 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700827 if BoolDefault(d.properties.High_mem, false) {
828 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
829 rule.HighMem()
830 }
831
Jihoon Kang3c89f042023-12-19 02:40:22 +0000832 if params.stubConfig.generateStubs {
833 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
834 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700835 }
836
Jihoon Kang3c89f042023-12-19 02:40:22 +0000837 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700838
Jihoon Kang3c89f042023-12-19 02:40:22 +0000839 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
Paul Duffin27819362024-07-22 21:03:50 +0100840
841 configFiles := android.PathsForModuleSrc(ctx, d.properties.ConfigFiles)
842
843 cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig, configFiles)
Colin Cross2207f872021-03-24 12:39:08 -0700844 cmd.Implicits(d.Javadoc.implicits)
845
Jihoon Kang3c89f042023-12-19 02:40:22 +0000846 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700847
Jihoon Kang3c89f042023-12-19 02:40:22 +0000848 if params.stubConfig.writeSdkValues {
849 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
850 }
851
852 annotationParams := annotationFlagsParams{
853 migratingNullability: params.stubConfig.migratingNullability,
854 validatingNullability: params.stubConfig.validatingNullability,
855 nullabilityWarningsFile: params.nullabilityWarningsFile,
856 annotationsZip: params.annotationsZip,
857 }
858
Jihoon Kanga11d6792024-03-05 16:12:20 +0000859 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700860 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000861 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700862
Jihoon Kang472f73f2024-03-28 20:59:29 +0000863 if params.stubConfig.doCheckReleased {
864 d.apiCompatibilityFlags(ctx, cmd, params.stubConfig.stubsType)
865 }
866
Colin Crossbc139922021-03-25 18:33:16 -0700867 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700868
Colin Cross2207f872021-03-24 12:39:08 -0700869 for _, o := range d.Javadoc.properties.Out {
870 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
871 }
872
Jihoon Kang3c89f042023-12-19 02:40:22 +0000873 return cmd
874}
Colin Cross2207f872021-03-24 12:39:08 -0700875
Jihoon Kang3c89f042023-12-19 02:40:22 +0000876// Sandbox rule for generating the everything stubs and other artifacts
877func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
878 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
879 rule := android.NewRuleBuilder(pctx, ctx)
880 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
881 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
882 SandboxInputs()
883
884 var stubsDir android.OptionalPath
885 if params.generateStubs {
886 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
887 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
888 }
889
890 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000891 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
892 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000893 }
894
Jihoon Kanga11d6792024-03-05 16:12:20 +0000895 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000896 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000897 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000898 }
Jihoon Kangee113282024-01-23 00:16:41 +0000899 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000900 }
Jihoon Kanga11d6792024-03-05 16:12:20 +0000901 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +0000902 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000903 }
904
905 commonCmdParams := stubsCommandParams{
906 srcJarDir: srcJarDir,
907 stubsDir: stubsDir,
908 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000909 metadataDir: d.everythingArtifacts.metadataDir,
910 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
911 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
912 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000913 stubConfig: params,
914 }
915
916 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
917
918 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
919
920 if params.generateStubs {
921 rule.Command().
922 BuiltTool("soong_zip").
923 Flag("-write_if_changed").
924 Flag("-jar").
925 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
926 FlagWithArg("-C ", stubsDir.String()).
927 FlagWithArg("-D ", stubsDir.String())
928 }
929
930 if params.writeSdkValues {
931 rule.Command().
932 BuiltTool("soong_zip").
933 Flag("-write_if_changed").
934 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000935 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
936 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
937 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000938 }
939
940 // TODO: We don't really need two separate API files, but this is a reminiscence of how
941 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
942 if params.doApiLint {
943 rule.Command().Text("touch").Output(d.apiLintTimestamp)
944 }
945 if params.doCheckReleased {
946 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
947 }
948
949 // TODO(b/183630617): rewrapper doesn't support restat rules
950 if !metalavaUseRbe(ctx) {
951 rule.Restat()
952 }
953
954 zipSyncCleanupCmd(rule, srcJarDir)
955
956 rule.Build("metalava", "metalava merged")
957}
958
959// Sandbox rule for generating the everything artifacts that are not run by
960// default but only run based on the module configurations
961func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700962
963 // Add API lint options.
Paul Duffinbaf34782024-05-28 17:27:22 +0100964 treatDocumentationIssuesAsErrors := false
Jihoon Kang3c89f042023-12-19 02:40:22 +0000965 if doApiLint {
Jihoon Kang5623e542024-01-31 23:27:26 +0000966 var newSince android.Paths
967 if d.properties.Check_api.Api_lint.New_since != nil {
968 newSince = android.PathsForModuleSrc(ctx, []string{proptools.String(d.properties.Check_api.Api_lint.New_since)})
969 }
Paul Duffin0a71d732024-04-22 13:22:56 +0100970 cmd.Flag("--api-lint")
971 cmd.FlagForEachInput("--api-lint-previous-api ", newSince)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000972 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700973 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
974
Paul Duffinc540bee2024-08-29 15:35:58 +0100975 // If UnflaggedApi issues have not already been configured then make sure that existing
976 // UnflaggedApi issues are reported as warnings but issues in new/changed code are treated as
977 // errors by the Build Warnings Aye Aye Analyzer in Gerrit.
Paul Duffin88d3b392024-08-28 17:37:36 +0100978 // Once existing issues have been fixed this will be changed to error.
Paul Duffinc540bee2024-08-29 15:35:58 +0100979 // TODO(b/362771529): Switch to --error
980 if !strings.Contains(cmd.String(), " UnflaggedApi ") {
981 cmd.Flag("--error-when-new UnflaggedApi")
982 }
Paul Duffin88d3b392024-08-28 17:37:36 +0100983
Colin Cross0d532412021-03-25 09:38:45 -0700984 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700985 if d.Name() != "android.car-system-stubs-docs" &&
986 d.Name() != "android.car-stubs-docs" {
Paul Duffinbaf34782024-05-28 17:27:22 +0100987 treatDocumentationIssuesAsErrors = true
Colin Cross2207f872021-03-24 12:39:08 -0700988 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
989 }
990
991 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000992 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
993 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700994
995 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700996 //
997 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
998 // message and metalava's one?
999 msg := `$'` + // Enclose with $' ... '
1000 `************************************************************\n` +
1001 `Your API changes are triggering API Lint warnings or errors.\n` +
Colin Cross2207f872021-03-24 12:39:08 -07001002 `\n` +
Adrian Roos40be6472024-11-05 14:25:35 +00001003 `To make the failures go away:\n` +
Colin Cross2207f872021-03-24 12:39:08 -07001004 `\n` +
Adrian Roos40be6472024-11-05 14:25:35 +00001005 `1. REQUIRED: Read the messages carefully and address them by` +
1006 ` fixing the API if appropriate.\n` +
1007 `2. If the failure is a false positive, you can suppress it with:\n` +
1008 ` @SuppressLint("<id>")\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +00001009 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -07001010
1011 if baselineFile.Valid() {
1012 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1013 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
1014
1015 msg += fmt.Sprintf(``+
Cole Faust5146e782024-11-15 14:47:49 -08001016 `3. FOR LSC ONLY: You can update the baseline by executing\n`+
Adrian Roos40be6472024-11-05 14:25:35 +00001017 ` the following command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -07001018 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
1019 ` "%s" \\\n`+
1020 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -07001021 ` To submit the revised baseline.txt to the main Android\n`+
1022 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
1023 } else {
1024 msg += fmt.Sprintf(``+
Adrian Roos40be6472024-11-05 14:25:35 +00001025 `3. FOR LSC ONLY: You can add a baseline file of existing lint failures\n`+
Colin Cross2207f872021-03-24 12:39:08 -07001026 ` to the build rule of %s.\n`, d.Name())
1027 }
1028 // Note the message ends with a ' (single quote), to close the $' ... ' .
1029 msg += `************************************************************\n'`
1030
1031 cmd.FlagWithArg("--error-message:api-lint ", msg)
1032 }
1033
Paul Duffinbaf34782024-05-28 17:27:22 +01001034 if !treatDocumentationIssuesAsErrors {
Paul Duffinb679bdd2024-06-10 14:29:41 +01001035 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffinbaf34782024-05-28 17:27:22 +01001036 }
1037
Colin Cross2207f872021-03-24 12:39:08 -07001038 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001039 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -07001040 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001041 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001042 if baselineFile.Valid() {
Jihoon Kang472f73f2024-03-28 20:59:29 +00001043 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001044 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
1045 }
Colin Cross2207f872021-03-24 12:39:08 -07001046 // Note this string includes quote ($' ... '), which decodes the "\n"s.
1047 msg := `$'\n******************************\n` +
1048 `You have tried to change the API from what has been previously released in\n` +
1049 `an SDK. Please fix the errors listed above.\n` +
1050 `******************************\n'`
1051
1052 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1053 }
1054
Paul Duffin10a23c22023-08-11 22:47:31 +01001055 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1056 // Pass the current API file into metalava so it can use it as the basis for determining how to
1057 // generate the output signature files (both api and removed).
1058 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1059 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1060 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001061}
Paul Duffin10a23c22023-08-11 22:47:31 +01001062
Paul Duffinb679bdd2024-06-10 14:29:41 +01001063// HIDDEN_DOCUMENTATION_ISSUES is the set of documentation related issues that should always be
1064// hidden as they are very noisy and provide little value.
1065var HIDDEN_DOCUMENTATION_ISSUES = []string{
1066 "Deprecated",
1067 "IntDef",
1068 "Nullable",
1069}
1070
1071func treatDocumentationIssuesAsWarningErrorWhenNew(cmd *android.RuleBuilderCommand) {
1072 // Treat documentation issues as warnings, but error when new.
1073 cmd.Flag("--error-when-new-category").Flag("Documentation")
1074
1075 // Hide some documentation issues that generated a lot of noise for little benefit.
1076 cmd.FlagForEachArg("--hide ", HIDDEN_DOCUMENTATION_ISSUES)
1077}
1078
Jihoon Kang3c89f042023-12-19 02:40:22 +00001079// Sandbox rule for generating exportable stubs and other artifacts
1080func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1081 optionalCmdParams := stubsCommandParams{
1082 stubConfig: params,
1083 }
1084
Jihoon Kang246690a2024-02-01 21:55:01 +00001085 if params.generateStubs {
1086 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1087 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1088 }
1089
Jihoon Kang3c89f042023-12-19 02:40:22 +00001090 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001091 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1092 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1093 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1094 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001095 }
1096
Jihoon Kanga11d6792024-03-05 16:12:20 +00001097 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001098 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001099 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1100 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001101 }
Jihoon Kangee113282024-01-23 00:16:41 +00001102 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1103 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001104 }
Jihoon Kanga11d6792024-03-05 16:12:20 +00001105 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +00001106 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1107 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001108 }
1109
1110 if params.checkApi || String(d.properties.Api_filename) != "" {
1111 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1112 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1113 }
1114
1115 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1116 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1117 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1118 }
1119
1120 d.optionalStubCmd(ctx, optionalCmdParams)
1121}
1122
1123func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1124
1125 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1126 rule := android.NewRuleBuilder(pctx, ctx)
1127 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1128 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1129 SandboxInputs()
1130
1131 if params.stubConfig.generateStubs {
1132 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1133 }
1134
1135 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1136
Jihoon Kang5d701272024-02-15 21:53:49 +00001137 generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001138
1139 if params.stubConfig.doApiLint {
1140 // Pass the lint baseline file as an input to resolve the lint errors.
1141 // The exportable stubs generation does not update the lint baseline file.
1142 // Lint baseline file update is handled by the everything stubs
1143 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1144 if baselineFile.Valid() {
1145 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1146 }
1147 }
1148
Paul Duffin71527b72024-05-31 13:30:32 +01001149 // Treat documentation issues as warnings, but error when new.
Paul Duffinb679bdd2024-06-10 14:29:41 +01001150 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffin71527b72024-05-31 13:30:32 +01001151
Jihoon Kang3c89f042023-12-19 02:40:22 +00001152 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001153 rule.Command().
1154 BuiltTool("soong_zip").
1155 Flag("-write_if_changed").
1156 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001157 FlagWithOutput("-o ", params.stubsSrcJar).
1158 FlagWithArg("-C ", params.stubsDir.String()).
1159 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001160 }
1161
Jihoon Kang3c89f042023-12-19 02:40:22 +00001162 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001163 rule.Command().
1164 BuiltTool("soong_zip").
1165 Flag("-write_if_changed").
1166 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001167 FlagWithOutput("-o ", params.metadataZip).
1168 FlagWithArg("-C ", params.metadataDir.String()).
1169 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001170 }
1171
Colin Cross6aa5c402021-03-24 12:28:50 -07001172 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001173 if !metalavaUseRbe(ctx) {
1174 rule.Restat()
1175 }
Colin Cross2207f872021-03-24 12:39:08 -07001176
Jihoon Kang3c89f042023-12-19 02:40:22 +00001177 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001178
Jihoon Kang3c89f042023-12-19 02:40:22 +00001179 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1180}
1181
1182func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1183 deps := d.Javadoc.collectDeps(ctx)
1184
1185 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1186 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1187
1188 // Add options for the other optional tasks: API-lint and check-released.
1189 // We generate separate timestamp files for them.
1190 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1191 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1192
1193 writeSdkValues := Bool(d.properties.Write_sdk_values)
1194
1195 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1196
1197 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1198 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1199 String(d.properties.Validate_nullability_from_list) != "")
1200
1201 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1202 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1203
1204 stubCmdParams := stubsCommandConfigParams{
Jihoon Kanga11d6792024-03-05 16:12:20 +00001205 javaVersion: javaVersion,
1206 deps: deps,
1207 checkApi: checkApi,
1208 generateStubs: generateStubs,
1209 doApiLint: doApiLint,
1210 doCheckReleased: doCheckReleased,
1211 writeSdkValues: writeSdkValues,
1212 migratingNullability: migratingNullability,
1213 validatingNullability: validatingNullability,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001214 }
1215 stubCmdParams.stubsType = Everything
1216 // Create default (i.e. "everything" stubs) rule for metalava
1217 d.everythingStubCmd(ctx, stubCmdParams)
1218
Jihoon Kangd40c5912024-03-05 16:12:20 +00001219 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001220 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1221 // strips all flagged apis to generate the "exportable" stubs
1222 stubCmdParams.stubsType = Exportable
1223 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001224
Paul Duffine7a86642022-08-16 15:43:20 +00001225 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1226
1227 if len(d.Javadoc.properties.Out) > 0 {
1228 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1229 }
1230
1231 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1232 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1233 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1234
1235 if baselineFile.Valid() {
1236 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1237 }
1238
Jihoon Kang3c89f042023-12-19 02:40:22 +00001239 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001240
1241 rule := android.NewRuleBuilder(pctx, ctx)
1242
1243 // Diff command line.
1244 // -F matches the closest "opening" line, such as "package android {"
1245 // and " public class Intent {".
1246 diff := `diff -u -F '{ *$'`
1247
1248 rule.Command().Text("( true")
1249 rule.Command().
1250 Text(diff).
1251 Input(apiFile).Input(d.apiFile)
1252
1253 rule.Command().
1254 Text(diff).
1255 Input(removedApiFile).Input(d.removedApiFile)
1256
1257 msg := fmt.Sprintf(`\n******************************\n`+
1258 `You have tried to change the API from what has been previously approved.\n\n`+
1259 `To make these errors go away, you have two choices:\n`+
1260 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1261 ` to the new methods, etc. shown in the above diff.\n\n`+
1262 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1263 ` m %s-update-current-api\n\n`+
1264 ` To submit the revised current.txt to the main Android repository,\n`+
1265 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001266 `If your build failed due to stub validation, you can resolve the errors with\n`+
1267 `either of the two choices above and try re-building the target.\n`+
1268 `If the mismatch between the stubs and the current.txt is intended,\n`+
1269 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001270 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1271 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001272 `******************************\n`, ctx.ModuleName())
1273
1274 rule.Command().
1275 Text("touch").Output(d.checkCurrentApiTimestamp).
1276 Text(") || (").
1277 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1278 Text("; exit 38").
1279 Text(")")
1280
1281 rule.Build("metalavaCurrentApiCheck", "check current API")
1282
Jihoon Kang3c89f042023-12-19 02:40:22 +00001283 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001284
1285 // update API rule
1286 rule = android.NewRuleBuilder(pctx, ctx)
1287
1288 rule.Command().Text("( true")
1289
1290 rule.Command().
1291 Text("cp").Flag("-f").
1292 Input(d.apiFile).Flag(apiFile.String())
1293
1294 rule.Command().
1295 Text("cp").Flag("-f").
1296 Input(d.removedApiFile).Flag(removedApiFile.String())
1297
1298 msg = "failed to update public API"
1299
1300 rule.Command().
1301 Text("touch").Output(d.updateCurrentApiTimestamp).
1302 Text(") || (").
1303 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1304 Text("; exit 38").
1305 Text(")")
1306
1307 rule.Build("metalavaCurrentApiUpdate", "update current API")
1308 }
1309
Colin Cross2207f872021-03-24 12:39:08 -07001310 if String(d.properties.Check_nullability_warnings) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001311 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001312 ctx.PropertyErrorf("check_nullability_warnings",
1313 "Cannot specify check_nullability_warnings unless validating nullability")
1314 }
1315
1316 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1317
Jihoon Kang3c89f042023-12-19 02:40:22 +00001318 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001319
1320 msg := fmt.Sprintf(`\n******************************\n`+
1321 `The warnings encountered during nullability annotation validation did\n`+
1322 `not match the checked in file of expected warnings. The diffs are shown\n`+
1323 `above. You have two options:\n`+
1324 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1325 ` 2. Update the file of expected warnings by running:\n`+
1326 ` cp %s %s\n`+
1327 ` and submitting the updated file as part of your change.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001328 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001329
1330 rule := android.NewRuleBuilder(pctx, ctx)
1331
1332 rule.Command().
1333 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001334 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001335 Text("&&").
1336 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1337 Text(") || (").
1338 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1339 Text("; exit 38").
1340 Text(")")
1341
1342 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1343 }
mrziwang39e68ff2024-07-01 16:35:32 -07001344
1345 d.setOutputFiles(ctx)
1346}
1347
1348// This method sets the outputFiles property, which is used to set the
1349// OutputFilesProvider later.
1350// Droidstubs' tag supports specifying with the stubs type.
1351// While supporting the pre-existing tags, it also supports tags with
1352// the stubs type prefix. Some examples are shown below:
1353// {.annotations.zip} - pre-existing behavior. Returns the path to the
1354// annotation zip.
1355// {.exportable} - Returns the path to the exportable stubs src jar.
1356// {.exportable.annotations.zip} - Returns the path to the exportable
1357// annotations zip file.
1358// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
1359// xml file. For unsupported combinations, the default everything output file
1360// is returned.
1361func (d *Droidstubs) setOutputFiles(ctx android.ModuleContext) {
1362 tagToOutputFileFunc := map[string]func(StubsType) (android.Path, error){
1363 "": d.StubsSrcJar,
1364 ".docs.zip": d.DocZip,
1365 ".api.txt": d.ApiFilePath,
1366 android.DefaultDistTag: d.ApiFilePath,
1367 ".removed-api.txt": d.RemovedApiFilePath,
1368 ".annotations.zip": d.AnnotationsZip,
1369 ".api_versions.xml": d.ApiVersionsXmlFilePath,
1370 }
1371 stubsTypeToPrefix := map[StubsType]string{
1372 Everything: "",
1373 Exportable: ".exportable",
1374 }
1375 for _, tag := range android.SortedKeys(tagToOutputFileFunc) {
1376 for _, stubType := range android.SortedKeys(stubsTypeToPrefix) {
1377 tagWithPrefix := stubsTypeToPrefix[stubType] + tag
1378 outputFile, err := tagToOutputFileFunc[tag](stubType)
Cole Faust5146e782024-11-15 14:47:49 -08001379 if err == nil && outputFile != nil {
mrziwang39e68ff2024-07-01 16:35:32 -07001380 ctx.SetOutputFiles(android.Paths{outputFile}, tagWithPrefix)
1381 }
1382 }
1383 }
Colin Cross2207f872021-03-24 12:39:08 -07001384}
1385
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001386func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1387 api_file := d.properties.Check_api.Current.Api_file
1388 api_surface := d.properties.Api_surface
1389
1390 props := struct {
1391 Name *string
1392 Api_surface *string
1393 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001394 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001395 }{}
1396
1397 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1398 props.Api_surface = api_surface
1399 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001400 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001401
1402 ctx.CreateModule(ApiContributionFactory, &props)
1403}
1404
Spandan Das0b555e32022-11-28 18:48:51 +00001405// TODO (b/262014796): Export the API contributions of CorePlatformApi
1406// A map to populate the api surface of a droidstub from a substring appearing in its name
1407// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1408// use a strict naming convention
1409var (
1410 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
Paul Duffin2ced2eb2024-05-01 13:13:51 +01001411 // public is commented out since the core libraries use public in their java_sdk_library names
Spandan Das0b555e32022-11-28 18:48:51 +00001412 "intracore": android.SdkIntraCore,
1413 "intra.core": android.SdkIntraCore,
1414 "system_server": android.SdkSystemServer,
1415 "system-server": android.SdkSystemServer,
1416 "system": android.SdkSystem,
1417 "module_lib": android.SdkModule,
1418 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001419 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001420 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001421 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001422 }
1423)
1424
Colin Cross2207f872021-03-24 12:39:08 -07001425func StubsDefaultsFactory() android.Module {
1426 module := &DocDefaults{}
1427
1428 module.AddProperties(
1429 &JavadocProperties{},
1430 &DroidstubsProperties{},
1431 )
1432
1433 android.InitDefaultsModule(module)
1434
1435 return module
1436}
1437
1438var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1439
1440type PrebuiltStubsSourcesProperties struct {
1441 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001442
1443 // Name of the source soong module that gets shadowed by this prebuilt
1444 // If unspecified, follows the naming convention that the source module of
1445 // the prebuilt is Name() without "prebuilt_" prefix
1446 Source_module_name *string
1447
1448 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1449 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1450 // (without any prebuilt_ prefix)
1451 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1452}
1453
1454func (j *PrebuiltStubsSources) BaseModuleName() string {
1455 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1456}
1457
1458func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1459 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001460}
1461
1462type PrebuiltStubsSources struct {
1463 android.ModuleBase
1464 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001465 embeddableInModuleAndImport
1466
Colin Cross2207f872021-03-24 12:39:08 -07001467 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001468
1469 properties PrebuiltStubsSourcesProperties
1470
kgui67007242022-01-25 13:50:25 +08001471 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001472}
1473
Jihoon Kangee113282024-01-23 00:16:41 +00001474func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1475 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001476}
1477
1478func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001479 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001480 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 -07001481 return
1482 }
1483
Anton Hansson86758ac2021-11-03 14:44:12 +00001484 src := p.properties.Srcs[0]
1485 if filepath.Ext(src) == ".srcjar" {
1486 // This is a srcjar. We can use it directly.
1487 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1488 } else {
1489 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001490
Anton Hansson86758ac2021-11-03 14:44:12 +00001491 // This is a directory. Glob the contents just in case the directory does not exist.
1492 srcGlob := src + "/**/*"
1493 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001494
Anton Hansson86758ac2021-11-03 14:44:12 +00001495 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1496 // the path components are invalid it won't in this case because no components
1497 // are specified and the module directory must exist in order to get this far.
1498 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001499
Anton Hansson86758ac2021-11-03 14:44:12 +00001500 rule := android.NewRuleBuilder(pctx, ctx)
1501 rule.Command().
1502 BuiltTool("soong_zip").
1503 Flag("-write_if_changed").
1504 Flag("-jar").
1505 FlagWithOutput("-o ", outPath).
1506 FlagWithArg("-C ", srcDir.String()).
1507 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1508 rule.Restat()
1509 rule.Build("zip src", "Create srcjar from prebuilt source")
1510 p.stubsSrcJar = outPath
1511 }
mrziwangaa2a2b62024-07-01 12:09:20 -07001512
1513 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, "")
1514 // prebuilt droidstubs does not output "exportable" stubs.
1515 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1516 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, ".exportable")
Colin Cross2207f872021-03-24 12:39:08 -07001517}
1518
1519func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1520 return &p.prebuilt
1521}
1522
1523func (p *PrebuiltStubsSources) Name() string {
1524 return p.prebuilt.Name(p.ModuleBase.Name())
1525}
1526
1527// prebuilt_stubs_sources imports a set of java source files as if they were
1528// generated by droidstubs.
1529//
1530// By default, a prebuilt_stubs_sources has a single variant that expects a
1531// set of `.java` files generated by droidstubs.
1532//
1533// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1534// for host modules.
1535//
1536// Intended only for use by sdk snapshots.
1537func PrebuiltStubsSourcesFactory() android.Module {
1538 module := &PrebuiltStubsSources{}
1539
1540 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001541 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001542
1543 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001544 InitDroiddocModule(module, android.HostAndDeviceSupported)
1545 return module
1546}