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