blob: c839dbaaa7d9c391833fc66a744ade5e34a027f6 [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
39)
40
41func (s StubsType) String() string {
42 switch s {
43 case Everything:
44 return "everything"
45 case Runtime:
46 return "runtime"
47 case Exportable:
48 return "exportable"
49 default:
50 return ""
51 }
52}
53
Colin Cross2207f872021-03-24 12:39:08 -070054func init() {
55 RegisterStubsBuildComponents(android.InitRegistrationContext)
56}
57
58func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
59 ctx.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
60
61 ctx.RegisterModuleType("droidstubs", DroidstubsFactory)
62 ctx.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
63
64 ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
65}
66
Colin Cross2207f872021-03-24 12:39:08 -070067// Droidstubs
Colin Cross2207f872021-03-24 12:39:08 -070068type Droidstubs struct {
69 Javadoc
Spandan Das2cc80ba2023-10-27 17:21:52 +000070 embeddableInModuleAndImport
Colin Cross2207f872021-03-24 12:39:08 -070071
72 properties DroidstubsProperties
Paul Duffinc71d2b72022-08-16 15:24:01 +000073 apiFile android.Path
74 removedApiFile android.Path
Colin Cross2207f872021-03-24 12:39:08 -070075 nullabilityWarningsFile android.WritablePath
76
77 checkCurrentApiTimestamp android.WritablePath
78 updateCurrentApiTimestamp android.WritablePath
79 checkLastReleasedApiTimestamp android.WritablePath
80 apiLintTimestamp android.WritablePath
81 apiLintReport android.WritablePath
82
83 checkNullabilityWarningsTimestamp android.WritablePath
84
85 annotationsZip android.WritablePath
86 apiVersionsXml android.WritablePath
87
Colin Cross2207f872021-03-24 12:39:08 -070088 metadataZip android.WritablePath
89 metadataDir android.WritablePath
90}
91
92type DroidstubsProperties struct {
93 // The generated public API filename by Metalava, defaults to <module>_api.txt
94 Api_filename *string
95
96 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
97 Removed_api_filename *string
98
Colin Cross2207f872021-03-24 12:39:08 -070099 Check_api struct {
100 Last_released ApiToCheck
101
102 Current ApiToCheck
103
104 Api_lint struct {
105 Enabled *bool
106
107 // If set, performs api_lint on any new APIs not found in the given signature file
108 New_since *string `android:"path"`
109
110 // If not blank, path to the baseline txt file for approved API lint violations.
111 Baseline_file *string `android:"path"`
112 }
113 }
114
115 // user can specify the version of previous released API file in order to do compatibility check.
116 Previous_api *string `android:"path"`
117
118 // is set to true, Metalava will allow framework SDK to contain annotations.
119 Annotations_enabled *bool
120
121 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
122 Merge_annotations_dirs []string
123
124 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
125 Merge_inclusion_annotations_dirs []string
126
127 // a file containing a list of classes to do nullability validation for.
128 Validate_nullability_from_list *string
129
130 // a file containing expected warnings produced by validation of nullability annotations.
131 Check_nullability_warnings *string
132
133 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
134 Create_doc_stubs *bool
135
136 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
137 // Has no effect if create_doc_stubs: true.
138 Output_javadoc_comments *bool
139
140 // if set to false then do not write out stubs. Defaults to true.
141 //
142 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
143 Generate_stubs *bool
144
145 // 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 -0400146 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700147 High_mem *bool
148
satayev783195c2021-06-23 21:49:57 +0100149 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700150 Api_levels_annotations_enabled *bool
151
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000152 // Apply the api levels database created by this module rather than generating one in this droidstubs.
153 Api_levels_module *string
154
Colin Cross2207f872021-03-24 12:39:08 -0700155 // the dirs which Metalava extracts API levels annotations from.
156 Api_levels_annotations_dirs []string
157
Cole Faust051fa912022-10-05 12:45:42 -0700158 // 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 +0100159 Api_levels_sdk_type *string
160
Colin Cross2207f872021-03-24 12:39:08 -0700161 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
162 Api_levels_jar_filename *string
163
164 // if set to true, collect the values used by the Dev tools and
165 // write them in files packaged with the SDK. Defaults to false.
166 Write_sdk_values *bool
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200167
168 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
169 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
170 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000171
172 // API surface of this module. If set, the module contributes to an API surface.
173 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
174 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000175
176 // a list of aconfig_declarations module names that the stubs generated in this module
177 // depend on.
178 Aconfig_declarations []string
Colin Cross2207f872021-03-24 12:39:08 -0700179}
180
Anton Hansson52609322021-05-05 10:36:05 +0100181// Used by xsd_config
182type ApiFilePath interface {
183 ApiFilePath() android.Path
184}
185
186type ApiStubsSrcProvider interface {
187 StubsSrcJar() android.Path
188}
189
190// Provider of information about API stubs, used by java_sdk_library.
191type ApiStubsProvider interface {
Anton Hanssond78eb762021-09-21 15:25:12 +0100192 AnnotationsZip() android.Path
Anton Hansson52609322021-05-05 10:36:05 +0100193 ApiFilePath
194 RemovedApiFilePath() android.Path
195
196 ApiStubsSrcProvider
197}
198
Jihoon Kang063ec002023-06-28 01:16:23 +0000199type currentApiTimestampProvider interface {
200 CurrentApiTimestamp() android.Path
201}
202
Colin Cross2207f872021-03-24 12:39:08 -0700203// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
204// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
205// a droiddoc module to generate documentation.
206func DroidstubsFactory() android.Module {
207 module := &Droidstubs{}
208
209 module.AddProperties(&module.properties,
210 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000211 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700212
213 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000214
215 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
216 module.createApiContribution(ctx)
217 })
Colin Cross2207f872021-03-24 12:39:08 -0700218 return module
219}
220
221// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
222// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
223// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
224// module when symbols needed by the source files are provided by java_library_host modules.
225func DroidstubsHostFactory() android.Module {
226 module := &Droidstubs{}
227
228 module.AddProperties(&module.properties,
229 &module.Javadoc.properties)
230
231 InitDroiddocModule(module, android.HostSupported)
232 return module
233}
234
235func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
236 switch tag {
237 case "":
238 return android.Paths{d.stubsSrcJar}, nil
239 case ".docs.zip":
240 return android.Paths{d.docZip}, nil
241 case ".api.txt", android.DefaultDistTag:
242 // This is the default dist path for dist properties that have no tag property.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000243 return android.Paths{d.apiFile}, nil
Colin Cross2207f872021-03-24 12:39:08 -0700244 case ".removed-api.txt":
Paul Duffinc71d2b72022-08-16 15:24:01 +0000245 return android.Paths{d.removedApiFile}, nil
Colin Cross2207f872021-03-24 12:39:08 -0700246 case ".annotations.zip":
247 return android.Paths{d.annotationsZip}, nil
248 case ".api_versions.xml":
249 return android.Paths{d.apiVersionsXml}, nil
250 default:
251 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
252 }
253}
254
Anton Hanssond78eb762021-09-21 15:25:12 +0100255func (d *Droidstubs) AnnotationsZip() android.Path {
256 return d.annotationsZip
257}
258
Colin Cross2207f872021-03-24 12:39:08 -0700259func (d *Droidstubs) ApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000260 return d.apiFile
Colin Cross2207f872021-03-24 12:39:08 -0700261}
262
263func (d *Droidstubs) RemovedApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000264 return d.removedApiFile
Colin Cross2207f872021-03-24 12:39:08 -0700265}
266
267func (d *Droidstubs) StubsSrcJar() android.Path {
268 return d.stubsSrcJar
269}
270
Jihoon Kang063ec002023-06-28 01:16:23 +0000271func (d *Droidstubs) CurrentApiTimestamp() android.Path {
272 return d.checkCurrentApiTimestamp
273}
274
Colin Cross2207f872021-03-24 12:39:08 -0700275var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
276var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
277var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000278var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000279var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700280
281func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
282 d.Javadoc.addDeps(ctx)
283
284 if len(d.properties.Merge_annotations_dirs) != 0 {
285 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
286 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
287 }
288 }
289
290 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
291 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
292 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
293 }
294 }
295
296 if len(d.properties.Api_levels_annotations_dirs) != 0 {
297 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
298 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
299 }
300 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000301
Jihoon Kang6592e872023-12-19 01:13:16 +0000302 if len(d.properties.Aconfig_declarations) != 0 {
303 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
304 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
305 }
306 }
307
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000308 if d.properties.Api_levels_module != nil {
309 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
310 }
Colin Cross2207f872021-03-24 12:39:08 -0700311}
312
313func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
314 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
315 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
316 String(d.properties.Api_filename) != "" {
317 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Paul Duffinc71d2b72022-08-16 15:24:01 +0000318 uncheckedApiFile := android.PathForModuleOut(ctx, "metalava", filename)
319 cmd.FlagWithOutput("--api ", uncheckedApiFile)
320 d.apiFile = uncheckedApiFile
Colin Cross2207f872021-03-24 12:39:08 -0700321 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
322 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000323 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700324 }
325
326 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
327 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
328 String(d.properties.Removed_api_filename) != "" {
329 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Paul Duffinc71d2b72022-08-16 15:24:01 +0000330 uncheckedRemovedFile := android.PathForModuleOut(ctx, "metalava", filename)
331 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
332 d.removedApiFile = uncheckedRemovedFile
Colin Cross2207f872021-03-24 12:39:08 -0700333 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
334 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000335 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700336 }
337
Colin Cross2207f872021-03-24 12:39:08 -0700338 if Bool(d.properties.Write_sdk_values) {
Colin Crosscb77f752021-03-24 12:04:44 -0700339 d.metadataDir = android.PathForModuleOut(ctx, "metalava", "metadata")
Colin Cross2207f872021-03-24 12:39:08 -0700340 cmd.FlagWithArg("--sdk-values ", d.metadataDir.String())
341 }
342
343 if stubsDir.Valid() {
344 if Bool(d.properties.Create_doc_stubs) {
345 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
346 } else {
347 cmd.FlagWithArg("--stubs ", stubsDir.String())
348 if !Bool(d.properties.Output_javadoc_comments) {
349 cmd.Flag("--exclude-documentation-from-stubs")
350 }
351 }
352 }
353}
354
355func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
356 if Bool(d.properties.Annotations_enabled) {
Liz Kammere09e20e2023-10-16 15:07:54 -0400357 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100358
Colin Cross2207f872021-03-24 12:39:08 -0700359 validatingNullability :=
Colin Crossbc139922021-03-25 18:33:16 -0700360 strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
Colin Cross2207f872021-03-24 12:39:08 -0700361 String(d.properties.Validate_nullability_from_list) != ""
362
363 migratingNullability := String(d.properties.Previous_api) != ""
364 if migratingNullability {
365 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
366 cmd.FlagWithInput("--migrate-nullness ", previousApi)
367 }
368
369 if s := String(d.properties.Validate_nullability_from_list); s != "" {
370 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
371 }
372
373 if validatingNullability {
Colin Crosscb77f752021-03-24 12:04:44 -0700374 d.nullabilityWarningsFile = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"_nullability_warnings.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700375 cmd.FlagWithOutput("--nullability-warnings-txt ", d.nullabilityWarningsFile)
376 }
377
Colin Crosscb77f752021-03-24 12:04:44 -0700378 d.annotationsZip = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"_annotations.zip")
Colin Cross2207f872021-03-24 12:39:08 -0700379 cmd.FlagWithOutput("--extract-annotations ", d.annotationsZip)
380
381 if len(d.properties.Merge_annotations_dirs) != 0 {
382 d.mergeAnnoDirFlags(ctx, cmd)
383 }
384
Liz Kammere09e20e2023-10-16 15:07:54 -0400385 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700386 }
387}
388
389func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
390 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
391 if t, ok := m.(*ExportedDroiddocDir); ok {
392 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
393 } else {
394 ctx.PropertyErrorf("merge_annotations_dirs",
395 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
396 }
397 })
398}
399
400func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
401 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
402 if t, ok := m.(*ExportedDroiddocDir); ok {
403 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
404 } else {
405 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
406 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
407 }
408 })
409}
410
411func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000412 var apiVersions android.Path
413 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
414 d.apiLevelsGenerationFlags(ctx, cmd)
415 apiVersions = d.apiVersionsXml
416 } else {
417 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
418 if s, ok := m.(*Droidstubs); ok {
419 apiVersions = s.apiVersionsXml
420 } else {
421 ctx.PropertyErrorf("api_levels_module",
422 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
423 }
424 })
Colin Cross2207f872021-03-24 12:39:08 -0700425 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000426 if apiVersions != nil {
427 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
428 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
429 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
430 }
431}
Colin Cross2207f872021-03-24 12:39:08 -0700432
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000433func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
Colin Cross2207f872021-03-24 12:39:08 -0700434 if len(d.properties.Api_levels_annotations_dirs) == 0 {
435 ctx.PropertyErrorf("api_levels_annotations_dirs",
436 "has to be non-empty if api levels annotations was enabled!")
437 }
438
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000439 d.apiVersionsXml = android.PathForModuleOut(ctx, "metalava", "api-versions.xml")
Colin Cross2207f872021-03-24 12:39:08 -0700440 cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700441
442 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
443
satayev783195c2021-06-23 21:49:57 +0100444 var dirs []string
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200445 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700446 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
447 if t, ok := m.(*ExportedDroiddocDir); ok {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200448 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
449
450 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
451 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700452 for _, dep := range t.deps {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200453 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
454 if extensions_dir == "" {
455 extensions_dir = t.dir.String() + "/extensions"
456 }
457 cmd.Implicit(dep)
458 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700459 if dep.Base() == filename {
460 cmd.Implicit(dep)
461 }
462 if filename != "android.jar" && dep.Base() == "android.jar" {
463 // Metalava implicitly searches these patterns:
464 // prebuilts/tools/common/api-versions/android-%/android.jar
465 // prebuilts/sdk/%/public/android.jar
466 // Add android.jar files from the api_levels_annotations_dirs directories to try
467 // to satisfy these patterns. If Metalava can't find a match for an API level
468 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700469 cmd.Implicit(dep)
470 }
471 }
satayev783195c2021-06-23 21:49:57 +0100472
473 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700474 } else {
475 ctx.PropertyErrorf("api_levels_annotations_dirs",
476 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
477 }
478 })
satayev783195c2021-06-23 21:49:57 +0100479
480 // Add all relevant --android-jar-pattern patterns for Metalava.
481 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
482 // an actual file present on disk (in the order the patterns were passed). For system APIs for
483 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000484 // for older releases. Similarly, module-lib falls back to system API.
485 var sdkDirs []string
486 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700487 case "system-server":
488 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000489 case "module-lib":
490 sdkDirs = []string{"module-lib", "system", "public"}
491 case "system":
492 sdkDirs = []string{"system", "public"}
493 case "public":
494 sdkDirs = []string{"public"}
495 default:
496 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
497 return
satayev783195c2021-06-23 21:49:57 +0100498 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000499
500 for _, sdkDir := range sdkDirs {
501 for _, dir := range dirs {
502 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
503 }
satayev783195c2021-06-23 21:49:57 +0100504 }
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200505
506 if d.properties.Extensions_info_file != nil {
507 if extensions_dir == "" {
508 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
509 }
510 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
511 cmd.Implicit(info_file)
512 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
513 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
514 }
Colin Cross2207f872021-03-24 12:39:08 -0700515}
516
Colin Crosse52c2ac2022-03-28 17:03:35 -0700517func metalavaUseRbe(ctx android.ModuleContext) bool {
518 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
519}
520
Colin Cross2207f872021-03-24 12:39:08 -0700521func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100522 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700523 rule.Command().Text("rm -rf").Flag(homeDir.String())
524 rule.Command().Text("mkdir -p").Flag(homeDir.String())
525
Anton Hansson556e8142021-06-04 16:20:25 +0100526 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700527 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
528
Colin Crosse52c2ac2022-03-28 17:03:35 -0700529 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700530 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700531 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000532 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
533 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700534 labels := map[string]string{"type": "tool", "name": "metalava"}
535 // TODO: metalava pool rejects these jobs
536 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
537 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000538 Labels: labels,
539 ExecStrategy: execStrategy,
540 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
541 Platform: map[string]string{remoteexec.PoolKey: pool},
542 Compare: compare,
543 NumLocalRuns: 1,
544 NumRemoteRuns: 1,
545 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700546 })
Colin Cross2207f872021-03-24 12:39:08 -0700547 }
548
Colin Cross6aa5c402021-03-24 12:28:50 -0700549 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700550 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400551 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100552 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700553 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
554 FlagWithInput("@", srcJarList)
555
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100556 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
557 // years, so it is unlikely to change any time soon.
558 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
559 combinedPaths = append(combinedPaths, classpath.Paths()...)
560 if len(combinedPaths) > 0 {
561 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700562 }
563
Liz Kammere09e20e2023-10-16 15:07:54 -0400564 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000565 if ctx.DeviceConfig().HideFlaggedApis() {
Liz Kammere09e20e2023-10-16 15:07:54 -0400566 cmd.Flag(config.MetalavaHideFlaggedApis)
Jihoon Kangc8313892023-09-20 00:54:47 +0000567 }
568
Colin Cross2207f872021-03-24 12:39:08 -0700569 return cmd
570}
571
Jihoon Kang6592e872023-12-19 01:13:16 +0000572// Generate flagged apis related flags. Apply transformations and only revert the flagged apis
573// that are not enabled via release configurations and are not specified in aconfig_declarations
574func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, stubsType StubsType, aconfigFlagsPaths android.Paths) {
575
576 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
577 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
578
579 var filterArgs string
580 switch stubsType {
581 // No flagged apis specific flags need to be passed to metalava when generating
582 // everything stubs
583 case Everything:
584 return
585
586 case Runtime:
587 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
588
589 case Exportable:
590 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
591
592 }
593
594 ctx.Build(pctx, android.BuildParams{
595 Rule: gatherReleasedFlaggedApisRule,
596 Inputs: aconfigFlagsPaths,
597 Output: releasedFlaggedApisFile,
598 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
599 Args: map[string]string{
600 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
601 "filter_args": filterArgs,
602 },
603 })
604
605 ctx.Build(pctx, android.BuildParams{
606 Rule: generateMetalavaRevertAnnotationsRule,
607 Input: releasedFlaggedApisFile,
608 Output: revertAnnotationsFile,
609 Description: fmt.Sprintf("%s revert annotations", stubsType),
610 })
611}
612
Colin Cross2207f872021-03-24 12:39:08 -0700613func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
614 deps := d.Javadoc.collectDeps(ctx)
615
Jiyong Parkf1691d22021-03-29 20:11:58 +0900616 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
Colin Cross2207f872021-03-24 12:39:08 -0700617
Jihoon Kang6592e872023-12-19 01:13:16 +0000618 // If the module specifies aconfig_declarations property, "exportable" (and "runtime" eventually) stubs are generated
619 if len(deps.aconfigProtoFiles) > 0 {
620 // Files required to generate "exportable" stubs
621 stubsType := Exportable
622 d.generateRevertAnnotationArgs(ctx, stubsType, deps.aconfigProtoFiles)
623 }
624
Colin Cross2207f872021-03-24 12:39:08 -0700625 // Create rule for metalava
626
Colin Crosscb77f752021-03-24 12:04:44 -0700627 srcJarDir := android.PathForModuleOut(ctx, "metalava", "srcjars")
Colin Cross2207f872021-03-24 12:39:08 -0700628
629 rule := android.NewRuleBuilder(pctx, ctx)
630
Colin Cross8095c292021-03-30 16:40:48 -0700631 rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
632 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
633 SandboxInputs()
Colin Cross6aa5c402021-03-24 12:28:50 -0700634
Colin Cross2207f872021-03-24 12:39:08 -0700635 if BoolDefault(d.properties.High_mem, false) {
636 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
637 rule.HighMem()
638 }
639
640 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
641 var stubsDir android.OptionalPath
642 if generateStubs {
Colin Crosscb77f752021-03-24 12:04:44 -0700643 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
644 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
Colin Cross2207f872021-03-24 12:39:08 -0700645 rule.Command().Text("rm -rf").Text(stubsDir.String())
646 rule.Command().Text("mkdir -p").Text(stubsDir.String())
647 }
648
649 srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
650
Colin Crosscb77f752021-03-24 12:04:44 -0700651 homeDir := android.PathForModuleOut(ctx, "metalava", "home")
Colin Cross2207f872021-03-24 12:39:08 -0700652 cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
Anton Hansson556e8142021-06-04 16:20:25 +0100653 deps.bootClasspath, deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700654 cmd.Implicits(d.Javadoc.implicits)
655
656 d.stubsFlags(ctx, cmd, stubsDir)
657
658 d.annotationsFlags(ctx, cmd)
659 d.inclusionAnnotationsFlags(ctx, cmd)
660 d.apiLevelsAnnotationsFlags(ctx, cmd)
661
Colin Crossbc139922021-03-25 18:33:16 -0700662 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700663
Colin Cross2207f872021-03-24 12:39:08 -0700664 for _, o := range d.Javadoc.properties.Out {
665 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
666 }
667
668 // Add options for the other optional tasks: API-lint and check-released.
669 // We generate separate timestamp files for them.
670
671 doApiLint := false
672 doCheckReleased := false
673
674 // Add API lint options.
675
676 if BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) {
677 doApiLint = true
678
679 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
680 if newSince.Valid() {
681 cmd.FlagWithInput("--api-lint ", newSince.Path())
682 } else {
683 cmd.Flag("--api-lint")
684 }
Colin Crosscb77f752021-03-24 12:04:44 -0700685 d.apiLintReport = android.PathForModuleOut(ctx, "metalava", "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700686 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
687
Colin Cross0d532412021-03-25 09:38:45 -0700688 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700689 if d.Name() != "android.car-system-stubs-docs" &&
690 d.Name() != "android.car-stubs-docs" {
691 cmd.Flag("--lints-as-errors")
692 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
693 }
694
695 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Colin Crosscb77f752021-03-24 12:04:44 -0700696 updatedBaselineOutput := android.PathForModuleOut(ctx, "metalava", "api_lint_baseline.txt")
697 d.apiLintTimestamp = android.PathForModuleOut(ctx, "metalava", "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700698
699 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700700 //
701 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
702 // message and metalava's one?
703 msg := `$'` + // Enclose with $' ... '
704 `************************************************************\n` +
705 `Your API changes are triggering API Lint warnings or errors.\n` +
706 `To make these errors go away, fix the code according to the\n` +
707 `error and/or warning messages above.\n` +
708 `\n` +
709 `If it is not possible to do so, there are workarounds:\n` +
710 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000711 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
712 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700713
714 if baselineFile.Valid() {
715 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
716 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
717
718 msg += fmt.Sprintf(``+
719 `2. You can update the baseline by executing the following\n`+
720 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700721 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
722 ` "%s" \\\n`+
723 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700724 ` To submit the revised baseline.txt to the main Android\n`+
725 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
726 } else {
727 msg += fmt.Sprintf(``+
728 `2. You can add a baseline file of existing lint failures\n`+
729 ` to the build rule of %s.\n`, d.Name())
730 }
731 // Note the message ends with a ' (single quote), to close the $' ... ' .
732 msg += `************************************************************\n'`
733
734 cmd.FlagWithArg("--error-message:api-lint ", msg)
735 }
736
737 // Add "check released" options. (Detect incompatible API changes from the last public release)
738
739 if apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") {
740 doCheckReleased = true
741
742 if len(d.Javadoc.properties.Out) > 0 {
743 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
744 }
745
746 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
747 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
748 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Colin Crosscb77f752021-03-24 12:04:44 -0700749 updatedBaselineOutput := android.PathForModuleOut(ctx, "metalava", "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700750
Colin Crosscb77f752021-03-24 12:04:44 -0700751 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "metalava", "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700752
753 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
754 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
755
756 if baselineFile.Valid() {
757 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
758 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
759 }
760
761 // Note this string includes quote ($' ... '), which decodes the "\n"s.
762 msg := `$'\n******************************\n` +
763 `You have tried to change the API from what has been previously released in\n` +
764 `an SDK. Please fix the errors listed above.\n` +
765 `******************************\n'`
766
767 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
768 }
769
Paul Duffin10a23c22023-08-11 22:47:31 +0100770 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
771 // Pass the current API file into metalava so it can use it as the basis for determining how to
772 // generate the output signature files (both api and removed).
773 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
774 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
775 }
776
Colin Cross2207f872021-03-24 12:39:08 -0700777 if generateStubs {
778 rule.Command().
779 BuiltTool("soong_zip").
780 Flag("-write_if_changed").
781 Flag("-jar").
782 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
783 FlagWithArg("-C ", stubsDir.String()).
784 FlagWithArg("-D ", stubsDir.String())
785 }
786
787 if Bool(d.properties.Write_sdk_values) {
Colin Crosscb77f752021-03-24 12:04:44 -0700788 d.metadataZip = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-metadata.zip")
Colin Cross2207f872021-03-24 12:39:08 -0700789 rule.Command().
790 BuiltTool("soong_zip").
791 Flag("-write_if_changed").
792 Flag("-d").
793 FlagWithOutput("-o ", d.metadataZip).
794 FlagWithArg("-C ", d.metadataDir.String()).
795 FlagWithArg("-D ", d.metadataDir.String())
796 }
797
798 // TODO: We don't really need two separate API files, but this is a reminiscence of how
799 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
800 if doApiLint {
801 rule.Command().Text("touch").Output(d.apiLintTimestamp)
802 }
803 if doCheckReleased {
804 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
805 }
806
Colin Cross6aa5c402021-03-24 12:28:50 -0700807 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -0700808 if !metalavaUseRbe(ctx) {
809 rule.Restat()
810 }
Colin Cross2207f872021-03-24 12:39:08 -0700811
812 zipSyncCleanupCmd(rule, srcJarDir)
813
Paul Duffinc166b682022-05-27 12:23:08 +0000814 rule.Build("metalava", "metalava merged")
815
Paul Duffine7a86642022-08-16 15:43:20 +0000816 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
817
818 if len(d.Javadoc.properties.Out) > 0 {
819 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
820 }
821
822 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
823 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
824 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
825
826 if baselineFile.Valid() {
827 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
828 }
829
830 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "metalava", "check_current_api.timestamp")
831
832 rule := android.NewRuleBuilder(pctx, ctx)
833
834 // Diff command line.
835 // -F matches the closest "opening" line, such as "package android {"
836 // and " public class Intent {".
837 diff := `diff -u -F '{ *$'`
838
839 rule.Command().Text("( true")
840 rule.Command().
841 Text(diff).
842 Input(apiFile).Input(d.apiFile)
843
844 rule.Command().
845 Text(diff).
846 Input(removedApiFile).Input(d.removedApiFile)
847
848 msg := fmt.Sprintf(`\n******************************\n`+
849 `You have tried to change the API from what has been previously approved.\n\n`+
850 `To make these errors go away, you have two choices:\n`+
851 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
852 ` to the new methods, etc. shown in the above diff.\n\n`+
853 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
854 ` m %s-update-current-api\n\n`+
855 ` To submit the revised current.txt to the main Android repository,\n`+
856 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +0000857 `If your build failed due to stub validation, you can resolve the errors with\n`+
858 `either of the two choices above and try re-building the target.\n`+
859 `If the mismatch between the stubs and the current.txt is intended,\n`+
860 `you can try re-building the target by executing the following command:\n`+
861 `m DISABLE_STUB_VALIDATION=true <your build target>\n`+
Paul Duffine7a86642022-08-16 15:43:20 +0000862 `******************************\n`, ctx.ModuleName())
863
864 rule.Command().
865 Text("touch").Output(d.checkCurrentApiTimestamp).
866 Text(") || (").
867 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
868 Text("; exit 38").
869 Text(")")
870
871 rule.Build("metalavaCurrentApiCheck", "check current API")
872
873 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "metalava", "update_current_api.timestamp")
874
875 // update API rule
876 rule = android.NewRuleBuilder(pctx, ctx)
877
878 rule.Command().Text("( true")
879
880 rule.Command().
881 Text("cp").Flag("-f").
882 Input(d.apiFile).Flag(apiFile.String())
883
884 rule.Command().
885 Text("cp").Flag("-f").
886 Input(d.removedApiFile).Flag(removedApiFile.String())
887
888 msg = "failed to update public API"
889
890 rule.Command().
891 Text("touch").Output(d.updateCurrentApiTimestamp).
892 Text(") || (").
893 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
894 Text("; exit 38").
895 Text(")")
896
897 rule.Build("metalavaCurrentApiUpdate", "update current API")
898 }
899
Colin Cross2207f872021-03-24 12:39:08 -0700900 if String(d.properties.Check_nullability_warnings) != "" {
901 if d.nullabilityWarningsFile == nil {
902 ctx.PropertyErrorf("check_nullability_warnings",
903 "Cannot specify check_nullability_warnings unless validating nullability")
904 }
905
906 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
907
Colin Crosscb77f752021-03-24 12:04:44 -0700908 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, "metalava", "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700909
910 msg := fmt.Sprintf(`\n******************************\n`+
911 `The warnings encountered during nullability annotation validation did\n`+
912 `not match the checked in file of expected warnings. The diffs are shown\n`+
913 `above. You have two options:\n`+
914 ` 1. Resolve the differences by editing the nullability annotations.\n`+
915 ` 2. Update the file of expected warnings by running:\n`+
916 ` cp %s %s\n`+
917 ` and submitting the updated file as part of your change.`,
918 d.nullabilityWarningsFile, checkNullabilityWarnings)
919
920 rule := android.NewRuleBuilder(pctx, ctx)
921
922 rule.Command().
923 Text("(").
924 Text("diff").Input(checkNullabilityWarnings).Input(d.nullabilityWarningsFile).
925 Text("&&").
926 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
927 Text(") || (").
928 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
929 Text("; exit 38").
930 Text(")")
931
932 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
933 }
934}
935
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000936func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
937 api_file := d.properties.Check_api.Current.Api_file
938 api_surface := d.properties.Api_surface
939
940 props := struct {
941 Name *string
942 Api_surface *string
943 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +0000944 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000945 }{}
946
947 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
948 props.Api_surface = api_surface
949 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +0000950 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000951
952 ctx.CreateModule(ApiContributionFactory, &props)
953}
954
Spandan Das0b555e32022-11-28 18:48:51 +0000955// TODO (b/262014796): Export the API contributions of CorePlatformApi
956// A map to populate the api surface of a droidstub from a substring appearing in its name
957// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
958// use a strict naming convention
959var (
960 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
961 //public is commented out since the core libraries use public in their java_sdk_library names
962 "intracore": android.SdkIntraCore,
963 "intra.core": android.SdkIntraCore,
964 "system_server": android.SdkSystemServer,
965 "system-server": android.SdkSystemServer,
966 "system": android.SdkSystem,
967 "module_lib": android.SdkModule,
968 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +0000969 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +0000970 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +0000971 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +0000972 }
973)
974
Colin Cross2207f872021-03-24 12:39:08 -0700975func StubsDefaultsFactory() android.Module {
976 module := &DocDefaults{}
977
978 module.AddProperties(
979 &JavadocProperties{},
980 &DroidstubsProperties{},
981 )
982
983 android.InitDefaultsModule(module)
984
985 return module
986}
987
988var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
989
990type PrebuiltStubsSourcesProperties struct {
991 Srcs []string `android:"path"`
992}
993
994type PrebuiltStubsSources struct {
995 android.ModuleBase
996 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +0000997 embeddableInModuleAndImport
998
Colin Cross2207f872021-03-24 12:39:08 -0700999 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001000
1001 properties PrebuiltStubsSourcesProperties
1002
kgui67007242022-01-25 13:50:25 +08001003 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001004}
1005
1006func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1007 switch tag {
1008 case "":
1009 return android.Paths{p.stubsSrcJar}, nil
1010 default:
1011 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1012 }
1013}
1014
1015func (d *PrebuiltStubsSources) StubsSrcJar() android.Path {
1016 return d.stubsSrcJar
1017}
1018
1019func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001020 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001021 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 -07001022 return
1023 }
1024
Anton Hansson86758ac2021-11-03 14:44:12 +00001025 src := p.properties.Srcs[0]
1026 if filepath.Ext(src) == ".srcjar" {
1027 // This is a srcjar. We can use it directly.
1028 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1029 } else {
1030 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001031
Anton Hansson86758ac2021-11-03 14:44:12 +00001032 // This is a directory. Glob the contents just in case the directory does not exist.
1033 srcGlob := src + "/**/*"
1034 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001035
Anton Hansson86758ac2021-11-03 14:44:12 +00001036 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1037 // the path components are invalid it won't in this case because no components
1038 // are specified and the module directory must exist in order to get this far.
1039 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001040
Anton Hansson86758ac2021-11-03 14:44:12 +00001041 rule := android.NewRuleBuilder(pctx, ctx)
1042 rule.Command().
1043 BuiltTool("soong_zip").
1044 Flag("-write_if_changed").
1045 Flag("-jar").
1046 FlagWithOutput("-o ", outPath).
1047 FlagWithArg("-C ", srcDir.String()).
1048 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1049 rule.Restat()
1050 rule.Build("zip src", "Create srcjar from prebuilt source")
1051 p.stubsSrcJar = outPath
1052 }
Colin Cross2207f872021-03-24 12:39:08 -07001053}
1054
1055func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1056 return &p.prebuilt
1057}
1058
1059func (p *PrebuiltStubsSources) Name() string {
1060 return p.prebuilt.Name(p.ModuleBase.Name())
1061}
1062
1063// prebuilt_stubs_sources imports a set of java source files as if they were
1064// generated by droidstubs.
1065//
1066// By default, a prebuilt_stubs_sources has a single variant that expects a
1067// set of `.java` files generated by droidstubs.
1068//
1069// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1070// for host modules.
1071//
1072// Intended only for use by sdk snapshots.
1073func PrebuiltStubsSourcesFactory() android.Module {
1074 module := &PrebuiltStubsSources{}
1075
1076 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001077 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001078
1079 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001080 InitDroiddocModule(module, android.HostAndDeviceSupported)
1081 return module
1082}