• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 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	"errors"
19	"fmt"
20	"path"
21	"path/filepath"
22	"reflect"
23	"regexp"
24	"sort"
25	"strings"
26	"sync"
27
28	"github.com/google/blueprint"
29	"github.com/google/blueprint/proptools"
30
31	"android/soong/android"
32	"android/soong/dexpreopt"
33	"android/soong/etc"
34)
35
36const (
37	sdkXmlFileSuffix = ".xml"
38)
39
40// A tag to associated a dependency with a specific api scope.
41type scopeDependencyTag struct {
42	blueprint.BaseDependencyTag
43	name     string
44	apiScope *apiScope
45
46	// Function for extracting appropriate path information from the dependency.
47	depInfoExtractor func(paths *scopePaths, ctx android.ModuleContext, dep android.Module) error
48}
49
50// Extract tag specific information from the dependency.
51func (tag scopeDependencyTag) extractDepInfo(ctx android.ModuleContext, dep android.Module, paths *scopePaths) {
52	err := tag.depInfoExtractor(paths, ctx, dep)
53	if err != nil {
54		ctx.ModuleErrorf("has an invalid {scopeDependencyTag: %s} dependency on module %s: %s", tag.name, ctx.OtherModuleName(dep), err.Error())
55	}
56}
57
58var _ android.ReplaceSourceWithPrebuilt = (*scopeDependencyTag)(nil)
59
60func (tag scopeDependencyTag) ReplaceSourceWithPrebuilt() bool {
61	return false
62}
63
64// Provides information about an api scope, e.g. public, system, test.
65type apiScope struct {
66	// The name of the api scope, e.g. public, system, test
67	name string
68
69	// The api scope that this scope extends.
70	//
71	// This organizes the scopes into an extension hierarchy.
72	//
73	// If set this means that the API provided by this scope includes the API provided by the scope
74	// set in this field.
75	extends *apiScope
76
77	// The next api scope that a library that uses this scope can access.
78	//
79	// This organizes the scopes into an access hierarchy.
80	//
81	// If set this means that a library that can access this API can also access the API provided by
82	// the scope set in this field.
83	//
84	// A module that sets sdk_version: "<scope>_current" should have access to the <scope> API of
85	// every java_sdk_library that it depends on. If the library does not provide an API for <scope>
86	// then it will traverse up this access hierarchy to find an API that it does provide.
87	//
88	// If this is not set then it defaults to the scope set in extends.
89	canAccess *apiScope
90
91	// The legacy enabled status for a specific scope can be dependent on other
92	// properties that have been specified on the library so it is provided by
93	// a function that can determine the status by examining those properties.
94	legacyEnabledStatus func(module *SdkLibrary) bool
95
96	// The default enabled status for non-legacy behavior, which is triggered by
97	// explicitly enabling at least one api scope.
98	defaultEnabledStatus bool
99
100	// Gets a pointer to the scope specific properties.
101	scopeSpecificProperties func(module *SdkLibrary) *ApiScopeProperties
102
103	// The name of the field in the dynamically created structure.
104	fieldName string
105
106	// The name of the property in the java_sdk_library_import
107	propertyName string
108
109	// The tag to use to depend on the prebuilt stubs library module
110	prebuiltStubsTag scopeDependencyTag
111
112	// The tag to use to depend on the everything stubs library module.
113	everythingStubsTag scopeDependencyTag
114
115	// The tag to use to depend on the exportable stubs library module.
116	exportableStubsTag scopeDependencyTag
117
118	// The tag to use to depend on the stubs source module (if separate from the API module).
119	stubsSourceTag scopeDependencyTag
120
121	// The tag to use to depend on the API file generating module (if separate from the stubs source module).
122	apiFileTag scopeDependencyTag
123
124	// The tag to use to depend on the stubs source and API module.
125	stubsSourceAndApiTag scopeDependencyTag
126
127	// The tag to use to depend on the module that provides the latest version of the API .txt file.
128	latestApiModuleTag scopeDependencyTag
129
130	// The tag to use to depend on the module that provides the latest version of the API removed.txt
131	// file.
132	latestRemovedApiModuleTag scopeDependencyTag
133
134	// The scope specific prefix to add to the api file base of "current.txt" or "removed.txt".
135	apiFilePrefix string
136
137	// The scope specific suffix to add to the sdk library module name to construct a scope specific
138	// module name.
139	moduleSuffix string
140
141	// SDK version that the stubs library is built against. Note that this is always
142	// *current. Older stubs library built with a numbered SDK version is created from
143	// the prebuilt jar.
144	sdkVersion string
145
146	// The annotation that identifies this API level, empty for the public API scope.
147	annotation string
148
149	// Extra arguments to pass to droidstubs for this scope.
150	//
151	// This is not used directly but is used to construct the droidstubsArgs.
152	extraArgs []string
153
154	// The args that must be passed to droidstubs to generate the API and stubs source
155	// for this scope, constructed dynamically by initApiScope().
156	//
157	// The API only includes the additional members that this scope adds over the scope
158	// that it extends.
159	//
160	// The stubs source must include the definitions of everything that is in this
161	// api scope and all the scopes that this one extends.
162	droidstubsArgs []string
163
164	// Whether the api scope can be treated as unstable, and should skip compat checks.
165	unstable bool
166
167	// Represents the SDK kind of this scope.
168	kind android.SdkKind
169}
170
171// Initialize a scope, creating and adding appropriate dependency tags
172func initApiScope(scope *apiScope) *apiScope {
173	name := scope.name
174	scopeByName[name] = scope
175	allScopeNames = append(allScopeNames, name)
176	scope.propertyName = strings.ReplaceAll(name, "-", "_")
177	scope.fieldName = proptools.FieldNameForProperty(scope.propertyName)
178	scope.prebuiltStubsTag = scopeDependencyTag{
179		name:             name + "-stubs",
180		apiScope:         scope,
181		depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency,
182	}
183	scope.everythingStubsTag = scopeDependencyTag{
184		name:             name + "-stubs-everything",
185		apiScope:         scope,
186		depInfoExtractor: (*scopePaths).extractEverythingStubsLibraryInfoFromDependency,
187	}
188	scope.exportableStubsTag = scopeDependencyTag{
189		name:             name + "-stubs-exportable",
190		apiScope:         scope,
191		depInfoExtractor: (*scopePaths).extractExportableStubsLibraryInfoFromDependency,
192	}
193	scope.stubsSourceTag = scopeDependencyTag{
194		name:             name + "-stubs-source",
195		apiScope:         scope,
196		depInfoExtractor: (*scopePaths).extractStubsSourceInfoFromDep,
197	}
198	scope.apiFileTag = scopeDependencyTag{
199		name:             name + "-api",
200		apiScope:         scope,
201		depInfoExtractor: (*scopePaths).extractApiInfoFromDep,
202	}
203	scope.stubsSourceAndApiTag = scopeDependencyTag{
204		name:             name + "-stubs-source-and-api",
205		apiScope:         scope,
206		depInfoExtractor: (*scopePaths).extractStubsSourceAndApiInfoFromApiStubsProvider,
207	}
208	scope.latestApiModuleTag = scopeDependencyTag{
209		name:             name + "-latest-api",
210		apiScope:         scope,
211		depInfoExtractor: (*scopePaths).extractLatestApiPath,
212	}
213	scope.latestRemovedApiModuleTag = scopeDependencyTag{
214		name:             name + "-latest-removed-api",
215		apiScope:         scope,
216		depInfoExtractor: (*scopePaths).extractLatestRemovedApiPath,
217	}
218
219	// To get the args needed to generate the stubs source append all the args from
220	// this scope and all the scopes it extends as each set of args adds additional
221	// members to the stubs.
222	var scopeSpecificArgs []string
223	if scope.annotation != "" {
224		scopeSpecificArgs = []string{"--show-annotation", scope.annotation}
225	}
226	for s := scope; s != nil; s = s.extends {
227		scopeSpecificArgs = append(scopeSpecificArgs, s.extraArgs...)
228
229		// Ensure that the generated stubs includes all the API elements from the API scope
230		// that this scope extends.
231		if s != scope && s.annotation != "" {
232			scopeSpecificArgs = append(scopeSpecificArgs, "--show-for-stub-purposes-annotation", s.annotation)
233		}
234	}
235
236	// By default, a library that can access a scope can also access the scope it extends.
237	if scope.canAccess == nil {
238		scope.canAccess = scope.extends
239	}
240
241	// Escape any special characters in the arguments. This is needed because droidstubs
242	// passes these directly to the shell command.
243	scope.droidstubsArgs = proptools.ShellEscapeList(scopeSpecificArgs)
244
245	return scope
246}
247
248func (scope *apiScope) stubsLibraryModuleNameSuffix() string {
249	return ".stubs" + scope.moduleSuffix
250}
251
252func (scope *apiScope) exportableStubsLibraryModuleNameSuffix() string {
253	return ".stubs.exportable" + scope.moduleSuffix
254}
255
256func (scope *apiScope) apiLibraryModuleName(baseName string) string {
257	return scope.stubsLibraryModuleName(baseName) + ".from-text"
258}
259
260func (scope *apiScope) sourceStubLibraryModuleName(baseName string) string {
261	return scope.stubsLibraryModuleName(baseName) + ".from-source"
262}
263
264func (scope *apiScope) exportableSourceStubsLibraryModuleName(baseName string) string {
265	return scope.exportableStubsLibraryModuleName(baseName) + ".from-source"
266}
267
268func (scope *apiScope) stubsLibraryModuleName(baseName string) string {
269	return baseName + scope.stubsLibraryModuleNameSuffix()
270}
271
272func (scope *apiScope) exportableStubsLibraryModuleName(baseName string) string {
273	return baseName + scope.exportableStubsLibraryModuleNameSuffix()
274}
275
276func (scope *apiScope) stubsSourceModuleName(baseName string) string {
277	return baseName + ".stubs.source" + scope.moduleSuffix
278}
279
280func (scope *apiScope) apiModuleName(baseName string) string {
281	return baseName + ".api" + scope.moduleSuffix
282}
283
284func (scope *apiScope) String() string {
285	return scope.name
286}
287
288// snapshotRelativeDir returns the snapshot directory into which the files related to scopes will
289// be stored.
290func (scope *apiScope) snapshotRelativeDir() string {
291	return filepath.Join("sdk_library", scope.name)
292}
293
294// snapshotRelativeCurrentApiTxtPath returns the snapshot path to the API .txt file for the named
295// library.
296func (scope *apiScope) snapshotRelativeCurrentApiTxtPath(name string) string {
297	return filepath.Join(scope.snapshotRelativeDir(), name+".txt")
298}
299
300// snapshotRelativeRemovedApiTxtPath returns the snapshot path to the removed API .txt file for the
301// named library.
302func (scope *apiScope) snapshotRelativeRemovedApiTxtPath(name string) string {
303	return filepath.Join(scope.snapshotRelativeDir(), name+"-removed.txt")
304}
305
306type apiScopes []*apiScope
307
308func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string {
309	var list []string
310	for _, scope := range scopes {
311		list = append(list, accessor(scope))
312	}
313	return list
314}
315
316// Method that maps the apiScopes properties to the index of each apiScopes elements.
317// apiScopes property to be used as the key can be specified with the input accessor.
318// Only a string property of apiScope can be used as the key of the map.
319func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]int {
320	ret := make(map[string]int)
321	for i, scope := range scopes {
322		ret[accessor(scope)] = i
323	}
324	return ret
325}
326
327func (scopes apiScopes) ConvertStubsLibraryExportableToEverything(name string) string {
328	for _, scope := range scopes {
329		if strings.HasSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) {
330			return strings.TrimSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) +
331				scope.stubsLibraryModuleNameSuffix()
332		}
333	}
334	return name
335}
336
337var (
338	scopeByName    = make(map[string]*apiScope)
339	allScopeNames  []string
340	apiScopePublic = initApiScope(&apiScope{
341		name: "public",
342
343		// Public scope is enabled by default for both legacy and non-legacy modes.
344		legacyEnabledStatus: func(module *SdkLibrary) bool {
345			return true
346		},
347		defaultEnabledStatus: true,
348
349		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
350			return &module.sdkLibraryProperties.Public
351		},
352		sdkVersion: "current",
353		kind:       android.SdkPublic,
354	})
355	apiScopeSystem = initApiScope(&apiScope{
356		name:                "system",
357		extends:             apiScopePublic,
358		legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
359		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
360			return &module.sdkLibraryProperties.System
361		},
362		apiFilePrefix: "system-",
363		moduleSuffix:  ".system",
364		sdkVersion:    "system_current",
365		annotation:    "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS)",
366		kind:          android.SdkSystem,
367	})
368	apiScopeTest = initApiScope(&apiScope{
369		name:                "test",
370		extends:             apiScopeSystem,
371		legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
372		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
373			return &module.sdkLibraryProperties.Test
374		},
375		apiFilePrefix: "test-",
376		moduleSuffix:  ".test",
377		sdkVersion:    "test_current",
378		annotation:    "android.annotation.TestApi",
379		unstable:      true,
380		kind:          android.SdkTest,
381	})
382	apiScopeModuleLib = initApiScope(&apiScope{
383		name:    "module-lib",
384		extends: apiScopeSystem,
385		// The module-lib scope is disabled by default in legacy mode.
386		//
387		// Enabling this would break existing usages.
388		legacyEnabledStatus: func(module *SdkLibrary) bool {
389			return false
390		},
391		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
392			return &module.sdkLibraryProperties.Module_lib
393		},
394		apiFilePrefix: "module-lib-",
395		moduleSuffix:  ".module_lib",
396		sdkVersion:    "module_current",
397		annotation:    "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)",
398		kind:          android.SdkModule,
399	})
400	apiScopeSystemServer = initApiScope(&apiScope{
401		name:    "system-server",
402		extends: apiScopePublic,
403
404		// The system-server scope can access the module-lib scope.
405		//
406		// A module that provides a system-server API is appended to the standard bootclasspath that is
407		// used by the system server. So, it should be able to access module-lib APIs provided by
408		// libraries on the bootclasspath.
409		canAccess: apiScopeModuleLib,
410
411		// The system-server scope is disabled by default in legacy mode.
412		//
413		// Enabling this would break existing usages.
414		legacyEnabledStatus: func(module *SdkLibrary) bool {
415			return false
416		},
417		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
418			return &module.sdkLibraryProperties.System_server
419		},
420		apiFilePrefix: "system-server-",
421		moduleSuffix:  ".system_server",
422		sdkVersion:    "system_server_current",
423		annotation:    "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.SYSTEM_SERVER)",
424		extraArgs: []string{
425			"--hide-annotation", "android.annotation.Hide",
426			// com.android.* classes are okay in this interface"
427			"--hide", "InternalClasses",
428		},
429		kind: android.SdkSystemServer,
430	})
431	AllApiScopes = apiScopes{
432		apiScopePublic,
433		apiScopeSystem,
434		apiScopeTest,
435		apiScopeModuleLib,
436		apiScopeSystemServer,
437	}
438	apiLibraryAdditionalProperties = map[string]struct {
439		FullApiSurfaceStubLib     string
440		AdditionalApiContribution string
441	}{
442		"legacy.i18n.module.platform.api": {
443			FullApiSurfaceStubLib:     "legacy.core.platform.api.stubs",
444			AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution",
445		},
446		"stable.i18n.module.platform.api": {
447			FullApiSurfaceStubLib:     "stable.core.platform.api.stubs",
448			AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution",
449		},
450		"conscrypt.module.platform.api": {
451			FullApiSurfaceStubLib:     "stable.core.platform.api.stubs",
452			AdditionalApiContribution: "conscrypt.module.public.api.stubs.source.api.contribution",
453		},
454	}
455)
456
457var (
458	javaSdkLibrariesLock sync.Mutex
459)
460
461// TODO: these are big features that are currently missing
462// 1) disallowing linking to the runtime shared lib
463// 2) HTML generation
464
465func init() {
466	RegisterSdkLibraryBuildComponents(android.InitRegistrationContext)
467
468	android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
469		javaSdkLibraries := javaSdkLibraries(ctx.Config())
470		sort.Strings(*javaSdkLibraries)
471		ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " "))
472	})
473
474	// Register sdk member types.
475	android.RegisterSdkMemberType(javaSdkLibrarySdkMemberType)
476}
477
478func RegisterSdkLibraryBuildComponents(ctx android.RegistrationContext) {
479	ctx.RegisterModuleType("java_sdk_library", SdkLibraryFactory)
480	ctx.RegisterModuleType("java_sdk_library_import", sdkLibraryImportFactory)
481}
482
483// Properties associated with each api scope.
484type ApiScopeProperties struct {
485	// Indicates whether the api surface is generated.
486	//
487	// If this is set for any scope then all scopes must explicitly specify if they
488	// are enabled. This is to prevent new usages from depending on legacy behavior.
489	//
490	// Otherwise, if this is not set for any scope then the default  behavior is
491	// scope specific so please refer to the scope specific property documentation.
492	Enabled *bool
493
494	// The sdk_version to use for building the stubs.
495	//
496	// If not specified then it will use an sdk_version determined as follows:
497	//
498	// 1) If the sdk_version specified on the java_sdk_library is none then this
499	// will be none. This is used for java_sdk_library instances that are used
500	// to create stubs that contribute to the core_current sdk version.
501	// 2) Otherwise, it is assumed that this library extends but does not
502	// contribute directly to a specific sdk_version and so this uses the
503	// sdk_version appropriate for the api scope. e.g. public will use
504	// sdk_version: current, system will use sdk_version: system_current, etc.
505	//
506	// This does not affect the sdk_version used for either generating the stubs source
507	// or the API file. They both have to use the same sdk_version as is used for
508	// compiling the implementation library.
509	Sdk_version *string
510
511	// Extra libs used when compiling stubs for this scope.
512	Libs []string
513}
514
515type sdkLibraryProperties struct {
516	// List of source files that are needed to compile the API, but are not part of runtime library.
517	Api_srcs []string `android:"arch_variant"`
518
519	// Visibility for impl library module. If not specified then defaults to the
520	// visibility property.
521	Impl_library_visibility []string
522
523	// Visibility for stubs library modules. If not specified then defaults to the
524	// visibility property.
525	Stubs_library_visibility []string
526
527	// Visibility for stubs source modules. If not specified then defaults to the
528	// visibility property.
529	Stubs_source_visibility []string
530
531	// List of Java libraries that will be in the classpath when building the implementation lib
532	Impl_only_libs []string `android:"arch_variant"`
533
534	// List of Java libraries that will included in the implementation lib.
535	Impl_only_static_libs []string `android:"arch_variant"`
536
537	// List of Java libraries that will be in the classpath when building stubs
538	Stub_only_libs []string `android:"arch_variant"`
539
540	// List of Java libraries that will included in stub libraries
541	Stub_only_static_libs []string `android:"arch_variant"`
542
543	// list of package names that will be documented and publicized as API.
544	// This allows the API to be restricted to a subset of the source files provided.
545	// If this is unspecified then all the source files will be treated as being part
546	// of the API.
547	Api_packages []string
548
549	// list of package names that must be hidden from the API
550	Hidden_api_packages []string
551
552	// the relative path to the directory containing the api specification files.
553	// Defaults to "api".
554	Api_dir *string
555
556	// Determines whether a runtime implementation library is built; defaults to false.
557	//
558	// If true then it also prevents the module from being used as a shared module, i.e.
559	// it is as if shared_library: false, was set.
560	Api_only *bool
561
562	// local files that are used within user customized droiddoc options.
563	Droiddoc_option_files []string
564
565	// additional droiddoc options.
566	// Available variables for substitution:
567	//
568	//  $(location <label>): the path to the droiddoc_option_files with name <label>
569	Droiddoc_options []string
570
571	// is set to true, Metalava will allow framework SDK to contain annotations.
572	Annotations_enabled *bool
573
574	// a list of top-level directories containing files to merge qualifier annotations
575	// (i.e. those intended to be included in the stubs written) from.
576	Merge_annotations_dirs []string
577
578	// a list of top-level directories containing Java stub files to merge show/hide annotations from.
579	Merge_inclusion_annotations_dirs []string
580
581	// If set to true then don't create dist rules.
582	No_dist *bool
583
584	// The stem for the artifacts that are copied to the dist, if not specified
585	// then defaults to the base module name.
586	//
587	// For each scope the following artifacts are copied to the apistubs/<scope>
588	// directory in the dist.
589	// * stubs impl jar -> <dist-stem>.jar
590	// * API specification file -> api/<dist-stem>.txt
591	// * Removed API specification file -> api/<dist-stem>-removed.txt
592	//
593	// Also used to construct the name of the filegroup (created by prebuilt_apis)
594	// that references the latest released API and remove API specification files.
595	// * API specification filegroup -> <dist-stem>.api.<scope>.latest
596	// * Removed API specification filegroup -> <dist-stem>-removed.api.<scope>.latest
597	// * API incompatibilities baseline filegroup -> <dist-stem>-incompatibilities.api.<scope>.latest
598	Dist_stem *string
599
600	// The subdirectory for the artifacts that are copied to the dist directory.  If not specified
601	// then defaults to "unknown".  Should be set to "android" for anything that should be published
602	// in the public Android SDK.
603	Dist_group *string
604
605	// A compatibility mode that allows historical API-tracking files to not exist.
606	// Do not use.
607	Unsafe_ignore_missing_latest_api bool
608
609	// indicates whether system and test apis should be generated.
610	Generate_system_and_test_apis bool `blueprint:"mutated"`
611
612	// The properties specific to the public api scope
613	//
614	// Unless explicitly specified by using public.enabled the public api scope is
615	// enabled by default in both legacy and non-legacy mode.
616	Public ApiScopeProperties
617
618	// The properties specific to the system api scope
619	//
620	// In legacy mode the system api scope is enabled by default when sdk_version
621	// is set to something other than "none".
622	//
623	// In non-legacy mode the system api scope is disabled by default.
624	System ApiScopeProperties
625
626	// The properties specific to the test api scope
627	//
628	// In legacy mode the test api scope is enabled by default when sdk_version
629	// is set to something other than "none".
630	//
631	// In non-legacy mode the test api scope is disabled by default.
632	Test ApiScopeProperties
633
634	// The properties specific to the module-lib api scope
635	//
636	// Unless explicitly specified by using module_lib.enabled the module_lib api
637	// scope is disabled by default.
638	Module_lib ApiScopeProperties
639
640	// The properties specific to the system-server api scope
641	//
642	// Unless explicitly specified by using system_server.enabled the
643	// system_server api scope is disabled by default.
644	System_server ApiScopeProperties
645
646	// Determines if the stubs are preferred over the implementation library
647	// for linking, even when the client doesn't specify sdk_version. When this
648	// is set to true, such clients are provided with the widest API surface that
649	// this lib provides. Note however that this option doesn't affect the clients
650	// that are in the same APEX as this library. In that case, the clients are
651	// always linked with the implementation library. Default is false.
652	Default_to_stubs *bool
653
654	// Properties related to api linting.
655	Api_lint struct {
656		// Enable api linting.
657		Enabled *bool
658
659		// If API lint is enabled, this flag controls whether a set of legitimate lint errors
660		// are turned off. The default is true.
661		Legacy_errors_allowed *bool
662	}
663
664	// Determines if the module contributes to any api surfaces.
665	// This property should be set to true only if the module is listed under
666	// frameworks-base-api.bootclasspath in frameworks/base/api/Android.bp.
667	// Otherwise, this property should be set to false.
668	// Defaults to false.
669	Contribute_to_android_api *bool
670
671	// a list of aconfig_declarations module names that the stubs generated in this module
672	// depend on.
673	Aconfig_declarations []string
674
675	// TODO: determines whether to create HTML doc or not
676	// Html_doc *bool
677}
678
679// Paths to outputs from java_sdk_library and java_sdk_library_import.
680//
681// Fields that are android.Paths are always set (during GenerateAndroidBuildActions).
682// OptionalPaths are always set by java_sdk_library but may not be set by
683// java_sdk_library_import as not all instances provide that information.
684type scopePaths struct {
685	// The path (represented as Paths for convenience when returning) to the stubs header jar.
686	//
687	// That is the jar that is created by turbine.
688	stubsHeaderPath android.Paths
689
690	// The path (represented as Paths for convenience when returning) to the stubs implementation jar.
691	//
692	// This is not the implementation jar, it still only contains stubs.
693	stubsImplPath android.Paths
694
695	// The dex jar for the stubs.
696	//
697	// This is not the implementation jar, it still only contains stubs.
698	stubsDexJarPath OptionalDexJarPath
699
700	// The exportable dex jar for the stubs.
701	// This is not the implementation jar, it still only contains stubs.
702	// Includes unflagged apis and flagged apis enabled by release configurations.
703	exportableStubsDexJarPath OptionalDexJarPath
704
705	// The API specification file, e.g. system_current.txt.
706	currentApiFilePath android.OptionalPath
707
708	// The specification of API elements removed since the last release.
709	removedApiFilePath android.OptionalPath
710
711	// The stubs source jar.
712	stubsSrcJar android.OptionalPath
713
714	// Extracted annotations.
715	annotationsZip android.OptionalPath
716
717	// The path to the latest API file.
718	latestApiPaths android.Paths
719
720	// The path to the latest removed API file.
721	latestRemovedApiPaths android.Paths
722}
723
724func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
725	if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
726		paths.stubsHeaderPath = lib.HeaderJars
727		paths.stubsImplPath = lib.ImplementationJars
728
729		libDep := dep.(UsesLibraryDependency)
730		paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx)
731		paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx)
732		return nil
733	} else {
734		return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
735	}
736}
737
738func (paths *scopePaths) extractEverythingStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
739	if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
740		paths.stubsHeaderPath = lib.HeaderJars
741		if !ctx.Config().ReleaseHiddenApiExportableStubs() {
742			paths.stubsImplPath = lib.ImplementationJars
743		}
744
745		libDep := dep.(UsesLibraryDependency)
746		paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx)
747		return nil
748	} else {
749		return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
750	}
751}
752
753func (paths *scopePaths) extractExportableStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
754	if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
755		if ctx.Config().ReleaseHiddenApiExportableStubs() {
756			paths.stubsImplPath = lib.ImplementationJars
757		}
758
759		libDep := dep.(UsesLibraryDependency)
760		paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx)
761		return nil
762	} else {
763		return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
764	}
765}
766
767func (paths *scopePaths) treatDepAsApiStubsProvider(dep android.Module, action func(provider ApiStubsProvider) error) error {
768	if apiStubsProvider, ok := dep.(ApiStubsProvider); ok {
769		err := action(apiStubsProvider)
770		if err != nil {
771			return err
772		}
773		return nil
774	} else {
775		return fmt.Errorf("expected module that implements ExportableApiStubsSrcProvider, e.g. droidstubs")
776	}
777}
778
779func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider) error) error {
780	if apiStubsProvider, ok := dep.(ApiStubsSrcProvider); ok {
781		err := action(apiStubsProvider)
782		if err != nil {
783			return err
784		}
785		return nil
786	} else {
787		return fmt.Errorf("expected module that implements ApiStubsSrcProvider, e.g. droidstubs")
788	}
789}
790
791func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider, stubsType StubsType) error {
792	var annotationsZip, currentApiFilePath, removedApiFilePath android.Path
793	annotationsZip, annotationsZipErr := provider.AnnotationsZip(stubsType)
794	currentApiFilePath, currentApiFilePathErr := provider.ApiFilePath(stubsType)
795	removedApiFilePath, removedApiFilePathErr := provider.RemovedApiFilePath(stubsType)
796
797	combinedError := errors.Join(annotationsZipErr, currentApiFilePathErr, removedApiFilePathErr)
798
799	if combinedError == nil {
800		paths.annotationsZip = android.OptionalPathForPath(annotationsZip)
801		paths.currentApiFilePath = android.OptionalPathForPath(currentApiFilePath)
802		paths.removedApiFilePath = android.OptionalPathForPath(removedApiFilePath)
803	}
804	return combinedError
805}
806
807func (paths *scopePaths) extractApiInfoFromDep(ctx android.ModuleContext, dep android.Module) error {
808	return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error {
809		return paths.extractApiInfoFromApiStubsProvider(provider, Everything)
810	})
811}
812
813func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider, stubsType StubsType) error {
814	stubsSrcJar, err := provider.StubsSrcJar(stubsType)
815	if err == nil {
816		paths.stubsSrcJar = android.OptionalPathForPath(stubsSrcJar)
817	}
818	return err
819}
820
821func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext, dep android.Module) error {
822	return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) error {
823		return paths.extractStubsSourceInfoFromApiStubsProviders(provider, Everything)
824	})
825}
826
827func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx android.ModuleContext, dep android.Module) error {
828	if ctx.Config().ReleaseHiddenApiExportableStubs() {
829		return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error {
830			extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(provider, Exportable)
831			extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(provider, Exportable)
832			return errors.Join(extractApiInfoErr, extractStubsSourceInfoErr)
833		})
834	}
835	return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error {
836		extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(provider, Everything)
837		extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(provider, Everything)
838		return errors.Join(extractApiInfoErr, extractStubsSourceInfoErr)
839	})
840}
841
842func extractOutputPaths(dep android.Module) (android.Paths, error) {
843	var paths android.Paths
844	if sourceFileProducer, ok := dep.(android.SourceFileProducer); ok {
845		paths = sourceFileProducer.Srcs()
846		return paths, nil
847	} else {
848		return nil, fmt.Errorf("module %q does not produce source files", dep)
849	}
850}
851
852func (paths *scopePaths) extractLatestApiPath(ctx android.ModuleContext, dep android.Module) error {
853	outputPaths, err := extractOutputPaths(dep)
854	paths.latestApiPaths = outputPaths
855	return err
856}
857
858func (paths *scopePaths) extractLatestRemovedApiPath(ctx android.ModuleContext, dep android.Module) error {
859	outputPaths, err := extractOutputPaths(dep)
860	paths.latestRemovedApiPaths = outputPaths
861	return err
862}
863
864type commonToSdkLibraryAndImportProperties struct {
865	// The naming scheme to use for the components that this module creates.
866	//
867	// If not specified then it defaults to "default".
868	//
869	// This is a temporary mechanism to simplify conversion from separate modules for each
870	// component that follow a different naming pattern to the default one.
871	//
872	// TODO(b/155480189) - Remove once naming inconsistencies have been resolved.
873	Naming_scheme *string
874
875	// Specifies whether this module can be used as an Android shared library; defaults
876	// to true.
877	//
878	// An Android shared library is one that can be referenced in a <uses-library> element
879	// in an AndroidManifest.xml.
880	Shared_library *bool
881
882	// Files containing information about supported java doc tags.
883	Doctag_files []string `android:"path"`
884
885	// Signals that this shared library is part of the bootclasspath starting
886	// on the version indicated in this attribute.
887	//
888	// This will make platforms at this level and above to ignore
889	// <uses-library> tags with this library name because the library is already
890	// available
891	On_bootclasspath_since *string
892
893	// Signals that this shared library was part of the bootclasspath before
894	// (but not including) the version indicated in this attribute.
895	//
896	// The system will automatically add a <uses-library> tag with this library to
897	// apps that target any SDK less than the version indicated in this attribute.
898	On_bootclasspath_before *string
899
900	// Indicates that PackageManager should ignore this shared library if the
901	// platform is below the version indicated in this attribute.
902	//
903	// This means that the device won't recognise this library as installed.
904	Min_device_sdk *string
905
906	// Indicates that PackageManager should ignore this shared library if the
907	// platform is above the version indicated in this attribute.
908	//
909	// This means that the device won't recognise this library as installed.
910	Max_device_sdk *string
911}
912
913// commonSdkLibraryAndImportModule defines the interface that must be provided by a module that
914// embeds the commonToSdkLibraryAndImport struct.
915type commonSdkLibraryAndImportModule interface {
916	android.Module
917
918	// Returns the name of the root java_sdk_library that creates the child stub libraries
919	// This is the `name` as it appears in Android.bp, and not the name in Soong's build graph
920	// (with the prebuilt_ prefix)
921	//
922	// e.g. in the following java_sdk_library_import
923	// java_sdk_library_import {
924	//    name: "framework-foo.v1",
925	//    source_module_name: "framework-foo",
926	// }
927	// the values returned by
928	// 1. Name(): prebuilt_framework-foo.v1 # unique
929	// 2. BaseModuleName(): framework-foo # the source
930	// 3. RootLibraryName: framework-foo.v1 # the undecordated `name` from Android.bp
931	RootLibraryName() string
932}
933
934func (m *SdkLibrary) RootLibraryName() string {
935	return m.BaseModuleName()
936}
937
938func (m *SdkLibraryImport) RootLibraryName() string {
939	// m.BaseModuleName refers to the source of the import
940	// use moduleBase.Name to get the name of the module as it appears in the .bp file
941	return m.ModuleBase.Name()
942}
943
944// Common code between sdk library and sdk library import
945type commonToSdkLibraryAndImport struct {
946	module commonSdkLibraryAndImportModule
947
948	scopePaths map[*apiScope]*scopePaths
949
950	namingScheme sdkLibraryComponentNamingScheme
951
952	commonSdkLibraryProperties commonToSdkLibraryAndImportProperties
953
954	// Paths to commonSdkLibraryProperties.Doctag_files
955	doctagPaths android.Paths
956
957	// Functionality related to this being used as a component of a java_sdk_library.
958	EmbeddableSdkLibraryComponent
959
960	// Path to the header jars of the implementation library
961	// This is non-empty only when api_only is false.
962	implLibraryHeaderJars android.Paths
963
964	// The reference to the implementation library created by the source module.
965	// Is nil if the source module does not exist.
966	implLibraryModule *Library
967}
968
969func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) {
970	c.module = module
971
972	module.AddProperties(&c.commonSdkLibraryProperties)
973
974	// Initialize this as an sdk library component.
975	c.initSdkLibraryComponent(module)
976}
977
978func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool {
979	schemeProperty := proptools.StringDefault(c.commonSdkLibraryProperties.Naming_scheme, "default")
980	switch schemeProperty {
981	case "default":
982		c.namingScheme = &defaultNamingScheme{}
983	default:
984		ctx.PropertyErrorf("naming_scheme", "expected 'default' but was %q", schemeProperty)
985		return false
986	}
987
988	namePtr := proptools.StringPtr(c.module.RootLibraryName())
989	c.sdkLibraryComponentProperties.SdkLibraryName = namePtr
990
991	// Only track this sdk library if this can be used as a shared library.
992	if c.sharedLibrary() {
993		// Use the name specified in the module definition as the owner.
994		c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = namePtr
995	}
996
997	return true
998}
999
1000// uniqueApexVariations provides common implementation of the ApexModule.UniqueApexVariations
1001// method.
1002func (c *commonToSdkLibraryAndImport) uniqueApexVariations() bool {
1003	// A java_sdk_library that is a shared library produces an XML file that makes the shared library
1004	// usable from an AndroidManifest.xml's <uses-library> entry. That XML file contains the name of
1005	// the APEX and so it needs a unique variation per APEX.
1006	return c.sharedLibrary()
1007}
1008
1009func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) {
1010	c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files)
1011}
1012
1013func (c *commonToSdkLibraryAndImport) getImplLibraryModule() *Library {
1014	return c.implLibraryModule
1015}
1016
1017// Module name of the runtime implementation library
1018func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
1019	return c.module.RootLibraryName() + ".impl"
1020}
1021
1022// Module name of the XML file for the lib
1023func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
1024	return c.module.RootLibraryName() + sdkXmlFileSuffix
1025}
1026
1027// Name of the java_library module that compiles the stubs source.
1028func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
1029	baseName := c.module.RootLibraryName()
1030	return c.namingScheme.stubsLibraryModuleName(apiScope, baseName)
1031}
1032
1033// Name of the java_library module that compiles the exportable stubs source.
1034func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string {
1035	baseName := c.module.RootLibraryName()
1036	return c.namingScheme.exportableStubsLibraryModuleName(apiScope, baseName)
1037}
1038
1039// Name of the droidstubs module that generates the stubs source and may also
1040// generate/check the API.
1041func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
1042	baseName := c.module.RootLibraryName()
1043	return c.namingScheme.stubsSourceModuleName(apiScope, baseName)
1044}
1045
1046// Name of the java_api_library module that generates the from-text stubs source
1047// and compiles to a jar file.
1048func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) string {
1049	baseName := c.module.RootLibraryName()
1050	return c.namingScheme.apiLibraryModuleName(apiScope, baseName)
1051}
1052
1053// Name of the java_library module that compiles the stubs
1054// generated from source Java files.
1055func (c *commonToSdkLibraryAndImport) sourceStubsLibraryModuleName(apiScope *apiScope) string {
1056	baseName := c.module.RootLibraryName()
1057	return c.namingScheme.sourceStubsLibraryModuleName(apiScope, baseName)
1058}
1059
1060// Name of the java_library module that compiles the exportable stubs
1061// generated from source Java files.
1062func (c *commonToSdkLibraryAndImport) exportableSourceStubsLibraryModuleName(apiScope *apiScope) string {
1063	baseName := c.module.RootLibraryName()
1064	return c.namingScheme.exportableSourceStubsLibraryModuleName(apiScope, baseName)
1065}
1066
1067// The component names for different outputs of the java_sdk_library.
1068//
1069// They are similar to the names used for the child modules it creates
1070const (
1071	stubsSourceComponentName = "stubs.source"
1072
1073	apiTxtComponentName = "api.txt"
1074
1075	removedApiTxtComponentName = "removed-api.txt"
1076
1077	annotationsComponentName = "annotations.zip"
1078)
1079
1080// A regular expression to match tags that reference a specific stubs component.
1081//
1082// It will only match if given a valid scope and a valid component. It is verfy strict
1083// to ensure it does not accidentally match a similar looking tag that should be processed
1084// by the embedded Library.
1085var tagSplitter = func() *regexp.Regexp {
1086	// Given a list of literal string items returns a regular expression that will
1087	// match any one of the items.
1088	choice := func(items ...string) string {
1089		return `\Q` + strings.Join(items, `\E|\Q`) + `\E`
1090	}
1091
1092	// Regular expression to match one of the scopes.
1093	scopesRegexp := choice(allScopeNames...)
1094
1095	// Regular expression to match one of the components.
1096	componentsRegexp := choice(stubsSourceComponentName, apiTxtComponentName, removedApiTxtComponentName, annotationsComponentName)
1097
1098	// Regular expression to match any combination of one scope and one component.
1099	return regexp.MustCompile(fmt.Sprintf(`^\.(%s)\.(%s)$`, scopesRegexp, componentsRegexp))
1100}()
1101
1102// For OutputFileProducer interface
1103//
1104// .<scope>.<component name>, for all ComponentNames (for example: .public.removed-api.txt)
1105func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Paths, error) {
1106	if groups := tagSplitter.FindStringSubmatch(tag); groups != nil {
1107		scopeName := groups[1]
1108		component := groups[2]
1109
1110		if scope, ok := scopeByName[scopeName]; ok {
1111			paths := c.findScopePaths(scope)
1112			if paths == nil {
1113				return nil, fmt.Errorf("%q does not provide api scope %s", c.module.RootLibraryName(), scopeName)
1114			}
1115
1116			switch component {
1117			case stubsSourceComponentName:
1118				if paths.stubsSrcJar.Valid() {
1119					return android.Paths{paths.stubsSrcJar.Path()}, nil
1120				}
1121
1122			case apiTxtComponentName:
1123				if paths.currentApiFilePath.Valid() {
1124					return android.Paths{paths.currentApiFilePath.Path()}, nil
1125				}
1126
1127			case removedApiTxtComponentName:
1128				if paths.removedApiFilePath.Valid() {
1129					return android.Paths{paths.removedApiFilePath.Path()}, nil
1130				}
1131
1132			case annotationsComponentName:
1133				if paths.annotationsZip.Valid() {
1134					return android.Paths{paths.annotationsZip.Path()}, nil
1135				}
1136			}
1137
1138			return nil, fmt.Errorf("%s not available for api scope %s", component, scopeName)
1139		} else {
1140			return nil, fmt.Errorf("unknown scope %s in %s", scope, tag)
1141		}
1142
1143	} else {
1144		switch tag {
1145		case ".doctags":
1146			if c.doctagPaths != nil {
1147				return c.doctagPaths, nil
1148			} else {
1149				return nil, fmt.Errorf("no doctag_files specified on %s", c.module.RootLibraryName())
1150			}
1151		}
1152		return nil, nil
1153	}
1154}
1155
1156func (c *commonToSdkLibraryAndImport) getScopePathsCreateIfNeeded(scope *apiScope) *scopePaths {
1157	if c.scopePaths == nil {
1158		c.scopePaths = make(map[*apiScope]*scopePaths)
1159	}
1160	paths := c.scopePaths[scope]
1161	if paths == nil {
1162		paths = &scopePaths{}
1163		c.scopePaths[scope] = paths
1164	}
1165
1166	return paths
1167}
1168
1169func (c *commonToSdkLibraryAndImport) findScopePaths(scope *apiScope) *scopePaths {
1170	if c.scopePaths == nil {
1171		return nil
1172	}
1173
1174	return c.scopePaths[scope]
1175}
1176
1177// If this does not support the requested api scope then find the closest available
1178// scope it does support. Returns nil if no such scope is available.
1179func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *scopePaths {
1180	for s := scope; s != nil; s = s.canAccess {
1181		if paths := c.findScopePaths(s); paths != nil {
1182			return paths
1183		}
1184	}
1185
1186	// This should never happen outside tests as public should be the base scope for every
1187	// scope and is enabled by default.
1188	return nil
1189}
1190
1191func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
1192
1193	// If a specific numeric version has been requested then use prebuilt versions of the sdk.
1194	if !sdkVersion.ApiLevel.IsPreview() {
1195		return PrebuiltJars(ctx, c.module.RootLibraryName(), sdkVersion)
1196	}
1197
1198	paths := c.selectScopePaths(ctx, sdkVersion.Kind)
1199	if paths == nil {
1200		return nil
1201	}
1202
1203	return paths.stubsHeaderPath
1204}
1205
1206// selectScopePaths returns the *scopePaths appropriate for the specific kind.
1207//
1208// If the module does not support the specific kind then it will return the *scopePaths for the
1209// closest kind which is a subset of the requested kind. e.g. if requesting android.SdkModule then
1210// it will return *scopePaths for android.SdkSystem if available or android.SdkPublic of not.
1211func (c *commonToSdkLibraryAndImport) selectScopePaths(ctx android.BaseModuleContext, kind android.SdkKind) *scopePaths {
1212	apiScope := sdkKindToApiScope(kind)
1213
1214	paths := c.findClosestScopePath(apiScope)
1215	if paths == nil {
1216		var scopes []string
1217		for _, s := range AllApiScopes {
1218			if c.findScopePaths(s) != nil {
1219				scopes = append(scopes, s.name)
1220			}
1221		}
1222		ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.RootLibraryName(), scopes)
1223		return nil
1224	}
1225
1226	return paths
1227}
1228
1229// sdkKindToApiScope maps from android.SdkKind to apiScope.
1230func sdkKindToApiScope(kind android.SdkKind) *apiScope {
1231	var apiScope *apiScope
1232	switch kind {
1233	case android.SdkSystem:
1234		apiScope = apiScopeSystem
1235	case android.SdkModule:
1236		apiScope = apiScopeModuleLib
1237	case android.SdkTest:
1238		apiScope = apiScopeTest
1239	case android.SdkSystemServer:
1240		apiScope = apiScopeSystemServer
1241	default:
1242		apiScope = apiScopePublic
1243	}
1244	return apiScope
1245}
1246
1247// to satisfy SdkLibraryDependency interface
1248func (c *commonToSdkLibraryAndImport) SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath {
1249	paths := c.selectScopePaths(ctx, kind)
1250	if paths == nil {
1251		return makeUnsetDexJarPath()
1252	}
1253
1254	return paths.stubsDexJarPath
1255}
1256
1257// to satisfy SdkLibraryDependency interface
1258func (c *commonToSdkLibraryAndImport) SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath {
1259	paths := c.selectScopePaths(ctx, kind)
1260	if paths == nil {
1261		return makeUnsetDexJarPath()
1262	}
1263
1264	return paths.exportableStubsDexJarPath
1265}
1266
1267// to satisfy SdkLibraryDependency interface
1268func (c *commonToSdkLibraryAndImport) SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath {
1269	apiScope := sdkKindToApiScope(kind)
1270	paths := c.findScopePaths(apiScope)
1271	if paths == nil {
1272		return android.OptionalPath{}
1273	}
1274
1275	return paths.removedApiFilePath
1276}
1277
1278func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} {
1279	componentProps := &struct {
1280		SdkLibraryName              *string
1281		SdkLibraryToImplicitlyTrack *string
1282	}{}
1283
1284	namePtr := proptools.StringPtr(c.module.RootLibraryName())
1285	componentProps.SdkLibraryName = namePtr
1286
1287	if c.sharedLibrary() {
1288		// Mark the stubs library as being components of this java_sdk_library so that
1289		// any app that includes code which depends (directly or indirectly) on the stubs
1290		// library will have the appropriate <uses-library> invocation inserted into its
1291		// manifest if necessary.
1292		componentProps.SdkLibraryToImplicitlyTrack = namePtr
1293	}
1294
1295	return componentProps
1296}
1297
1298func (c *commonToSdkLibraryAndImport) sharedLibrary() bool {
1299	return proptools.BoolDefault(c.commonSdkLibraryProperties.Shared_library, true)
1300}
1301
1302// Check if the stub libraries should be compiled for dex
1303func (c *commonToSdkLibraryAndImport) stubLibrariesCompiledForDex() bool {
1304	// Always compile the dex file files for the stub libraries if they will be used on the
1305	// bootclasspath.
1306	return !c.sharedLibrary()
1307}
1308
1309// Properties related to the use of a module as an component of a java_sdk_library.
1310type SdkLibraryComponentProperties struct {
1311	// The name of the java_sdk_library/_import module.
1312	SdkLibraryName *string `blueprint:"mutated"`
1313
1314	// The name of the java_sdk_library/_import to add to a <uses-library> entry
1315	// in the AndroidManifest.xml of any Android app that includes code that references
1316	// this module. If not set then no java_sdk_library/_import is tracked.
1317	SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"`
1318}
1319
1320// Structure to be embedded in a module struct that needs to support the
1321// SdkLibraryComponentDependency interface.
1322type EmbeddableSdkLibraryComponent struct {
1323	sdkLibraryComponentProperties SdkLibraryComponentProperties
1324}
1325
1326func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(module android.Module) {
1327	module.AddProperties(&e.sdkLibraryComponentProperties)
1328}
1329
1330// to satisfy SdkLibraryComponentDependency
1331func (e *EmbeddableSdkLibraryComponent) SdkLibraryName() *string {
1332	return e.sdkLibraryComponentProperties.SdkLibraryName
1333}
1334
1335// to satisfy SdkLibraryComponentDependency
1336func (e *EmbeddableSdkLibraryComponent) OptionalSdkLibraryImplementation() *string {
1337	// For shared libraries, this is the same as the SDK library name. If a Java library or app
1338	// depends on a component library (e.g. a stub library) it still needs to know the name of the
1339	// run-time library and the corresponding module that provides the implementation. This name is
1340	// passed to manifest_fixer (to be added to AndroidManifest.xml) and added to CLC (to be used
1341	// in dexpreopt).
1342	//
1343	// For non-shared SDK (component or not) libraries this returns `nil`, as they are not
1344	// <uses-library> and should not be added to the manifest or to CLC.
1345	return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
1346}
1347
1348// Implemented by modules that are (or possibly could be) a component of a java_sdk_library
1349// (including the java_sdk_library) itself.
1350type SdkLibraryComponentDependency interface {
1351	UsesLibraryDependency
1352
1353	// SdkLibraryName returns the name of the java_sdk_library/_import module.
1354	SdkLibraryName() *string
1355
1356	// The name of the implementation library for the optional SDK library or nil, if there isn't one.
1357	OptionalSdkLibraryImplementation() *string
1358}
1359
1360// Make sure that all the module types that are components of java_sdk_library/_import
1361// and which can be referenced (directly or indirectly) from an android app implement
1362// the SdkLibraryComponentDependency interface.
1363var _ SdkLibraryComponentDependency = (*Library)(nil)
1364var _ SdkLibraryComponentDependency = (*Import)(nil)
1365var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil)
1366var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil)
1367
1368// Provides access to sdk_version related files, e.g. header and implementation jars.
1369type SdkLibraryDependency interface {
1370	SdkLibraryComponentDependency
1371
1372	// Get the header jars appropriate for the supplied sdk_version.
1373	//
1374	// These are turbine generated jars so they only change if the externals of the
1375	// class changes but it does not contain and implementation or JavaDoc.
1376	SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
1377
1378	// SdkApiStubDexJar returns the dex jar for the stubs for the prebuilt
1379	// java_sdk_library_import module. It is needed by the hiddenapi processing tool which
1380	// processes dex files.
1381	SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath
1382
1383	// SdkApiExportableStubDexJar returns the exportable dex jar for the stubs for
1384	// java_sdk_library module. It is needed by the hiddenapi processing tool which processes
1385	// dex files.
1386	SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath
1387
1388	// SdkRemovedTxtFile returns the optional path to the removed.txt file for the specified sdk kind.
1389	SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath
1390
1391	// sharedLibrary returns true if this can be used as a shared library.
1392	sharedLibrary() bool
1393
1394	getImplLibraryModule() *Library
1395}
1396
1397type SdkLibrary struct {
1398	Library
1399
1400	sdkLibraryProperties sdkLibraryProperties
1401
1402	// Map from api scope to the scope specific property structure.
1403	scopeToProperties map[*apiScope]*ApiScopeProperties
1404
1405	commonToSdkLibraryAndImport
1406
1407	builtInstalledForApex []dexpreopterInstall
1408}
1409
1410var _ SdkLibraryDependency = (*SdkLibrary)(nil)
1411
1412func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool {
1413	return module.sdkLibraryProperties.Generate_system_and_test_apis
1414}
1415
1416func (module *SdkLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
1417	if module.implLibraryModule != nil {
1418		return module.implLibraryModule.DexJarBuildPath(ctx)
1419	}
1420	return makeUnsetDexJarPath()
1421}
1422
1423func (module *SdkLibrary) DexJarInstallPath() android.Path {
1424	if module.implLibraryModule != nil {
1425		return module.implLibraryModule.DexJarInstallPath()
1426	}
1427	return nil
1428}
1429
1430func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) apiScopes {
1431	// Check to see if any scopes have been explicitly enabled. If any have then all
1432	// must be.
1433	anyScopesExplicitlyEnabled := false
1434	for _, scope := range AllApiScopes {
1435		scopeProperties := module.scopeToProperties[scope]
1436		if scopeProperties.Enabled != nil {
1437			anyScopesExplicitlyEnabled = true
1438			break
1439		}
1440	}
1441
1442	var generatedScopes apiScopes
1443	enabledScopes := make(map[*apiScope]struct{})
1444	for _, scope := range AllApiScopes {
1445		scopeProperties := module.scopeToProperties[scope]
1446		// If any scopes are explicitly enabled then ignore the legacy enabled status.
1447		// This is to ensure that any new usages of this module type do not rely on legacy
1448		// behaviour.
1449		defaultEnabledStatus := false
1450		if anyScopesExplicitlyEnabled {
1451			defaultEnabledStatus = scope.defaultEnabledStatus
1452		} else {
1453			defaultEnabledStatus = scope.legacyEnabledStatus(module)
1454		}
1455		enabled := proptools.BoolDefault(scopeProperties.Enabled, defaultEnabledStatus)
1456		if enabled {
1457			enabledScopes[scope] = struct{}{}
1458			generatedScopes = append(generatedScopes, scope)
1459		}
1460	}
1461
1462	// Now check to make sure that any scope that is extended by an enabled scope is also
1463	// enabled.
1464	for _, scope := range AllApiScopes {
1465		if _, ok := enabledScopes[scope]; ok {
1466			extends := scope.extends
1467			if extends != nil {
1468				if _, ok := enabledScopes[extends]; !ok {
1469					ctx.ModuleErrorf("enabled api scope %q depends on disabled scope %q", scope, extends)
1470				}
1471			}
1472		}
1473	}
1474
1475	return generatedScopes
1476}
1477
1478var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil)
1479
1480func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) {
1481	CheckMinSdkVersion(ctx, &module.Library)
1482}
1483
1484func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) {
1485	android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.ModuleContext, do android.PayloadDepsCallback) {
1486		ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
1487			isExternal := !module.depIsInSameApex(ctx, child)
1488			if am, ok := child.(android.ApexModule); ok {
1489				if !do(ctx, parent, am, isExternal) {
1490					return false
1491				}
1492			}
1493			return !isExternal
1494		})
1495	})
1496}
1497
1498type sdkLibraryComponentTag struct {
1499	blueprint.BaseDependencyTag
1500	name string
1501}
1502
1503// Mark this tag so dependencies that use it are excluded from visibility enforcement.
1504func (t sdkLibraryComponentTag) ExcludeFromVisibilityEnforcement() {}
1505
1506var xmlPermissionsFileTag = sdkLibraryComponentTag{name: "xml-permissions-file"}
1507
1508func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool {
1509	if dt, ok := depTag.(sdkLibraryComponentTag); ok {
1510		return dt == xmlPermissionsFileTag
1511	}
1512	return false
1513}
1514
1515var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"}
1516
1517var _ android.InstallNeededDependencyTag = sdkLibraryComponentTag{}
1518
1519// To satisfy the CopyDirectlyInAnyApexTag interface. Implementation library of the sdk library
1520// in an apex is considered to be directly in the apex, as if it was listed in java_libs.
1521func (t sdkLibraryComponentTag) CopyDirectlyInAnyApex() {}
1522
1523var _ android.CopyDirectlyInAnyApexTag = implLibraryTag
1524
1525func (t sdkLibraryComponentTag) InstallDepNeeded() bool {
1526	return t.name == "xml-permissions-file" || t.name == "impl-library"
1527}
1528
1529// Add the dependencies on the child modules in the component deps mutator.
1530func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
1531	for _, apiScope := range module.getGeneratedApiScopes(ctx) {
1532		// Add dependencies to the stubs library
1533		stubModuleName := module.stubsLibraryModuleName(apiScope)
1534		ctx.AddVariationDependencies(nil, apiScope.everythingStubsTag, stubModuleName)
1535
1536		exportableStubModuleName := module.exportableStubsLibraryModuleName(apiScope)
1537		ctx.AddVariationDependencies(nil, apiScope.exportableStubsTag, exportableStubModuleName)
1538
1539		// Add a dependency on the stubs source in order to access both stubs source and api information.
1540		ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope))
1541
1542		if module.compareAgainstLatestApi(apiScope) {
1543			// Add dependencies on the latest finalized version of the API .txt file.
1544			latestApiModuleName := module.latestApiModuleName(apiScope)
1545			ctx.AddDependency(module, apiScope.latestApiModuleTag, latestApiModuleName)
1546
1547			// Add dependencies on the latest finalized version of the remove API .txt file.
1548			latestRemovedApiModuleName := module.latestRemovedApiModuleName(apiScope)
1549			ctx.AddDependency(module, apiScope.latestRemovedApiModuleTag, latestRemovedApiModuleName)
1550		}
1551	}
1552
1553	if module.requiresRuntimeImplementationLibrary() {
1554		// Add dependency to the rule for generating the implementation library.
1555		ctx.AddDependency(module, implLibraryTag, module.implLibraryModuleName())
1556
1557		if module.sharedLibrary() {
1558			// Add dependency to the rule for generating the xml permissions file
1559			ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlPermissionsModuleName())
1560		}
1561	}
1562}
1563
1564// Add other dependencies as normal.
1565func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
1566	var missingApiModules []string
1567	for _, apiScope := range module.getGeneratedApiScopes(ctx) {
1568		if apiScope.unstable {
1569			continue
1570		}
1571		if m := module.latestApiModuleName(apiScope); !ctx.OtherModuleExists(m) {
1572			missingApiModules = append(missingApiModules, m)
1573		}
1574		if m := module.latestRemovedApiModuleName(apiScope); !ctx.OtherModuleExists(m) {
1575			missingApiModules = append(missingApiModules, m)
1576		}
1577		if m := module.latestIncompatibilitiesModuleName(apiScope); !ctx.OtherModuleExists(m) {
1578			missingApiModules = append(missingApiModules, m)
1579		}
1580	}
1581	if len(missingApiModules) != 0 && !module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api {
1582		m := module.Name() + " is missing tracking files for previously released library versions.\n"
1583		m += "You need to do one of the following:\n"
1584		m += "- Add `unsafe_ignore_missing_latest_api: true` to your blueprint (to disable compat tracking)\n"
1585		m += "- Add a set of prebuilt txt files representing the last released version of this library for compat checking.\n"
1586		m += "  (the current set of API files can be used as a seed for this compatibility tracking\n"
1587		m += "\n"
1588		m += "The following filegroup modules are missing:\n  "
1589		m += strings.Join(missingApiModules, "\n  ") + "\n"
1590		m += "Please see the documentation of the prebuilt_apis module type (and a usage example in prebuilts/sdk) for a convenient way to generate these."
1591		ctx.ModuleErrorf(m)
1592	}
1593}
1594
1595func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
1596	paths, err := module.commonOutputFiles(tag)
1597	if paths != nil || err != nil {
1598		return paths, err
1599	}
1600	if module.requiresRuntimeImplementationLibrary() {
1601		return module.implLibraryModule.OutputFiles(tag)
1602	}
1603	if tag == "" {
1604		return nil, nil
1605	}
1606	return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1607}
1608
1609func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1610	if disableSourceApexVariant(ctx) {
1611		// Prebuilts are active, do not create the installation rules for the source javalib.
1612		// Even though the source javalib is not used, we need to hide it to prevent duplicate installation rules.
1613		// TODO (b/331665856): Implement a principled solution for this.
1614		module.HideFromMake()
1615	}
1616
1617	module.generateCommonBuildActions(ctx)
1618
1619	module.stem = proptools.StringDefault(module.overridableProperties.Stem, ctx.ModuleName())
1620
1621	module.provideHiddenAPIPropertyInfo(ctx)
1622
1623	// Collate the components exported by this module. All scope specific modules are exported but
1624	// the impl and xml component modules are not.
1625	exportedComponents := map[string]struct{}{}
1626
1627	// Record the paths to the header jars of the library (stubs and impl).
1628	// When this java_sdk_library is depended upon from others via "libs" property,
1629	// the recorded paths will be returned depending on the link type of the caller.
1630	ctx.VisitDirectDeps(func(to android.Module) {
1631		tag := ctx.OtherModuleDependencyTag(to)
1632
1633		// Extract information from any of the scope specific dependencies.
1634		if scopeTag, ok := tag.(scopeDependencyTag); ok {
1635			apiScope := scopeTag.apiScope
1636			scopePaths := module.getScopePathsCreateIfNeeded(apiScope)
1637
1638			// Extract information from the dependency. The exact information extracted
1639			// is determined by the nature of the dependency which is determined by the tag.
1640			scopeTag.extractDepInfo(ctx, to, scopePaths)
1641
1642			exportedComponents[ctx.OtherModuleName(to)] = struct{}{}
1643		}
1644
1645		if tag == implLibraryTag {
1646			if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok {
1647				module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...)
1648				module.implLibraryModule = to.(*Library)
1649				android.SetProvider(ctx, JavaInfoProvider, dep)
1650			}
1651		}
1652	})
1653
1654	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
1655	if !apexInfo.IsForPlatform() {
1656		module.hideApexVariantFromMake = true
1657	}
1658
1659	if module.implLibraryModule != nil {
1660		if ctx.Device() {
1661			module.classesJarPaths = android.Paths{module.implLibraryModule.implementationJarFile}
1662			module.bootDexJarPath = module.implLibraryModule.bootDexJarPath
1663			module.uncompressDexState = module.implLibraryModule.uncompressDexState
1664			module.active = module.implLibraryModule.active
1665		}
1666
1667		module.outputFile = module.implLibraryModule.outputFile
1668		module.dexJarFile = makeDexJarPathFromPath(module.implLibraryModule.dexJarFile.Path())
1669		module.headerJarFile = module.implLibraryModule.headerJarFile
1670		module.implementationAndResourcesJar = module.implLibraryModule.implementationAndResourcesJar
1671		module.builtInstalledForApex = module.implLibraryModule.builtInstalledForApex
1672		module.dexpreopter.configPath = module.implLibraryModule.dexpreopter.configPath
1673		module.dexpreopter.outputProfilePathOnHost = module.implLibraryModule.dexpreopter.outputProfilePathOnHost
1674
1675		// Properties required for Library.AndroidMkEntries
1676		module.logtagsSrcs = module.implLibraryModule.logtagsSrcs
1677		module.dexpreopter.builtInstalled = module.implLibraryModule.dexpreopter.builtInstalled
1678		module.jacocoReportClassesFile = module.implLibraryModule.jacocoReportClassesFile
1679		module.dexer.proguardDictionary = module.implLibraryModule.dexer.proguardDictionary
1680		module.dexer.proguardUsageZip = module.implLibraryModule.dexer.proguardUsageZip
1681		module.linter.reports = module.implLibraryModule.linter.reports
1682
1683		if !module.Host() {
1684			module.hostdexInstallFile = module.implLibraryModule.hostdexInstallFile
1685		}
1686
1687		android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: module.implLibraryModule.uniqueSrcFiles.Strings()})
1688	}
1689
1690	// Make the set of components exported by this module available for use elsewhere.
1691	exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedKeys(exportedComponents)}
1692	android.SetProvider(ctx, android.ExportedComponentsInfoProvider, exportedComponentInfo)
1693
1694	// Provide additional information for inclusion in an sdk's generated .info file.
1695	additionalSdkInfo := map[string]interface{}{}
1696	additionalSdkInfo["dist_stem"] = module.distStem()
1697	baseModuleName := module.distStem()
1698	scopes := map[string]interface{}{}
1699	additionalSdkInfo["scopes"] = scopes
1700	for scope, scopePaths := range module.scopePaths {
1701		scopeInfo := map[string]interface{}{}
1702		scopes[scope.name] = scopeInfo
1703		scopeInfo["current_api"] = scope.snapshotRelativeCurrentApiTxtPath(baseModuleName)
1704		scopeInfo["removed_api"] = scope.snapshotRelativeRemovedApiTxtPath(baseModuleName)
1705		if p := scopePaths.latestApiPaths; len(p) > 0 {
1706			// The last path in the list is the one that applies to this scope, the
1707			// preceding ones, if any, are for the scope(s) that it extends.
1708			scopeInfo["latest_api"] = p[len(p)-1].String()
1709		}
1710		if p := scopePaths.latestRemovedApiPaths; len(p) > 0 {
1711			// The last path in the list is the one that applies to this scope, the
1712			// preceding ones, if any, are for the scope(s) that it extends.
1713			scopeInfo["latest_removed_api"] = p[len(p)-1].String()
1714		}
1715	}
1716	android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo})
1717}
1718
1719func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall {
1720	return module.builtInstalledForApex
1721}
1722
1723func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
1724	if !module.requiresRuntimeImplementationLibrary() {
1725		return nil
1726	}
1727	entriesList := module.Library.AndroidMkEntries()
1728	entries := &entriesList[0]
1729	entries.Required = append(entries.Required, module.implLibraryModuleName())
1730	if module.sharedLibrary() {
1731		entries.Required = append(entries.Required, module.xmlPermissionsModuleName())
1732	}
1733	return entriesList
1734}
1735
1736// The dist path of the stub artifacts
1737func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string {
1738	return path.Join("apistubs", module.distGroup(), apiScope.name)
1739}
1740
1741// Get the sdk version for use when compiling the stubs library.
1742func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.EarlyModuleContext, apiScope *apiScope) string {
1743	scopeProperties := module.scopeToProperties[apiScope]
1744	if scopeProperties.Sdk_version != nil {
1745		return proptools.String(scopeProperties.Sdk_version)
1746	}
1747
1748	sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library))
1749	if sdkDep.hasStandardLibs() {
1750		// If building against a standard sdk then use the sdk version appropriate for the scope.
1751		return apiScope.sdkVersion
1752	} else {
1753		// Otherwise, use no system module.
1754		return "none"
1755	}
1756}
1757
1758func (module *SdkLibrary) distStem() string {
1759	return proptools.StringDefault(module.sdkLibraryProperties.Dist_stem, module.BaseModuleName())
1760}
1761
1762// distGroup returns the subdirectory of the dist path of the stub artifacts.
1763func (module *SdkLibrary) distGroup() string {
1764	return proptools.StringDefault(module.sdkLibraryProperties.Dist_group, "unknown")
1765}
1766
1767func latestPrebuiltApiModuleName(name string, apiScope *apiScope) string {
1768	return PrebuiltApiModuleName(name, apiScope.name, "latest")
1769}
1770
1771func latestPrebuiltApiCombinedModuleName(name string, apiScope *apiScope) string {
1772	return PrebuiltApiCombinedModuleName(name, apiScope.name, "latest")
1773}
1774
1775func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string {
1776	return ":" + module.latestApiModuleName(apiScope)
1777}
1778
1779func (module *SdkLibrary) latestApiModuleName(apiScope *apiScope) string {
1780	return latestPrebuiltApiCombinedModuleName(module.distStem(), apiScope)
1781}
1782
1783func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) string {
1784	return ":" + module.latestRemovedApiModuleName(apiScope)
1785}
1786
1787func (module *SdkLibrary) latestRemovedApiModuleName(apiScope *apiScope) string {
1788	return latestPrebuiltApiCombinedModuleName(module.distStem()+"-removed", apiScope)
1789}
1790
1791func (module *SdkLibrary) latestIncompatibilitiesFilegroupName(apiScope *apiScope) string {
1792	return ":" + module.latestIncompatibilitiesModuleName(apiScope)
1793}
1794
1795func (module *SdkLibrary) latestIncompatibilitiesModuleName(apiScope *apiScope) string {
1796	return latestPrebuiltApiModuleName(module.distStem()+"-incompatibilities", apiScope)
1797}
1798
1799func (module *SdkLibrary) contributesToApiSurface(c android.Config) bool {
1800	_, exists := c.GetApiLibraries()[module.Name()]
1801	return exists
1802}
1803
1804// The listed modules are the special java_sdk_libraries where apiScope.kind do not match the
1805// api surface that the module contribute to. For example, the public droidstubs and java_library
1806// do not contribute to the public api surface, but contributes to the core platform api surface.
1807// This method returns the full api surface stub lib that
1808// the generated java_api_library should depend on.
1809func (module *SdkLibrary) alternativeFullApiSurfaceStubLib() string {
1810	if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok {
1811		return val.FullApiSurfaceStubLib
1812	}
1813	return ""
1814}
1815
1816// The listed modules' stubs contents do not match the corresponding txt files,
1817// but require additional api contributions to generate the full stubs.
1818// This method returns the name of the additional api contribution module
1819// for corresponding sdk_library modules.
1820func (module *SdkLibrary) apiLibraryAdditionalApiContribution() string {
1821	if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok {
1822		return val.AdditionalApiContribution
1823	}
1824	return ""
1825}
1826
1827func childModuleVisibility(childVisibility []string) []string {
1828	if childVisibility == nil {
1829		// No child visibility set. The child will use the visibility of the sdk_library.
1830		return nil
1831	}
1832
1833	// Prepend an override to ignore the sdk_library's visibility, and rely on the child visibility.
1834	var visibility []string
1835	visibility = append(visibility, "//visibility:override")
1836	visibility = append(visibility, childVisibility...)
1837	return visibility
1838}
1839
1840// Creates the implementation java library
1841func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
1842	visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility)
1843
1844	props := struct {
1845		Name           *string
1846		Visibility     []string
1847		Libs           []string
1848		Static_libs    []string
1849		Apex_available []string
1850		Stem           *string
1851	}{
1852		Name:       proptools.StringPtr(module.implLibraryModuleName()),
1853		Visibility: visibility,
1854
1855		Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...),
1856
1857		Static_libs: append(module.properties.Static_libs, module.sdkLibraryProperties.Impl_only_static_libs...),
1858		// Pass the apex_available settings down so that the impl library can be statically
1859		// embedded within a library that is added to an APEX. Needed for updatable-media.
1860		Apex_available: module.ApexAvailable(),
1861
1862		Stem: proptools.StringPtr(module.Name()),
1863	}
1864
1865	properties := []interface{}{
1866		&module.properties,
1867		&module.protoProperties,
1868		&module.deviceProperties,
1869		&module.dexProperties,
1870		&module.dexpreoptProperties,
1871		&module.linter.properties,
1872		&module.overridableProperties,
1873		&props,
1874		module.sdkComponentPropertiesForChildLibrary(),
1875	}
1876	mctx.CreateModule(LibraryFactory, properties...)
1877}
1878
1879type libraryProperties struct {
1880	Name           *string
1881	Visibility     []string
1882	Srcs           []string
1883	Installable    *bool
1884	Sdk_version    *string
1885	System_modules *string
1886	Patch_module   *string
1887	Libs           []string
1888	Static_libs    []string
1889	Compile_dex    *bool
1890	Java_version   *string
1891	Openjdk9       struct {
1892		Srcs       []string
1893		Javacflags []string
1894	}
1895	Dist struct {
1896		Targets []string
1897		Dest    *string
1898		Dir     *string
1899		Tag     *string
1900	}
1901	Is_stubs_module *bool
1902}
1903
1904func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
1905	props := libraryProperties{}
1906	props.Visibility = []string{"//visibility:override", "//visibility:private"}
1907	// sources are generated from the droiddoc
1908	sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
1909	props.Sdk_version = proptools.StringPtr(sdkVersion)
1910	props.System_modules = module.deviceProperties.System_modules
1911	props.Patch_module = module.properties.Patch_module
1912	props.Installable = proptools.BoolPtr(false)
1913	props.Libs = module.sdkLibraryProperties.Stub_only_libs
1914	props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
1915	props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
1916	// The stub-annotations library contains special versions of the annotations
1917	// with CLASS retention policy, so that they're kept.
1918	if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) {
1919		props.Libs = append(props.Libs, "stub-annotations")
1920	}
1921	props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
1922	props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
1923	// We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
1924	// interop with older developer tools that don't support 1.9.
1925	props.Java_version = proptools.StringPtr("1.8")
1926	props.Is_stubs_module = proptools.BoolPtr(true)
1927
1928	return props
1929}
1930
1931// Creates a static java library that has API stubs
1932func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
1933
1934	props := module.stubsLibraryProps(mctx, apiScope)
1935	props.Name = proptools.StringPtr(module.sourceStubsLibraryModuleName(apiScope))
1936	props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
1937
1938	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
1939}
1940
1941// Create a static java library that compiles the "exportable" stubs
1942func (module *SdkLibrary) createExportableStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
1943	props := module.stubsLibraryProps(mctx, apiScope)
1944	props.Name = proptools.StringPtr(module.exportableSourceStubsLibraryModuleName(apiScope))
1945	props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope) + "{.exportable}"}
1946
1947	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
1948}
1949
1950// Creates a droidstubs module that creates stubs source files from the given full source
1951// files and also updates and checks the API specification files.
1952func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) {
1953	props := struct {
1954		Name                             *string
1955		Visibility                       []string
1956		Srcs                             []string
1957		Installable                      *bool
1958		Sdk_version                      *string
1959		Api_surface                      *string
1960		System_modules                   *string
1961		Libs                             []string
1962		Output_javadoc_comments          *bool
1963		Arg_files                        []string
1964		Args                             *string
1965		Java_version                     *string
1966		Annotations_enabled              *bool
1967		Merge_annotations_dirs           []string
1968		Merge_inclusion_annotations_dirs []string
1969		Generate_stubs                   *bool
1970		Previous_api                     *string
1971		Aconfig_declarations             []string
1972		Check_api                        struct {
1973			Current       ApiToCheck
1974			Last_released ApiToCheck
1975
1976			Api_lint struct {
1977				Enabled       *bool
1978				New_since     *string
1979				Baseline_file *string
1980			}
1981		}
1982		Aidl struct {
1983			Include_dirs       []string
1984			Local_include_dirs []string
1985		}
1986		Dists []android.Dist
1987	}{}
1988
1989	// The stubs source processing uses the same compile time classpath when extracting the
1990	// API from the implementation library as it does when compiling it. i.e. the same
1991	// * sdk version
1992	// * system_modules
1993	// * libs (static_libs/libs)
1994
1995	props.Name = proptools.StringPtr(name)
1996	props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility)
1997	props.Srcs = append(props.Srcs, module.properties.Srcs...)
1998	props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...)
1999	props.Sdk_version = module.deviceProperties.Sdk_version
2000	props.Api_surface = &apiScope.name
2001	props.System_modules = module.deviceProperties.System_modules
2002	props.Installable = proptools.BoolPtr(false)
2003	// A droiddoc module has only one Libs property and doesn't distinguish between
2004	// shared libs and static libs. So we need to add both of these libs to Libs property.
2005	props.Libs = module.properties.Libs
2006	props.Libs = append(props.Libs, module.properties.Static_libs...)
2007	props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
2008	props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
2009	props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
2010	props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
2011	props.Java_version = module.properties.Java_version
2012
2013	props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
2014	props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
2015	props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
2016	props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations
2017
2018	droidstubsArgs := []string{}
2019	if len(module.sdkLibraryProperties.Api_packages) != 0 {
2020		droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
2021	}
2022	if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 {
2023		droidstubsArgs = append(droidstubsArgs,
2024			android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package "))
2025	}
2026	droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
2027	disabledWarnings := []string{"HiddenSuperclass"}
2028	if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) {
2029		disabledWarnings = append(disabledWarnings,
2030			"BroadcastBehavior",
2031			"DeprecationMismatch",
2032			"MissingPermission",
2033			"SdkConstant",
2034			"Todo",
2035		)
2036	}
2037	droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
2038
2039	// Output Javadoc comments for public scope.
2040	if apiScope == apiScopePublic {
2041		props.Output_javadoc_comments = proptools.BoolPtr(true)
2042	}
2043
2044	// Add in scope specific arguments.
2045	droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
2046	props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
2047	props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
2048
2049	// List of APIs identified from the provided source files are created. They are later
2050	// compared against to the not-yet-released (a.k.a current) list of APIs and to the
2051	// last-released (a.k.a numbered) list of API.
2052	currentApiFileName := apiScope.apiFilePrefix + "current.txt"
2053	removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
2054	apiDir := module.getApiDir()
2055	currentApiFileName = path.Join(apiDir, currentApiFileName)
2056	removedApiFileName = path.Join(apiDir, removedApiFileName)
2057
2058	// check against the not-yet-release API
2059	props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
2060	props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
2061
2062	if module.compareAgainstLatestApi(apiScope) {
2063		// check against the latest released API
2064		latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
2065		props.Previous_api = latestApiFilegroupName
2066		props.Check_api.Last_released.Api_file = latestApiFilegroupName
2067		props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
2068			module.latestRemovedApiFilegroupName(apiScope))
2069		props.Check_api.Last_released.Baseline_file = proptools.StringPtr(
2070			module.latestIncompatibilitiesFilegroupName(apiScope))
2071
2072		if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
2073			// Enable api lint.
2074			props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true)
2075			props.Check_api.Api_lint.New_since = latestApiFilegroupName
2076
2077			// If it exists then pass a lint-baseline.txt through to droidstubs.
2078			baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt")
2079			baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath)
2080			paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil)
2081			if err != nil {
2082				mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err)
2083			}
2084			if len(paths) == 1 {
2085				props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath)
2086			} else if len(paths) != 0 {
2087				mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths)
2088			}
2089		}
2090	}
2091
2092	if !Bool(module.sdkLibraryProperties.No_dist) {
2093		// Dist the api txt and removed api txt artifacts for sdk builds.
2094		distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
2095		stubsTypeTagPrefix := ""
2096		if mctx.Config().ReleaseHiddenApiExportableStubs() {
2097			stubsTypeTagPrefix = ".exportable"
2098		}
2099		for _, p := range []struct {
2100			tag     string
2101			pattern string
2102		}{
2103			// "exportable" api files are copied to the dist directory instead of the
2104			// "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag
2105			// is set. Otherwise, the "everything" api files are copied to the dist directory.
2106			{tag: "%s.api.txt", pattern: "%s.txt"},
2107			{tag: "%s.removed-api.txt", pattern: "%s-removed.txt"},
2108		} {
2109			props.Dists = append(props.Dists, android.Dist{
2110				Targets: []string{"sdk", "win_sdk"},
2111				Dir:     distDir,
2112				Dest:    proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
2113				Tag:     proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)),
2114			})
2115		}
2116	}
2117
2118	mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx)
2119}
2120
2121func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope, alternativeFullApiSurfaceStub string) {
2122	props := struct {
2123		Name                  *string
2124		Visibility            []string
2125		Api_contributions     []string
2126		Libs                  []string
2127		Static_libs           []string
2128		Full_api_surface_stub *string
2129		System_modules        *string
2130		Enable_validation     *bool
2131		Stubs_type            *string
2132	}{}
2133
2134	props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
2135	props.Visibility = []string{"//visibility:override", "//visibility:private"}
2136
2137	apiContributions := []string{}
2138
2139	// Api surfaces are not independent of each other, but have subset relationships,
2140	// and so does the api files. To generate from-text stubs for api surfaces other than public,
2141	// all subset api domains' api_contriubtions must be added as well.
2142	scope := apiScope
2143	for scope != nil {
2144		apiContributions = append(apiContributions, module.stubsSourceModuleName(scope)+".api.contribution")
2145		scope = scope.extends
2146	}
2147	if apiScope == apiScopePublic {
2148		additionalApiContribution := module.apiLibraryAdditionalApiContribution()
2149		if additionalApiContribution != "" {
2150			apiContributions = append(apiContributions, additionalApiContribution)
2151		}
2152	}
2153
2154	props.Api_contributions = apiContributions
2155	props.Libs = module.properties.Libs
2156	props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
2157	props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
2158	props.Libs = append(props.Libs, "stub-annotations")
2159	props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
2160	props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName())
2161	if alternativeFullApiSurfaceStub != "" {
2162		props.Full_api_surface_stub = proptools.StringPtr(alternativeFullApiSurfaceStub)
2163	}
2164
2165	// android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n.
2166	// Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains.
2167	if apiScope.kind == android.SdkModule {
2168		props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text")
2169	}
2170
2171	// java_sdk_library modules that set sdk_version as none does not depend on other api
2172	// domains. Therefore, java_api_library created from such modules should not depend on
2173	// full_api_surface_stubs but create and compile stubs by the java_api_library module
2174	// itself.
2175	if module.SdkVersion(mctx).Kind == android.SdkNone {
2176		props.Full_api_surface_stub = nil
2177	}
2178
2179	props.System_modules = module.deviceProperties.System_modules
2180	props.Enable_validation = proptools.BoolPtr(true)
2181	props.Stubs_type = proptools.StringPtr("everything")
2182
2183	mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
2184}
2185
2186func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties {
2187	props := libraryProperties{}
2188
2189	props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
2190	sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
2191	props.Sdk_version = proptools.StringPtr(sdkVersion)
2192
2193	props.System_modules = module.deviceProperties.System_modules
2194
2195	// The imports need to be compiled to dex if the java_sdk_library requests it.
2196	compileDex := module.dexProperties.Compile_dex
2197	if module.stubLibrariesCompiledForDex() {
2198		compileDex = proptools.BoolPtr(true)
2199	}
2200	props.Compile_dex = compileDex
2201
2202	if !Bool(module.sdkLibraryProperties.No_dist) && doDist {
2203		props.Dist.Targets = []string{"sdk", "win_sdk"}
2204		props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
2205		props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
2206		props.Dist.Tag = proptools.StringPtr(".jar")
2207	}
2208
2209	return props
2210}
2211
2212func (module *SdkLibrary) createTopLevelStubsLibrary(
2213	mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) {
2214
2215	// Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false
2216	doDist := !mctx.Config().ReleaseHiddenApiExportableStubs()
2217	props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
2218	props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
2219
2220	// Add the stub compiling java_library/java_api_library as static lib based on build config
2221	staticLib := module.sourceStubsLibraryModuleName(apiScope)
2222	if mctx.Config().BuildFromTextStub() && contributesToApiSurface {
2223		staticLib = module.apiLibraryModuleName(apiScope)
2224	}
2225	props.Static_libs = append(props.Static_libs, staticLib)
2226
2227	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
2228}
2229
2230func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
2231	mctx android.DefaultableHookContext, apiScope *apiScope) {
2232
2233	// Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true
2234	doDist := mctx.Config().ReleaseHiddenApiExportableStubs()
2235	props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
2236	props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))
2237
2238	staticLib := module.exportableSourceStubsLibraryModuleName(apiScope)
2239	props.Static_libs = append(props.Static_libs, staticLib)
2240
2241	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
2242}
2243
2244func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool {
2245	return !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api)
2246}
2247
2248// Implements android.ApexModule
2249func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
2250	depTag := mctx.OtherModuleDependencyTag(dep)
2251	if depTag == xmlPermissionsFileTag {
2252		return true
2253	}
2254	if dep.Name() == module.implLibraryModuleName() {
2255		return true
2256	}
2257	return module.Library.DepIsInSameApex(mctx, dep)
2258}
2259
2260// Implements android.ApexModule
2261func (module *SdkLibrary) UniqueApexVariations() bool {
2262	return module.uniqueApexVariations()
2263}
2264
2265func (module *SdkLibrary) ContributeToApi() bool {
2266	return proptools.BoolDefault(module.sdkLibraryProperties.Contribute_to_android_api, false)
2267}
2268
2269// Creates the xml file that publicizes the runtime library
2270func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
2271	moduleMinApiLevel := module.Library.MinSdkVersion(mctx)
2272	var moduleMinApiLevelStr = moduleMinApiLevel.String()
2273	if moduleMinApiLevel == android.NoneApiLevel {
2274		moduleMinApiLevelStr = "current"
2275	}
2276	props := struct {
2277		Name                      *string
2278		Lib_name                  *string
2279		Apex_available            []string
2280		On_bootclasspath_since    *string
2281		On_bootclasspath_before   *string
2282		Min_device_sdk            *string
2283		Max_device_sdk            *string
2284		Sdk_library_min_api_level *string
2285		Uses_libs_dependencies    []string
2286	}{
2287		Name:                      proptools.StringPtr(module.xmlPermissionsModuleName()),
2288		Lib_name:                  proptools.StringPtr(module.BaseModuleName()),
2289		Apex_available:            module.ApexProperties.Apex_available,
2290		On_bootclasspath_since:    module.commonSdkLibraryProperties.On_bootclasspath_since,
2291		On_bootclasspath_before:   module.commonSdkLibraryProperties.On_bootclasspath_before,
2292		Min_device_sdk:            module.commonSdkLibraryProperties.Min_device_sdk,
2293		Max_device_sdk:            module.commonSdkLibraryProperties.Max_device_sdk,
2294		Sdk_library_min_api_level: &moduleMinApiLevelStr,
2295		Uses_libs_dependencies:    module.usesLibraryProperties.Uses_libs,
2296	}
2297
2298	mctx.CreateModule(sdkLibraryXmlFactory, &props)
2299}
2300
2301func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s android.SdkSpec) android.Paths {
2302	var ver android.ApiLevel
2303	var kind android.SdkKind
2304	if s.UsePrebuilt(ctx) {
2305		ver = s.ApiLevel
2306		kind = s.Kind
2307	} else {
2308		// We don't have prebuilt SDK for the specific sdkVersion.
2309		// Instead of breaking the build, fallback to use "system_current"
2310		ver = android.FutureApiLevel
2311		kind = android.SdkSystem
2312	}
2313
2314	dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String())
2315	jar := filepath.Join(dir, baseName+".jar")
2316	jarPath := android.ExistentPathForSource(ctx, jar)
2317	if !jarPath.Valid() {
2318		if ctx.Config().AllowMissingDependencies() {
2319			return android.Paths{android.PathForSource(ctx, jar)}
2320		} else {
2321			ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", s.Raw, jar)
2322		}
2323		return nil
2324	}
2325	return android.Paths{jarPath.Path()}
2326}
2327
2328// Check to see if the other module is within the same set of named APEXes as this module.
2329//
2330// If either this or the other module are on the platform then this will return
2331// false.
2332func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool {
2333	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
2334	otherApexInfo, _ := android.OtherModuleProvider(ctx, other, android.ApexInfoProvider)
2335	return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants)
2336}
2337
2338func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
2339	// If the client doesn't set sdk_version, but if this library prefers stubs over
2340	// the impl library, let's provide the widest API surface possible. To do so,
2341	// force override sdk_version to module_current so that the closest possible API
2342	// surface could be found in selectHeaderJarsForSdkVersion
2343	if module.defaultsToStubs() && !sdkVersion.Specified() {
2344		sdkVersion = android.SdkSpecFrom(ctx, "module_current")
2345	}
2346
2347	// Only provide access to the implementation library if it is actually built.
2348	if module.requiresRuntimeImplementationLibrary() {
2349		// Check any special cases for java_sdk_library.
2350		//
2351		// Only allow access to the implementation library in the following condition:
2352		// * No sdk_version specified on the referencing module.
2353		// * The referencing module is in the same apex as this.
2354		if sdkVersion.Kind == android.SdkPrivate || withinSameApexesAs(ctx, module) {
2355			return module.implLibraryHeaderJars
2356		}
2357	}
2358
2359	return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
2360}
2361
2362// to satisfy SdkLibraryDependency interface
2363func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
2364	return module.sdkJars(ctx, sdkVersion)
2365}
2366
2367var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries")
2368
2369func javaSdkLibraries(config android.Config) *[]string {
2370	return config.Once(javaSdkLibrariesKey, func() interface{} {
2371		return &[]string{}
2372	}).(*[]string)
2373}
2374
2375func (module *SdkLibrary) getApiDir() string {
2376	return proptools.StringDefault(module.sdkLibraryProperties.Api_dir, "api")
2377}
2378
2379// For a java_sdk_library module, create internal modules for stubs, docs,
2380// runtime libs and xml file. If requested, the stubs and docs are created twice
2381// once for public API level and once for system API level
2382func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) {
2383	// If the module has been disabled then don't create any child modules.
2384	if !module.Enabled(mctx) {
2385		return
2386	}
2387
2388	if len(module.properties.Srcs) == 0 {
2389		mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
2390		return
2391	}
2392
2393	// If this builds against standard libraries (i.e. is not part of the core libraries)
2394	// then assume it provides both system and test apis.
2395	sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library))
2396	hasSystemAndTestApis := sdkDep.hasStandardLibs()
2397	module.sdkLibraryProperties.Generate_system_and_test_apis = hasSystemAndTestApis
2398
2399	missingCurrentApi := false
2400
2401	generatedScopes := module.getGeneratedApiScopes(mctx)
2402
2403	apiDir := module.getApiDir()
2404	for _, scope := range generatedScopes {
2405		for _, api := range []string{"current.txt", "removed.txt"} {
2406			path := path.Join(mctx.ModuleDir(), apiDir, scope.apiFilePrefix+api)
2407			p := android.ExistentPathForSource(mctx, path)
2408			if !p.Valid() {
2409				if mctx.Config().AllowMissingDependencies() {
2410					mctx.AddMissingDependencies([]string{path})
2411				} else {
2412					mctx.ModuleErrorf("Current api file %#v doesn't exist", path)
2413					missingCurrentApi = true
2414				}
2415			}
2416		}
2417	}
2418
2419	if missingCurrentApi {
2420		script := "build/soong/scripts/gen-java-current-api-files.sh"
2421		p := android.ExistentPathForSource(mctx, script)
2422
2423		if !p.Valid() {
2424			panic(fmt.Sprintf("script file %s doesn't exist", script))
2425		}
2426
2427		mctx.ModuleErrorf("One or more current api files are missing. "+
2428			"You can update them by:\n"+
2429			"%s %q %s && m update-api",
2430			script, filepath.Join(mctx.ModuleDir(), apiDir),
2431			strings.Join(generatedScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " "))
2432		return
2433	}
2434
2435	for _, scope := range generatedScopes {
2436		// Use the stubs source name for legacy reasons.
2437		module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs)
2438
2439		module.createStubsLibrary(mctx, scope)
2440		module.createExportableStubsLibrary(mctx, scope)
2441
2442		alternativeFullApiSurfaceStubLib := ""
2443		if scope == apiScopePublic {
2444			alternativeFullApiSurfaceStubLib = module.alternativeFullApiSurfaceStubLib()
2445		}
2446		contributesToApiSurface := module.contributesToApiSurface(mctx.Config()) || alternativeFullApiSurfaceStubLib != ""
2447		if contributesToApiSurface {
2448			module.createApiLibrary(mctx, scope, alternativeFullApiSurfaceStubLib)
2449		}
2450
2451		module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface)
2452		module.createTopLevelExportableStubsLibrary(mctx, scope)
2453	}
2454
2455	if module.requiresRuntimeImplementationLibrary() {
2456		// Create child module to create an implementation library.
2457		//
2458		// This temporarily creates a second implementation library that can be explicitly
2459		// referenced.
2460		//
2461		// TODO(b/156618935) - update comment once only one implementation library is created.
2462		module.createImplLibrary(mctx)
2463
2464		// Only create an XML permissions file that declares the library as being usable
2465		// as a shared library if required.
2466		if module.sharedLibrary() {
2467			module.createXmlFile(mctx)
2468		}
2469
2470		// record java_sdk_library modules so that they are exported to make
2471		javaSdkLibraries := javaSdkLibraries(mctx.Config())
2472		javaSdkLibrariesLock.Lock()
2473		defer javaSdkLibrariesLock.Unlock()
2474		*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
2475	}
2476
2477	// Add the impl_only_libs and impl_only_static_libs *after* we're done using them in submodules.
2478	module.properties.Libs = append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...)
2479	module.properties.Static_libs = append(module.properties.Static_libs, module.sdkLibraryProperties.Impl_only_static_libs...)
2480}
2481
2482func (module *SdkLibrary) InitSdkLibraryProperties() {
2483	module.addHostAndDeviceProperties()
2484	module.AddProperties(&module.sdkLibraryProperties)
2485
2486	module.initSdkLibraryComponent(module)
2487
2488	module.properties.Installable = proptools.BoolPtr(true)
2489	module.deviceProperties.IsSDKLibrary = true
2490}
2491
2492func (module *SdkLibrary) requiresRuntimeImplementationLibrary() bool {
2493	return !proptools.Bool(module.sdkLibraryProperties.Api_only)
2494}
2495
2496func (module *SdkLibrary) defaultsToStubs() bool {
2497	return proptools.Bool(module.sdkLibraryProperties.Default_to_stubs)
2498}
2499
2500// Defines how to name the individual component modules the sdk library creates.
2501type sdkLibraryComponentNamingScheme interface {
2502	stubsLibraryModuleName(scope *apiScope, baseName string) string
2503
2504	stubsSourceModuleName(scope *apiScope, baseName string) string
2505
2506	apiLibraryModuleName(scope *apiScope, baseName string) string
2507
2508	sourceStubsLibraryModuleName(scope *apiScope, baseName string) string
2509
2510	exportableStubsLibraryModuleName(scope *apiScope, baseName string) string
2511
2512	exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string
2513}
2514
2515type defaultNamingScheme struct {
2516}
2517
2518func (s *defaultNamingScheme) stubsLibraryModuleName(scope *apiScope, baseName string) string {
2519	return scope.stubsLibraryModuleName(baseName)
2520}
2521
2522func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName string) string {
2523	return scope.stubsSourceModuleName(baseName)
2524}
2525
2526func (s *defaultNamingScheme) apiLibraryModuleName(scope *apiScope, baseName string) string {
2527	return scope.apiLibraryModuleName(baseName)
2528}
2529
2530func (s *defaultNamingScheme) sourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
2531	return scope.sourceStubLibraryModuleName(baseName)
2532}
2533
2534func (s *defaultNamingScheme) exportableStubsLibraryModuleName(scope *apiScope, baseName string) string {
2535	return scope.exportableStubsLibraryModuleName(baseName)
2536}
2537
2538func (s *defaultNamingScheme) exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
2539	return scope.exportableSourceStubsLibraryModuleName(baseName)
2540}
2541
2542var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil)
2543
2544func hasStubsLibrarySuffix(name string, apiScope *apiScope) bool {
2545	return strings.HasSuffix(name, apiScope.stubsLibraryModuleNameSuffix()) ||
2546		strings.HasSuffix(name, apiScope.exportableStubsLibraryModuleNameSuffix())
2547}
2548
2549func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) {
2550	name = strings.TrimSuffix(name, ".from-source")
2551
2552	// This suffix-based approach is fragile and could potentially mis-trigger.
2553	// TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly.
2554	if hasStubsLibrarySuffix(name, apiScopePublic) {
2555		if name == "hwbinder.stubs" || name == "libcore_private.stubs" {
2556			// Due to a previous bug, these modules were not considered stubs, so we retain that.
2557			return false, javaPlatform
2558		}
2559		return true, javaSdk
2560	}
2561	if hasStubsLibrarySuffix(name, apiScopeSystem) {
2562		return true, javaSystem
2563	}
2564	if hasStubsLibrarySuffix(name, apiScopeModuleLib) {
2565		return true, javaModule
2566	}
2567	if hasStubsLibrarySuffix(name, apiScopeTest) {
2568		return true, javaSystem
2569	}
2570	if hasStubsLibrarySuffix(name, apiScopeSystemServer) {
2571		return true, javaSystemServer
2572	}
2573	return false, javaPlatform
2574}
2575
2576// java_sdk_library is a special Java library that provides optional platform APIs to apps.
2577// In practice, it can be viewed as a combination of several modules: 1) stubs library that clients
2578// are linked against to, 2) droiddoc module that internally generates API stubs source files,
2579// 3) the real runtime shared library that implements the APIs, and 4) XML file for adding
2580// the runtime lib to the classpath at runtime if requested via <uses-library>.
2581func SdkLibraryFactory() android.Module {
2582	module := &SdkLibrary{}
2583
2584	// Initialize information common between source and prebuilt.
2585	module.initCommon(module)
2586
2587	module.InitSdkLibraryProperties()
2588	android.InitApexModule(module)
2589	InitJavaModule(module, android.HostAndDeviceSupported)
2590
2591	// Initialize the map from scope to scope specific properties.
2592	scopeToProperties := make(map[*apiScope]*ApiScopeProperties)
2593	for _, scope := range AllApiScopes {
2594		scopeToProperties[scope] = scope.scopeSpecificProperties(module)
2595	}
2596	module.scopeToProperties = scopeToProperties
2597
2598	// Add the properties containing visibility rules so that they are checked.
2599	android.AddVisibilityProperty(module, "impl_library_visibility", &module.sdkLibraryProperties.Impl_library_visibility)
2600	android.AddVisibilityProperty(module, "stubs_library_visibility", &module.sdkLibraryProperties.Stubs_library_visibility)
2601	android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility)
2602
2603	module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
2604		// If no implementation is required then it cannot be used as a shared library
2605		// either.
2606		if !module.requiresRuntimeImplementationLibrary() {
2607			// If shared_library has been explicitly set to true then it is incompatible
2608			// with api_only: true.
2609			if proptools.Bool(module.commonSdkLibraryProperties.Shared_library) {
2610				ctx.PropertyErrorf("api_only/shared_library", "inconsistent settings, shared_library and api_only cannot both be true")
2611			}
2612			// Set shared_library: false.
2613			module.commonSdkLibraryProperties.Shared_library = proptools.BoolPtr(false)
2614		}
2615
2616		if module.initCommonAfterDefaultsApplied(ctx) {
2617			module.CreateInternalModules(ctx)
2618		}
2619	})
2620	return module
2621}
2622
2623//
2624// SDK library prebuilts
2625//
2626
2627// Properties associated with each api scope.
2628type sdkLibraryScopeProperties struct {
2629	Jars []string `android:"path"`
2630
2631	Sdk_version *string
2632
2633	// List of shared java libs that this module has dependencies to
2634	Libs []string
2635
2636	// The stubs source.
2637	Stub_srcs []string `android:"path"`
2638
2639	// The current.txt
2640	Current_api *string `android:"path"`
2641
2642	// The removed.txt
2643	Removed_api *string `android:"path"`
2644
2645	// Annotation zip
2646	Annotations *string `android:"path"`
2647}
2648
2649type sdkLibraryImportProperties struct {
2650	// List of shared java libs, common to all scopes, that this module has
2651	// dependencies to
2652	Libs []string
2653
2654	// If set to true, compile dex files for the stubs. Defaults to false.
2655	Compile_dex *bool
2656
2657	// If not empty, classes are restricted to the specified packages and their sub-packages.
2658	Permitted_packages []string
2659
2660	// Name of the source soong module that gets shadowed by this prebuilt
2661	// If unspecified, follows the naming convention that the source module of
2662	// the prebuilt is Name() without "prebuilt_" prefix
2663	Source_module_name *string
2664}
2665
2666type SdkLibraryImport struct {
2667	android.ModuleBase
2668	android.DefaultableModuleBase
2669	prebuilt android.Prebuilt
2670	android.ApexModuleBase
2671
2672	hiddenAPI
2673	dexpreopter
2674
2675	properties sdkLibraryImportProperties
2676
2677	// Map from api scope to the scope specific property structure.
2678	scopeProperties map[*apiScope]*sdkLibraryScopeProperties
2679
2680	commonToSdkLibraryAndImport
2681
2682	// The reference to the xml permissions module created by the source module.
2683	// Is nil if the source module does not exist.
2684	xmlPermissionsFileModule *sdkLibraryXml
2685
2686	// Build path to the dex implementation jar obtained from the prebuilt_apex, if any.
2687	dexJarFile    OptionalDexJarPath
2688	dexJarFileErr error
2689
2690	// Expected install file path of the source module(sdk_library)
2691	// or dex implementation jar obtained from the prebuilt_apex, if any.
2692	installFile android.Path
2693}
2694
2695var _ SdkLibraryDependency = (*SdkLibraryImport)(nil)
2696
2697// The type of a structure that contains a field of type sdkLibraryScopeProperties
2698// for each apiscope in allApiScopes, e.g. something like:
2699//
2700//	struct {
2701//	  Public sdkLibraryScopeProperties
2702//	  System sdkLibraryScopeProperties
2703//	  ...
2704//	}
2705var allScopeStructType = createAllScopePropertiesStructType()
2706
2707// Dynamically create a structure type for each apiscope in allApiScopes.
2708func createAllScopePropertiesStructType() reflect.Type {
2709	var fields []reflect.StructField
2710	for _, apiScope := range AllApiScopes {
2711		field := reflect.StructField{
2712			Name: apiScope.fieldName,
2713			Type: reflect.TypeOf(sdkLibraryScopeProperties{}),
2714		}
2715		fields = append(fields, field)
2716	}
2717
2718	return reflect.StructOf(fields)
2719}
2720
2721// Create an instance of the scope specific structure type and return a map
2722// from apiscope to a pointer to each scope specific field.
2723func createPropertiesInstance() (interface{}, map[*apiScope]*sdkLibraryScopeProperties) {
2724	allScopePropertiesPtr := reflect.New(allScopeStructType)
2725	allScopePropertiesStruct := allScopePropertiesPtr.Elem()
2726	scopeProperties := make(map[*apiScope]*sdkLibraryScopeProperties)
2727
2728	for _, apiScope := range AllApiScopes {
2729		field := allScopePropertiesStruct.FieldByName(apiScope.fieldName)
2730		scopeProperties[apiScope] = field.Addr().Interface().(*sdkLibraryScopeProperties)
2731	}
2732
2733	return allScopePropertiesPtr.Interface(), scopeProperties
2734}
2735
2736// java_sdk_library_import imports a prebuilt java_sdk_library.
2737func sdkLibraryImportFactory() android.Module {
2738	module := &SdkLibraryImport{}
2739
2740	allScopeProperties, scopeToProperties := createPropertiesInstance()
2741	module.scopeProperties = scopeToProperties
2742	module.AddProperties(&module.properties, allScopeProperties, &module.importDexpreoptProperties)
2743
2744	// Initialize information common between source and prebuilt.
2745	module.initCommon(module)
2746
2747	android.InitPrebuiltModule(module, &[]string{""})
2748	android.InitApexModule(module)
2749	InitJavaModule(module, android.HostAndDeviceSupported)
2750
2751	module.SetDefaultableHook(func(mctx android.DefaultableHookContext) {
2752		if module.initCommonAfterDefaultsApplied(mctx) {
2753			module.createInternalModules(mctx)
2754		}
2755	})
2756	return module
2757}
2758
2759var _ PermittedPackagesForUpdatableBootJars = (*SdkLibraryImport)(nil)
2760
2761func (module *SdkLibraryImport) PermittedPackagesForUpdatableBootJars() []string {
2762	return module.properties.Permitted_packages
2763}
2764
2765func (module *SdkLibraryImport) Prebuilt() *android.Prebuilt {
2766	return &module.prebuilt
2767}
2768
2769func (module *SdkLibraryImport) Name() string {
2770	return module.prebuilt.Name(module.ModuleBase.Name())
2771}
2772
2773func (module *SdkLibraryImport) BaseModuleName() string {
2774	return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name())
2775}
2776
2777func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
2778
2779	// If the build is configured to use prebuilts then force this to be preferred.
2780	if mctx.Config().AlwaysUsePrebuiltSdks() {
2781		module.prebuilt.ForcePrefer()
2782	}
2783
2784	for apiScope, scopeProperties := range module.scopeProperties {
2785		if len(scopeProperties.Jars) == 0 {
2786			continue
2787		}
2788
2789		module.createJavaImportForStubs(mctx, apiScope, scopeProperties)
2790
2791		if len(scopeProperties.Stub_srcs) > 0 {
2792			module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
2793		}
2794
2795		if scopeProperties.Current_api != nil {
2796			module.createPrebuiltApiContribution(mctx, apiScope, scopeProperties)
2797		}
2798	}
2799
2800	javaSdkLibraries := javaSdkLibraries(mctx.Config())
2801	javaSdkLibrariesLock.Lock()
2802	defer javaSdkLibrariesLock.Unlock()
2803	*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
2804}
2805
2806func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
2807	// Creates a java import for the jar with ".stubs" suffix
2808	props := struct {
2809		Name                             *string
2810		Source_module_name               *string
2811		Created_by_java_sdk_library_name *string
2812		Sdk_version                      *string
2813		Libs                             []string
2814		Jars                             []string
2815		Compile_dex                      *bool
2816		Is_stubs_module                  *bool
2817
2818		android.UserSuppliedPrebuiltProperties
2819	}{}
2820	props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
2821	props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName()))
2822	props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
2823	props.Sdk_version = scopeProperties.Sdk_version
2824	// Prepend any of the libs from the legacy public properties to the libs for each of the
2825	// scopes to avoid having to duplicate them in each scope.
2826	props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
2827	props.Jars = scopeProperties.Jars
2828
2829	// The imports are preferred if the java_sdk_library_import is preferred.
2830	props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
2831
2832	// The imports need to be compiled to dex if the java_sdk_library_import requests it.
2833	compileDex := module.properties.Compile_dex
2834	if module.stubLibrariesCompiledForDex() {
2835		compileDex = proptools.BoolPtr(true)
2836	}
2837	props.Compile_dex = compileDex
2838	props.Is_stubs_module = proptools.BoolPtr(true)
2839
2840	mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
2841}
2842
2843func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
2844	props := struct {
2845		Name                             *string
2846		Source_module_name               *string
2847		Created_by_java_sdk_library_name *string
2848		Srcs                             []string
2849
2850		android.UserSuppliedPrebuiltProperties
2851	}{}
2852	props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope))
2853	props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()))
2854	props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
2855	props.Srcs = scopeProperties.Stub_srcs
2856
2857	// The stubs source is preferred if the java_sdk_library_import is preferred.
2858	props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
2859
2860	mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary())
2861}
2862
2863func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
2864	api_file := scopeProperties.Current_api
2865	api_surface := &apiScope.name
2866
2867	props := struct {
2868		Name                             *string
2869		Source_module_name               *string
2870		Created_by_java_sdk_library_name *string
2871		Api_surface                      *string
2872		Api_file                         *string
2873		Visibility                       []string
2874	}{}
2875
2876	props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution")
2877	props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution")
2878	props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
2879	props.Api_surface = api_surface
2880	props.Api_file = api_file
2881	props.Visibility = []string{"//visibility:override", "//visibility:public"}
2882
2883	mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
2884}
2885
2886// Add the dependencies on the child module in the component deps mutator so that it
2887// creates references to the prebuilt and not the source modules.
2888func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
2889	for apiScope, scopeProperties := range module.scopeProperties {
2890		if len(scopeProperties.Jars) == 0 {
2891			continue
2892		}
2893
2894		// Add dependencies to the prebuilt stubs library
2895		ctx.AddVariationDependencies(nil, apiScope.prebuiltStubsTag, android.PrebuiltNameFromSource(module.stubsLibraryModuleName(apiScope)))
2896
2897		if len(scopeProperties.Stub_srcs) > 0 {
2898			// Add dependencies to the prebuilt stubs source library
2899			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, android.PrebuiltNameFromSource(module.stubsSourceModuleName(apiScope)))
2900		}
2901	}
2902}
2903
2904// Add other dependencies as normal.
2905func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
2906
2907	implName := module.implLibraryModuleName()
2908	if ctx.OtherModuleExists(implName) {
2909		ctx.AddVariationDependencies(nil, implLibraryTag, implName)
2910
2911		xmlPermissionsModuleName := module.xmlPermissionsModuleName()
2912		if module.sharedLibrary() && ctx.OtherModuleExists(xmlPermissionsModuleName) {
2913			// Add dependency to the rule for generating the xml permissions file
2914			ctx.AddDependency(module, xmlPermissionsFileTag, xmlPermissionsModuleName)
2915		}
2916	}
2917}
2918
2919var _ android.ApexModule = (*SdkLibraryImport)(nil)
2920
2921// Implements android.ApexModule
2922func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
2923	depTag := mctx.OtherModuleDependencyTag(dep)
2924	if depTag == xmlPermissionsFileTag {
2925		return true
2926	}
2927
2928	// None of the other dependencies of the java_sdk_library_import are in the same apex
2929	// as the one that references this module.
2930	return false
2931}
2932
2933// Implements android.ApexModule
2934func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
2935	sdkVersion android.ApiLevel) error {
2936	// we don't check prebuilt modules for sdk_version
2937	return nil
2938}
2939
2940// Implements android.ApexModule
2941func (module *SdkLibraryImport) UniqueApexVariations() bool {
2942	return module.uniqueApexVariations()
2943}
2944
2945// MinSdkVersion - Implements hiddenAPIModule
2946func (module *SdkLibraryImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
2947	return android.NoneApiLevel
2948}
2949
2950var _ hiddenAPIModule = (*SdkLibraryImport)(nil)
2951
2952func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
2953	paths, err := module.commonOutputFiles(tag)
2954	if paths != nil || err != nil {
2955		return paths, err
2956	}
2957	if module.implLibraryModule != nil {
2958		return module.implLibraryModule.OutputFiles(tag)
2959	} else {
2960		return nil, nil
2961	}
2962}
2963
2964func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2965	module.generateCommonBuildActions(ctx)
2966
2967	// Assume that source module(sdk_library) is installed in /<sdk_library partition>/framework
2968	module.installFile = android.PathForModuleInstall(ctx, "framework", module.Stem()+".jar")
2969
2970	// Record the paths to the prebuilt stubs library and stubs source.
2971	ctx.VisitDirectDeps(func(to android.Module) {
2972		tag := ctx.OtherModuleDependencyTag(to)
2973
2974		// Extract information from any of the scope specific dependencies.
2975		if scopeTag, ok := tag.(scopeDependencyTag); ok {
2976			apiScope := scopeTag.apiScope
2977			scopePaths := module.getScopePathsCreateIfNeeded(apiScope)
2978
2979			// Extract information from the dependency. The exact information extracted
2980			// is determined by the nature of the dependency which is determined by the tag.
2981			scopeTag.extractDepInfo(ctx, to, scopePaths)
2982		} else if tag == implLibraryTag {
2983			if implLibrary, ok := to.(*Library); ok {
2984				module.implLibraryModule = implLibrary
2985			} else {
2986				ctx.ModuleErrorf("implementation library must be of type *java.Library but was %T", to)
2987			}
2988		} else if tag == xmlPermissionsFileTag {
2989			if xmlPermissionsFileModule, ok := to.(*sdkLibraryXml); ok {
2990				module.xmlPermissionsFileModule = xmlPermissionsFileModule
2991			} else {
2992				ctx.ModuleErrorf("xml permissions file module must be of type *sdkLibraryXml but was %T", to)
2993			}
2994		}
2995	})
2996
2997	// Populate the scope paths with information from the properties.
2998	for apiScope, scopeProperties := range module.scopeProperties {
2999		if len(scopeProperties.Jars) == 0 {
3000			continue
3001		}
3002
3003		paths := module.getScopePathsCreateIfNeeded(apiScope)
3004		paths.annotationsZip = android.OptionalPathForModuleSrc(ctx, scopeProperties.Annotations)
3005		paths.currentApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Current_api)
3006		paths.removedApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Removed_api)
3007	}
3008
3009	if ctx.Device() {
3010		// If this is a variant created for a prebuilt_apex then use the dex implementation jar
3011		// obtained from the associated deapexer module.
3012		ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
3013		if ai.ForPrebuiltApex {
3014			// Get the path of the dex implementation jar from the `deapexer` module.
3015			di, err := android.FindDeapexerProviderForModule(ctx)
3016			if err != nil {
3017				// An error was found, possibly due to multiple apexes in the tree that export this library
3018				// Defer the error till a client tries to call DexJarBuildPath
3019				module.dexJarFileErr = err
3020				module.initHiddenAPIError(err)
3021				return
3022			}
3023			dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(module.BaseModuleName())
3024			if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
3025				dexJarFile := makeDexJarPathFromPath(dexOutputPath)
3026				module.dexJarFile = dexJarFile
3027				installPath := android.PathForModuleInPartitionInstall(
3028					ctx, "apex", ai.ApexVariationName, dexJarFileApexRootRelative)
3029				module.installFile = installPath
3030				module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
3031
3032				module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
3033				module.dexpreopter.isSDKLibrary = true
3034				module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &module.dexpreopter)
3035
3036				if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
3037					module.dexpreopter.inputProfilePathOnHost = profilePath
3038				}
3039			} else {
3040				// This should never happen as a variant for a prebuilt_apex is only created if the
3041				// prebuilt_apex has been configured to export the java library dex file.
3042				ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName())
3043			}
3044		}
3045	}
3046}
3047
3048func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
3049
3050	// For consistency with SdkLibrary make the implementation jar available to libraries that
3051	// are within the same APEX.
3052	implLibraryModule := module.implLibraryModule
3053	if implLibraryModule != nil && withinSameApexesAs(ctx, module) {
3054		if headerJars {
3055			return implLibraryModule.HeaderJars()
3056		} else {
3057			return implLibraryModule.ImplementationJars()
3058		}
3059	}
3060
3061	return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
3062}
3063
3064// to satisfy SdkLibraryDependency interface
3065func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
3066	// This module is just a wrapper for the prebuilt stubs.
3067	return module.sdkJars(ctx, sdkVersion, true)
3068}
3069
3070// to satisfy UsesLibraryDependency interface
3071func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
3072	// The dex implementation jar extracted from the .apex file should be used in preference to the
3073	// source.
3074	if module.dexJarFileErr != nil {
3075		ctx.ModuleErrorf(module.dexJarFileErr.Error())
3076	}
3077	if module.dexJarFile.IsSet() {
3078		return module.dexJarFile
3079	}
3080	if module.implLibraryModule == nil {
3081		return makeUnsetDexJarPath()
3082	} else {
3083		return module.implLibraryModule.DexJarBuildPath(ctx)
3084	}
3085}
3086
3087// to satisfy UsesLibraryDependency interface
3088func (module *SdkLibraryImport) DexJarInstallPath() android.Path {
3089	return module.installFile
3090}
3091
3092// to satisfy UsesLibraryDependency interface
3093func (module *SdkLibraryImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
3094	return nil
3095}
3096
3097// to satisfy apex.javaDependency interface
3098func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
3099	if module.implLibraryModule == nil {
3100		return nil
3101	} else {
3102		return module.implLibraryModule.JacocoReportClassesFile()
3103	}
3104}
3105
3106// to satisfy apex.javaDependency interface
3107func (module *SdkLibraryImport) LintDepSets() LintDepSets {
3108	if module.implLibraryModule == nil {
3109		return LintDepSets{}
3110	} else {
3111		return module.implLibraryModule.LintDepSets()
3112	}
3113}
3114
3115func (module *SdkLibraryImport) GetStrictUpdatabilityLinting() bool {
3116	if module.implLibraryModule == nil {
3117		return false
3118	} else {
3119		return module.implLibraryModule.GetStrictUpdatabilityLinting()
3120	}
3121}
3122
3123func (module *SdkLibraryImport) SetStrictUpdatabilityLinting(strictLinting bool) {
3124	if module.implLibraryModule != nil {
3125		module.implLibraryModule.SetStrictUpdatabilityLinting(strictLinting)
3126	}
3127}
3128
3129// to satisfy apex.javaDependency interface
3130func (module *SdkLibraryImport) Stem() string {
3131	return module.BaseModuleName()
3132}
3133
3134var _ ApexDependency = (*SdkLibraryImport)(nil)
3135
3136// to satisfy java.ApexDependency interface
3137func (module *SdkLibraryImport) HeaderJars() android.Paths {
3138	if module.implLibraryModule == nil {
3139		return nil
3140	} else {
3141		return module.implLibraryModule.HeaderJars()
3142	}
3143}
3144
3145// to satisfy java.ApexDependency interface
3146func (module *SdkLibraryImport) ImplementationAndResourcesJars() android.Paths {
3147	if module.implLibraryModule == nil {
3148		return nil
3149	} else {
3150		return module.implLibraryModule.ImplementationAndResourcesJars()
3151	}
3152}
3153
3154// to satisfy java.DexpreopterInterface interface
3155func (module *SdkLibraryImport) IsInstallable() bool {
3156	return true
3157}
3158
3159var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil)
3160
3161func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
3162	name := module.BaseModuleName()
3163	return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter)
3164}
3165
3166func (j *SdkLibraryImport) UseProfileGuidedDexpreopt() bool {
3167	return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
3168}
3169
3170// java_sdk_library_xml
3171type sdkLibraryXml struct {
3172	android.ModuleBase
3173	android.DefaultableModuleBase
3174	android.ApexModuleBase
3175
3176	properties sdkLibraryXmlProperties
3177
3178	outputFilePath android.OutputPath
3179	installDirPath android.InstallPath
3180
3181	hideApexVariantFromMake bool
3182}
3183
3184type sdkLibraryXmlProperties struct {
3185	// canonical name of the lib
3186	Lib_name *string
3187
3188	// Signals that this shared library is part of the bootclasspath starting
3189	// on the version indicated in this attribute.
3190	//
3191	// This will make platforms at this level and above to ignore
3192	// <uses-library> tags with this library name because the library is already
3193	// available
3194	On_bootclasspath_since *string
3195
3196	// Signals that this shared library was part of the bootclasspath before
3197	// (but not including) the version indicated in this attribute.
3198	//
3199	// The system will automatically add a <uses-library> tag with this library to
3200	// apps that target any SDK less than the version indicated in this attribute.
3201	On_bootclasspath_before *string
3202
3203	// Indicates that PackageManager should ignore this shared library if the
3204	// platform is below the version indicated in this attribute.
3205	//
3206	// This means that the device won't recognise this library as installed.
3207	Min_device_sdk *string
3208
3209	// Indicates that PackageManager should ignore this shared library if the
3210	// platform is above the version indicated in this attribute.
3211	//
3212	// This means that the device won't recognise this library as installed.
3213	Max_device_sdk *string
3214
3215	// The SdkLibrary's min api level as a string
3216	//
3217	// This value comes from the ApiLevel of the MinSdkVersion property.
3218	Sdk_library_min_api_level *string
3219
3220	// Uses-libs dependencies that the shared library requires to work correctly.
3221	//
3222	// This will add dependency="foo:bar" to the <library> section.
3223	Uses_libs_dependencies []string
3224}
3225
3226// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
3227// Not to be used directly by users. java_sdk_library internally uses this.
3228func sdkLibraryXmlFactory() android.Module {
3229	module := &sdkLibraryXml{}
3230
3231	module.AddProperties(&module.properties)
3232
3233	android.InitApexModule(module)
3234	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
3235
3236	return module
3237}
3238
3239func (module *sdkLibraryXml) UniqueApexVariations() bool {
3240	// sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the
3241	// mounted APEX, which contains the name of the APEX.
3242	return true
3243}
3244
3245// from android.PrebuiltEtcModule
3246func (module *sdkLibraryXml) BaseDir() string {
3247	return "etc"
3248}
3249
3250// from android.PrebuiltEtcModule
3251func (module *sdkLibraryXml) SubDir() string {
3252	return "permissions"
3253}
3254
3255var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)
3256
3257// from android.ApexModule
3258func (module *sdkLibraryXml) AvailableFor(what string) bool {
3259	return true
3260}
3261
3262func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
3263	// do nothing
3264}
3265
3266var _ android.ApexModule = (*sdkLibraryXml)(nil)
3267
3268// Implements android.ApexModule
3269func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
3270	sdkVersion android.ApiLevel) error {
3271	// sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked
3272	return nil
3273}
3274
3275// File path to the runtime implementation library
3276func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
3277	implName := proptools.String(module.properties.Lib_name)
3278	if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
3279		// TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
3280		// In most cases, this works fine. But when apex_name is set or override_apex is used
3281		// this can be wrong.
3282		return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.ApexVariationName, implName)
3283	}
3284	partition := "system"
3285	if module.SocSpecific() {
3286		partition = "vendor"
3287	} else if module.DeviceSpecific() {
3288		partition = "odm"
3289	} else if module.ProductSpecific() {
3290		partition = "product"
3291	} else if module.SystemExtSpecific() {
3292		partition = "system_ext"
3293	}
3294	return "/" + partition + "/framework/" + implName + ".jar"
3295}
3296
3297func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string {
3298	if value == nil {
3299		return ""
3300	}
3301	apiLevel, err := android.ApiLevelFromUser(ctx, *value)
3302	if err != nil {
3303		// attributes in bp files have underscores but in the xml have dashes.
3304		ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error())
3305		return ""
3306	}
3307	if apiLevel.IsCurrent() {
3308		// passing "current" would always mean a future release, never the current (or the current in
3309		// progress) which means some conditions would never be triggered.
3310		ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"),
3311			`"current" is not an allowed value for this attribute`)
3312		return ""
3313	}
3314	// "safeValue" is safe because it translates finalized codenames to a string
3315	// with their SDK int.
3316	safeValue := apiLevel.String()
3317	return formattedOptionalAttribute(attrName, &safeValue)
3318}
3319
3320// formats an attribute for the xml permissions file if the value is not null
3321// returns empty string otherwise
3322func formattedOptionalAttribute(attrName string, value *string) string {
3323	if value == nil {
3324		return ""
3325	}
3326	return fmt.Sprintf("        %s=\"%s\"\n", attrName, *value)
3327}
3328
3329func formattedDependenciesAttribute(dependencies []string) string {
3330	if dependencies == nil {
3331		return ""
3332	}
3333	return fmt.Sprintf("        dependency=\"%s\"\n", strings.Join(dependencies, ":"))
3334}
3335
3336func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
3337	libName := proptools.String(module.properties.Lib_name)
3338	libNameAttr := formattedOptionalAttribute("name", &libName)
3339	filePath := module.implPath(ctx)
3340	filePathAttr := formattedOptionalAttribute("file", &filePath)
3341	implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since)
3342	implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
3343	minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
3344	maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
3345	dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies)
3346	// <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
3347	// similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
3348	var libraryTag string
3349	if module.properties.Min_device_sdk != nil {
3350		libraryTag = "    <apex-library\n"
3351	} else {
3352		libraryTag = "    <library\n"
3353	}
3354
3355	return strings.Join([]string{
3356		"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
3357		"<!-- Copyright (C) 2018 The Android Open Source Project\n",
3358		"\n",
3359		"    Licensed under the Apache License, Version 2.0 (the \"License\");\n",
3360		"    you may not use this file except in compliance with the License.\n",
3361		"    You may obtain a copy of the License at\n",
3362		"\n",
3363		"        http://www.apache.org/licenses/LICENSE-2.0\n",
3364		"\n",
3365		"    Unless required by applicable law or agreed to in writing, software\n",
3366		"    distributed under the License is distributed on an \"AS IS\" BASIS,\n",
3367		"    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
3368		"    See the License for the specific language governing permissions and\n",
3369		"    limitations under the License.\n",
3370		"-->\n",
3371		"<permissions>\n",
3372		libraryTag,
3373		libNameAttr,
3374		filePathAttr,
3375		implicitFromAttr,
3376		implicitUntilAttr,
3377		minSdkAttr,
3378		maxSdkAttr,
3379		dependenciesAttr,
3380		"    />\n",
3381		"</permissions>\n",
3382	}, "")
3383}
3384
3385func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
3386	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
3387	module.hideApexVariantFromMake = !apexInfo.IsForPlatform()
3388
3389	libName := proptools.String(module.properties.Lib_name)
3390	module.selfValidate(ctx)
3391	xmlContent := module.permissionsContents(ctx)
3392
3393	module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
3394	android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent)
3395
3396	module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
3397	ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)
3398
3399	ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "")
3400}
3401
3402func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
3403	if module.hideApexVariantFromMake {
3404		return []android.AndroidMkEntries{{
3405			Disabled: true,
3406		}}
3407	}
3408
3409	return []android.AndroidMkEntries{{
3410		Class:      "ETC",
3411		OutputFile: android.OptionalPathForPath(module.outputFilePath),
3412		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
3413			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
3414				entries.SetString("LOCAL_MODULE_TAGS", "optional")
3415				entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.String())
3416				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base())
3417			},
3418		},
3419	}}
3420}
3421
3422func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) {
3423	module.validateAtLeastTAttributes(ctx)
3424	module.validateMinAndMaxDeviceSdk(ctx)
3425	module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx)
3426	module.validateOnBootclasspathBeforeRequirements(ctx)
3427}
3428
3429func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) {
3430	t := android.ApiLevelOrPanic(ctx, "Tiramisu")
3431	module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk")
3432	module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk")
3433	module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before")
3434	module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since")
3435}
3436
3437func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) {
3438	if attr != nil {
3439		if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil {
3440			// we will inform the user of invalid inputs when we try to write the
3441			// permissions xml file so we don't need to do it here
3442			if t.GreaterThan(level) {
3443				ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T")
3444			}
3445		}
3446	}
3447}
3448
3449func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) {
3450	if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil {
3451		min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
3452		max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
3453		if minErr == nil && maxErr == nil {
3454			// we will inform the user of invalid inputs when we try to write the
3455			// permissions xml file so we don't need to do it here
3456			if min.GreaterThan(max) {
3457				ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk")
3458			}
3459		}
3460	}
3461}
3462
3463func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) {
3464	moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
3465	if module.properties.Min_device_sdk != nil {
3466		api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
3467		if err == nil {
3468			if moduleMinApi.GreaterThan(api) {
3469				ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
3470			}
3471		}
3472	}
3473	if module.properties.Max_device_sdk != nil {
3474		api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
3475		if err == nil {
3476			if moduleMinApi.GreaterThan(api) {
3477				ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
3478			}
3479		}
3480	}
3481}
3482
3483func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) {
3484	moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
3485	if module.properties.On_bootclasspath_before != nil {
3486		t := android.ApiLevelOrPanic(ctx, "Tiramisu")
3487		// if we use the attribute, then we need to do this validation
3488		if moduleMinApi.LessThan(t) {
3489			// if minAPi is < T, then we need to have min_device_sdk (which only accepts T+)
3490			if module.properties.Min_device_sdk == nil {
3491				ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T")
3492			}
3493		}
3494	}
3495}
3496
3497type sdkLibrarySdkMemberType struct {
3498	android.SdkMemberTypeBase
3499}
3500
3501func (s *sdkLibrarySdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
3502	ctx.AddVariationDependencies(nil, dependencyTag, names...)
3503}
3504
3505func (s *sdkLibrarySdkMemberType) IsInstance(module android.Module) bool {
3506	_, ok := module.(*SdkLibrary)
3507	return ok
3508}
3509
3510func (s *sdkLibrarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
3511	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_sdk_library_import")
3512}
3513
3514func (s *sdkLibrarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
3515	return &sdkLibrarySdkMemberProperties{}
3516}
3517
3518var javaSdkLibrarySdkMemberType = &sdkLibrarySdkMemberType{
3519	android.SdkMemberTypeBase{
3520		PropertyName: "java_sdk_libs",
3521		SupportsSdk:  true,
3522	},
3523}
3524
3525type sdkLibrarySdkMemberProperties struct {
3526	android.SdkMemberPropertiesBase
3527
3528	// Stem name for files in the sdk snapshot.
3529	//
3530	// This is used to construct the path names of various sdk library files in the sdk snapshot to
3531	// make sure that they match the finalized versions of those files in prebuilts/sdk.
3532	//
3533	// This property is marked as keep so that it will be kept in all instances of this struct, will
3534	// not be cleared but will be copied to common structs. That is needed because this field is used
3535	// to construct many file names for other parts of this struct and so it needs to be present in
3536	// all structs. If it was not marked as keep then it would be cleared in some structs and so would
3537	// be unavailable for generating file names if there were other properties that were still set.
3538	Stem string `sdk:"keep"`
3539
3540	// Scope to per scope properties.
3541	Scopes map[*apiScope]*scopeProperties
3542
3543	// The Java stubs source files.
3544	Stub_srcs []string
3545
3546	// The naming scheme.
3547	Naming_scheme *string
3548
3549	// True if the java_sdk_library_import is for a shared library, false
3550	// otherwise.
3551	Shared_library *bool
3552
3553	// True if the stub imports should produce dex jars.
3554	Compile_dex *bool
3555
3556	// The paths to the doctag files to add to the prebuilt.
3557	Doctag_paths android.Paths
3558
3559	Permitted_packages []string
3560
3561	// Signals that this shared library is part of the bootclasspath starting
3562	// on the version indicated in this attribute.
3563	//
3564	// This will make platforms at this level and above to ignore
3565	// <uses-library> tags with this library name because the library is already
3566	// available
3567	On_bootclasspath_since *string
3568
3569	// Signals that this shared library was part of the bootclasspath before
3570	// (but not including) the version indicated in this attribute.
3571	//
3572	// The system will automatically add a <uses-library> tag with this library to
3573	// apps that target any SDK less than the version indicated in this attribute.
3574	On_bootclasspath_before *string
3575
3576	// Indicates that PackageManager should ignore this shared library if the
3577	// platform is below the version indicated in this attribute.
3578	//
3579	// This means that the device won't recognise this library as installed.
3580	Min_device_sdk *string
3581
3582	// Indicates that PackageManager should ignore this shared library if the
3583	// platform is above the version indicated in this attribute.
3584	//
3585	// This means that the device won't recognise this library as installed.
3586	Max_device_sdk *string
3587
3588	DexPreoptProfileGuided *bool `supported_build_releases:"UpsideDownCake+"`
3589}
3590
3591type scopeProperties struct {
3592	Jars           android.Paths
3593	StubsSrcJar    android.Path
3594	CurrentApiFile android.Path
3595	RemovedApiFile android.Path
3596	AnnotationsZip android.Path `supported_build_releases:"Tiramisu+"`
3597	SdkVersion     string
3598}
3599
3600func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
3601	sdk := variant.(*SdkLibrary)
3602
3603	// Copy the stem name for files in the sdk snapshot.
3604	s.Stem = sdk.distStem()
3605
3606	s.Scopes = make(map[*apiScope]*scopeProperties)
3607	for _, apiScope := range AllApiScopes {
3608		paths := sdk.findScopePaths(apiScope)
3609		if paths == nil {
3610			continue
3611		}
3612
3613		jars := paths.stubsImplPath
3614		if len(jars) > 0 {
3615			properties := scopeProperties{}
3616			properties.Jars = jars
3617			properties.SdkVersion = sdk.sdkVersionForStubsLibrary(ctx.SdkModuleContext(), apiScope)
3618			properties.StubsSrcJar = paths.stubsSrcJar.Path()
3619			if paths.currentApiFilePath.Valid() {
3620				properties.CurrentApiFile = paths.currentApiFilePath.Path()
3621			}
3622			if paths.removedApiFilePath.Valid() {
3623				properties.RemovedApiFile = paths.removedApiFilePath.Path()
3624			}
3625			// The annotations zip is only available for modules that set annotations_enabled: true.
3626			if paths.annotationsZip.Valid() {
3627				properties.AnnotationsZip = paths.annotationsZip.Path()
3628			}
3629			s.Scopes[apiScope] = &properties
3630		}
3631	}
3632
3633	s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme
3634	s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary())
3635	s.Compile_dex = sdk.dexProperties.Compile_dex
3636	s.Doctag_paths = sdk.doctagPaths
3637	s.Permitted_packages = sdk.PermittedPackagesForUpdatableBootJars()
3638	s.On_bootclasspath_since = sdk.commonSdkLibraryProperties.On_bootclasspath_since
3639	s.On_bootclasspath_before = sdk.commonSdkLibraryProperties.On_bootclasspath_before
3640	s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk
3641	s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk
3642
3643	implLibrary := sdk.getImplLibraryModule()
3644	if implLibrary != nil && implLibrary.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
3645		s.DexPreoptProfileGuided = proptools.BoolPtr(true)
3646	}
3647}
3648
3649func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
3650	if s.Naming_scheme != nil {
3651		propertySet.AddProperty("naming_scheme", proptools.String(s.Naming_scheme))
3652	}
3653	if s.Shared_library != nil {
3654		propertySet.AddProperty("shared_library", *s.Shared_library)
3655	}
3656	if s.Compile_dex != nil {
3657		propertySet.AddProperty("compile_dex", *s.Compile_dex)
3658	}
3659	if len(s.Permitted_packages) > 0 {
3660		propertySet.AddProperty("permitted_packages", s.Permitted_packages)
3661	}
3662	dexPreoptSet := propertySet.AddPropertySet("dex_preopt")
3663	if s.DexPreoptProfileGuided != nil {
3664		dexPreoptSet.AddProperty("profile_guided", proptools.Bool(s.DexPreoptProfileGuided))
3665	}
3666
3667	stem := s.Stem
3668
3669	for _, apiScope := range AllApiScopes {
3670		if properties, ok := s.Scopes[apiScope]; ok {
3671			scopeSet := propertySet.AddPropertySet(apiScope.propertyName)
3672
3673			scopeDir := apiScope.snapshotRelativeDir()
3674
3675			var jars []string
3676			for _, p := range properties.Jars {
3677				dest := filepath.Join(scopeDir, stem+"-stubs.jar")
3678				ctx.SnapshotBuilder().CopyToSnapshot(p, dest)
3679				jars = append(jars, dest)
3680			}
3681			scopeSet.AddProperty("jars", jars)
3682
3683			if ctx.SdkModuleContext().Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_USE_SRCJAR") {
3684				// Copy the stubs source jar into the snapshot zip as is.
3685				srcJarSnapshotPath := filepath.Join(scopeDir, stem+".srcjar")
3686				ctx.SnapshotBuilder().CopyToSnapshot(properties.StubsSrcJar, srcJarSnapshotPath)
3687				scopeSet.AddProperty("stub_srcs", []string{srcJarSnapshotPath})
3688			} else {
3689				// Merge the stubs source jar into the snapshot zip so that when it is unpacked
3690				// the source files are also unpacked.
3691				snapshotRelativeDir := filepath.Join(scopeDir, stem+"_stub_sources")
3692				ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir)
3693				scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir})
3694			}
3695
3696			if properties.CurrentApiFile != nil {
3697				currentApiSnapshotPath := apiScope.snapshotRelativeCurrentApiTxtPath(stem)
3698				ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, currentApiSnapshotPath)
3699				scopeSet.AddProperty("current_api", currentApiSnapshotPath)
3700			}
3701
3702			if properties.RemovedApiFile != nil {
3703				removedApiSnapshotPath := apiScope.snapshotRelativeRemovedApiTxtPath(stem)
3704				ctx.SnapshotBuilder().CopyToSnapshot(properties.RemovedApiFile, removedApiSnapshotPath)
3705				scopeSet.AddProperty("removed_api", removedApiSnapshotPath)
3706			}
3707
3708			if properties.AnnotationsZip != nil {
3709				annotationsSnapshotPath := filepath.Join(scopeDir, stem+"_annotations.zip")
3710				ctx.SnapshotBuilder().CopyToSnapshot(properties.AnnotationsZip, annotationsSnapshotPath)
3711				scopeSet.AddProperty("annotations", annotationsSnapshotPath)
3712			}
3713
3714			if properties.SdkVersion != "" {
3715				scopeSet.AddProperty("sdk_version", properties.SdkVersion)
3716			}
3717		}
3718	}
3719
3720	if len(s.Doctag_paths) > 0 {
3721		dests := []string{}
3722		for _, p := range s.Doctag_paths {
3723			dest := filepath.Join("doctags", p.Rel())
3724			ctx.SnapshotBuilder().CopyToSnapshot(p, dest)
3725			dests = append(dests, dest)
3726		}
3727		propertySet.AddProperty("doctag_files", dests)
3728	}
3729}
3730