blob: f4bcaca15f38cd8a1aa2ad285839d346bffb1ab4 [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
LaMont Jonesafe7baf2024-01-09 22:47:39 +0000109 // Single aconfig "cache file" merged from this module and all dependencies.
110 mergedAconfigFiles map[string]android.Paths
111
Jihoon Kangee113282024-01-23 00:16:41 +0000112 exportableApiFile android.WritablePath
113 exportableRemovedApiFile android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -0700114}
115
116type DroidstubsProperties struct {
117 // The generated public API filename by Metalava, defaults to <module>_api.txt
118 Api_filename *string
119
120 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
121 Removed_api_filename *string
122
Colin Cross2207f872021-03-24 12:39:08 -0700123 Check_api struct {
124 Last_released ApiToCheck
125
126 Current ApiToCheck
127
128 Api_lint struct {
129 Enabled *bool
130
131 // If set, performs api_lint on any new APIs not found in the given signature file
132 New_since *string `android:"path"`
133
134 // If not blank, path to the baseline txt file for approved API lint violations.
135 Baseline_file *string `android:"path"`
136 }
137 }
138
139 // user can specify the version of previous released API file in order to do compatibility check.
140 Previous_api *string `android:"path"`
141
142 // is set to true, Metalava will allow framework SDK to contain annotations.
143 Annotations_enabled *bool
144
145 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
146 Merge_annotations_dirs []string
147
148 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
149 Merge_inclusion_annotations_dirs []string
150
151 // a file containing a list of classes to do nullability validation for.
152 Validate_nullability_from_list *string
153
154 // a file containing expected warnings produced by validation of nullability annotations.
155 Check_nullability_warnings *string
156
157 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
158 Create_doc_stubs *bool
159
160 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
161 // Has no effect if create_doc_stubs: true.
162 Output_javadoc_comments *bool
163
164 // if set to false then do not write out stubs. Defaults to true.
165 //
166 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
167 Generate_stubs *bool
168
169 // 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 -0400170 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700171 High_mem *bool
172
satayev783195c2021-06-23 21:49:57 +0100173 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700174 Api_levels_annotations_enabled *bool
175
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000176 // Apply the api levels database created by this module rather than generating one in this droidstubs.
177 Api_levels_module *string
178
Colin Cross2207f872021-03-24 12:39:08 -0700179 // the dirs which Metalava extracts API levels annotations from.
180 Api_levels_annotations_dirs []string
181
Cole Faust051fa912022-10-05 12:45:42 -0700182 // 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 +0100183 Api_levels_sdk_type *string
184
Colin Cross2207f872021-03-24 12:39:08 -0700185 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
186 Api_levels_jar_filename *string
187
188 // if set to true, collect the values used by the Dev tools and
189 // write them in files packaged with the SDK. Defaults to false.
190 Write_sdk_values *bool
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200191
192 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
193 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
194 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000195
196 // API surface of this module. If set, the module contributes to an API surface.
197 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
198 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000199
200 // a list of aconfig_declarations module names that the stubs generated in this module
201 // depend on.
202 Aconfig_declarations []string
Colin Cross2207f872021-03-24 12:39:08 -0700203}
204
Anton Hansson52609322021-05-05 10:36:05 +0100205// Used by xsd_config
206type ApiFilePath interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000207 ApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100208}
209
210type ApiStubsSrcProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000211 StubsSrcJar(StubsType) (android.Path, error)
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000212}
213
Anton Hansson52609322021-05-05 10:36:05 +0100214// Provider of information about API stubs, used by java_sdk_library.
215type ApiStubsProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000216 AnnotationsZip(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100217 ApiFilePath
Jihoon Kangee113282024-01-23 00:16:41 +0000218 RemovedApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100219
220 ApiStubsSrcProvider
221}
222
Jihoon Kang063ec002023-06-28 01:16:23 +0000223type currentApiTimestampProvider interface {
224 CurrentApiTimestamp() android.Path
225}
226
Jihoon Kang3c89f042023-12-19 02:40:22 +0000227type annotationFlagsParams struct {
228 migratingNullability bool
229 validatingNullability bool
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000230 extractAnnotations bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000231 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 Kang6b93b382024-01-26 22:37:41 +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
256 annotationsEnabled bool
257 apiLevelsAnnotationsEnabled bool
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000258 extractAnnotations bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000259}
260
Colin Cross2207f872021-03-24 12:39:08 -0700261// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
262// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
263// a droiddoc module to generate documentation.
264func DroidstubsFactory() android.Module {
265 module := &Droidstubs{}
266
267 module.AddProperties(&module.properties,
268 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000269 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700270
271 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000272
273 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
274 module.createApiContribution(ctx)
275 })
Colin Cross2207f872021-03-24 12:39:08 -0700276 return module
277}
278
279// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
280// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
281// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
282// module when symbols needed by the source files are provided by java_library_host modules.
283func DroidstubsHostFactory() android.Module {
284 module := &Droidstubs{}
285
286 module.AddProperties(&module.properties,
287 &module.Javadoc.properties)
288
289 InitDroiddocModule(module, android.HostSupported)
290 return module
291}
292
Jihoon Kang78f89142023-12-27 01:40:29 +0000293func getStubsTypeAndTag(tag string) (StubsType, string, error) {
294 if len(tag) == 0 {
295 return Everything, "", nil
296 }
297 if tag[0] != '.' {
298 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
299 }
300
301 stubsType := Everything
302 // Check if the tag has a stubs type prefix (e.g. ".exportable")
303 for st := Everything; st <= Exportable; st++ {
304 if strings.HasPrefix(tag, "."+st.String()) {
305 stubsType = st
306 }
307 }
308
309 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
310}
311
312// Droidstubs' tag supports specifying with the stubs type.
313// While supporting the pre-existing tags, it also supports tags with
314// the stubs type prefix. Some examples are shown below:
315// {.annotations.zip} - pre-existing behavior. Returns the path to the
316// annotation zip.
317// {.exportable} - Returns the path to the exportable stubs src jar.
318// {.exportable.annotations.zip} - Returns the path to the exportable
319// annotations zip file.
320// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
321// xml file. For unsupported combinations, the default everything output file
322// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700323func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000324 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
325 if err != nil {
326 return nil, err
327 }
328 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700329 case "":
Jihoon Kangee113282024-01-23 00:16:41 +0000330 stubsSrcJar, err := d.StubsSrcJar(stubsType)
331 return android.Paths{stubsSrcJar}, err
Colin Cross2207f872021-03-24 12:39:08 -0700332 case ".docs.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000333 docZip, err := d.DocZip(stubsType)
334 return android.Paths{docZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700335 case ".api.txt", android.DefaultDistTag:
336 // This is the default dist path for dist properties that have no tag property.
Jihoon Kangee113282024-01-23 00:16:41 +0000337 apiFilePath, err := d.ApiFilePath(stubsType)
338 return android.Paths{apiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700339 case ".removed-api.txt":
Jihoon Kangee113282024-01-23 00:16:41 +0000340 removedApiFilePath, err := d.RemovedApiFilePath(stubsType)
341 return android.Paths{removedApiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700342 case ".annotations.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000343 annotationsZip, err := d.AnnotationsZip(stubsType)
344 return android.Paths{annotationsZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700345 case ".api_versions.xml":
Jihoon Kangee113282024-01-23 00:16:41 +0000346 apiVersionsXmlFilePath, err := d.ApiVersionsXmlFilePath(stubsType)
347 return android.Paths{apiVersionsXmlFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700348 default:
349 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
350 }
351}
352
Jihoon Kang246690a2024-02-01 21:55:01 +0000353func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000354 switch stubsType {
355 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000356 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000357 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000358 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000359 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000360 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000361 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000362 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000363}
364
Jihoon Kang246690a2024-02-01 21:55:01 +0000365func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000366 switch stubsType {
367 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000368 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000369 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000370 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000371 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000372 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000373 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000374 if ret == nil && err == nil {
375 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
376 }
377 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000378}
379
Jihoon Kang246690a2024-02-01 21:55:01 +0000380func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000381 switch stubsType {
382 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000383 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000384 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000385 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000386 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000387 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 +0000388 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000389 if ret == nil && err == nil {
390 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
391 }
392 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000393}
394
Jihoon Kang246690a2024-02-01 21:55:01 +0000395func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000396 switch stubsType {
397 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000398 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000399 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000400 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000401 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000402 if ret == nil && err == nil {
403 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
404 }
405 return ret, err
406}
407
408func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
409 switch stubsType {
410 case Everything:
411 ret, err = d.removedApiFile, nil
412 case Exportable:
413 ret, err = d.exportableRemovedApiFile, nil
414 default:
415 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
416 }
417 if ret == nil && err == nil {
418 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
419 }
420 return ret, err
421}
422
423func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
424 switch stubsType {
425 case Everything:
426 ret, err = d.stubsSrcJar, nil
427 case Exportable:
428 ret, err = d.exportableStubsSrcJar, nil
429 default:
430 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
431 }
432 if ret == nil && err == nil {
433 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
434 }
435 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000436}
437
Jihoon Kang063ec002023-06-28 01:16:23 +0000438func (d *Droidstubs) CurrentApiTimestamp() android.Path {
439 return d.checkCurrentApiTimestamp
440}
441
Colin Cross2207f872021-03-24 12:39:08 -0700442var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
443var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
444var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000445var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000446var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700447
448func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
449 d.Javadoc.addDeps(ctx)
450
451 if len(d.properties.Merge_annotations_dirs) != 0 {
452 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
453 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
454 }
455 }
456
457 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
458 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
459 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
460 }
461 }
462
463 if len(d.properties.Api_levels_annotations_dirs) != 0 {
464 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
465 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
466 }
467 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000468
Jihoon Kang6592e872023-12-19 01:13:16 +0000469 if len(d.properties.Aconfig_declarations) != 0 {
470 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
471 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
472 }
473 }
474
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000475 if d.properties.Api_levels_module != nil {
476 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
477 }
Colin Cross2207f872021-03-24 12:39:08 -0700478}
479
Jihoon Kang3c89f042023-12-19 02:40:22 +0000480func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
481 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
482}
483
484func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
485 if checkApi || String(d.properties.Api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700486 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000487 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000488 cmd.FlagWithOutput("--api ", uncheckedApiFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000489
490 if stubsType == Everything {
491 d.apiFile = uncheckedApiFile
492 } else if stubsType == Exportable {
493 d.exportableApiFile = uncheckedApiFile
494 }
Colin Cross2207f872021-03-24 12:39:08 -0700495 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
496 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000497 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700498 }
499
Jihoon Kang3c89f042023-12-19 02:40:22 +0000500 if checkApi || String(d.properties.Removed_api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700501 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000502 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000503 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000504
505 if stubsType == Everything {
506 d.removedApiFile = uncheckedRemovedFile
507 } else if stubsType == Exportable {
508 d.exportableRemovedApiFile = uncheckedRemovedFile
509 }
Colin Cross2207f872021-03-24 12:39:08 -0700510 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
511 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000512 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700513 }
514
Colin Cross2207f872021-03-24 12:39:08 -0700515 if stubsDir.Valid() {
516 if Bool(d.properties.Create_doc_stubs) {
517 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
518 } else {
519 cmd.FlagWithArg("--stubs ", stubsDir.String())
520 if !Bool(d.properties.Output_javadoc_comments) {
521 cmd.Flag("--exclude-documentation-from-stubs")
522 }
523 }
524 }
525}
526
Jihoon Kang3c89f042023-12-19 02:40:22 +0000527func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kang6b93b382024-01-26 22:37:41 +0000528 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100529
Jihoon Kang6b93b382024-01-26 22:37:41 +0000530 if params.migratingNullability {
531 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
532 cmd.FlagWithInput("--migrate-nullness ", previousApi)
Colin Cross2207f872021-03-24 12:39:08 -0700533 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000534
535 if s := String(d.properties.Validate_nullability_from_list); s != "" {
536 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
537 }
538
539 if params.validatingNullability {
540 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
541 }
542
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000543 if params.extractAnnotations {
544 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
545 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000546
547 if len(d.properties.Merge_annotations_dirs) != 0 {
548 d.mergeAnnoDirFlags(ctx, cmd)
549 }
550
551 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700552}
553
554func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
555 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
556 if t, ok := m.(*ExportedDroiddocDir); ok {
557 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
558 } else {
559 ctx.PropertyErrorf("merge_annotations_dirs",
560 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
561 }
562 })
563}
564
565func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
566 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
567 if t, ok := m.(*ExportedDroiddocDir); ok {
568 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
569 } else {
570 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
571 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
572 }
573 })
574}
575
Jihoon Kang6b93b382024-01-26 22:37:41 +0000576func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params stubsCommandParams) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000577 var apiVersions android.Path
Jihoon Kang6b93b382024-01-26 22:37:41 +0000578 stubsType := params.stubConfig.stubsType
579 apiVersionsXml := params.apiVersionsXml
580 if params.stubConfig.apiLevelsAnnotationsEnabled {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000581 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000582 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000583 } else {
584 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
585 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000586 if stubsType == Everything {
587 apiVersions = s.everythingArtifacts.apiVersionsXml
588 } else if stubsType == Exportable {
589 apiVersions = s.exportableArtifacts.apiVersionsXml
590 } else {
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000591 // if the stubs type does not generate api-versions.xml file, default to using the
592 // everything artifacts
593 apiVersions = s.everythingArtifacts.apiVersionsXml
Jihoon Kangd9a06942024-01-26 01:49:20 +0000594 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000595 } else {
596 ctx.PropertyErrorf("api_levels_module",
597 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
598 }
599 })
Colin Cross2207f872021-03-24 12:39:08 -0700600 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000601 if apiVersions != nil {
602 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
603 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
604 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
605 }
606}
Colin Cross2207f872021-03-24 12:39:08 -0700607
Jihoon Kang3c89f042023-12-19 02:40:22 +0000608func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700609 if len(d.properties.Api_levels_annotations_dirs) == 0 {
610 ctx.PropertyErrorf("api_levels_annotations_dirs",
611 "has to be non-empty if api levels annotations was enabled!")
612 }
613
Jihoon Kang3c89f042023-12-19 02:40:22 +0000614 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700615
616 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
617
satayev783195c2021-06-23 21:49:57 +0100618 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200619 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700620 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
621 if t, ok := m.(*ExportedDroiddocDir); ok {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200622 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
623
624 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
625 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700626 for _, dep := range t.deps {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200627 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
628 if extensions_dir == "" {
629 extensions_dir = t.dir.String() + "/extensions"
630 }
631 cmd.Implicit(dep)
632 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700633 if dep.Base() == filename {
634 cmd.Implicit(dep)
635 }
636 if filename != "android.jar" && dep.Base() == "android.jar" {
637 // Metalava implicitly searches these patterns:
638 // prebuilts/tools/common/api-versions/android-%/android.jar
639 // prebuilts/sdk/%/public/android.jar
640 // Add android.jar files from the api_levels_annotations_dirs directories to try
641 // to satisfy these patterns. If Metalava can't find a match for an API level
642 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700643 cmd.Implicit(dep)
644 }
645 }
satayev783195c2021-06-23 21:49:57 +0100646
647 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700648 } else {
649 ctx.PropertyErrorf("api_levels_annotations_dirs",
650 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
651 }
652 })
satayev783195c2021-06-23 21:49:57 +0100653
654 // Add all relevant --android-jar-pattern patterns for Metalava.
655 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
656 // an actual file present on disk (in the order the patterns were passed). For system APIs for
657 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000658 // for older releases. Similarly, module-lib falls back to system API.
659 var sdkDirs []string
660 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700661 case "system-server":
662 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000663 case "module-lib":
664 sdkDirs = []string{"module-lib", "system", "public"}
665 case "system":
666 sdkDirs = []string{"system", "public"}
667 case "public":
668 sdkDirs = []string{"public"}
669 default:
670 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
671 return
satayev783195c2021-06-23 21:49:57 +0100672 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000673
674 for _, sdkDir := range sdkDirs {
675 for _, dir := range dirs {
676 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
677 }
satayev783195c2021-06-23 21:49:57 +0100678 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200679
680 if d.properties.Extensions_info_file != nil {
681 if extensions_dir == "" {
682 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
683 }
684 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
685 cmd.Implicit(info_file)
686 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
687 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
688 }
Colin Cross2207f872021-03-24 12:39:08 -0700689}
690
Colin Crosse52c2ac2022-03-28 17:03:35 -0700691func metalavaUseRbe(ctx android.ModuleContext) bool {
692 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
693}
694
Colin Cross2207f872021-03-24 12:39:08 -0700695func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100696 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700697 rule.Command().Text("rm -rf").Flag(homeDir.String())
698 rule.Command().Text("mkdir -p").Flag(homeDir.String())
699
Anton Hansson556e8142021-06-04 16:20:25 +0100700 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700701 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
702
Colin Crosse52c2ac2022-03-28 17:03:35 -0700703 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700704 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700705 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000706 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
707 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700708 labels := map[string]string{"type": "tool", "name": "metalava"}
709 // TODO: metalava pool rejects these jobs
710 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
711 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000712 Labels: labels,
713 ExecStrategy: execStrategy,
714 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
715 Platform: map[string]string{remoteexec.PoolKey: pool},
716 Compare: compare,
717 NumLocalRuns: 1,
718 NumRemoteRuns: 1,
719 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700720 })
Colin Cross2207f872021-03-24 12:39:08 -0700721 }
722
Colin Cross6aa5c402021-03-24 12:28:50 -0700723 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700724 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400725 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100726 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700727 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
728 FlagWithInput("@", srcJarList)
729
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100730 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
731 // years, so it is unlikely to change any time soon.
732 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
733 combinedPaths = append(combinedPaths, classpath.Paths()...)
734 if len(combinedPaths) > 0 {
735 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700736 }
737
Liz Kammere09e20e2023-10-16 15:07:54 -0400738 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000739
Colin Cross2207f872021-03-24 12:39:08 -0700740 return cmd
741}
742
Jihoon Kang3c89f042023-12-19 02:40:22 +0000743// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
744// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
745// property is defined, apply transformations and only revert the flagged apis that are not
746// enabled via release configurations and are not specified in aconfig_declarations
Jihoon Kang5d701272024-02-15 21:53:49 +0000747func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000748
749 if len(aconfigFlagsPaths) == 0 {
750 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
751 return
752 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000753
754 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
755 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
756
757 var filterArgs string
758 switch stubsType {
759 // No flagged apis specific flags need to be passed to metalava when generating
760 // everything stubs
761 case Everything:
762 return
763
764 case Runtime:
765 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
766
767 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000768 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
769 // the flagged apis that have read_write permissions are exposed on top of the enabled
770 // and read_only apis. This is to support local override of flag values at runtime.
771 if ctx.Config().ReleaseExportRuntimeApis() {
772 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
773 } else {
774 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
775 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000776 }
777
778 ctx.Build(pctx, android.BuildParams{
779 Rule: gatherReleasedFlaggedApisRule,
780 Inputs: aconfigFlagsPaths,
781 Output: releasedFlaggedApisFile,
782 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
783 Args: map[string]string{
784 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
785 "filter_args": filterArgs,
786 },
787 })
788
789 ctx.Build(pctx, android.BuildParams{
790 Rule: generateMetalavaRevertAnnotationsRule,
791 Input: releasedFlaggedApisFile,
792 Output: revertAnnotationsFile,
793 Description: fmt.Sprintf("%s revert annotations", stubsType),
794 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000795
796 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000797}
798
Jihoon Kang3c89f042023-12-19 02:40:22 +0000799func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
800 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700801 if BoolDefault(d.properties.High_mem, false) {
802 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
803 rule.HighMem()
804 }
805
Jihoon Kang3c89f042023-12-19 02:40:22 +0000806 if params.stubConfig.generateStubs {
807 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
808 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700809 }
810
Jihoon Kang3c89f042023-12-19 02:40:22 +0000811 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700812
Jihoon Kang3c89f042023-12-19 02:40:22 +0000813 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
814 cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
815 params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
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,
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000827 extractAnnotations: params.stubConfig.extractAnnotations,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000828 nullabilityWarningsFile: params.nullabilityWarningsFile,
829 annotationsZip: params.annotationsZip,
830 }
831
Jihoon Kang6b93b382024-01-26 22:37:41 +0000832 if params.stubConfig.annotationsEnabled {
833 d.annotationsFlags(ctx, cmd, annotationParams)
834 }
Colin Cross2207f872021-03-24 12:39:08 -0700835 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000836 d.apiLevelsAnnotationsFlags(ctx, cmd, params)
Colin Cross2207f872021-03-24 12:39:08 -0700837
Colin Crossbc139922021-03-25 18:33:16 -0700838 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700839
Colin Cross2207f872021-03-24 12:39:08 -0700840 for _, o := range d.Javadoc.properties.Out {
841 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
842 }
843
Jihoon Kang3c89f042023-12-19 02:40:22 +0000844 return cmd
845}
Colin Cross2207f872021-03-24 12:39:08 -0700846
Jihoon Kang3c89f042023-12-19 02:40:22 +0000847// Sandbox rule for generating the everything stubs and other artifacts
848func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
849 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
850 rule := android.NewRuleBuilder(pctx, ctx)
851 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
852 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
853 SandboxInputs()
854
855 var stubsDir android.OptionalPath
856 if params.generateStubs {
857 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
858 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
859 }
860
861 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000862 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
863 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000864 }
865
Jihoon Kang6b93b382024-01-26 22:37:41 +0000866 if params.annotationsEnabled {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000867 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000868 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000869 }
Jihoon Kangee113282024-01-23 00:16:41 +0000870 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000871 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000872 if params.apiLevelsAnnotationsEnabled {
Jihoon Kangee113282024-01-23 00:16:41 +0000873 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000874 }
875
876 commonCmdParams := stubsCommandParams{
877 srcJarDir: srcJarDir,
878 stubsDir: stubsDir,
879 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000880 metadataDir: d.everythingArtifacts.metadataDir,
881 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
882 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
883 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000884 stubConfig: params,
885 }
886
887 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
888
889 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
890
891 if params.generateStubs {
892 rule.Command().
893 BuiltTool("soong_zip").
894 Flag("-write_if_changed").
895 Flag("-jar").
896 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
897 FlagWithArg("-C ", stubsDir.String()).
898 FlagWithArg("-D ", stubsDir.String())
899 }
900
901 if params.writeSdkValues {
902 rule.Command().
903 BuiltTool("soong_zip").
904 Flag("-write_if_changed").
905 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000906 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
907 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
908 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000909 }
910
911 // TODO: We don't really need two separate API files, but this is a reminiscence of how
912 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
913 if params.doApiLint {
914 rule.Command().Text("touch").Output(d.apiLintTimestamp)
915 }
916 if params.doCheckReleased {
917 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
918 }
919
920 // TODO(b/183630617): rewrapper doesn't support restat rules
921 if !metalavaUseRbe(ctx) {
922 rule.Restat()
923 }
924
925 zipSyncCleanupCmd(rule, srcJarDir)
926
927 rule.Build("metalava", "metalava merged")
928}
929
930// Sandbox rule for generating the everything artifacts that are not run by
931// default but only run based on the module configurations
932func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700933
934 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000935 if doApiLint {
Colin Cross2207f872021-03-24 12:39:08 -0700936 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
937 if newSince.Valid() {
938 cmd.FlagWithInput("--api-lint ", newSince.Path())
939 } else {
940 cmd.Flag("--api-lint")
941 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000942 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700943 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
944
Colin Cross0d532412021-03-25 09:38:45 -0700945 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700946 if d.Name() != "android.car-system-stubs-docs" &&
947 d.Name() != "android.car-stubs-docs" {
948 cmd.Flag("--lints-as-errors")
949 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
950 }
951
952 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000953 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
954 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700955
956 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700957 //
958 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
959 // message and metalava's one?
960 msg := `$'` + // Enclose with $' ... '
961 `************************************************************\n` +
962 `Your API changes are triggering API Lint warnings or errors.\n` +
963 `To make these errors go away, fix the code according to the\n` +
964 `error and/or warning messages above.\n` +
965 `\n` +
966 `If it is not possible to do so, there are workarounds:\n` +
967 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000968 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
969 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700970
971 if baselineFile.Valid() {
972 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
973 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
974
975 msg += fmt.Sprintf(``+
976 `2. You can update the baseline by executing the following\n`+
977 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700978 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
979 ` "%s" \\\n`+
980 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700981 ` To submit the revised baseline.txt to the main Android\n`+
982 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
983 } else {
984 msg += fmt.Sprintf(``+
985 `2. You can add a baseline file of existing lint failures\n`+
986 ` to the build rule of %s.\n`, d.Name())
987 }
988 // Note the message ends with a ' (single quote), to close the $' ... ' .
989 msg += `************************************************************\n'`
990
991 cmd.FlagWithArg("--error-message:api-lint ", msg)
992 }
993
994 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000995 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -0700996 if len(d.Javadoc.properties.Out) > 0 {
997 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
998 }
999
1000 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
1001 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
1002 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001003 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001004
Jihoon Kang3c89f042023-12-19 02:40:22 +00001005 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001006
1007 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
1008 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
1009
1010 if baselineFile.Valid() {
1011 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
1012 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
1013 }
1014
1015 // Note this string includes quote ($' ... '), which decodes the "\n"s.
1016 msg := `$'\n******************************\n` +
1017 `You have tried to change the API from what has been previously released in\n` +
1018 `an SDK. Please fix the errors listed above.\n` +
1019 `******************************\n'`
1020
1021 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1022 }
1023
Paul Duffin10a23c22023-08-11 22:47:31 +01001024 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1025 // Pass the current API file into metalava so it can use it as the basis for determining how to
1026 // generate the output signature files (both api and removed).
1027 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1028 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1029 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001030}
Paul Duffin10a23c22023-08-11 22:47:31 +01001031
Jihoon Kang3c89f042023-12-19 02:40:22 +00001032// Sandbox rule for generating exportable stubs and other artifacts
1033func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1034 optionalCmdParams := stubsCommandParams{
1035 stubConfig: params,
1036 }
1037
Jihoon Kang246690a2024-02-01 21:55:01 +00001038 if params.generateStubs {
1039 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1040 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1041 }
1042
Jihoon Kang3c89f042023-12-19 02:40:22 +00001043 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001044 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1045 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1046 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1047 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001048 }
1049
Jihoon Kang6b93b382024-01-26 22:37:41 +00001050 if params.annotationsEnabled {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001051 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001052 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1053 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001054 }
Jihoon Kangee113282024-01-23 00:16:41 +00001055 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1056 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001057 }
Jihoon Kang6b93b382024-01-26 22:37:41 +00001058 if params.apiLevelsAnnotationsEnabled {
Jihoon Kangee113282024-01-23 00:16:41 +00001059 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1060 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001061 }
1062
1063 if params.checkApi || String(d.properties.Api_filename) != "" {
1064 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1065 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1066 }
1067
1068 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1069 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1070 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1071 }
1072
1073 d.optionalStubCmd(ctx, optionalCmdParams)
1074}
1075
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001076// Sandbox rule for generating runtime stubs
1077func (d *Droidstubs) runtimeStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1078
1079 // We are only interested in generating the stubs srcjar,
1080 // not other artifacts for the runtime stubs
1081 params.checkApi = false
1082 params.writeSdkValues = false
1083 params.validatingNullability = false
1084 params.extractAnnotations = false
1085 params.apiLevelsAnnotationsEnabled = false
1086
1087 optionalCmdParams := stubsCommandParams{
1088 stubConfig: params,
1089 }
1090
1091 d.Javadoc.runtimeStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1092 optionalCmdParams.stubsSrcJar = d.Javadoc.runtimeStubsSrcJar
1093
1094 // If aconfig_declarations property is not defined, all flagged apis symbols are stripped
1095 // as no aconfig flags are enabled. In such case, the runtime stubs are identical to the
1096 // exportable stubs, thus no additional metalava invocation is needed.
1097 if len(d.properties.Aconfig_declarations) == 0 {
1098 rule := android.NewRuleBuilder(pctx, ctx)
1099 rule.Command().
1100 Text("cp").Flag("-f").
1101 Input(d.exportableStubsSrcJar).Output(d.runtimeStubsSrcJar)
1102 rule.Build(fmt.Sprintf("metalava_%s", params.stubsType.String()), "metalava merged")
1103 } else {
1104 d.optionalStubCmd(ctx, optionalCmdParams)
1105 }
1106}
1107
Jihoon Kang3c89f042023-12-19 02:40:22 +00001108func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1109
1110 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1111 rule := android.NewRuleBuilder(pctx, ctx)
1112 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1113 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1114 SandboxInputs()
1115
1116 if params.stubConfig.generateStubs {
1117 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1118 }
1119
1120 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1121
Jihoon Kang5d701272024-02-15 21:53:49 +00001122 generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001123
1124 if params.stubConfig.doApiLint {
1125 // Pass the lint baseline file as an input to resolve the lint errors.
1126 // The exportable stubs generation does not update the lint baseline file.
1127 // Lint baseline file update is handled by the everything stubs
1128 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1129 if baselineFile.Valid() {
1130 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1131 }
1132 }
1133
1134 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001135 rule.Command().
1136 BuiltTool("soong_zip").
1137 Flag("-write_if_changed").
1138 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001139 FlagWithOutput("-o ", params.stubsSrcJar).
1140 FlagWithArg("-C ", params.stubsDir.String()).
1141 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001142 }
1143
Jihoon Kang3c89f042023-12-19 02:40:22 +00001144 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001145 rule.Command().
1146 BuiltTool("soong_zip").
1147 Flag("-write_if_changed").
1148 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001149 FlagWithOutput("-o ", params.metadataZip).
1150 FlagWithArg("-C ", params.metadataDir.String()).
1151 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001152 }
1153
Colin Cross6aa5c402021-03-24 12:28:50 -07001154 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001155 if !metalavaUseRbe(ctx) {
1156 rule.Restat()
1157 }
Colin Cross2207f872021-03-24 12:39:08 -07001158
Jihoon Kang3c89f042023-12-19 02:40:22 +00001159 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001160
Jihoon Kang3c89f042023-12-19 02:40:22 +00001161 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1162}
1163
1164func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1165 deps := d.Javadoc.collectDeps(ctx)
1166
1167 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1168 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1169
1170 // Add options for the other optional tasks: API-lint and check-released.
1171 // We generate separate timestamp files for them.
1172 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1173 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1174
1175 writeSdkValues := Bool(d.properties.Write_sdk_values)
1176
1177 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1178
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001179 extractAnnotations := annotationsEnabled
1180
Jihoon Kang3c89f042023-12-19 02:40:22 +00001181 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1182 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1183 String(d.properties.Validate_nullability_from_list) != "")
1184
1185 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1186 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1187
Jihoon Kang6b93b382024-01-26 22:37:41 +00001188 apiLevelsAnnotationsEnabled := proptools.Bool(d.properties.Api_levels_annotations_enabled)
1189
Jihoon Kang3c89f042023-12-19 02:40:22 +00001190 stubCmdParams := stubsCommandConfigParams{
Jihoon Kang6b93b382024-01-26 22:37:41 +00001191 javaVersion: javaVersion,
1192 deps: deps,
1193 checkApi: checkApi,
1194 generateStubs: generateStubs,
1195 doApiLint: doApiLint,
1196 doCheckReleased: doCheckReleased,
1197 writeSdkValues: writeSdkValues,
1198 migratingNullability: migratingNullability,
1199 validatingNullability: validatingNullability,
1200 annotationsEnabled: annotationsEnabled,
1201 apiLevelsAnnotationsEnabled: apiLevelsAnnotationsEnabled,
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001202 extractAnnotations: extractAnnotations,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001203 }
1204 stubCmdParams.stubsType = Everything
1205 // Create default (i.e. "everything" stubs) rule for metalava
1206 d.everythingStubCmd(ctx, stubCmdParams)
1207
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001208 // The module generates "exportable" stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001209 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1210 // strips all flagged apis to generate the "exportable" stubs
1211 stubCmdParams.stubsType = Exportable
1212 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001213
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001214 // "runtime" stubs do not generate any other artifacts than the stubs.
1215 // Therefore, metalava does not have to run for "runtime" configuration
1216 // when the module does not generate stubs.
1217 if stubCmdParams.generateStubs {
1218 stubCmdParams.stubsType = Runtime
1219 d.runtimeStubCmd(ctx, stubCmdParams)
1220 }
1221
Paul Duffine7a86642022-08-16 15:43:20 +00001222 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1223
1224 if len(d.Javadoc.properties.Out) > 0 {
1225 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1226 }
1227
1228 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1229 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1230 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1231
1232 if baselineFile.Valid() {
1233 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1234 }
1235
Jihoon Kang3c89f042023-12-19 02:40:22 +00001236 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001237
1238 rule := android.NewRuleBuilder(pctx, ctx)
1239
1240 // Diff command line.
1241 // -F matches the closest "opening" line, such as "package android {"
1242 // and " public class Intent {".
1243 diff := `diff -u -F '{ *$'`
1244
1245 rule.Command().Text("( true")
1246 rule.Command().
1247 Text(diff).
1248 Input(apiFile).Input(d.apiFile)
1249
1250 rule.Command().
1251 Text(diff).
1252 Input(removedApiFile).Input(d.removedApiFile)
1253
1254 msg := fmt.Sprintf(`\n******************************\n`+
1255 `You have tried to change the API from what has been previously approved.\n\n`+
1256 `To make these errors go away, you have two choices:\n`+
1257 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1258 ` to the new methods, etc. shown in the above diff.\n\n`+
1259 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1260 ` m %s-update-current-api\n\n`+
1261 ` To submit the revised current.txt to the main Android repository,\n`+
1262 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001263 `If your build failed due to stub validation, you can resolve the errors with\n`+
1264 `either of the two choices above and try re-building the target.\n`+
1265 `If the mismatch between the stubs and the current.txt is intended,\n`+
1266 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001267 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1268 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001269 `******************************\n`, ctx.ModuleName())
1270
1271 rule.Command().
1272 Text("touch").Output(d.checkCurrentApiTimestamp).
1273 Text(") || (").
1274 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1275 Text("; exit 38").
1276 Text(")")
1277
1278 rule.Build("metalavaCurrentApiCheck", "check current API")
1279
Jihoon Kang3c89f042023-12-19 02:40:22 +00001280 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001281
1282 // update API rule
1283 rule = android.NewRuleBuilder(pctx, ctx)
1284
1285 rule.Command().Text("( true")
1286
1287 rule.Command().
1288 Text("cp").Flag("-f").
1289 Input(d.apiFile).Flag(apiFile.String())
1290
1291 rule.Command().
1292 Text("cp").Flag("-f").
1293 Input(d.removedApiFile).Flag(removedApiFile.String())
1294
1295 msg = "failed to update public API"
1296
1297 rule.Command().
1298 Text("touch").Output(d.updateCurrentApiTimestamp).
1299 Text(") || (").
1300 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1301 Text("; exit 38").
1302 Text(")")
1303
1304 rule.Build("metalavaCurrentApiUpdate", "update current API")
1305 }
1306
Colin Cross2207f872021-03-24 12:39:08 -07001307 if String(d.properties.Check_nullability_warnings) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001308 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001309 ctx.PropertyErrorf("check_nullability_warnings",
1310 "Cannot specify check_nullability_warnings unless validating nullability")
1311 }
1312
1313 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1314
Jihoon Kang3c89f042023-12-19 02:40:22 +00001315 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001316
1317 msg := fmt.Sprintf(`\n******************************\n`+
1318 `The warnings encountered during nullability annotation validation did\n`+
1319 `not match the checked in file of expected warnings. The diffs are shown\n`+
1320 `above. You have two options:\n`+
1321 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1322 ` 2. Update the file of expected warnings by running:\n`+
1323 ` cp %s %s\n`+
1324 ` and submitting the updated file as part of your change.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001325 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001326
1327 rule := android.NewRuleBuilder(pctx, ctx)
1328
1329 rule.Command().
1330 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001331 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001332 Text("&&").
1333 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1334 Text(") || (").
1335 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1336 Text("; exit 38").
1337 Text(")")
1338
1339 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1340 }
LaMont Jonesafe7baf2024-01-09 22:47:39 +00001341 android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
Colin Cross2207f872021-03-24 12:39:08 -07001342}
1343
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001344func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1345 api_file := d.properties.Check_api.Current.Api_file
1346 api_surface := d.properties.Api_surface
1347
1348 props := struct {
1349 Name *string
1350 Api_surface *string
1351 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001352 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001353 }{}
1354
1355 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1356 props.Api_surface = api_surface
1357 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001358 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001359
1360 ctx.CreateModule(ApiContributionFactory, &props)
1361}
1362
Spandan Das0b555e32022-11-28 18:48:51 +00001363// TODO (b/262014796): Export the API contributions of CorePlatformApi
1364// A map to populate the api surface of a droidstub from a substring appearing in its name
1365// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1366// use a strict naming convention
1367var (
1368 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
1369 //public is commented out since the core libraries use public in their java_sdk_library names
1370 "intracore": android.SdkIntraCore,
1371 "intra.core": android.SdkIntraCore,
1372 "system_server": android.SdkSystemServer,
1373 "system-server": android.SdkSystemServer,
1374 "system": android.SdkSystem,
1375 "module_lib": android.SdkModule,
1376 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001377 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001378 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001379 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001380 }
1381)
1382
Colin Cross2207f872021-03-24 12:39:08 -07001383func StubsDefaultsFactory() android.Module {
1384 module := &DocDefaults{}
1385
1386 module.AddProperties(
1387 &JavadocProperties{},
1388 &DroidstubsProperties{},
1389 )
1390
1391 android.InitDefaultsModule(module)
1392
1393 return module
1394}
1395
1396var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1397
1398type PrebuiltStubsSourcesProperties struct {
1399 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001400
1401 // Name of the source soong module that gets shadowed by this prebuilt
1402 // If unspecified, follows the naming convention that the source module of
1403 // the prebuilt is Name() without "prebuilt_" prefix
1404 Source_module_name *string
1405
1406 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1407 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1408 // (without any prebuilt_ prefix)
1409 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1410}
1411
1412func (j *PrebuiltStubsSources) BaseModuleName() string {
1413 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1414}
1415
1416func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1417 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001418}
1419
1420type PrebuiltStubsSources struct {
1421 android.ModuleBase
1422 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001423 embeddableInModuleAndImport
1424
Colin Cross2207f872021-03-24 12:39:08 -07001425 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001426
1427 properties PrebuiltStubsSourcesProperties
1428
kgui67007242022-01-25 13:50:25 +08001429 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001430}
1431
1432func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1433 switch tag {
Jihoon Kangfa4a90d2023-12-20 02:53:38 +00001434 // prebuilt droidstubs does not output "exportable" stubs.
1435 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1436 case "", ".exportable":
Colin Cross2207f872021-03-24 12:39:08 -07001437 return android.Paths{p.stubsSrcJar}, nil
1438 default:
1439 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1440 }
1441}
1442
Jihoon Kangee113282024-01-23 00:16:41 +00001443func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1444 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001445}
1446
1447func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001448 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001449 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 -07001450 return
1451 }
1452
Anton Hansson86758ac2021-11-03 14:44:12 +00001453 src := p.properties.Srcs[0]
1454 if filepath.Ext(src) == ".srcjar" {
1455 // This is a srcjar. We can use it directly.
1456 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1457 } else {
1458 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001459
Anton Hansson86758ac2021-11-03 14:44:12 +00001460 // This is a directory. Glob the contents just in case the directory does not exist.
1461 srcGlob := src + "/**/*"
1462 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001463
Anton Hansson86758ac2021-11-03 14:44:12 +00001464 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1465 // the path components are invalid it won't in this case because no components
1466 // are specified and the module directory must exist in order to get this far.
1467 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001468
Anton Hansson86758ac2021-11-03 14:44:12 +00001469 rule := android.NewRuleBuilder(pctx, ctx)
1470 rule.Command().
1471 BuiltTool("soong_zip").
1472 Flag("-write_if_changed").
1473 Flag("-jar").
1474 FlagWithOutput("-o ", outPath).
1475 FlagWithArg("-C ", srcDir.String()).
1476 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1477 rule.Restat()
1478 rule.Build("zip src", "Create srcjar from prebuilt source")
1479 p.stubsSrcJar = outPath
1480 }
Colin Cross2207f872021-03-24 12:39:08 -07001481}
1482
1483func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1484 return &p.prebuilt
1485}
1486
1487func (p *PrebuiltStubsSources) Name() string {
1488 return p.prebuilt.Name(p.ModuleBase.Name())
1489}
1490
1491// prebuilt_stubs_sources imports a set of java source files as if they were
1492// generated by droidstubs.
1493//
1494// By default, a prebuilt_stubs_sources has a single variant that expects a
1495// set of `.java` files generated by droidstubs.
1496//
1497// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1498// for host modules.
1499//
1500// Intended only for use by sdk snapshots.
1501func PrebuiltStubsSourcesFactory() android.Module {
1502 module := &PrebuiltStubsSources{}
1503
1504 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001505 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001506
1507 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001508 InitDroiddocModule(module, android.HostAndDeviceSupported)
1509 return module
1510}