• 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	"fmt"
19	"path"
20	"path/filepath"
21	"reflect"
22	"regexp"
23	"sort"
24	"strings"
25	"sync"
26
27	"github.com/google/blueprint"
28	"github.com/google/blueprint/proptools"
29
30	"android/soong/android"
31	"android/soong/dexpreopt"
32)
33
34const (
35	sdkXmlFileSuffix    = ".xml"
36	permissionsTemplate = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n` +
37		`<!-- Copyright (C) 2018 The Android Open Source Project\n` +
38		`\n` +
39		`    Licensed under the Apache License, Version 2.0 (the \"License\");\n` +
40		`    you may not use this file except in compliance with the License.\n` +
41		`    You may obtain a copy of the License at\n` +
42		`\n` +
43		`        http://www.apache.org/licenses/LICENSE-2.0\n` +
44		`\n` +
45		`    Unless required by applicable law or agreed to in writing, software\n` +
46		`    distributed under the License is distributed on an \"AS IS\" BASIS,\n` +
47		`    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n` +
48		`    See the License for the specific language governing permissions and\n` +
49		`    limitations under the License.\n` +
50		`-->\n` +
51		`<permissions>\n` +
52		`    <library name=\"%s\" file=\"%s\"/>\n` +
53		`</permissions>\n`
54)
55
56// A tag to associated a dependency with a specific api scope.
57type scopeDependencyTag struct {
58	blueprint.BaseDependencyTag
59	name     string
60	apiScope *apiScope
61
62	// Function for extracting appropriate path information from the dependency.
63	depInfoExtractor func(paths *scopePaths, ctx android.ModuleContext, dep android.Module) error
64}
65
66// Extract tag specific information from the dependency.
67func (tag scopeDependencyTag) extractDepInfo(ctx android.ModuleContext, dep android.Module, paths *scopePaths) {
68	err := tag.depInfoExtractor(paths, ctx, dep)
69	if err != nil {
70		ctx.ModuleErrorf("has an invalid {scopeDependencyTag: %s} dependency on module %s: %s", tag.name, ctx.OtherModuleName(dep), err.Error())
71	}
72}
73
74var _ android.ReplaceSourceWithPrebuilt = (*scopeDependencyTag)(nil)
75
76func (tag scopeDependencyTag) ReplaceSourceWithPrebuilt() bool {
77	return false
78}
79
80// Provides information about an api scope, e.g. public, system, test.
81type apiScope struct {
82	// The name of the api scope, e.g. public, system, test
83	name string
84
85	// The api scope that this scope extends.
86	extends *apiScope
87
88	// The legacy enabled status for a specific scope can be dependent on other
89	// properties that have been specified on the library so it is provided by
90	// a function that can determine the status by examining those properties.
91	legacyEnabledStatus func(module *SdkLibrary) bool
92
93	// The default enabled status for non-legacy behavior, which is triggered by
94	// explicitly enabling at least one api scope.
95	defaultEnabledStatus bool
96
97	// Gets a pointer to the scope specific properties.
98	scopeSpecificProperties func(module *SdkLibrary) *ApiScopeProperties
99
100	// The name of the field in the dynamically created structure.
101	fieldName string
102
103	// The name of the property in the java_sdk_library_import
104	propertyName string
105
106	// The tag to use to depend on the stubs library module.
107	stubsTag scopeDependencyTag
108
109	// The tag to use to depend on the stubs source module (if separate from the API module).
110	stubsSourceTag scopeDependencyTag
111
112	// The tag to use to depend on the API file generating module (if separate from the stubs source module).
113	apiFileTag scopeDependencyTag
114
115	// The tag to use to depend on the stubs source and API module.
116	stubsSourceAndApiTag scopeDependencyTag
117
118	// The scope specific prefix to add to the api file base of "current.txt" or "removed.txt".
119	apiFilePrefix string
120
121	// The scope specific prefix to add to the sdk library module name to construct a scope specific
122	// module name.
123	moduleSuffix string
124
125	// SDK version that the stubs library is built against. Note that this is always
126	// *current. Older stubs library built with a numbered SDK version is created from
127	// the prebuilt jar.
128	sdkVersion string
129
130	// The annotation that identifies this API level, empty for the public API scope.
131	annotation string
132
133	// Extra arguments to pass to droidstubs for this scope.
134	//
135	// This is not used directly but is used to construct the droidstubsArgs.
136	extraArgs []string
137
138	// The args that must be passed to droidstubs to generate the API and stubs source
139	// for this scope, constructed dynamically by initApiScope().
140	//
141	// The API only includes the additional members that this scope adds over the scope
142	// that it extends.
143	//
144	// The stubs source must include the definitions of everything that is in this
145	// api scope and all the scopes that this one extends.
146	droidstubsArgs []string
147
148	// Whether the api scope can be treated as unstable, and should skip compat checks.
149	unstable bool
150}
151
152// Initialize a scope, creating and adding appropriate dependency tags
153func initApiScope(scope *apiScope) *apiScope {
154	name := scope.name
155	scopeByName[name] = scope
156	allScopeNames = append(allScopeNames, name)
157	scope.propertyName = strings.ReplaceAll(name, "-", "_")
158	scope.fieldName = proptools.FieldNameForProperty(scope.propertyName)
159	scope.stubsTag = scopeDependencyTag{
160		name:             name + "-stubs",
161		apiScope:         scope,
162		depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency,
163	}
164	scope.stubsSourceTag = scopeDependencyTag{
165		name:             name + "-stubs-source",
166		apiScope:         scope,
167		depInfoExtractor: (*scopePaths).extractStubsSourceInfoFromDep,
168	}
169	scope.apiFileTag = scopeDependencyTag{
170		name:             name + "-api",
171		apiScope:         scope,
172		depInfoExtractor: (*scopePaths).extractApiInfoFromDep,
173	}
174	scope.stubsSourceAndApiTag = scopeDependencyTag{
175		name:             name + "-stubs-source-and-api",
176		apiScope:         scope,
177		depInfoExtractor: (*scopePaths).extractStubsSourceAndApiInfoFromApiStubsProvider,
178	}
179
180	// To get the args needed to generate the stubs source append all the args from
181	// this scope and all the scopes it extends as each set of args adds additional
182	// members to the stubs.
183	var scopeSpecificArgs []string
184	if scope.annotation != "" {
185		scopeSpecificArgs = []string{"--show-annotation", scope.annotation}
186	}
187	for s := scope; s != nil; s = s.extends {
188		scopeSpecificArgs = append(scopeSpecificArgs, s.extraArgs...)
189
190		// Ensure that the generated stubs includes all the API elements from the API scope
191		// that this scope extends.
192		if s != scope && s.annotation != "" {
193			scopeSpecificArgs = append(scopeSpecificArgs, "--show-for-stub-purposes-annotation", s.annotation)
194		}
195	}
196
197	// Escape any special characters in the arguments. This is needed because droidstubs
198	// passes these directly to the shell command.
199	scope.droidstubsArgs = proptools.ShellEscapeList(scopeSpecificArgs)
200
201	return scope
202}
203
204func (scope *apiScope) stubsLibraryModuleNameSuffix() string {
205	return ".stubs" + scope.moduleSuffix
206}
207
208func (scope *apiScope) stubsLibraryModuleName(baseName string) string {
209	return baseName + scope.stubsLibraryModuleNameSuffix()
210}
211
212func (scope *apiScope) stubsSourceModuleName(baseName string) string {
213	return baseName + ".stubs.source" + scope.moduleSuffix
214}
215
216func (scope *apiScope) apiModuleName(baseName string) string {
217	return baseName + ".api" + scope.moduleSuffix
218}
219
220func (scope *apiScope) String() string {
221	return scope.name
222}
223
224type apiScopes []*apiScope
225
226func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string {
227	var list []string
228	for _, scope := range scopes {
229		list = append(list, accessor(scope))
230	}
231	return list
232}
233
234var (
235	scopeByName    = make(map[string]*apiScope)
236	allScopeNames  []string
237	apiScopePublic = initApiScope(&apiScope{
238		name: "public",
239
240		// Public scope is enabled by default for both legacy and non-legacy modes.
241		legacyEnabledStatus: func(module *SdkLibrary) bool {
242			return true
243		},
244		defaultEnabledStatus: true,
245
246		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
247			return &module.sdkLibraryProperties.Public
248		},
249		sdkVersion: "current",
250	})
251	apiScopeSystem = initApiScope(&apiScope{
252		name:                "system",
253		extends:             apiScopePublic,
254		legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
255		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
256			return &module.sdkLibraryProperties.System
257		},
258		apiFilePrefix: "system-",
259		moduleSuffix:  ".system",
260		sdkVersion:    "system_current",
261		annotation:    "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS)",
262	})
263	apiScopeTest = initApiScope(&apiScope{
264		name:                "test",
265		extends:             apiScopeSystem,
266		legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault,
267		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
268			return &module.sdkLibraryProperties.Test
269		},
270		apiFilePrefix: "test-",
271		moduleSuffix:  ".test",
272		sdkVersion:    "test_current",
273		annotation:    "android.annotation.TestApi",
274		unstable:      true,
275	})
276	apiScopeModuleLib = initApiScope(&apiScope{
277		name:    "module-lib",
278		extends: apiScopeSystem,
279		// The module-lib scope is disabled by default in legacy mode.
280		//
281		// Enabling this would break existing usages.
282		legacyEnabledStatus: func(module *SdkLibrary) bool {
283			return false
284		},
285		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
286			return &module.sdkLibraryProperties.Module_lib
287		},
288		apiFilePrefix: "module-lib-",
289		moduleSuffix:  ".module_lib",
290		sdkVersion:    "module_current",
291		annotation:    "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)",
292	})
293	apiScopeSystemServer = initApiScope(&apiScope{
294		name:    "system-server",
295		extends: apiScopePublic,
296		// The system-server scope is disabled by default in legacy mode.
297		//
298		// Enabling this would break existing usages.
299		legacyEnabledStatus: func(module *SdkLibrary) bool {
300			return false
301		},
302		scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
303			return &module.sdkLibraryProperties.System_server
304		},
305		apiFilePrefix: "system-server-",
306		moduleSuffix:  ".system_server",
307		sdkVersion:    "system_server_current",
308		annotation:    "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.SYSTEM_SERVER)",
309		extraArgs: []string{
310			"--hide-annotation", "android.annotation.Hide",
311			// com.android.* classes are okay in this interface"
312			"--hide", "InternalClasses",
313		},
314	})
315	allApiScopes = apiScopes{
316		apiScopePublic,
317		apiScopeSystem,
318		apiScopeTest,
319		apiScopeModuleLib,
320		apiScopeSystemServer,
321	}
322)
323
324var (
325	javaSdkLibrariesLock sync.Mutex
326)
327
328// TODO: these are big features that are currently missing
329// 1) disallowing linking to the runtime shared lib
330// 2) HTML generation
331
332func init() {
333	RegisterSdkLibraryBuildComponents(android.InitRegistrationContext)
334
335	android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
336		javaSdkLibraries := javaSdkLibraries(ctx.Config())
337		sort.Strings(*javaSdkLibraries)
338		ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " "))
339	})
340
341	// Register sdk member types.
342	android.RegisterSdkMemberType(javaSdkLibrarySdkMemberType)
343}
344
345func RegisterSdkLibraryBuildComponents(ctx android.RegistrationContext) {
346	ctx.RegisterModuleType("java_sdk_library", SdkLibraryFactory)
347	ctx.RegisterModuleType("java_sdk_library_import", sdkLibraryImportFactory)
348}
349
350// Properties associated with each api scope.
351type ApiScopeProperties struct {
352	// Indicates whether the api surface is generated.
353	//
354	// If this is set for any scope then all scopes must explicitly specify if they
355	// are enabled. This is to prevent new usages from depending on legacy behavior.
356	//
357	// Otherwise, if this is not set for any scope then the default  behavior is
358	// scope specific so please refer to the scope specific property documentation.
359	Enabled *bool
360
361	// The sdk_version to use for building the stubs.
362	//
363	// If not specified then it will use an sdk_version determined as follows:
364	// 1) If the sdk_version specified on the java_sdk_library is none then this
365	//    will be none. This is used for java_sdk_library instances that are used
366	//    to create stubs that contribute to the core_current sdk version.
367	// 2) Otherwise, it is assumed that this library extends but does not contribute
368	//    directly to a specific sdk_version and so this uses the sdk_version appropriate
369	//    for the api scope. e.g. public will use sdk_version: current, system will use
370	//    sdk_version: system_current, etc.
371	//
372	// This does not affect the sdk_version used for either generating the stubs source
373	// or the API file. They both have to use the same sdk_version as is used for
374	// compiling the implementation library.
375	Sdk_version *string
376}
377
378type sdkLibraryProperties struct {
379	// Visibility for impl library module. If not specified then defaults to the
380	// visibility property.
381	Impl_library_visibility []string
382
383	// Visibility for stubs library modules. If not specified then defaults to the
384	// visibility property.
385	Stubs_library_visibility []string
386
387	// Visibility for stubs source modules. If not specified then defaults to the
388	// visibility property.
389	Stubs_source_visibility []string
390
391	// List of Java libraries that will be in the classpath when building the implementation lib
392	Impl_only_libs []string `android:"arch_variant"`
393
394	// List of Java libraries that will be in the classpath when building stubs
395	Stub_only_libs []string `android:"arch_variant"`
396
397	// List of Java libraries that will included in stub libraries
398	Stub_only_static_libs []string `android:"arch_variant"`
399
400	// list of package names that will be documented and publicized as API.
401	// This allows the API to be restricted to a subset of the source files provided.
402	// If this is unspecified then all the source files will be treated as being part
403	// of the API.
404	Api_packages []string
405
406	// list of package names that must be hidden from the API
407	Hidden_api_packages []string
408
409	// the relative path to the directory containing the api specification files.
410	// Defaults to "api".
411	Api_dir *string
412
413	// Determines whether a runtime implementation library is built; defaults to false.
414	//
415	// If true then it also prevents the module from being used as a shared module, i.e.
416	// it is as is shared_library: false, was set.
417	Api_only *bool
418
419	// local files that are used within user customized droiddoc options.
420	Droiddoc_option_files []string
421
422	// additional droiddoc options
423	// Available variables for substitution:
424	//
425	//  $(location <label>): the path to the droiddoc_option_files with name <label>
426	Droiddoc_options []string
427
428	// is set to true, Metalava will allow framework SDK to contain annotations.
429	Annotations_enabled *bool
430
431	// a list of top-level directories containing files to merge qualifier annotations
432	// (i.e. those intended to be included in the stubs written) from.
433	Merge_annotations_dirs []string
434
435	// a list of top-level directories containing Java stub files to merge show/hide annotations from.
436	Merge_inclusion_annotations_dirs []string
437
438	// If set to true then don't create dist rules.
439	No_dist *bool
440
441	// The stem for the artifacts that are copied to the dist, if not specified
442	// then defaults to the base module name.
443	//
444	// For each scope the following artifacts are copied to the apistubs/<scope>
445	// directory in the dist.
446	// * stubs impl jar -> <dist-stem>.jar
447	// * API specification file -> api/<dist-stem>.txt
448	// * Removed API specification file -> api/<dist-stem>-removed.txt
449	//
450	// Also used to construct the name of the filegroup (created by prebuilt_apis)
451	// that references the latest released API and remove API specification files.
452	// * API specification filegroup -> <dist-stem>.api.<scope>.latest
453	// * Removed API specification filegroup -> <dist-stem>-removed.api.<scope>.latest
454	// * API incompatibilities baseline filegroup -> <dist-stem>-incompatibilities.api.<scope>.latest
455	Dist_stem *string
456
457	// The subdirectory for the artifacts that are copied to the dist directory.  If not specified
458	// then defaults to "unknown".  Should be set to "android" for anything that should be published
459	// in the public Android SDK.
460	Dist_group *string
461
462	// A compatibility mode that allows historical API-tracking files to not exist.
463	// Do not use.
464	Unsafe_ignore_missing_latest_api bool
465
466	// indicates whether system and test apis should be generated.
467	Generate_system_and_test_apis bool `blueprint:"mutated"`
468
469	// The properties specific to the public api scope
470	//
471	// Unless explicitly specified by using public.enabled the public api scope is
472	// enabled by default in both legacy and non-legacy mode.
473	Public ApiScopeProperties
474
475	// The properties specific to the system api scope
476	//
477	// In legacy mode the system api scope is enabled by default when sdk_version
478	// is set to something other than "none".
479	//
480	// In non-legacy mode the system api scope is disabled by default.
481	System ApiScopeProperties
482
483	// The properties specific to the test api scope
484	//
485	// In legacy mode the test api scope is enabled by default when sdk_version
486	// is set to something other than "none".
487	//
488	// In non-legacy mode the test api scope is disabled by default.
489	Test ApiScopeProperties
490
491	// The properties specific to the module-lib api scope
492	//
493	// Unless explicitly specified by using test.enabled the module-lib api scope is
494	// disabled by default.
495	Module_lib ApiScopeProperties
496
497	// The properties specific to the system-server api scope
498	//
499	// Unless explicitly specified by using test.enabled the module-lib api scope is
500	// disabled by default.
501	System_server ApiScopeProperties
502
503	// Determines if the stubs are preferred over the implementation library
504	// for linking, even when the client doesn't specify sdk_version. When this
505	// is set to true, such clients are provided with the widest API surface that
506	// this lib provides. Note however that this option doesn't affect the clients
507	// that are in the same APEX as this library. In that case, the clients are
508	// always linked with the implementation library. Default is false.
509	Default_to_stubs *bool
510
511	// Properties related to api linting.
512	Api_lint struct {
513		// Enable api linting.
514		Enabled *bool
515	}
516
517	// TODO: determines whether to create HTML doc or not
518	//Html_doc *bool
519}
520
521// Paths to outputs from java_sdk_library and java_sdk_library_import.
522//
523// Fields that are android.Paths are always set (during GenerateAndroidBuildActions).
524// OptionalPaths are always set by java_sdk_library but may not be set by
525// java_sdk_library_import as not all instances provide that information.
526type scopePaths struct {
527	// The path (represented as Paths for convenience when returning) to the stubs header jar.
528	//
529	// That is the jar that is created by turbine.
530	stubsHeaderPath android.Paths
531
532	// The path (represented as Paths for convenience when returning) to the stubs implementation jar.
533	//
534	// This is not the implementation jar, it still only contains stubs.
535	stubsImplPath android.Paths
536
537	// The dex jar for the stubs.
538	//
539	// This is not the implementation jar, it still only contains stubs.
540	stubsDexJarPath android.Path
541
542	// The API specification file, e.g. system_current.txt.
543	currentApiFilePath android.OptionalPath
544
545	// The specification of API elements removed since the last release.
546	removedApiFilePath android.OptionalPath
547
548	// The stubs source jar.
549	stubsSrcJar android.OptionalPath
550}
551
552func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
553	if ctx.OtherModuleHasProvider(dep, JavaInfoProvider) {
554		lib := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
555		paths.stubsHeaderPath = lib.HeaderJars
556		paths.stubsImplPath = lib.ImplementationJars
557
558		libDep := dep.(UsesLibraryDependency)
559		paths.stubsDexJarPath = libDep.DexJarBuildPath()
560		return nil
561	} else {
562		return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
563	}
564}
565
566func (paths *scopePaths) treatDepAsApiStubsProvider(dep android.Module, action func(provider ApiStubsProvider)) error {
567	if apiStubsProvider, ok := dep.(ApiStubsProvider); ok {
568		action(apiStubsProvider)
569		return nil
570	} else {
571		return fmt.Errorf("expected module that implements ApiStubsProvider, e.g. droidstubs")
572	}
573}
574
575func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider)) error {
576	if apiStubsProvider, ok := dep.(ApiStubsSrcProvider); ok {
577		action(apiStubsProvider)
578		return nil
579	} else {
580		return fmt.Errorf("expected module that implements ApiStubsSrcProvider, e.g. droidstubs")
581	}
582}
583
584func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider) {
585	paths.currentApiFilePath = android.OptionalPathForPath(provider.ApiFilePath())
586	paths.removedApiFilePath = android.OptionalPathForPath(provider.RemovedApiFilePath())
587}
588
589func (paths *scopePaths) extractApiInfoFromDep(ctx android.ModuleContext, dep android.Module) error {
590	return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) {
591		paths.extractApiInfoFromApiStubsProvider(provider)
592	})
593}
594
595func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider) {
596	paths.stubsSrcJar = android.OptionalPathForPath(provider.StubsSrcJar())
597}
598
599func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext, dep android.Module) error {
600	return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) {
601		paths.extractStubsSourceInfoFromApiStubsProviders(provider)
602	})
603}
604
605func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx android.ModuleContext, dep android.Module) error {
606	return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) {
607		paths.extractApiInfoFromApiStubsProvider(provider)
608		paths.extractStubsSourceInfoFromApiStubsProviders(provider)
609	})
610}
611
612type commonToSdkLibraryAndImportProperties struct {
613	// The naming scheme to use for the components that this module creates.
614	//
615	// If not specified then it defaults to "default".
616	//
617	// This is a temporary mechanism to simplify conversion from separate modules for each
618	// component that follow a different naming pattern to the default one.
619	//
620	// TODO(b/155480189) - Remove once naming inconsistencies have been resolved.
621	Naming_scheme *string
622
623	// Specifies whether this module can be used as an Android shared library; defaults
624	// to true.
625	//
626	// An Android shared library is one that can be referenced in a <uses-library> element
627	// in an AndroidManifest.xml.
628	Shared_library *bool
629
630	// Files containing information about supported java doc tags.
631	Doctag_files []string `android:"path"`
632}
633
634// commonSdkLibraryAndImportModule defines the interface that must be provided by a module that
635// embeds the commonToSdkLibraryAndImport struct.
636type commonSdkLibraryAndImportModule interface {
637	android.SdkAware
638
639	BaseModuleName() string
640}
641
642// Common code between sdk library and sdk library import
643type commonToSdkLibraryAndImport struct {
644	module commonSdkLibraryAndImportModule
645
646	scopePaths map[*apiScope]*scopePaths
647
648	namingScheme sdkLibraryComponentNamingScheme
649
650	commonSdkLibraryProperties commonToSdkLibraryAndImportProperties
651
652	// Paths to commonSdkLibraryProperties.Doctag_files
653	doctagPaths android.Paths
654
655	// Functionality related to this being used as a component of a java_sdk_library.
656	EmbeddableSdkLibraryComponent
657}
658
659func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) {
660	c.module = module
661
662	module.AddProperties(&c.commonSdkLibraryProperties)
663
664	// Initialize this as an sdk library component.
665	c.initSdkLibraryComponent(module)
666}
667
668func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool {
669	schemeProperty := proptools.StringDefault(c.commonSdkLibraryProperties.Naming_scheme, "default")
670	switch schemeProperty {
671	case "default":
672		c.namingScheme = &defaultNamingScheme{}
673	default:
674		ctx.PropertyErrorf("naming_scheme", "expected 'default' but was %q", schemeProperty)
675		return false
676	}
677
678	namePtr := proptools.StringPtr(c.module.BaseModuleName())
679	c.sdkLibraryComponentProperties.SdkLibraryName = namePtr
680
681	// Only track this sdk library if this can be used as a shared library.
682	if c.sharedLibrary() {
683		// Use the name specified in the module definition as the owner.
684		c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = namePtr
685	}
686
687	return true
688}
689
690// uniqueApexVariations provides common implementation of the ApexModule.UniqueApexVariations
691// method.
692func (c *commonToSdkLibraryAndImport) uniqueApexVariations() bool {
693	// A java_sdk_library that is a shared library produces an XML file that makes the shared library
694	// usable from an AndroidManifest.xml's <uses-library> entry. That XML file contains the name of
695	// the APEX and so it needs a unique variation per APEX.
696	return c.sharedLibrary()
697}
698
699func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) {
700	c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files)
701}
702
703// Module name of the runtime implementation library
704func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
705	return c.module.BaseModuleName() + ".impl"
706}
707
708// Module name of the XML file for the lib
709func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
710	return c.module.BaseModuleName() + sdkXmlFileSuffix
711}
712
713// Name of the java_library module that compiles the stubs source.
714func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
715	baseName := c.module.BaseModuleName()
716	return c.module.SdkMemberComponentName(baseName, func(name string) string {
717		return c.namingScheme.stubsLibraryModuleName(apiScope, name)
718	})
719}
720
721// Name of the droidstubs module that generates the stubs source and may also
722// generate/check the API.
723func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
724	baseName := c.module.BaseModuleName()
725	return c.module.SdkMemberComponentName(baseName, func(name string) string {
726		return c.namingScheme.stubsSourceModuleName(apiScope, name)
727	})
728}
729
730// The component names for different outputs of the java_sdk_library.
731//
732// They are similar to the names used for the child modules it creates
733const (
734	stubsSourceComponentName = "stubs.source"
735
736	apiTxtComponentName = "api.txt"
737
738	removedApiTxtComponentName = "removed-api.txt"
739)
740
741// A regular expression to match tags that reference a specific stubs component.
742//
743// It will only match if given a valid scope and a valid component. It is verfy strict
744// to ensure it does not accidentally match a similar looking tag that should be processed
745// by the embedded Library.
746var tagSplitter = func() *regexp.Regexp {
747	// Given a list of literal string items returns a regular expression that will
748	// match any one of the items.
749	choice := func(items ...string) string {
750		return `\Q` + strings.Join(items, `\E|\Q`) + `\E`
751	}
752
753	// Regular expression to match one of the scopes.
754	scopesRegexp := choice(allScopeNames...)
755
756	// Regular expression to match one of the components.
757	componentsRegexp := choice(stubsSourceComponentName, apiTxtComponentName, removedApiTxtComponentName)
758
759	// Regular expression to match any combination of one scope and one component.
760	return regexp.MustCompile(fmt.Sprintf(`^\.(%s)\.(%s)$`, scopesRegexp, componentsRegexp))
761}()
762
763// For OutputFileProducer interface
764//
765// .<scope>.stubs.source
766// .<scope>.api.txt
767// .<scope>.removed-api.txt
768func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Paths, error) {
769	if groups := tagSplitter.FindStringSubmatch(tag); groups != nil {
770		scopeName := groups[1]
771		component := groups[2]
772
773		if scope, ok := scopeByName[scopeName]; ok {
774			paths := c.findScopePaths(scope)
775			if paths == nil {
776				return nil, fmt.Errorf("%q does not provide api scope %s", c.module.BaseModuleName(), scopeName)
777			}
778
779			switch component {
780			case stubsSourceComponentName:
781				if paths.stubsSrcJar.Valid() {
782					return android.Paths{paths.stubsSrcJar.Path()}, nil
783				}
784
785			case apiTxtComponentName:
786				if paths.currentApiFilePath.Valid() {
787					return android.Paths{paths.currentApiFilePath.Path()}, nil
788				}
789
790			case removedApiTxtComponentName:
791				if paths.removedApiFilePath.Valid() {
792					return android.Paths{paths.removedApiFilePath.Path()}, nil
793				}
794			}
795
796			return nil, fmt.Errorf("%s not available for api scope %s", component, scopeName)
797		} else {
798			return nil, fmt.Errorf("unknown scope %s in %s", scope, tag)
799		}
800
801	} else {
802		switch tag {
803		case ".doctags":
804			if c.doctagPaths != nil {
805				return c.doctagPaths, nil
806			} else {
807				return nil, fmt.Errorf("no doctag_files specified on %s", c.module.BaseModuleName())
808			}
809		}
810		return nil, nil
811	}
812}
813
814func (c *commonToSdkLibraryAndImport) getScopePathsCreateIfNeeded(scope *apiScope) *scopePaths {
815	if c.scopePaths == nil {
816		c.scopePaths = make(map[*apiScope]*scopePaths)
817	}
818	paths := c.scopePaths[scope]
819	if paths == nil {
820		paths = &scopePaths{}
821		c.scopePaths[scope] = paths
822	}
823
824	return paths
825}
826
827func (c *commonToSdkLibraryAndImport) findScopePaths(scope *apiScope) *scopePaths {
828	if c.scopePaths == nil {
829		return nil
830	}
831
832	return c.scopePaths[scope]
833}
834
835// If this does not support the requested api scope then find the closest available
836// scope it does support. Returns nil if no such scope is available.
837func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *scopePaths {
838	for s := scope; s != nil; s = s.extends {
839		if paths := c.findScopePaths(s); paths != nil {
840			return paths
841		}
842	}
843
844	// This should never happen outside tests as public should be the base scope for every
845	// scope and is enabled by default.
846	return nil
847}
848
849func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
850
851	// If a specific numeric version has been requested then use prebuilt versions of the sdk.
852	if !sdkVersion.ApiLevel.IsPreview() {
853		return PrebuiltJars(ctx, c.module.BaseModuleName(), sdkVersion)
854	}
855
856	paths := c.selectScopePaths(ctx, sdkVersion.Kind)
857	if paths == nil {
858		return nil
859	}
860
861	return paths.stubsHeaderPath
862}
863
864// selectScopePaths returns the *scopePaths appropriate for the specific kind.
865//
866// If the module does not support the specific kind then it will return the *scopePaths for the
867// closest kind which is a subset of the requested kind. e.g. if requesting android.SdkModule then
868// it will return *scopePaths for android.SdkSystem if available or android.SdkPublic of not.
869func (c *commonToSdkLibraryAndImport) selectScopePaths(ctx android.BaseModuleContext, kind android.SdkKind) *scopePaths {
870	apiScope := sdkKindToApiScope(kind)
871
872	paths := c.findClosestScopePath(apiScope)
873	if paths == nil {
874		var scopes []string
875		for _, s := range allApiScopes {
876			if c.findScopePaths(s) != nil {
877				scopes = append(scopes, s.name)
878			}
879		}
880		ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.BaseModuleName(), scopes)
881		return nil
882	}
883
884	return paths
885}
886
887// sdkKindToApiScope maps from android.SdkKind to apiScope.
888func sdkKindToApiScope(kind android.SdkKind) *apiScope {
889	var apiScope *apiScope
890	switch kind {
891	case android.SdkSystem:
892		apiScope = apiScopeSystem
893	case android.SdkModule:
894		apiScope = apiScopeModuleLib
895	case android.SdkTest:
896		apiScope = apiScopeTest
897	case android.SdkSystemServer:
898		apiScope = apiScopeSystemServer
899	default:
900		apiScope = apiScopePublic
901	}
902	return apiScope
903}
904
905// to satisfy SdkLibraryDependency interface
906func (c *commonToSdkLibraryAndImport) SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path {
907	paths := c.selectScopePaths(ctx, kind)
908	if paths == nil {
909		return nil
910	}
911
912	return paths.stubsDexJarPath
913}
914
915// to satisfy SdkLibraryDependency interface
916func (c *commonToSdkLibraryAndImport) SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath {
917	apiScope := sdkKindToApiScope(kind)
918	paths := c.findScopePaths(apiScope)
919	if paths == nil {
920		return android.OptionalPath{}
921	}
922
923	return paths.removedApiFilePath
924}
925
926func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} {
927	componentProps := &struct {
928		SdkLibraryName              *string
929		SdkLibraryToImplicitlyTrack *string
930	}{}
931
932	namePtr := proptools.StringPtr(c.module.BaseModuleName())
933	componentProps.SdkLibraryName = namePtr
934
935	if c.sharedLibrary() {
936		// Mark the stubs library as being components of this java_sdk_library so that
937		// any app that includes code which depends (directly or indirectly) on the stubs
938		// library will have the appropriate <uses-library> invocation inserted into its
939		// manifest if necessary.
940		componentProps.SdkLibraryToImplicitlyTrack = namePtr
941	}
942
943	return componentProps
944}
945
946func (c *commonToSdkLibraryAndImport) sharedLibrary() bool {
947	return proptools.BoolDefault(c.commonSdkLibraryProperties.Shared_library, true)
948}
949
950// Check if the stub libraries should be compiled for dex
951func (c *commonToSdkLibraryAndImport) stubLibrariesCompiledForDex() bool {
952	// Always compile the dex file files for the stub libraries if they will be used on the
953	// bootclasspath.
954	return !c.sharedLibrary()
955}
956
957// Properties related to the use of a module as an component of a java_sdk_library.
958type SdkLibraryComponentProperties struct {
959	// The name of the java_sdk_library/_import module.
960	SdkLibraryName *string `blueprint:"mutated"`
961
962	// The name of the java_sdk_library/_import to add to a <uses-library> entry
963	// in the AndroidManifest.xml of any Android app that includes code that references
964	// this module. If not set then no java_sdk_library/_import is tracked.
965	SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"`
966}
967
968// Structure to be embedded in a module struct that needs to support the
969// SdkLibraryComponentDependency interface.
970type EmbeddableSdkLibraryComponent struct {
971	sdkLibraryComponentProperties SdkLibraryComponentProperties
972}
973
974func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(module android.Module) {
975	module.AddProperties(&e.sdkLibraryComponentProperties)
976}
977
978// to satisfy SdkLibraryComponentDependency
979func (e *EmbeddableSdkLibraryComponent) SdkLibraryName() *string {
980	return e.sdkLibraryComponentProperties.SdkLibraryName
981}
982
983// to satisfy SdkLibraryComponentDependency
984func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() *string {
985	return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
986}
987
988// to satisfy SdkLibraryComponentDependency
989func (e *EmbeddableSdkLibraryComponent) OptionalSdkLibraryImplementation() *string {
990	// Currently implementation library name is the same as the SDK library name.
991	return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
992}
993
994// Implemented by modules that are (or possibly could be) a component of a java_sdk_library
995// (including the java_sdk_library) itself.
996type SdkLibraryComponentDependency interface {
997	UsesLibraryDependency
998
999	// SdkLibraryName returns the name of the java_sdk_library/_import module.
1000	SdkLibraryName() *string
1001
1002	// The optional name of the sdk library that should be implicitly added to the
1003	// AndroidManifest of an app that contains code which references the sdk library.
1004	//
1005	// Returns the name of the optional implicit SDK library or nil, if there isn't one.
1006	OptionalImplicitSdkLibrary() *string
1007
1008	// The name of the implementation library for the optional SDK library or nil, if there isn't one.
1009	OptionalSdkLibraryImplementation() *string
1010}
1011
1012// Make sure that all the module types that are components of java_sdk_library/_import
1013// and which can be referenced (directly or indirectly) from an android app implement
1014// the SdkLibraryComponentDependency interface.
1015var _ SdkLibraryComponentDependency = (*Library)(nil)
1016var _ SdkLibraryComponentDependency = (*Import)(nil)
1017var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil)
1018var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil)
1019
1020// Provides access to sdk_version related files, e.g. header and implementation jars.
1021type SdkLibraryDependency interface {
1022	SdkLibraryComponentDependency
1023
1024	// Get the header jars appropriate for the supplied sdk_version.
1025	//
1026	// These are turbine generated jars so they only change if the externals of the
1027	// class changes but it does not contain and implementation or JavaDoc.
1028	SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
1029
1030	// Get the implementation jars appropriate for the supplied sdk version.
1031	//
1032	// These are either the implementation jar for the whole sdk library or the implementation
1033	// jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise
1034	// they are identical to the corresponding header jars.
1035	SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
1036
1037	// SdkApiStubDexJar returns the dex jar for the stubs. It is needed by the hiddenapi processing
1038	// tool which processes dex files.
1039	SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path
1040
1041	// SdkRemovedTxtFile returns the optional path to the removed.txt file for the specified sdk kind.
1042	SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath
1043
1044	// sharedLibrary returns true if this can be used as a shared library.
1045	sharedLibrary() bool
1046}
1047
1048type SdkLibrary struct {
1049	Library
1050
1051	sdkLibraryProperties sdkLibraryProperties
1052
1053	// Map from api scope to the scope specific property structure.
1054	scopeToProperties map[*apiScope]*ApiScopeProperties
1055
1056	commonToSdkLibraryAndImport
1057}
1058
1059var _ SdkLibraryDependency = (*SdkLibrary)(nil)
1060
1061func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool {
1062	return module.sdkLibraryProperties.Generate_system_and_test_apis
1063}
1064
1065func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) apiScopes {
1066	// Check to see if any scopes have been explicitly enabled. If any have then all
1067	// must be.
1068	anyScopesExplicitlyEnabled := false
1069	for _, scope := range allApiScopes {
1070		scopeProperties := module.scopeToProperties[scope]
1071		if scopeProperties.Enabled != nil {
1072			anyScopesExplicitlyEnabled = true
1073			break
1074		}
1075	}
1076
1077	var generatedScopes apiScopes
1078	enabledScopes := make(map[*apiScope]struct{})
1079	for _, scope := range allApiScopes {
1080		scopeProperties := module.scopeToProperties[scope]
1081		// If any scopes are explicitly enabled then ignore the legacy enabled status.
1082		// This is to ensure that any new usages of this module type do not rely on legacy
1083		// behaviour.
1084		defaultEnabledStatus := false
1085		if anyScopesExplicitlyEnabled {
1086			defaultEnabledStatus = scope.defaultEnabledStatus
1087		} else {
1088			defaultEnabledStatus = scope.legacyEnabledStatus(module)
1089		}
1090		enabled := proptools.BoolDefault(scopeProperties.Enabled, defaultEnabledStatus)
1091		if enabled {
1092			enabledScopes[scope] = struct{}{}
1093			generatedScopes = append(generatedScopes, scope)
1094		}
1095	}
1096
1097	// Now check to make sure that any scope that is extended by an enabled scope is also
1098	// enabled.
1099	for _, scope := range allApiScopes {
1100		if _, ok := enabledScopes[scope]; ok {
1101			extends := scope.extends
1102			if extends != nil {
1103				if _, ok := enabledScopes[extends]; !ok {
1104					ctx.ModuleErrorf("enabled api scope %q depends on disabled scope %q", scope, extends)
1105				}
1106			}
1107		}
1108	}
1109
1110	return generatedScopes
1111}
1112
1113type sdkLibraryComponentTag struct {
1114	blueprint.BaseDependencyTag
1115	name string
1116}
1117
1118// Mark this tag so dependencies that use it are excluded from visibility enforcement.
1119func (t sdkLibraryComponentTag) ExcludeFromVisibilityEnforcement() {}
1120
1121var xmlPermissionsFileTag = sdkLibraryComponentTag{name: "xml-permissions-file"}
1122
1123func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool {
1124	if dt, ok := depTag.(sdkLibraryComponentTag); ok {
1125		return dt == xmlPermissionsFileTag
1126	}
1127	return false
1128}
1129
1130var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"}
1131
1132// Add the dependencies on the child modules in the component deps mutator.
1133func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
1134	for _, apiScope := range module.getGeneratedApiScopes(ctx) {
1135		// Add dependencies to the stubs library
1136		ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope))
1137
1138		// Add a dependency on the stubs source in order to access both stubs source and api information.
1139		ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope))
1140	}
1141
1142	if module.requiresRuntimeImplementationLibrary() {
1143		// Add dependency to the rule for generating the implementation library.
1144		ctx.AddDependency(module, implLibraryTag, module.implLibraryModuleName())
1145
1146		if module.sharedLibrary() {
1147			// Add dependency to the rule for generating the xml permissions file
1148			ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlPermissionsModuleName())
1149		}
1150	}
1151}
1152
1153// Add other dependencies as normal.
1154func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
1155	var missingApiModules []string
1156	for _, apiScope := range module.getGeneratedApiScopes(ctx) {
1157		if apiScope.unstable {
1158			continue
1159		}
1160		if m := android.SrcIsModule(module.latestApiFilegroupName(apiScope)); !ctx.OtherModuleExists(m) {
1161			missingApiModules = append(missingApiModules, m)
1162		}
1163		if m := android.SrcIsModule(module.latestRemovedApiFilegroupName(apiScope)); !ctx.OtherModuleExists(m) {
1164			missingApiModules = append(missingApiModules, m)
1165		}
1166		if m := android.SrcIsModule(module.latestIncompatibilitiesFilegroupName(apiScope)); !ctx.OtherModuleExists(m) {
1167			missingApiModules = append(missingApiModules, m)
1168		}
1169	}
1170	if len(missingApiModules) != 0 && !module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api {
1171		m := module.Name() + " is missing tracking files for previously released library versions.\n"
1172		m += "You need to do one of the following:\n"
1173		m += "- Add `unsafe_ignore_missing_latest_api: true` to your blueprint (to disable compat tracking)\n"
1174		m += "- Add a set of prebuilt txt files representing the last released version of this library for compat checking.\n"
1175		m += "  (the current set of API files can be used as a seed for this compatibility tracking\n"
1176		m += "\n"
1177		m += "The following filegroup modules are missing:\n  "
1178		m += strings.Join(missingApiModules, "\n  ") + "\n"
1179		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."
1180		ctx.ModuleErrorf(m)
1181	}
1182	if module.requiresRuntimeImplementationLibrary() {
1183		// Only add the deps for the library if it is actually going to be built.
1184		module.Library.deps(ctx)
1185	}
1186}
1187
1188func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
1189	paths, err := module.commonOutputFiles(tag)
1190	if paths == nil && err == nil {
1191		return module.Library.OutputFiles(tag)
1192	} else {
1193		return paths, err
1194	}
1195}
1196
1197func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1198	module.generateCommonBuildActions(ctx)
1199
1200	// Only build an implementation library if required.
1201	if module.requiresRuntimeImplementationLibrary() {
1202		module.Library.GenerateAndroidBuildActions(ctx)
1203	}
1204
1205	// Collate the components exported by this module. All scope specific modules are exported but
1206	// the impl and xml component modules are not.
1207	exportedComponents := map[string]struct{}{}
1208
1209	// Record the paths to the header jars of the library (stubs and impl).
1210	// When this java_sdk_library is depended upon from others via "libs" property,
1211	// the recorded paths will be returned depending on the link type of the caller.
1212	ctx.VisitDirectDeps(func(to android.Module) {
1213		tag := ctx.OtherModuleDependencyTag(to)
1214
1215		// Extract information from any of the scope specific dependencies.
1216		if scopeTag, ok := tag.(scopeDependencyTag); ok {
1217			apiScope := scopeTag.apiScope
1218			scopePaths := module.getScopePathsCreateIfNeeded(apiScope)
1219
1220			// Extract information from the dependency. The exact information extracted
1221			// is determined by the nature of the dependency which is determined by the tag.
1222			scopeTag.extractDepInfo(ctx, to, scopePaths)
1223
1224			exportedComponents[ctx.OtherModuleName(to)] = struct{}{}
1225		}
1226	})
1227
1228	// Make the set of components exported by this module available for use elsewhere.
1229	exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedStringKeys(exportedComponents)}
1230	ctx.SetProvider(android.ExportedComponentsInfoProvider, exportedComponentInfo)
1231}
1232
1233func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
1234	if !module.requiresRuntimeImplementationLibrary() {
1235		return nil
1236	}
1237	entriesList := module.Library.AndroidMkEntries()
1238	if module.sharedLibrary() {
1239		entries := &entriesList[0]
1240		entries.Required = append(entries.Required, module.xmlPermissionsModuleName())
1241	}
1242	return entriesList
1243}
1244
1245// The dist path of the stub artifacts
1246func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string {
1247	return path.Join("apistubs", module.distGroup(), apiScope.name)
1248}
1249
1250// Get the sdk version for use when compiling the stubs library.
1251func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.EarlyModuleContext, apiScope *apiScope) string {
1252	scopeProperties := module.scopeToProperties[apiScope]
1253	if scopeProperties.Sdk_version != nil {
1254		return proptools.String(scopeProperties.Sdk_version)
1255	}
1256
1257	sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library))
1258	if sdkDep.hasStandardLibs() {
1259		// If building against a standard sdk then use the sdk version appropriate for the scope.
1260		return apiScope.sdkVersion
1261	} else {
1262		// Otherwise, use no system module.
1263		return "none"
1264	}
1265}
1266
1267func (module *SdkLibrary) distStem() string {
1268	return proptools.StringDefault(module.sdkLibraryProperties.Dist_stem, module.BaseModuleName())
1269}
1270
1271// distGroup returns the subdirectory of the dist path of the stub artifacts.
1272func (module *SdkLibrary) distGroup() string {
1273	return proptools.StringDefault(module.sdkLibraryProperties.Dist_group, "unknown")
1274}
1275
1276func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string {
1277	return ":" + module.distStem() + ".api." + apiScope.name + ".latest"
1278}
1279
1280func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) string {
1281	return ":" + module.distStem() + "-removed.api." + apiScope.name + ".latest"
1282}
1283
1284func (module *SdkLibrary) latestIncompatibilitiesFilegroupName(apiScope *apiScope) string {
1285	return ":" + module.distStem() + "-incompatibilities.api." + apiScope.name + ".latest"
1286}
1287
1288func childModuleVisibility(childVisibility []string) []string {
1289	if childVisibility == nil {
1290		// No child visibility set. The child will use the visibility of the sdk_library.
1291		return nil
1292	}
1293
1294	// Prepend an override to ignore the sdk_library's visibility, and rely on the child visibility.
1295	var visibility []string
1296	visibility = append(visibility, "//visibility:override")
1297	visibility = append(visibility, childVisibility...)
1298	return visibility
1299}
1300
1301// Creates the implementation java library
1302func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
1303	visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility)
1304
1305	props := struct {
1306		Name       *string
1307		Visibility []string
1308		Instrument bool
1309		Libs       []string
1310	}{
1311		Name:       proptools.StringPtr(module.implLibraryModuleName()),
1312		Visibility: visibility,
1313		// Set the instrument property to ensure it is instrumented when instrumentation is required.
1314		Instrument: true,
1315		// Set the impl_only libs. Note that the module's "Libs" get appended as well, via the
1316		// addition of &module.properties below.
1317		Libs: module.sdkLibraryProperties.Impl_only_libs,
1318	}
1319
1320	properties := []interface{}{
1321		&module.properties,
1322		&module.protoProperties,
1323		&module.deviceProperties,
1324		&module.dexProperties,
1325		&module.dexpreoptProperties,
1326		&module.linter.properties,
1327		&props,
1328		module.sdkComponentPropertiesForChildLibrary(),
1329	}
1330	mctx.CreateModule(LibraryFactory, properties...)
1331}
1332
1333// Creates a static java library that has API stubs
1334func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
1335	props := struct {
1336		Name           *string
1337		Visibility     []string
1338		Srcs           []string
1339		Installable    *bool
1340		Sdk_version    *string
1341		System_modules *string
1342		Patch_module   *string
1343		Libs           []string
1344		Static_libs    []string
1345		Compile_dex    *bool
1346		Java_version   *string
1347		Openjdk9       struct {
1348			Srcs       []string
1349			Javacflags []string
1350		}
1351		Dist struct {
1352			Targets []string
1353			Dest    *string
1354			Dir     *string
1355			Tag     *string
1356		}
1357	}{}
1358
1359	props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
1360	props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
1361	// sources are generated from the droiddoc
1362	props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
1363	sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
1364	props.Sdk_version = proptools.StringPtr(sdkVersion)
1365	props.System_modules = module.deviceProperties.System_modules
1366	props.Patch_module = module.properties.Patch_module
1367	props.Installable = proptools.BoolPtr(false)
1368	props.Libs = module.sdkLibraryProperties.Stub_only_libs
1369	props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
1370	// The stub-annotations library contains special versions of the annotations
1371	// with CLASS retention policy, so that they're kept.
1372	if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) {
1373		props.Libs = append(props.Libs, "stub-annotations")
1374	}
1375	props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
1376	props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
1377	// We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
1378	// interop with older developer tools that don't support 1.9.
1379	props.Java_version = proptools.StringPtr("1.8")
1380
1381	// The imports need to be compiled to dex if the java_sdk_library requests it.
1382	compileDex := module.dexProperties.Compile_dex
1383	if module.stubLibrariesCompiledForDex() {
1384		compileDex = proptools.BoolPtr(true)
1385	}
1386	props.Compile_dex = compileDex
1387
1388	// Dist the class jar artifact for sdk builds.
1389	if !Bool(module.sdkLibraryProperties.No_dist) {
1390		props.Dist.Targets = []string{"sdk", "win_sdk"}
1391		props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
1392		props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
1393		props.Dist.Tag = proptools.StringPtr(".jar")
1394	}
1395
1396	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
1397}
1398
1399// Creates a droidstubs module that creates stubs source files from the given full source
1400// files and also updates and checks the API specification files.
1401func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) {
1402	props := struct {
1403		Name                             *string
1404		Visibility                       []string
1405		Srcs                             []string
1406		Installable                      *bool
1407		Sdk_version                      *string
1408		System_modules                   *string
1409		Libs                             []string
1410		Output_javadoc_comments          *bool
1411		Arg_files                        []string
1412		Args                             *string
1413		Java_version                     *string
1414		Annotations_enabled              *bool
1415		Merge_annotations_dirs           []string
1416		Merge_inclusion_annotations_dirs []string
1417		Generate_stubs                   *bool
1418		Previous_api                     *string
1419		Check_api                        struct {
1420			Current       ApiToCheck
1421			Last_released ApiToCheck
1422
1423			Api_lint struct {
1424				Enabled       *bool
1425				New_since     *string
1426				Baseline_file *string
1427			}
1428		}
1429		Aidl struct {
1430			Include_dirs       []string
1431			Local_include_dirs []string
1432		}
1433		Dists []android.Dist
1434	}{}
1435
1436	// The stubs source processing uses the same compile time classpath when extracting the
1437	// API from the implementation library as it does when compiling it. i.e. the same
1438	// * sdk version
1439	// * system_modules
1440	// * libs (static_libs/libs)
1441
1442	props.Name = proptools.StringPtr(name)
1443	props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility)
1444	props.Srcs = append(props.Srcs, module.properties.Srcs...)
1445	props.Sdk_version = module.deviceProperties.Sdk_version
1446	props.System_modules = module.deviceProperties.System_modules
1447	props.Installable = proptools.BoolPtr(false)
1448	// A droiddoc module has only one Libs property and doesn't distinguish between
1449	// shared libs and static libs. So we need to add both of these libs to Libs property.
1450	props.Libs = module.properties.Libs
1451	props.Libs = append(props.Libs, module.properties.Static_libs...)
1452	props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
1453	props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
1454	props.Java_version = module.properties.Java_version
1455
1456	props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
1457	props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
1458	props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
1459
1460	droidstubsArgs := []string{}
1461	if len(module.sdkLibraryProperties.Api_packages) != 0 {
1462		droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
1463	}
1464	if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 {
1465		droidstubsArgs = append(droidstubsArgs,
1466			android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package "))
1467	}
1468	droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
1469	disabledWarnings := []string{
1470		"MissingPermission",
1471		"BroadcastBehavior",
1472		"HiddenSuperclass",
1473		"DeprecationMismatch",
1474		"UnavailableSymbol",
1475		"SdkConstant",
1476		"HiddenTypeParameter",
1477		"Todo",
1478		"Typo",
1479	}
1480	droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
1481
1482	// Output Javadoc comments for public scope.
1483	if apiScope == apiScopePublic {
1484		props.Output_javadoc_comments = proptools.BoolPtr(true)
1485	}
1486
1487	// Add in scope specific arguments.
1488	droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
1489	props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
1490	props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
1491
1492	// List of APIs identified from the provided source files are created. They are later
1493	// compared against to the not-yet-released (a.k.a current) list of APIs and to the
1494	// last-released (a.k.a numbered) list of API.
1495	currentApiFileName := apiScope.apiFilePrefix + "current.txt"
1496	removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
1497	apiDir := module.getApiDir()
1498	currentApiFileName = path.Join(apiDir, currentApiFileName)
1499	removedApiFileName = path.Join(apiDir, removedApiFileName)
1500
1501	// check against the not-yet-release API
1502	props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
1503	props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
1504
1505	if !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api) {
1506		// check against the latest released API
1507		latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
1508		props.Previous_api = latestApiFilegroupName
1509		props.Check_api.Last_released.Api_file = latestApiFilegroupName
1510		props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
1511			module.latestRemovedApiFilegroupName(apiScope))
1512		props.Check_api.Last_released.Baseline_file = proptools.StringPtr(
1513			module.latestIncompatibilitiesFilegroupName(apiScope))
1514
1515		if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
1516			// Enable api lint.
1517			props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true)
1518			props.Check_api.Api_lint.New_since = latestApiFilegroupName
1519
1520			// If it exists then pass a lint-baseline.txt through to droidstubs.
1521			baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt")
1522			baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath)
1523			paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil)
1524			if err != nil {
1525				mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err)
1526			}
1527			if len(paths) == 1 {
1528				props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath)
1529			} else if len(paths) != 0 {
1530				mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths)
1531			}
1532		}
1533	}
1534
1535	if !Bool(module.sdkLibraryProperties.No_dist) {
1536		// Dist the api txt and removed api txt artifacts for sdk builds.
1537		distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
1538		for _, p := range []struct {
1539			tag     string
1540			pattern string
1541		}{
1542			{tag: ".api.txt", pattern: "%s.txt"},
1543			{tag: ".removed-api.txt", pattern: "%s-removed.txt"},
1544		} {
1545			props.Dists = append(props.Dists, android.Dist{
1546				Targets: []string{"sdk", "win_sdk"},
1547				Dir:     distDir,
1548				Dest:    proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
1549				Tag:     proptools.StringPtr(p.tag),
1550			})
1551		}
1552	}
1553
1554	mctx.CreateModule(DroidstubsFactory, &props)
1555}
1556
1557// Implements android.ApexModule
1558func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
1559	depTag := mctx.OtherModuleDependencyTag(dep)
1560	if depTag == xmlPermissionsFileTag {
1561		return true
1562	}
1563	return module.Library.DepIsInSameApex(mctx, dep)
1564}
1565
1566// Implements android.ApexModule
1567func (module *SdkLibrary) UniqueApexVariations() bool {
1568	return module.uniqueApexVariations()
1569}
1570
1571// Creates the xml file that publicizes the runtime library
1572func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
1573	props := struct {
1574		Name           *string
1575		Lib_name       *string
1576		Apex_available []string
1577	}{
1578		Name:           proptools.StringPtr(module.xmlPermissionsModuleName()),
1579		Lib_name:       proptools.StringPtr(module.BaseModuleName()),
1580		Apex_available: module.ApexProperties.Apex_available,
1581	}
1582
1583	mctx.CreateModule(sdkLibraryXmlFactory, &props)
1584}
1585
1586func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s android.SdkSpec) android.Paths {
1587	var ver android.ApiLevel
1588	var kind android.SdkKind
1589	if s.UsePrebuilt(ctx) {
1590		ver = s.ApiLevel
1591		kind = s.Kind
1592	} else {
1593		// We don't have prebuilt SDK for the specific sdkVersion.
1594		// Instead of breaking the build, fallback to use "system_current"
1595		ver = android.FutureApiLevel
1596		kind = android.SdkSystem
1597	}
1598
1599	dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String())
1600	jar := filepath.Join(dir, baseName+".jar")
1601	jarPath := android.ExistentPathForSource(ctx, jar)
1602	if !jarPath.Valid() {
1603		if ctx.Config().AllowMissingDependencies() {
1604			return android.Paths{android.PathForSource(ctx, jar)}
1605		} else {
1606			ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", s.Raw, jar)
1607		}
1608		return nil
1609	}
1610	return android.Paths{jarPath.Path()}
1611}
1612
1613// Check to see if the other module is within the same set of named APEXes as this module.
1614//
1615// If either this or the other module are on the platform then this will return
1616// false.
1617func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool {
1618	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
1619	otherApexInfo := ctx.OtherModuleProvider(other, android.ApexInfoProvider).(android.ApexInfo)
1620	return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants)
1621}
1622
1623func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
1624	// If the client doesn't set sdk_version, but if this library prefers stubs over
1625	// the impl library, let's provide the widest API surface possible. To do so,
1626	// force override sdk_version to module_current so that the closest possible API
1627	// surface could be found in selectHeaderJarsForSdkVersion
1628	if module.defaultsToStubs() && !sdkVersion.Specified() {
1629		sdkVersion = android.SdkSpecFrom(ctx, "module_current")
1630	}
1631
1632	// Only provide access to the implementation library if it is actually built.
1633	if module.requiresRuntimeImplementationLibrary() {
1634		// Check any special cases for java_sdk_library.
1635		//
1636		// Only allow access to the implementation library in the following condition:
1637		// * No sdk_version specified on the referencing module.
1638		// * The referencing module is in the same apex as this.
1639		if sdkVersion.Kind == android.SdkPrivate || withinSameApexesAs(ctx, module) {
1640			if headerJars {
1641				return module.HeaderJars()
1642			} else {
1643				return module.ImplementationJars()
1644			}
1645		}
1646	}
1647
1648	return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
1649}
1650
1651// to satisfy SdkLibraryDependency interface
1652func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
1653	return module.sdkJars(ctx, sdkVersion, true /*headerJars*/)
1654}
1655
1656// to satisfy SdkLibraryDependency interface
1657func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
1658	return module.sdkJars(ctx, sdkVersion, false /*headerJars*/)
1659}
1660
1661var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries")
1662
1663func javaSdkLibraries(config android.Config) *[]string {
1664	return config.Once(javaSdkLibrariesKey, func() interface{} {
1665		return &[]string{}
1666	}).(*[]string)
1667}
1668
1669func (module *SdkLibrary) getApiDir() string {
1670	return proptools.StringDefault(module.sdkLibraryProperties.Api_dir, "api")
1671}
1672
1673// For a java_sdk_library module, create internal modules for stubs, docs,
1674// runtime libs and xml file. If requested, the stubs and docs are created twice
1675// once for public API level and once for system API level
1676func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) {
1677	// If the module has been disabled then don't create any child modules.
1678	if !module.Enabled() {
1679		return
1680	}
1681
1682	if len(module.properties.Srcs) == 0 {
1683		mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
1684		return
1685	}
1686
1687	// If this builds against standard libraries (i.e. is not part of the core libraries)
1688	// then assume it provides both system and test apis.
1689	sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library))
1690	hasSystemAndTestApis := sdkDep.hasStandardLibs()
1691	module.sdkLibraryProperties.Generate_system_and_test_apis = hasSystemAndTestApis
1692
1693	missingCurrentApi := false
1694
1695	generatedScopes := module.getGeneratedApiScopes(mctx)
1696
1697	apiDir := module.getApiDir()
1698	for _, scope := range generatedScopes {
1699		for _, api := range []string{"current.txt", "removed.txt"} {
1700			path := path.Join(mctx.ModuleDir(), apiDir, scope.apiFilePrefix+api)
1701			p := android.ExistentPathForSource(mctx, path)
1702			if !p.Valid() {
1703				mctx.ModuleErrorf("Current api file %#v doesn't exist", path)
1704				missingCurrentApi = true
1705			}
1706		}
1707	}
1708
1709	if missingCurrentApi {
1710		script := "build/soong/scripts/gen-java-current-api-files.sh"
1711		p := android.ExistentPathForSource(mctx, script)
1712
1713		if !p.Valid() {
1714			panic(fmt.Sprintf("script file %s doesn't exist", script))
1715		}
1716
1717		mctx.ModuleErrorf("One or more current api files are missing. "+
1718			"You can update them by:\n"+
1719			"%s %q %s && m update-api",
1720			script, filepath.Join(mctx.ModuleDir(), apiDir),
1721			strings.Join(generatedScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " "))
1722		return
1723	}
1724
1725	for _, scope := range generatedScopes {
1726		// Use the stubs source name for legacy reasons.
1727		module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs)
1728
1729		module.createStubsLibrary(mctx, scope)
1730	}
1731
1732	if module.requiresRuntimeImplementationLibrary() {
1733		// Create child module to create an implementation library.
1734		//
1735		// This temporarily creates a second implementation library that can be explicitly
1736		// referenced.
1737		//
1738		// TODO(b/156618935) - update comment once only one implementation library is created.
1739		module.createImplLibrary(mctx)
1740
1741		// Only create an XML permissions file that declares the library as being usable
1742		// as a shared library if required.
1743		if module.sharedLibrary() {
1744			module.createXmlFile(mctx)
1745		}
1746
1747		// record java_sdk_library modules so that they are exported to make
1748		javaSdkLibraries := javaSdkLibraries(mctx.Config())
1749		javaSdkLibrariesLock.Lock()
1750		defer javaSdkLibrariesLock.Unlock()
1751		*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
1752	}
1753
1754	// Add the impl_only_libs *after* we're done using the Libs prop in submodules.
1755	module.properties.Libs = append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...)
1756}
1757
1758func (module *SdkLibrary) InitSdkLibraryProperties() {
1759	module.addHostAndDeviceProperties()
1760	module.AddProperties(&module.sdkLibraryProperties)
1761
1762	module.initSdkLibraryComponent(module)
1763
1764	module.properties.Installable = proptools.BoolPtr(true)
1765	module.deviceProperties.IsSDKLibrary = true
1766}
1767
1768func (module *SdkLibrary) requiresRuntimeImplementationLibrary() bool {
1769	return !proptools.Bool(module.sdkLibraryProperties.Api_only)
1770}
1771
1772func (module *SdkLibrary) defaultsToStubs() bool {
1773	return proptools.Bool(module.sdkLibraryProperties.Default_to_stubs)
1774}
1775
1776// Defines how to name the individual component modules the sdk library creates.
1777type sdkLibraryComponentNamingScheme interface {
1778	stubsLibraryModuleName(scope *apiScope, baseName string) string
1779
1780	stubsSourceModuleName(scope *apiScope, baseName string) string
1781}
1782
1783type defaultNamingScheme struct {
1784}
1785
1786func (s *defaultNamingScheme) stubsLibraryModuleName(scope *apiScope, baseName string) string {
1787	return scope.stubsLibraryModuleName(baseName)
1788}
1789
1790func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName string) string {
1791	return scope.stubsSourceModuleName(baseName)
1792}
1793
1794var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil)
1795
1796func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) {
1797	// This suffix-based approach is fragile and could potentially mis-trigger.
1798	// TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly.
1799	if strings.HasSuffix(name, apiScopePublic.stubsLibraryModuleNameSuffix()) {
1800		if name == "hwbinder.stubs" || name == "libcore_private.stubs" {
1801			// Due to a previous bug, these modules were not considered stubs, so we retain that.
1802			return false, javaPlatform
1803		}
1804		return true, javaSdk
1805	}
1806	if strings.HasSuffix(name, apiScopeSystem.stubsLibraryModuleNameSuffix()) {
1807		return true, javaSystem
1808	}
1809	if strings.HasSuffix(name, apiScopeModuleLib.stubsLibraryModuleNameSuffix()) {
1810		return true, javaModule
1811	}
1812	if strings.HasSuffix(name, apiScopeTest.stubsLibraryModuleNameSuffix()) {
1813		return true, javaSystem
1814	}
1815	return false, javaPlatform
1816}
1817
1818// java_sdk_library is a special Java library that provides optional platform APIs to apps.
1819// In practice, it can be viewed as a combination of several modules: 1) stubs library that clients
1820// are linked against to, 2) droiddoc module that internally generates API stubs source files,
1821// 3) the real runtime shared library that implements the APIs, and 4) XML file for adding
1822// the runtime lib to the classpath at runtime if requested via <uses-library>.
1823func SdkLibraryFactory() android.Module {
1824	module := &SdkLibrary{}
1825
1826	// Initialize information common between source and prebuilt.
1827	module.initCommon(module)
1828
1829	module.InitSdkLibraryProperties()
1830	android.InitApexModule(module)
1831	android.InitSdkAwareModule(module)
1832	InitJavaModule(module, android.HostAndDeviceSupported)
1833
1834	// Initialize the map from scope to scope specific properties.
1835	scopeToProperties := make(map[*apiScope]*ApiScopeProperties)
1836	for _, scope := range allApiScopes {
1837		scopeToProperties[scope] = scope.scopeSpecificProperties(module)
1838	}
1839	module.scopeToProperties = scopeToProperties
1840
1841	// Add the properties containing visibility rules so that they are checked.
1842	android.AddVisibilityProperty(module, "impl_library_visibility", &module.sdkLibraryProperties.Impl_library_visibility)
1843	android.AddVisibilityProperty(module, "stubs_library_visibility", &module.sdkLibraryProperties.Stubs_library_visibility)
1844	android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility)
1845
1846	module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
1847		// If no implementation is required then it cannot be used as a shared library
1848		// either.
1849		if !module.requiresRuntimeImplementationLibrary() {
1850			// If shared_library has been explicitly set to true then it is incompatible
1851			// with api_only: true.
1852			if proptools.Bool(module.commonSdkLibraryProperties.Shared_library) {
1853				ctx.PropertyErrorf("api_only/shared_library", "inconsistent settings, shared_library and api_only cannot both be true")
1854			}
1855			// Set shared_library: false.
1856			module.commonSdkLibraryProperties.Shared_library = proptools.BoolPtr(false)
1857		}
1858
1859		if module.initCommonAfterDefaultsApplied(ctx) {
1860			module.CreateInternalModules(ctx)
1861		}
1862	})
1863	return module
1864}
1865
1866//
1867// SDK library prebuilts
1868//
1869
1870// Properties associated with each api scope.
1871type sdkLibraryScopeProperties struct {
1872	Jars []string `android:"path"`
1873
1874	Sdk_version *string
1875
1876	// List of shared java libs that this module has dependencies to
1877	Libs []string
1878
1879	// The stubs source.
1880	Stub_srcs []string `android:"path"`
1881
1882	// The current.txt
1883	Current_api *string `android:"path"`
1884
1885	// The removed.txt
1886	Removed_api *string `android:"path"`
1887}
1888
1889type sdkLibraryImportProperties struct {
1890	// List of shared java libs, common to all scopes, that this module has
1891	// dependencies to
1892	Libs []string
1893
1894	// If set to true, compile dex files for the stubs. Defaults to false.
1895	Compile_dex *bool
1896
1897	// If not empty, classes are restricted to the specified packages and their sub-packages.
1898	// This information is used to generate the updatable-bcp-packages.txt file.
1899	Permitted_packages []string
1900}
1901
1902type SdkLibraryImport struct {
1903	android.ModuleBase
1904	android.DefaultableModuleBase
1905	prebuilt android.Prebuilt
1906	android.ApexModuleBase
1907	android.SdkBase
1908
1909	hiddenAPI
1910
1911	properties sdkLibraryImportProperties
1912
1913	// Map from api scope to the scope specific property structure.
1914	scopeProperties map[*apiScope]*sdkLibraryScopeProperties
1915
1916	commonToSdkLibraryAndImport
1917
1918	// The reference to the implementation library created by the source module.
1919	// Is nil if the source module does not exist.
1920	implLibraryModule *Library
1921
1922	// The reference to the xml permissions module created by the source module.
1923	// Is nil if the source module does not exist.
1924	xmlPermissionsFileModule *sdkLibraryXml
1925
1926	// Path to the dex implementation jar obtained from the prebuilt_apex, if any.
1927	dexJarFile android.Path
1928}
1929
1930var _ SdkLibraryDependency = (*SdkLibraryImport)(nil)
1931
1932// The type of a structure that contains a field of type sdkLibraryScopeProperties
1933// for each apiscope in allApiScopes, e.g. something like:
1934// struct {
1935//   Public sdkLibraryScopeProperties
1936//   System sdkLibraryScopeProperties
1937//   ...
1938// }
1939var allScopeStructType = createAllScopePropertiesStructType()
1940
1941// Dynamically create a structure type for each apiscope in allApiScopes.
1942func createAllScopePropertiesStructType() reflect.Type {
1943	var fields []reflect.StructField
1944	for _, apiScope := range allApiScopes {
1945		field := reflect.StructField{
1946			Name: apiScope.fieldName,
1947			Type: reflect.TypeOf(sdkLibraryScopeProperties{}),
1948		}
1949		fields = append(fields, field)
1950	}
1951
1952	return reflect.StructOf(fields)
1953}
1954
1955// Create an instance of the scope specific structure type and return a map
1956// from apiscope to a pointer to each scope specific field.
1957func createPropertiesInstance() (interface{}, map[*apiScope]*sdkLibraryScopeProperties) {
1958	allScopePropertiesPtr := reflect.New(allScopeStructType)
1959	allScopePropertiesStruct := allScopePropertiesPtr.Elem()
1960	scopeProperties := make(map[*apiScope]*sdkLibraryScopeProperties)
1961
1962	for _, apiScope := range allApiScopes {
1963		field := allScopePropertiesStruct.FieldByName(apiScope.fieldName)
1964		scopeProperties[apiScope] = field.Addr().Interface().(*sdkLibraryScopeProperties)
1965	}
1966
1967	return allScopePropertiesPtr.Interface(), scopeProperties
1968}
1969
1970// java_sdk_library_import imports a prebuilt java_sdk_library.
1971func sdkLibraryImportFactory() android.Module {
1972	module := &SdkLibraryImport{}
1973
1974	allScopeProperties, scopeToProperties := createPropertiesInstance()
1975	module.scopeProperties = scopeToProperties
1976	module.AddProperties(&module.properties, allScopeProperties)
1977
1978	// Initialize information common between source and prebuilt.
1979	module.initCommon(module)
1980
1981	android.InitPrebuiltModule(module, &[]string{""})
1982	android.InitApexModule(module)
1983	android.InitSdkAwareModule(module)
1984	InitJavaModule(module, android.HostAndDeviceSupported)
1985
1986	module.SetDefaultableHook(func(mctx android.DefaultableHookContext) {
1987		if module.initCommonAfterDefaultsApplied(mctx) {
1988			module.createInternalModules(mctx)
1989		}
1990	})
1991	return module
1992}
1993
1994var _ PermittedPackagesForUpdatableBootJars = (*SdkLibraryImport)(nil)
1995
1996func (module *SdkLibraryImport) PermittedPackagesForUpdatableBootJars() []string {
1997	return module.properties.Permitted_packages
1998}
1999
2000func (module *SdkLibraryImport) Prebuilt() *android.Prebuilt {
2001	return &module.prebuilt
2002}
2003
2004func (module *SdkLibraryImport) Name() string {
2005	return module.prebuilt.Name(module.ModuleBase.Name())
2006}
2007
2008func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
2009
2010	// If the build is configured to use prebuilts then force this to be preferred.
2011	if mctx.Config().AlwaysUsePrebuiltSdks() {
2012		module.prebuilt.ForcePrefer()
2013	}
2014
2015	for apiScope, scopeProperties := range module.scopeProperties {
2016		if len(scopeProperties.Jars) == 0 {
2017			continue
2018		}
2019
2020		module.createJavaImportForStubs(mctx, apiScope, scopeProperties)
2021
2022		if len(scopeProperties.Stub_srcs) > 0 {
2023			module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
2024		}
2025	}
2026
2027	javaSdkLibraries := javaSdkLibraries(mctx.Config())
2028	javaSdkLibrariesLock.Lock()
2029	defer javaSdkLibrariesLock.Unlock()
2030	*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
2031}
2032
2033func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
2034	// Creates a java import for the jar with ".stubs" suffix
2035	props := struct {
2036		Name        *string
2037		Sdk_version *string
2038		Libs        []string
2039		Jars        []string
2040		Prefer      *bool
2041		Compile_dex *bool
2042	}{}
2043	props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
2044	props.Sdk_version = scopeProperties.Sdk_version
2045	// Prepend any of the libs from the legacy public properties to the libs for each of the
2046	// scopes to avoid having to duplicate them in each scope.
2047	props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
2048	props.Jars = scopeProperties.Jars
2049
2050	// The imports are preferred if the java_sdk_library_import is preferred.
2051	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
2052
2053	// The imports need to be compiled to dex if the java_sdk_library_import requests it.
2054	compileDex := module.properties.Compile_dex
2055	if module.stubLibrariesCompiledForDex() {
2056		compileDex = proptools.BoolPtr(true)
2057	}
2058	props.Compile_dex = compileDex
2059
2060	mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
2061}
2062
2063func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
2064	props := struct {
2065		Name   *string
2066		Srcs   []string
2067		Prefer *bool
2068	}{}
2069	props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope))
2070	props.Srcs = scopeProperties.Stub_srcs
2071	mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
2072
2073	// The stubs source is preferred if the java_sdk_library_import is preferred.
2074	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
2075}
2076
2077// Add the dependencies on the child module in the component deps mutator so that it
2078// creates references to the prebuilt and not the source modules.
2079func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
2080	for apiScope, scopeProperties := range module.scopeProperties {
2081		if len(scopeProperties.Jars) == 0 {
2082			continue
2083		}
2084
2085		// Add dependencies to the prebuilt stubs library
2086		ctx.AddVariationDependencies(nil, apiScope.stubsTag, android.PrebuiltNameFromSource(module.stubsLibraryModuleName(apiScope)))
2087
2088		if len(scopeProperties.Stub_srcs) > 0 {
2089			// Add dependencies to the prebuilt stubs source library
2090			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, android.PrebuiltNameFromSource(module.stubsSourceModuleName(apiScope)))
2091		}
2092	}
2093}
2094
2095// Add other dependencies as normal.
2096func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
2097
2098	implName := module.implLibraryModuleName()
2099	if ctx.OtherModuleExists(implName) {
2100		ctx.AddVariationDependencies(nil, implLibraryTag, implName)
2101
2102		xmlPermissionsModuleName := module.xmlPermissionsModuleName()
2103		if module.sharedLibrary() && ctx.OtherModuleExists(xmlPermissionsModuleName) {
2104			// Add dependency to the rule for generating the xml permissions file
2105			ctx.AddDependency(module, xmlPermissionsFileTag, xmlPermissionsModuleName)
2106		}
2107	}
2108}
2109
2110var _ android.ApexModule = (*SdkLibraryImport)(nil)
2111
2112// Implements android.ApexModule
2113func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
2114	depTag := mctx.OtherModuleDependencyTag(dep)
2115	if depTag == xmlPermissionsFileTag {
2116		return true
2117	}
2118
2119	// None of the other dependencies of the java_sdk_library_import are in the same apex
2120	// as the one that references this module.
2121	return false
2122}
2123
2124// Implements android.ApexModule
2125func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
2126	sdkVersion android.ApiLevel) error {
2127	// we don't check prebuilt modules for sdk_version
2128	return nil
2129}
2130
2131// Implements android.ApexModule
2132func (module *SdkLibraryImport) UniqueApexVariations() bool {
2133	return module.uniqueApexVariations()
2134}
2135
2136func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
2137	return module.commonOutputFiles(tag)
2138}
2139
2140func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2141	module.generateCommonBuildActions(ctx)
2142
2143	var deapexerModule android.Module
2144
2145	// Record the paths to the prebuilt stubs library and stubs source.
2146	ctx.VisitDirectDeps(func(to android.Module) {
2147		tag := ctx.OtherModuleDependencyTag(to)
2148
2149		// Extract information from any of the scope specific dependencies.
2150		if scopeTag, ok := tag.(scopeDependencyTag); ok {
2151			apiScope := scopeTag.apiScope
2152			scopePaths := module.getScopePathsCreateIfNeeded(apiScope)
2153
2154			// Extract information from the dependency. The exact information extracted
2155			// is determined by the nature of the dependency which is determined by the tag.
2156			scopeTag.extractDepInfo(ctx, to, scopePaths)
2157		} else if tag == implLibraryTag {
2158			if implLibrary, ok := to.(*Library); ok {
2159				module.implLibraryModule = implLibrary
2160			} else {
2161				ctx.ModuleErrorf("implementation library must be of type *java.Library but was %T", to)
2162			}
2163		} else if tag == xmlPermissionsFileTag {
2164			if xmlPermissionsFileModule, ok := to.(*sdkLibraryXml); ok {
2165				module.xmlPermissionsFileModule = xmlPermissionsFileModule
2166			} else {
2167				ctx.ModuleErrorf("xml permissions file module must be of type *sdkLibraryXml but was %T", to)
2168			}
2169		}
2170
2171		// Save away the `deapexer` module on which this depends, if any.
2172		if tag == android.DeapexerTag {
2173			if deapexerModule != nil {
2174				ctx.ModuleErrorf("Ambiguous duplicate deapexer module dependencies %q and %q",
2175					deapexerModule.Name(), to.Name())
2176			}
2177			deapexerModule = to
2178		}
2179	})
2180
2181	// Populate the scope paths with information from the properties.
2182	for apiScope, scopeProperties := range module.scopeProperties {
2183		if len(scopeProperties.Jars) == 0 {
2184			continue
2185		}
2186
2187		paths := module.getScopePathsCreateIfNeeded(apiScope)
2188		paths.currentApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Current_api)
2189		paths.removedApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Removed_api)
2190	}
2191
2192	if ctx.Device() {
2193		// If this is a variant created for a prebuilt_apex then use the dex implementation jar
2194		// obtained from the associated deapexer module.
2195		ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
2196		if ai.ForPrebuiltApex {
2197			if deapexerModule == nil {
2198				// This should never happen as a variant for a prebuilt_apex is only created if the
2199				// deapxer module has been configured to export the dex implementation jar for this module.
2200				ctx.ModuleErrorf("internal error: module %q does not depend on a `deapexer` module for prebuilt_apex %q",
2201					module.Name(), ai.ApexVariationName)
2202			}
2203
2204			// Get the path of the dex implementation jar from the `deapexer` module.
2205			di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
2206			if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(module.BaseModuleName())); dexOutputPath != nil {
2207				module.dexJarFile = dexOutputPath
2208				module.initHiddenAPI(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
2209			} else {
2210				// This should never happen as a variant for a prebuilt_apex is only created if the
2211				// prebuilt_apex has been configured to export the java library dex file.
2212				ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt_apex %q", deapexerModule.Name())
2213			}
2214		}
2215	}
2216}
2217
2218func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
2219
2220	// For consistency with SdkLibrary make the implementation jar available to libraries that
2221	// are within the same APEX.
2222	implLibraryModule := module.implLibraryModule
2223	if implLibraryModule != nil && withinSameApexesAs(ctx, module) {
2224		if headerJars {
2225			return implLibraryModule.HeaderJars()
2226		} else {
2227			return implLibraryModule.ImplementationJars()
2228		}
2229	}
2230
2231	return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
2232}
2233
2234// to satisfy SdkLibraryDependency interface
2235func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
2236	// This module is just a wrapper for the prebuilt stubs.
2237	return module.sdkJars(ctx, sdkVersion, true)
2238}
2239
2240// to satisfy SdkLibraryDependency interface
2241func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
2242	// This module is just a wrapper for the stubs.
2243	return module.sdkJars(ctx, sdkVersion, false)
2244}
2245
2246// to satisfy UsesLibraryDependency interface
2247func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
2248	// The dex implementation jar extracted from the .apex file should be used in preference to the
2249	// source.
2250	if module.dexJarFile != nil {
2251		return module.dexJarFile
2252	}
2253	if module.implLibraryModule == nil {
2254		return nil
2255	} else {
2256		return module.implLibraryModule.DexJarBuildPath()
2257	}
2258}
2259
2260// to satisfy UsesLibraryDependency interface
2261func (module *SdkLibraryImport) DexJarInstallPath() android.Path {
2262	if module.implLibraryModule == nil {
2263		return nil
2264	} else {
2265		return module.implLibraryModule.DexJarInstallPath()
2266	}
2267}
2268
2269// to satisfy UsesLibraryDependency interface
2270func (module *SdkLibraryImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
2271	return nil
2272}
2273
2274// to satisfy apex.javaDependency interface
2275func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
2276	if module.implLibraryModule == nil {
2277		return nil
2278	} else {
2279		return module.implLibraryModule.JacocoReportClassesFile()
2280	}
2281}
2282
2283// to satisfy apex.javaDependency interface
2284func (module *SdkLibraryImport) LintDepSets() LintDepSets {
2285	if module.implLibraryModule == nil {
2286		return LintDepSets{}
2287	} else {
2288		return module.implLibraryModule.LintDepSets()
2289	}
2290}
2291
2292func (module *SdkLibraryImport) getStrictUpdatabilityLinting() bool {
2293	if module.implLibraryModule == nil {
2294		return false
2295	} else {
2296		return module.implLibraryModule.getStrictUpdatabilityLinting()
2297	}
2298}
2299
2300func (module *SdkLibraryImport) setStrictUpdatabilityLinting(strictLinting bool) {
2301	if module.implLibraryModule != nil {
2302		module.implLibraryModule.setStrictUpdatabilityLinting(strictLinting)
2303	}
2304}
2305
2306// to satisfy apex.javaDependency interface
2307func (module *SdkLibraryImport) Stem() string {
2308	return module.BaseModuleName()
2309}
2310
2311var _ ApexDependency = (*SdkLibraryImport)(nil)
2312
2313// to satisfy java.ApexDependency interface
2314func (module *SdkLibraryImport) HeaderJars() android.Paths {
2315	if module.implLibraryModule == nil {
2316		return nil
2317	} else {
2318		return module.implLibraryModule.HeaderJars()
2319	}
2320}
2321
2322// to satisfy java.ApexDependency interface
2323func (module *SdkLibraryImport) ImplementationAndResourcesJars() android.Paths {
2324	if module.implLibraryModule == nil {
2325		return nil
2326	} else {
2327		return module.implLibraryModule.ImplementationAndResourcesJars()
2328	}
2329}
2330
2331var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil)
2332
2333func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
2334	name := module.BaseModuleName()
2335	return requiredFilesFromPrebuiltApexForImport(name)
2336}
2337
2338//
2339// java_sdk_library_xml
2340//
2341type sdkLibraryXml struct {
2342	android.ModuleBase
2343	android.DefaultableModuleBase
2344	android.ApexModuleBase
2345
2346	properties sdkLibraryXmlProperties
2347
2348	outputFilePath android.OutputPath
2349	installDirPath android.InstallPath
2350
2351	hideApexVariantFromMake bool
2352}
2353
2354type sdkLibraryXmlProperties struct {
2355	// canonical name of the lib
2356	Lib_name *string
2357}
2358
2359// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
2360// Not to be used directly by users. java_sdk_library internally uses this.
2361func sdkLibraryXmlFactory() android.Module {
2362	module := &sdkLibraryXml{}
2363
2364	module.AddProperties(&module.properties)
2365
2366	android.InitApexModule(module)
2367	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
2368
2369	return module
2370}
2371
2372func (module *sdkLibraryXml) UniqueApexVariations() bool {
2373	// sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the
2374	// mounted APEX, which contains the name of the APEX.
2375	return true
2376}
2377
2378// from android.PrebuiltEtcModule
2379func (module *sdkLibraryXml) BaseDir() string {
2380	return "etc"
2381}
2382
2383// from android.PrebuiltEtcModule
2384func (module *sdkLibraryXml) SubDir() string {
2385	return "permissions"
2386}
2387
2388// from android.PrebuiltEtcModule
2389func (module *sdkLibraryXml) OutputFile() android.OutputPath {
2390	return module.outputFilePath
2391}
2392
2393// from android.ApexModule
2394func (module *sdkLibraryXml) AvailableFor(what string) bool {
2395	return true
2396}
2397
2398func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
2399	// do nothing
2400}
2401
2402var _ android.ApexModule = (*sdkLibraryXml)(nil)
2403
2404// Implements android.ApexModule
2405func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
2406	sdkVersion android.ApiLevel) error {
2407	// sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked
2408	return nil
2409}
2410
2411// File path to the runtime implementation library
2412func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
2413	implName := proptools.String(module.properties.Lib_name)
2414	if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
2415		// TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
2416		// In most cases, this works fine. But when apex_name is set or override_apex is used
2417		// this can be wrong.
2418		return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.ApexVariationName, implName)
2419	}
2420	partition := "system"
2421	if module.SocSpecific() {
2422		partition = "vendor"
2423	} else if module.DeviceSpecific() {
2424		partition = "odm"
2425	} else if module.ProductSpecific() {
2426		partition = "product"
2427	} else if module.SystemExtSpecific() {
2428		partition = "system_ext"
2429	}
2430	return "/" + partition + "/framework/" + implName + ".jar"
2431}
2432
2433func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2434	module.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
2435
2436	libName := proptools.String(module.properties.Lib_name)
2437	xmlContent := fmt.Sprintf(permissionsTemplate, libName, module.implPath(ctx))
2438
2439	module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
2440	rule := android.NewRuleBuilder(pctx, ctx)
2441	rule.Command().
2442		Text("/bin/bash -c \"echo -e '" + xmlContent + "'\" > ").
2443		Output(module.outputFilePath)
2444
2445	rule.Build("java_sdk_xml", "Permission XML")
2446
2447	module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
2448}
2449
2450func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
2451	if module.hideApexVariantFromMake {
2452		return []android.AndroidMkEntries{android.AndroidMkEntries{
2453			Disabled: true,
2454		}}
2455	}
2456
2457	return []android.AndroidMkEntries{android.AndroidMkEntries{
2458		Class:      "ETC",
2459		OutputFile: android.OptionalPathForPath(module.outputFilePath),
2460		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
2461			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
2462				entries.SetString("LOCAL_MODULE_TAGS", "optional")
2463				entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.ToMakePath().String())
2464				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base())
2465			},
2466		},
2467	}}
2468}
2469
2470type sdkLibrarySdkMemberType struct {
2471	android.SdkMemberTypeBase
2472}
2473
2474func (s *sdkLibrarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
2475	mctx.AddVariationDependencies(nil, dependencyTag, names...)
2476}
2477
2478func (s *sdkLibrarySdkMemberType) IsInstance(module android.Module) bool {
2479	_, ok := module.(*SdkLibrary)
2480	return ok
2481}
2482
2483func (s *sdkLibrarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
2484	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_sdk_library_import")
2485}
2486
2487func (s *sdkLibrarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
2488	return &sdkLibrarySdkMemberProperties{}
2489}
2490
2491var javaSdkLibrarySdkMemberType = &sdkLibrarySdkMemberType{
2492	android.SdkMemberTypeBase{
2493		PropertyName: "java_sdk_libs",
2494		SupportsSdk:  true,
2495	},
2496}
2497
2498type sdkLibrarySdkMemberProperties struct {
2499	android.SdkMemberPropertiesBase
2500
2501	// Scope to per scope properties.
2502	Scopes map[*apiScope]scopeProperties
2503
2504	// The Java stubs source files.
2505	Stub_srcs []string
2506
2507	// The naming scheme.
2508	Naming_scheme *string
2509
2510	// True if the java_sdk_library_import is for a shared library, false
2511	// otherwise.
2512	Shared_library *bool
2513
2514	// True if the stub imports should produce dex jars.
2515	Compile_dex *bool
2516
2517	// The paths to the doctag files to add to the prebuilt.
2518	Doctag_paths android.Paths
2519
2520	Permitted_packages []string
2521}
2522
2523type scopeProperties struct {
2524	Jars           android.Paths
2525	StubsSrcJar    android.Path
2526	CurrentApiFile android.Path
2527	RemovedApiFile android.Path
2528	SdkVersion     string
2529}
2530
2531func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
2532	sdk := variant.(*SdkLibrary)
2533
2534	s.Scopes = make(map[*apiScope]scopeProperties)
2535	for _, apiScope := range allApiScopes {
2536		paths := sdk.findScopePaths(apiScope)
2537		if paths == nil {
2538			continue
2539		}
2540
2541		jars := paths.stubsImplPath
2542		if len(jars) > 0 {
2543			properties := scopeProperties{}
2544			properties.Jars = jars
2545			properties.SdkVersion = sdk.sdkVersionForStubsLibrary(ctx.SdkModuleContext(), apiScope)
2546			properties.StubsSrcJar = paths.stubsSrcJar.Path()
2547			if paths.currentApiFilePath.Valid() {
2548				properties.CurrentApiFile = paths.currentApiFilePath.Path()
2549			}
2550			if paths.removedApiFilePath.Valid() {
2551				properties.RemovedApiFile = paths.removedApiFilePath.Path()
2552			}
2553			s.Scopes[apiScope] = properties
2554		}
2555	}
2556
2557	s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme
2558	s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary())
2559	s.Compile_dex = sdk.dexProperties.Compile_dex
2560	s.Doctag_paths = sdk.doctagPaths
2561	s.Permitted_packages = sdk.PermittedPackagesForUpdatableBootJars()
2562}
2563
2564func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
2565	if s.Naming_scheme != nil {
2566		propertySet.AddProperty("naming_scheme", proptools.String(s.Naming_scheme))
2567	}
2568	if s.Shared_library != nil {
2569		propertySet.AddProperty("shared_library", *s.Shared_library)
2570	}
2571	if s.Compile_dex != nil {
2572		propertySet.AddProperty("compile_dex", *s.Compile_dex)
2573	}
2574	if len(s.Permitted_packages) > 0 {
2575		propertySet.AddProperty("permitted_packages", s.Permitted_packages)
2576	}
2577
2578	for _, apiScope := range allApiScopes {
2579		if properties, ok := s.Scopes[apiScope]; ok {
2580			scopeSet := propertySet.AddPropertySet(apiScope.propertyName)
2581
2582			scopeDir := filepath.Join("sdk_library", s.OsPrefix(), apiScope.name)
2583
2584			var jars []string
2585			for _, p := range properties.Jars {
2586				dest := filepath.Join(scopeDir, ctx.Name()+"-stubs.jar")
2587				ctx.SnapshotBuilder().CopyToSnapshot(p, dest)
2588				jars = append(jars, dest)
2589			}
2590			scopeSet.AddProperty("jars", jars)
2591
2592			if ctx.SdkModuleContext().Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_USE_SRCJAR") {
2593				// Copy the stubs source jar into the snapshot zip as is.
2594				srcJarSnapshotPath := filepath.Join(scopeDir, ctx.Name()+".srcjar")
2595				ctx.SnapshotBuilder().CopyToSnapshot(properties.StubsSrcJar, srcJarSnapshotPath)
2596				scopeSet.AddProperty("stub_srcs", []string{srcJarSnapshotPath})
2597			} else {
2598				// Merge the stubs source jar into the snapshot zip so that when it is unpacked
2599				// the source files are also unpacked.
2600				snapshotRelativeDir := filepath.Join(scopeDir, ctx.Name()+"_stub_sources")
2601				ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir)
2602				scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir})
2603			}
2604
2605			if properties.CurrentApiFile != nil {
2606				currentApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+".txt")
2607				ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, currentApiSnapshotPath)
2608				scopeSet.AddProperty("current_api", currentApiSnapshotPath)
2609			}
2610
2611			if properties.RemovedApiFile != nil {
2612				removedApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+"-removed.txt")
2613				ctx.SnapshotBuilder().CopyToSnapshot(properties.RemovedApiFile, removedApiSnapshotPath)
2614				scopeSet.AddProperty("removed_api", removedApiSnapshotPath)
2615			}
2616
2617			if properties.SdkVersion != "" {
2618				scopeSet.AddProperty("sdk_version", properties.SdkVersion)
2619			}
2620		}
2621	}
2622
2623	if len(s.Doctag_paths) > 0 {
2624		dests := []string{}
2625		for _, p := range s.Doctag_paths {
2626			dest := filepath.Join("doctags", p.Rel())
2627			ctx.SnapshotBuilder().CopyToSnapshot(p, dest)
2628			dests = append(dests, dest)
2629		}
2630		propertySet.AddProperty("doctag_files", dests)
2631	}
2632}
2633