1// Copyright 2015 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
17// This file contains the module types for compiling Java for Android, and converts the properties
18// into the flags and filenames necessary to pass to the Module.  The final creation of the rules
19// is handled in builder.go
20
21import (
22	"fmt"
23	"path/filepath"
24	"slices"
25	"sort"
26	"strings"
27
28	"android/soong/remoteexec"
29	"android/soong/testing"
30
31	"github.com/google/blueprint"
32	"github.com/google/blueprint/proptools"
33
34	"android/soong/android"
35	"android/soong/cc"
36	"android/soong/dexpreopt"
37	"android/soong/java/config"
38	"android/soong/tradefed"
39)
40
41func init() {
42	registerJavaBuildComponents(android.InitRegistrationContext)
43
44	RegisterJavaSdkMemberTypes()
45}
46
47func registerJavaBuildComponents(ctx android.RegistrationContext) {
48	ctx.RegisterModuleType("java_defaults", DefaultsFactory)
49
50	ctx.RegisterModuleType("java_library", LibraryFactory)
51	ctx.RegisterModuleType("java_library_static", LibraryStaticFactory)
52	ctx.RegisterModuleType("java_library_host", LibraryHostFactory)
53	ctx.RegisterModuleType("java_binary", BinaryFactory)
54	ctx.RegisterModuleType("java_binary_host", BinaryHostFactory)
55	ctx.RegisterModuleType("java_test", TestFactory)
56	ctx.RegisterModuleType("java_test_helper_library", TestHelperLibraryFactory)
57	ctx.RegisterModuleType("java_test_host", TestHostFactory)
58	ctx.RegisterModuleType("java_test_import", JavaTestImportFactory)
59	ctx.RegisterModuleType("java_import", ImportFactory)
60	ctx.RegisterModuleType("java_import_host", ImportFactoryHost)
61	ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
62	ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
63	ctx.RegisterModuleType("dex_import", DexImportFactory)
64	ctx.RegisterModuleType("java_api_library", ApiLibraryFactory)
65	ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory)
66	ctx.RegisterModuleType("java_api_contribution_import", ApiContributionImportFactory)
67
68	// This mutator registers dependencies on dex2oat for modules that should be
69	// dexpreopted. This is done late when the final variants have been
70	// established, to not get the dependencies split into the wrong variants and
71	// to support the checks in dexpreoptDisabled().
72	ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
73		ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel()
74		// needs access to ApexInfoProvider which is available after variant creation
75		ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel()
76	})
77
78	ctx.RegisterParallelSingletonType("kythe_java_extract", kytheExtractJavaFactory)
79}
80
81func RegisterJavaSdkMemberTypes() {
82	// Register sdk member types.
83	android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
84	android.RegisterSdkMemberType(javaLibsSdkMemberType)
85	android.RegisterSdkMemberType(JavaBootLibsSdkMemberType)
86	android.RegisterSdkMemberType(JavaSystemserverLibsSdkMemberType)
87	android.RegisterSdkMemberType(javaTestSdkMemberType)
88}
89
90type StubsLinkType int
91
92const (
93	Unknown StubsLinkType = iota
94	Stubs
95	Implementation
96)
97
98var (
99	// Supports adding java header libraries to module_exports and sdk.
100	javaHeaderLibsSdkMemberType = &librarySdkMemberType{
101		android.SdkMemberTypeBase{
102			PropertyName: "java_header_libs",
103			SupportsSdk:  true,
104		},
105		func(_ android.SdkMemberContext, j *Library) android.Path {
106			headerJars := j.HeaderJars()
107			if len(headerJars) != 1 {
108				panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
109			}
110
111			return headerJars[0]
112		},
113		sdkSnapshotFilePathForJar,
114		copyEverythingToSnapshot,
115	}
116
117	// Export implementation classes jar as part of the sdk.
118	exportImplementationClassesJar = func(_ android.SdkMemberContext, j *Library) android.Path {
119		implementationJars := j.ImplementationAndResourcesJars()
120		if len(implementationJars) != 1 {
121			panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
122		}
123		return implementationJars[0]
124	}
125
126	// Supports adding java implementation libraries to module_exports but not sdk.
127	javaLibsSdkMemberType = &librarySdkMemberType{
128		android.SdkMemberTypeBase{
129			PropertyName: "java_libs",
130		},
131		exportImplementationClassesJar,
132		sdkSnapshotFilePathForJar,
133		copyEverythingToSnapshot,
134	}
135
136	snapshotRequiresImplementationJar = func(ctx android.SdkMemberContext) bool {
137		// In the S build the build will break if updatable-media does not provide a full implementation
138		// jar. That issue was fixed in Tiramisu by b/229932396.
139		if ctx.IsTargetBuildBeforeTiramisu() && ctx.Name() == "updatable-media" {
140			return true
141		}
142
143		return false
144	}
145
146	// Supports adding java boot libraries to module_exports and sdk.
147	//
148	// The build has some implicit dependencies (via the boot jars configuration) on a number of
149	// modules, e.g. core-oj, apache-xml, that are part of the java boot class path and which are
150	// provided by mainline modules (e.g. art, conscrypt, runtime-i18n) but which are not otherwise
151	// used outside those mainline modules.
152	//
153	// As they are not needed outside the mainline modules adding them to the sdk/module-exports as
154	// either java_libs, or java_header_libs would end up exporting more information than was strictly
155	// necessary. The java_boot_libs property to allow those modules to be exported as part of the
156	// sdk/module_exports without exposing any unnecessary information.
157	JavaBootLibsSdkMemberType = &librarySdkMemberType{
158		android.SdkMemberTypeBase{
159			PropertyName: "java_boot_libs",
160			SupportsSdk:  true,
161		},
162		func(ctx android.SdkMemberContext, j *Library) android.Path {
163			if snapshotRequiresImplementationJar(ctx) {
164				return exportImplementationClassesJar(ctx, j)
165			}
166
167			// Java boot libs are only provided in the SDK to provide access to their dex implementation
168			// jar for use by dexpreopting and boot jars package check. They do not need to provide an
169			// actual implementation jar but the java_import will need a file that exists so just copy an
170			// empty file. Any attempt to use that file as a jar will cause a build error.
171			return ctx.SnapshotBuilder().EmptyFile()
172		},
173		func(ctx android.SdkMemberContext, osPrefix, name string) string {
174			if snapshotRequiresImplementationJar(ctx) {
175				return sdkSnapshotFilePathForJar(ctx, osPrefix, name)
176			}
177
178			// Create a special name for the implementation jar to try and provide some useful information
179			// to a developer that attempts to compile against this.
180			// TODO(b/175714559): Provide a proper error message in Soong not ninja.
181			return filepath.Join(osPrefix, "java_boot_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix)
182		},
183		onlyCopyJarToSnapshot,
184	}
185
186	// Supports adding java systemserver libraries to module_exports and sdk.
187	//
188	// The build has some implicit dependencies (via the systemserver jars configuration) on a number
189	// of modules that are part of the java systemserver classpath and which are provided by mainline
190	// modules but which are not otherwise used outside those mainline modules.
191	//
192	// As they are not needed outside the mainline modules adding them to the sdk/module-exports as
193	// either java_libs, or java_header_libs would end up exporting more information than was strictly
194	// necessary. The java_systemserver_libs property to allow those modules to be exported as part of
195	// the sdk/module_exports without exposing any unnecessary information.
196	JavaSystemserverLibsSdkMemberType = &librarySdkMemberType{
197		android.SdkMemberTypeBase{
198			PropertyName: "java_systemserver_libs",
199			SupportsSdk:  true,
200
201			// This was only added in Tiramisu.
202			SupportedBuildReleaseSpecification: "Tiramisu+",
203		},
204		func(ctx android.SdkMemberContext, j *Library) android.Path {
205			// Java systemserver libs are only provided in the SDK to provide access to their dex
206			// implementation jar for use by dexpreopting. They do not need to provide an actual
207			// implementation jar but the java_import will need a file that exists so just copy an empty
208			// file. Any attempt to use that file as a jar will cause a build error.
209			return ctx.SnapshotBuilder().EmptyFile()
210		},
211		func(_ android.SdkMemberContext, osPrefix, name string) string {
212			// Create a special name for the implementation jar to try and provide some useful information
213			// to a developer that attempts to compile against this.
214			// TODO(b/175714559): Provide a proper error message in Soong not ninja.
215			return filepath.Join(osPrefix, "java_systemserver_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix)
216		},
217		onlyCopyJarToSnapshot,
218	}
219
220	// Supports adding java test libraries to module_exports but not sdk.
221	javaTestSdkMemberType = &testSdkMemberType{
222		SdkMemberTypeBase: android.SdkMemberTypeBase{
223			PropertyName: "java_tests",
224		},
225	}
226
227	// Rule for generating device binary default wrapper
228	deviceBinaryWrapper = pctx.StaticRule("deviceBinaryWrapper", blueprint.RuleParams{
229		Command: `echo -e '#!/system/bin/sh\n` +
230			`export CLASSPATH=/system/framework/$jar_name\n` +
231			`exec app_process /$partition/bin $main_class "$$@"'> ${out}`,
232		Description: "Generating device binary wrapper ${jar_name}",
233	}, "jar_name", "partition", "main_class")
234)
235
236type ProguardSpecInfo struct {
237	// If true, proguard flags files will be exported to reverse dependencies across libs edges
238	// If false, proguard flags files will only be exported to reverse dependencies across
239	// static_libs edges.
240	Export_proguard_flags_files bool
241
242	// TransitiveDepsProguardSpecFiles is a depset of paths to proguard flags files that are exported from
243	// all transitive deps. This list includes all proguard flags files from transitive static dependencies,
244	// and all proguard flags files from transitive libs dependencies which set `export_proguard_spec: true`.
245	ProguardFlagsFiles *android.DepSet[android.Path]
246
247	// implementation detail to store transitive proguard flags files from exporting shared deps
248	UnconditionallyExportedProguardFlags *android.DepSet[android.Path]
249}
250
251var ProguardSpecInfoProvider = blueprint.NewProvider[ProguardSpecInfo]()
252
253// JavaInfo contains information about a java module for use by modules that depend on it.
254type JavaInfo struct {
255	// HeaderJars is a list of jars that can be passed as the javac classpath in order to link
256	// against this module.  If empty, ImplementationJars should be used instead.
257	HeaderJars android.Paths
258
259	RepackagedHeaderJars android.Paths
260
261	// set of header jars for all transitive libs deps
262	TransitiveLibsHeaderJars *android.DepSet[android.Path]
263
264	// set of header jars for all transitive static libs deps
265	TransitiveStaticLibsHeaderJars *android.DepSet[android.Path]
266
267	// ImplementationAndResourceJars is a list of jars that contain the implementations of classes
268	// in the module as well as any resources included in the module.
269	ImplementationAndResourcesJars android.Paths
270
271	// ImplementationJars is a list of jars that contain the implementations of classes in the
272	//module.
273	ImplementationJars android.Paths
274
275	// ResourceJars is a list of jars that contain the resources included in the module.
276	ResourceJars android.Paths
277
278	// AidlIncludeDirs is a list of directories that should be passed to the aidl tool when
279	// depending on this module.
280	AidlIncludeDirs android.Paths
281
282	// SrcJarArgs is a list of arguments to pass to soong_zip to package the sources of this
283	// module.
284	SrcJarArgs []string
285
286	// SrcJarDeps is a list of paths to depend on when packaging the sources of this module.
287	SrcJarDeps android.Paths
288
289	// The source files of this module and all its transitive static dependencies.
290	TransitiveSrcFiles *android.DepSet[android.Path]
291
292	// ExportedPlugins is a list of paths that should be used as annotation processors for any
293	// module that depends on this module.
294	ExportedPlugins android.Paths
295
296	// ExportedPluginClasses is a list of classes that should be run as annotation processors for
297	// any module that depends on this module.
298	ExportedPluginClasses []string
299
300	// ExportedPluginDisableTurbine is true if this module's annotation processors generate APIs,
301	// requiring disbling turbine for any modules that depend on it.
302	ExportedPluginDisableTurbine bool
303
304	// JacocoReportClassesFile is the path to a jar containing uninstrumented classes that will be
305	// instrumented by jacoco.
306	JacocoReportClassesFile android.Path
307
308	// StubsLinkType provides information about whether the provided jars are stub jars or
309	// implementation jars. If the provider is set by java_sdk_library, the link type is "unknown"
310	// and selection between the stub jar vs implementation jar is deferred to SdkLibrary.sdkJars(...)
311	StubsLinkType StubsLinkType
312
313	// AconfigIntermediateCacheOutputPaths is a path to the cache files collected from the
314	// java_aconfig_library modules that are statically linked to this module.
315	AconfigIntermediateCacheOutputPaths android.Paths
316}
317
318var JavaInfoProvider = blueprint.NewProvider[JavaInfo]()
319
320// SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to
321// the sysprop implementation library.
322type SyspropPublicStubInfo struct {
323	// JavaInfo is the JavaInfoProvider of the sysprop public stub library that corresponds to
324	// the sysprop implementation library.
325	JavaInfo JavaInfo
326}
327
328var SyspropPublicStubInfoProvider = blueprint.NewProvider[SyspropPublicStubInfo]()
329
330// Methods that need to be implemented for a module that is added to apex java_libs property.
331type ApexDependency interface {
332	HeaderJars() android.Paths
333	ImplementationAndResourcesJars() android.Paths
334}
335
336// Provides build path and install path to DEX jars.
337type UsesLibraryDependency interface {
338	DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
339	DexJarInstallPath() android.Path
340	ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
341}
342
343// TODO(jungjw): Move this to kythe.go once it's created.
344type xref interface {
345	XrefJavaFiles() android.Paths
346}
347
348func (j *Module) XrefJavaFiles() android.Paths {
349	return j.kytheFiles
350}
351
352func (d dependencyTag) PropagateAconfigValidation() bool {
353	return d.static
354}
355
356var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{}
357
358type dependencyTag struct {
359	blueprint.BaseDependencyTag
360	name string
361
362	// True if the dependency is relinked at runtime.
363	runtimeLinked bool
364
365	// True if the dependency is a toolchain, for example an annotation processor.
366	toolchain bool
367
368	static bool
369
370	installable bool
371}
372
373var _ android.InstallNeededDependencyTag = (*dependencyTag)(nil)
374
375func (d dependencyTag) InstallDepNeeded() bool {
376	return d.installable
377}
378
379func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
380	if d.runtimeLinked {
381		return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
382	} else if d.toolchain {
383		return []android.LicenseAnnotation{android.LicenseAnnotationToolchain}
384	}
385	return nil
386}
387
388var _ android.LicenseAnnotationsDependencyTag = dependencyTag{}
389
390type usesLibraryDependencyTag struct {
391	dependencyTag
392	sdkVersion int  // SDK version in which the library appared as a standalone library.
393	optional   bool // If the dependency is optional or required.
394}
395
396func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDependencyTag {
397	return usesLibraryDependencyTag{
398		dependencyTag: dependencyTag{
399			name:          fmt.Sprintf("uses-library-%d", sdkVersion),
400			runtimeLinked: true,
401		},
402		sdkVersion: sdkVersion,
403		optional:   optional,
404	}
405}
406
407func IsJniDepTag(depTag blueprint.DependencyTag) bool {
408	return depTag == jniLibTag || depTag == jniInstallTag
409}
410
411var (
412	dataNativeBinsTag       = dependencyTag{name: "dataNativeBins"}
413	dataDeviceBinsTag       = dependencyTag{name: "dataDeviceBins"}
414	staticLibTag            = dependencyTag{name: "staticlib", static: true}
415	libTag                  = dependencyTag{name: "javalib", runtimeLinked: true}
416	sdkLibTag               = dependencyTag{name: "sdklib", runtimeLinked: true}
417	java9LibTag             = dependencyTag{name: "java9lib", runtimeLinked: true}
418	pluginTag               = dependencyTag{name: "plugin", toolchain: true}
419	errorpronePluginTag     = dependencyTag{name: "errorprone-plugin", toolchain: true}
420	exportedPluginTag       = dependencyTag{name: "exported-plugin", toolchain: true}
421	bootClasspathTag        = dependencyTag{name: "bootclasspath", runtimeLinked: true}
422	systemModulesTag        = dependencyTag{name: "system modules", runtimeLinked: true}
423	frameworkResTag         = dependencyTag{name: "framework-res"}
424	kotlinStdlibTag         = dependencyTag{name: "kotlin-stdlib", runtimeLinked: true}
425	kotlinAnnotationsTag    = dependencyTag{name: "kotlin-annotations", runtimeLinked: true}
426	kotlinPluginTag         = dependencyTag{name: "kotlin-plugin", toolchain: true}
427	proguardRaiseTag        = dependencyTag{name: "proguard-raise"}
428	certificateTag          = dependencyTag{name: "certificate"}
429	instrumentationForTag   = dependencyTag{name: "instrumentation_for"}
430	extraLintCheckTag       = dependencyTag{name: "extra-lint-check", toolchain: true}
431	jniLibTag               = dependencyTag{name: "jnilib", runtimeLinked: true}
432	r8LibraryJarTag         = dependencyTag{name: "r8-libraryjar", runtimeLinked: true}
433	syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
434	javaApiContributionTag  = dependencyTag{name: "java-api-contribution"}
435	depApiSrcsTag           = dependencyTag{name: "dep-api-srcs"}
436	aconfigDeclarationTag   = dependencyTag{name: "aconfig-declaration"}
437	jniInstallTag           = dependencyTag{name: "jni install", runtimeLinked: true, installable: true}
438	binaryInstallTag        = dependencyTag{name: "binary install", runtimeLinked: true, installable: true}
439	usesLibReqTag           = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
440	usesLibOptTag           = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
441	usesLibCompat28OptTag   = makeUsesLibraryDependencyTag(28, true)
442	usesLibCompat29ReqTag   = makeUsesLibraryDependencyTag(29, false)
443	usesLibCompat30OptTag   = makeUsesLibraryDependencyTag(30, true)
444)
445
446func IsLibDepTag(depTag blueprint.DependencyTag) bool {
447	return depTag == libTag || depTag == sdkLibTag
448}
449
450func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool {
451	return depTag == staticLibTag
452}
453
454type sdkDep struct {
455	useModule, useFiles, invalidVersion bool
456
457	// The modules that will be added to the bootclasspath when targeting 1.8 or lower
458	bootclasspath []string
459
460	// The default system modules to use. Will be an empty string if no system
461	// modules are to be used.
462	systemModules string
463
464	// The modules that will be added to the classpath regardless of the Java language level targeted
465	classpath []string
466
467	// The modules that will be added ot the classpath when targeting 1.9 or higher
468	// (normally these will be on the bootclasspath when targeting 1.8 or lower)
469	java9Classpath []string
470
471	frameworkResModule string
472
473	jars android.Paths
474	aidl android.OptionalPath
475
476	noStandardLibs, noFrameworksLibs bool
477}
478
479func (s sdkDep) hasStandardLibs() bool {
480	return !s.noStandardLibs
481}
482
483func (s sdkDep) hasFrameworkLibs() bool {
484	return !s.noStandardLibs && !s.noFrameworksLibs
485}
486
487type jniLib struct {
488	name           string
489	path           android.Path
490	target         android.Target
491	coverageFile   android.OptionalPath
492	unstrippedFile android.Path
493	partition      string
494	installPaths   android.InstallPaths
495}
496
497func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) {
498	sdkDep := decodeSdkDep(ctx, sdkContext)
499	if sdkDep.useModule {
500		ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
501		ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
502		ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...)
503		if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
504			ctx.AddVariationDependencies(nil, proguardRaiseTag,
505				config.LegacyCorePlatformBootclasspathLibraries...,
506			)
507		}
508		if d.effectiveOptimizeEnabled() && sdkDep.hasFrameworkLibs() {
509			ctx.AddVariationDependencies(nil, proguardRaiseTag, config.FrameworkLibraries...)
510		}
511	}
512	if sdkDep.systemModules != "" {
513		ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
514	}
515}
516
517type deps struct {
518	// bootClasspath is the list of jars that form the boot classpath (generally the java.* and
519	// android.* classes) for tools that still use it.  javac targeting 1.9 or higher uses
520	// systemModules and java9Classpath instead.
521	bootClasspath classpath
522
523	// classpath is the list of jars that form the classpath for javac and kotlinc rules.  It
524	// contains header jars for all static and non-static dependencies.
525	classpath classpath
526
527	// dexClasspath is the list of jars that form the classpath for d8 and r8 rules.  It contains
528	// header jars for all non-static dependencies.  Static dependencies have already been
529	// combined into the program jar.
530	dexClasspath classpath
531
532	// java9Classpath is the list of jars that will be added to the classpath when targeting
533	// 1.9 or higher.  It generally contains the android.* classes, while the java.* classes
534	// are provided by systemModules.
535	java9Classpath classpath
536
537	processorPath           classpath
538	errorProneProcessorPath classpath
539	processorClasses        []string
540	staticJars              android.Paths
541	staticHeaderJars        android.Paths
542	staticResourceJars      android.Paths
543	aidlIncludeDirs         android.Paths
544	srcs                    android.Paths
545	srcJars                 android.Paths
546	systemModules           *systemModules
547	aidlPreprocess          android.OptionalPath
548	kotlinStdlib            android.Paths
549	kotlinAnnotations       android.Paths
550	kotlinPlugins           android.Paths
551	aconfigProtoFiles       android.Paths
552
553	disableTurbine bool
554}
555
556func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
557	for _, f := range dep.Srcs() {
558		if f.Ext() != ".jar" {
559			ctx.ModuleErrorf("genrule %q must generate files ending with .jar to be used as a libs or static_libs dependency",
560				ctx.OtherModuleName(dep.(blueprint.Module)))
561		}
562	}
563}
564
565func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext android.SdkContext) javaVersion {
566	if javaVersion != "" {
567		return normalizeJavaVersion(ctx, javaVersion)
568	} else if ctx.Device() {
569		return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion(ctx))
570	} else if ctx.Config().TargetsJava21() {
571		// Temporary experimental flag to be able to try and build with
572		// java version 21 options.  The flag, if used, just sets Java
573		// 21 as the default version, leaving any components that
574		// target an older version intact.
575		return JAVA_VERSION_21
576	} else {
577		return JAVA_VERSION_17
578	}
579}
580
581// Java version for stubs generation
582func getStubsJavaVersion() javaVersion {
583	return JAVA_VERSION_8
584}
585
586type javaVersion int
587
588const (
589	JAVA_VERSION_UNSUPPORTED = 0
590	JAVA_VERSION_6           = 6
591	JAVA_VERSION_7           = 7
592	JAVA_VERSION_8           = 8
593	JAVA_VERSION_9           = 9
594	JAVA_VERSION_11          = 11
595	JAVA_VERSION_17          = 17
596	JAVA_VERSION_21          = 21
597)
598
599func (v javaVersion) String() string {
600	switch v {
601	case JAVA_VERSION_6:
602		// Java version 1.6 no longer supported, bumping to 1.8
603		return "1.8"
604	case JAVA_VERSION_7:
605		// Java version 1.7 no longer supported, bumping to 1.8
606		return "1.8"
607	case JAVA_VERSION_8:
608		return "1.8"
609	case JAVA_VERSION_9:
610		return "1.9"
611	case JAVA_VERSION_11:
612		return "11"
613	case JAVA_VERSION_17:
614		return "17"
615	case JAVA_VERSION_21:
616		return "21"
617	default:
618		return "unsupported"
619	}
620}
621
622func (v javaVersion) StringForKotlinc() string {
623	// $ ./external/kotlinc/bin/kotlinc -jvm-target foo
624	// error: unknown JVM target version: foo
625	// Supported versions: 1.8, 9, 10, 11, 12, 13, 14, 15, 16, 17
626	switch v {
627	case JAVA_VERSION_6:
628		return "1.8"
629	case JAVA_VERSION_7:
630		return "1.8"
631	case JAVA_VERSION_9:
632		return "9"
633	default:
634		return v.String()
635	}
636}
637
638// Returns true if javac targeting this version uses system modules instead of a bootclasspath.
639func (v javaVersion) usesJavaModules() bool {
640	return v >= 9
641}
642
643func normalizeJavaVersion(ctx android.BaseModuleContext, javaVersion string) javaVersion {
644	switch javaVersion {
645	case "1.6", "6":
646		// Java version 1.6 no longer supported, bumping to 1.8
647		return JAVA_VERSION_8
648	case "1.7", "7":
649		// Java version 1.7 no longer supported, bumping to 1.8
650		return JAVA_VERSION_8
651	case "1.8", "8":
652		return JAVA_VERSION_8
653	case "1.9", "9":
654		return JAVA_VERSION_9
655	case "11":
656		return JAVA_VERSION_11
657	case "17":
658		return JAVA_VERSION_17
659	case "21":
660		return JAVA_VERSION_21
661	case "10", "12", "13", "14", "15", "16":
662		ctx.PropertyErrorf("java_version", "Java language level %s is not supported", javaVersion)
663		return JAVA_VERSION_UNSUPPORTED
664	default:
665		ctx.PropertyErrorf("java_version", "Unrecognized Java language level")
666		return JAVA_VERSION_UNSUPPORTED
667	}
668}
669
670//
671// Java libraries (.jar file)
672//
673
674type Library struct {
675	Module
676
677	combinedExportedProguardFlagsFile android.Path
678
679	InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.InstallPaths)
680}
681
682var _ android.ApexModule = (*Library)(nil)
683
684func (j *Library) CheckDepsMinSdkVersion(ctx android.ModuleContext) {
685	CheckMinSdkVersion(ctx, j)
686}
687
688// Provides access to the list of permitted packages from apex boot jars.
689type PermittedPackagesForUpdatableBootJars interface {
690	PermittedPackagesForUpdatableBootJars() []string
691}
692
693var _ PermittedPackagesForUpdatableBootJars = (*Library)(nil)
694
695func (j *Library) PermittedPackagesForUpdatableBootJars() []string {
696	return j.properties.Permitted_packages
697}
698
699func shouldUncompressDex(ctx android.ModuleContext, libName string, dexpreopter *dexpreopter) bool {
700	// Store uncompressed (and aligned) any dex files from jars in APEXes.
701	if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
702		return true
703	}
704
705	// Store uncompressed (and do not strip) dex files from boot class path jars.
706	if inList(ctx.ModuleName(), ctx.Config().BootJars()) {
707		return true
708	}
709
710	// Store uncompressed dex files that are preopted on /system or /system_other.
711	if !dexpreopter.dexpreoptDisabled(ctx, libName) {
712		return true
713	}
714
715	if ctx.Config().UncompressPrivAppDex() &&
716		inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules()) {
717		return true
718	}
719
720	return false
721}
722
723// Sets `dexer.dexProperties.Uncompress_dex` to the proper value.
724func setUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter, dexer *dexer) {
725	if dexer.dexProperties.Uncompress_dex == nil {
726		// If the value was not force-set by the user, use reasonable default based on the module.
727		dexer.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), dexpreopter))
728	}
729}
730
731// list of java_library modules that set platform_apis: true
732// this property is a no-op for java_library
733// TODO (b/215379393): Remove this allowlist
734var (
735	aospPlatformApiAllowlist = map[string]bool{
736		"adservices-test-scenarios":                         true,
737		"aidl-cpp-java-test-interface-java":                 true,
738		"aidl-test-extras-java":                             true,
739		"aidl-test-interface-java":                          true,
740		"aidl-test-interface-permission-java":               true,
741		"aidl_test_java_client_permission":                  true,
742		"aidl_test_java_client_sdk1":                        true,
743		"aidl_test_java_client_sdk29":                       true,
744		"aidl_test_java_client":                             true,
745		"aidl_test_java_service_permission":                 true,
746		"aidl_test_java_service_sdk1":                       true,
747		"aidl_test_java_service_sdk29":                      true,
748		"aidl_test_java_service":                            true,
749		"aidl_test_loggable_interface-java":                 true,
750		"aidl_test_nonvintf_parcelable-V1-java":             true,
751		"aidl_test_nonvintf_parcelable-V2-java":             true,
752		"aidl_test_unstable_parcelable-java":                true,
753		"aidl_test_vintf_parcelable-V1-java":                true,
754		"aidl_test_vintf_parcelable-V2-java":                true,
755		"android.aidl.test.trunk-V1-java":                   true,
756		"android.aidl.test.trunk-V2-java":                   true,
757		"android.frameworks.location.altitude-V1-java":      true,
758		"android.frameworks.location.altitude-V2-java":      true,
759		"android.frameworks.stats-V1-java":                  true,
760		"android.frameworks.stats-V2-java":                  true,
761		"android.frameworks.stats-V3-java":                  true,
762		"android.hardware.authsecret-V1-java":               true,
763		"android.hardware.authsecret-V2-java":               true,
764		"android.hardware.biometrics.common-V1-java":        true,
765		"android.hardware.biometrics.common-V2-java":        true,
766		"android.hardware.biometrics.common-V3-java":        true,
767		"android.hardware.biometrics.common-V4-java":        true,
768		"android.hardware.biometrics.face-V1-java":          true,
769		"android.hardware.biometrics.face-V2-java":          true,
770		"android.hardware.biometrics.face-V3-java":          true,
771		"android.hardware.biometrics.face-V4-java":          true,
772		"android.hardware.biometrics.fingerprint-V1-java":   true,
773		"android.hardware.biometrics.fingerprint-V2-java":   true,
774		"android.hardware.biometrics.fingerprint-V3-java":   true,
775		"android.hardware.biometrics.fingerprint-V4-java":   true,
776		"android.hardware.bluetooth.lmp_event-V1-java":      true,
777		"android.hardware.confirmationui-V1-java":           true,
778		"android.hardware.confirmationui-V2-java":           true,
779		"android.hardware.gatekeeper-V1-java":               true,
780		"android.hardware.gatekeeper-V2-java":               true,
781		"android.hardware.gnss-V1-java":                     true,
782		"android.hardware.gnss-V2-java":                     true,
783		"android.hardware.gnss-V3-java":                     true,
784		"android.hardware.gnss-V4-java":                     true,
785		"android.hardware.graphics.common-V1-java":          true,
786		"android.hardware.graphics.common-V2-java":          true,
787		"android.hardware.graphics.common-V3-java":          true,
788		"android.hardware.graphics.common-V4-java":          true,
789		"android.hardware.graphics.common-V5-java":          true,
790		"android.hardware.identity-V1-java":                 true,
791		"android.hardware.identity-V2-java":                 true,
792		"android.hardware.identity-V3-java":                 true,
793		"android.hardware.identity-V4-java":                 true,
794		"android.hardware.identity-V5-java":                 true,
795		"android.hardware.identity-V6-java":                 true,
796		"android.hardware.keymaster-V1-java":                true,
797		"android.hardware.keymaster-V2-java":                true,
798		"android.hardware.keymaster-V3-java":                true,
799		"android.hardware.keymaster-V4-java":                true,
800		"android.hardware.keymaster-V5-java":                true,
801		"android.hardware.oemlock-V1-java":                  true,
802		"android.hardware.oemlock-V2-java":                  true,
803		"android.hardware.power.stats-V1-java":              true,
804		"android.hardware.power.stats-V2-java":              true,
805		"android.hardware.power.stats-V3-java":              true,
806		"android.hardware.power-V1-java":                    true,
807		"android.hardware.power-V2-java":                    true,
808		"android.hardware.power-V3-java":                    true,
809		"android.hardware.power-V4-java":                    true,
810		"android.hardware.power-V5-java":                    true,
811		"android.hardware.rebootescrow-V1-java":             true,
812		"android.hardware.rebootescrow-V2-java":             true,
813		"android.hardware.security.authgraph-V1-java":       true,
814		"android.hardware.security.keymint-V1-java":         true,
815		"android.hardware.security.keymint-V2-java":         true,
816		"android.hardware.security.keymint-V3-java":         true,
817		"android.hardware.security.keymint-V4-java":         true,
818		"android.hardware.security.secretkeeper-V1-java":    true,
819		"android.hardware.security.secureclock-V1-java":     true,
820		"android.hardware.security.secureclock-V2-java":     true,
821		"android.hardware.thermal-V1-java":                  true,
822		"android.hardware.thermal-V2-java":                  true,
823		"android.hardware.threadnetwork-V1-java":            true,
824		"android.hardware.weaver-V1-java":                   true,
825		"android.hardware.weaver-V2-java":                   true,
826		"android.hardware.weaver-V3-java":                   true,
827		"android.security.attestationmanager-java":          true,
828		"android.security.authorization-java":               true,
829		"android.security.compat-java":                      true,
830		"android.security.legacykeystore-java":              true,
831		"android.security.maintenance-java":                 true,
832		"android.security.metrics-java":                     true,
833		"android.system.keystore2-V1-java":                  true,
834		"android.system.keystore2-V2-java":                  true,
835		"android.system.keystore2-V3-java":                  true,
836		"android.system.keystore2-V4-java":                  true,
837		"binderReadParcelIface-java":                        true,
838		"binderRecordReplayTestIface-java":                  true,
839		"car-experimental-api-static-lib":                   true,
840		"collector-device-lib-platform":                     true,
841		"com.android.car.oem":                               true,
842		"com.google.hardware.pixel.display-V10-java":        true,
843		"com.google.hardware.pixel.display-V1-java":         true,
844		"com.google.hardware.pixel.display-V2-java":         true,
845		"com.google.hardware.pixel.display-V3-java":         true,
846		"com.google.hardware.pixel.display-V4-java":         true,
847		"com.google.hardware.pixel.display-V5-java":         true,
848		"com.google.hardware.pixel.display-V6-java":         true,
849		"com.google.hardware.pixel.display-V7-java":         true,
850		"com.google.hardware.pixel.display-V8-java":         true,
851		"com.google.hardware.pixel.display-V9-java":         true,
852		"conscrypt-support":                                 true,
853		"cts-keystore-test-util":                            true,
854		"cts-keystore-user-auth-helper-library":             true,
855		"ctsmediautil":                                      true,
856		"CtsNetTestsNonUpdatableLib":                        true,
857		"DpmWrapper":                                        true,
858		"flickerlib-apphelpers":                             true,
859		"flickerlib-helpers":                                true,
860		"flickerlib-parsers":                                true,
861		"flickerlib":                                        true,
862		"hardware.google.bluetooth.ccc-V1-java":             true,
863		"hardware.google.bluetooth.sar-V1-java":             true,
864		"monet":                                             true,
865		"pixel-power-ext-V1-java":                           true,
866		"pixel-power-ext-V2-java":                           true,
867		"pixel_stateresidency_provider_aidl_interface-java": true,
868		"pixel-thermal-ext-V1-java":                         true,
869		"protolog-lib":                                      true,
870		"RkpRegistrationCheck":                              true,
871		"rotary-service-javastream-protos":                  true,
872		"service_based_camera_extensions":                   true,
873		"statsd-helper-test":                                true,
874		"statsd-helper":                                     true,
875		"test-piece-2-V1-java":                              true,
876		"test-piece-2-V2-java":                              true,
877		"test-piece-3-V1-java":                              true,
878		"test-piece-3-V2-java":                              true,
879		"test-piece-3-V3-java":                              true,
880		"test-piece-4-V1-java":                              true,
881		"test-piece-4-V2-java":                              true,
882		"test-root-package-V1-java":                         true,
883		"test-root-package-V2-java":                         true,
884		"test-root-package-V3-java":                         true,
885		"test-root-package-V4-java":                         true,
886		"testServiceIface-java":                             true,
887		"wm-flicker-common-app-helpers":                     true,
888		"wm-flicker-common-assertions":                      true,
889		"wm-shell-flicker-utils":                            true,
890		"wycheproof-keystore":                               true,
891	}
892
893	// Union of aosp and internal allowlists
894	PlatformApiAllowlist = map[string]bool{}
895)
896
897func init() {
898	for k, v := range aospPlatformApiAllowlist {
899		PlatformApiAllowlist[k] = v
900	}
901}
902
903func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
904	if disableSourceApexVariant(ctx) {
905		// Prebuilts are active, do not create the installation rules for the source javalib.
906		// Even though the source javalib is not used, we need to hide it to prevent duplicate installation rules.
907		// TODO (b/331665856): Implement a principled solution for this.
908		j.HideFromMake()
909	}
910	j.provideHiddenAPIPropertyInfo(ctx)
911
912	j.sdkVersion = j.SdkVersion(ctx)
913	j.minSdkVersion = j.MinSdkVersion(ctx)
914	j.maxSdkVersion = j.MaxSdkVersion(ctx)
915
916	// Check min_sdk_version of the transitive dependencies if this module is created from
917	// java_sdk_library.
918	if j.overridableProperties.Min_sdk_version != nil && j.SdkLibraryName() != nil {
919		j.CheckDepsMinSdkVersion(ctx)
920	}
921
922	// SdkLibrary.GenerateAndroidBuildActions(ctx) sets the stubsLinkType to Unknown.
923	// If the stubsLinkType has already been set to Unknown, the stubsLinkType should
924	// not be overridden.
925	if j.stubsLinkType != Unknown {
926		if proptools.Bool(j.properties.Is_stubs_module) {
927			j.stubsLinkType = Stubs
928		} else {
929			j.stubsLinkType = Implementation
930		}
931	}
932
933	j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
934
935	proguardSpecInfo := j.collectProguardSpecInfo(ctx)
936	android.SetProvider(ctx, ProguardSpecInfoProvider, proguardSpecInfo)
937	exportedProguardFlagsFiles := proguardSpecInfo.ProguardFlagsFiles.ToList()
938	j.extraProguardFlagsFiles = append(j.extraProguardFlagsFiles, exportedProguardFlagsFiles...)
939
940	combinedExportedProguardFlagFile := android.PathForModuleOut(ctx, "export_proguard_flags")
941	writeCombinedProguardFlagsFile(ctx, combinedExportedProguardFlagFile, exportedProguardFlagsFiles)
942	j.combinedExportedProguardFlagsFile = combinedExportedProguardFlagFile
943
944	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
945	if !apexInfo.IsForPlatform() {
946		j.hideApexVariantFromMake = true
947	}
948
949	j.checkSdkVersions(ctx)
950	j.checkHeadersOnly(ctx)
951	if ctx.Device() {
952		libName := j.Name()
953		if j.SdkLibraryName() != nil && strings.HasSuffix(libName, ".impl") {
954			libName = proptools.String(j.SdkLibraryName())
955		}
956		j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
957			ctx, libName, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
958		j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
959		setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
960		j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
961		j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
962		if j.usesLibrary.shouldDisableDexpreopt {
963			j.dexpreopter.disableDexpreopt()
964		}
965	}
966	j.compile(ctx, nil, nil, nil)
967
968	// If this module is an impl library created from java_sdk_library,
969	// install the files under the java_sdk_library module outdir instead of this module outdir.
970	if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
971		j.setInstallRules(ctx, proptools.String(j.SdkLibraryName()))
972	} else {
973		j.setInstallRules(ctx, ctx.ModuleName())
974	}
975
976	android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
977		TestOnly:       Bool(j.sourceProperties.Test_only),
978		TopLevelTarget: j.sourceProperties.Top_level_test_target,
979	})
980}
981
982func (j *Library) setInstallRules(ctx android.ModuleContext, installModuleName string) {
983	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
984
985	if (Bool(j.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() {
986		var extraInstallDeps android.InstallPaths
987		if j.InstallMixin != nil {
988			extraInstallDeps = j.InstallMixin(ctx, j.outputFile)
989		}
990		hostDexNeeded := Bool(j.deviceProperties.Hostdex) && !ctx.Host()
991		if hostDexNeeded {
992			j.hostdexInstallFile = ctx.InstallFile(
993				android.PathForHostDexInstall(ctx, "framework"),
994				j.Stem()+"-hostdex.jar", j.outputFile)
995		}
996		var installDir android.InstallPath
997		if ctx.InstallInTestcases() {
998			var archDir string
999			if !ctx.Host() {
1000				archDir = ctx.DeviceConfig().DeviceArch()
1001			}
1002			installDir = android.PathForModuleInstall(ctx, installModuleName, archDir)
1003		} else {
1004			installDir = android.PathForModuleInstall(ctx, "framework")
1005		}
1006		j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
1007	}
1008}
1009
1010func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
1011	j.usesLibrary.deps(ctx, false)
1012	j.deps(ctx)
1013
1014	if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
1015		if dexpreopt.IsDex2oatNeeded(ctx) {
1016			dexpreopt.RegisterToolDeps(ctx)
1017		}
1018		prebuiltSdkLibExists := ctx.OtherModuleExists(android.PrebuiltNameFromSource(proptools.String(j.SdkLibraryName())))
1019		if prebuiltSdkLibExists && ctx.OtherModuleExists("all_apex_contributions") {
1020			ctx.AddDependency(ctx.Module(), android.AcDepTag, "all_apex_contributions")
1021		}
1022	}
1023}
1024
1025const (
1026	aidlIncludeDir   = "aidl"
1027	javaDir          = "java"
1028	jarFileSuffix    = ".jar"
1029	testConfigSuffix = "-AndroidTest.xml"
1030)
1031
1032// path to the jar file of a java library. Relative to <sdk_root>/<api_dir>
1033func sdkSnapshotFilePathForJar(_ android.SdkMemberContext, osPrefix, name string) string {
1034	return sdkSnapshotFilePathForMember(osPrefix, name, jarFileSuffix)
1035}
1036
1037func sdkSnapshotFilePathForMember(osPrefix, name string, suffix string) string {
1038	return filepath.Join(javaDir, osPrefix, name+suffix)
1039}
1040
1041type librarySdkMemberType struct {
1042	android.SdkMemberTypeBase
1043
1044	// Function to retrieve the appropriate output jar (implementation or header) from
1045	// the library.
1046	jarToExportGetter func(ctx android.SdkMemberContext, j *Library) android.Path
1047
1048	// Function to compute the snapshot relative path to which the named library's
1049	// jar should be copied.
1050	snapshotPathGetter func(ctx android.SdkMemberContext, osPrefix, name string) string
1051
1052	// True if only the jar should be copied to the snapshot, false if the jar plus any additional
1053	// files like aidl files should also be copied.
1054	onlyCopyJarToSnapshot bool
1055}
1056
1057const (
1058	onlyCopyJarToSnapshot    = true
1059	copyEverythingToSnapshot = false
1060)
1061
1062func (mt *librarySdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
1063	ctx.AddVariationDependencies(nil, dependencyTag, names...)
1064}
1065
1066func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
1067	_, ok := module.(*Library)
1068	return ok
1069}
1070
1071func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
1072	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_import")
1073}
1074
1075func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
1076	return &librarySdkMemberProperties{}
1077}
1078
1079type librarySdkMemberProperties struct {
1080	android.SdkMemberPropertiesBase
1081
1082	JarToExport     android.Path `android:"arch_variant"`
1083	AidlIncludeDirs android.Paths
1084
1085	// The list of permitted packages that need to be passed to the prebuilts as they are used to
1086	// create the updatable-bcp-packages.txt file.
1087	PermittedPackages []string
1088
1089	// The value of the min_sdk_version property, translated into a number where possible.
1090	MinSdkVersion *string `supported_build_releases:"Tiramisu+"`
1091
1092	DexPreoptProfileGuided *bool `supported_build_releases:"UpsideDownCake+"`
1093}
1094
1095func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
1096	j := variant.(*Library)
1097
1098	p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(ctx, j)
1099
1100	p.AidlIncludeDirs = j.AidlIncludeDirs()
1101
1102	p.PermittedPackages = j.PermittedPackagesForUpdatableBootJars()
1103
1104	// If the min_sdk_version was set then add the canonical representation of the API level to the
1105	// snapshot.
1106	if j.overridableProperties.Min_sdk_version != nil {
1107		canonical, err := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.String())
1108		if err != nil {
1109			ctx.ModuleErrorf("%s", err)
1110		}
1111		p.MinSdkVersion = proptools.StringPtr(canonical)
1112	}
1113
1114	if j.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
1115		p.DexPreoptProfileGuided = proptools.BoolPtr(true)
1116	}
1117}
1118
1119func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
1120	builder := ctx.SnapshotBuilder()
1121
1122	memberType := ctx.MemberType().(*librarySdkMemberType)
1123
1124	exportedJar := p.JarToExport
1125	if exportedJar != nil {
1126		// Delegate the creation of the snapshot relative path to the member type.
1127		snapshotRelativeJavaLibPath := memberType.snapshotPathGetter(ctx, p.OsPrefix(), ctx.Name())
1128
1129		// Copy the exported jar to the snapshot.
1130		builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
1131
1132		propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
1133	}
1134
1135	if p.MinSdkVersion != nil {
1136		propertySet.AddProperty("min_sdk_version", *p.MinSdkVersion)
1137	}
1138
1139	if len(p.PermittedPackages) > 0 {
1140		propertySet.AddProperty("permitted_packages", p.PermittedPackages)
1141	}
1142
1143	dexPreoptSet := propertySet.AddPropertySet("dex_preopt")
1144	if p.DexPreoptProfileGuided != nil {
1145		dexPreoptSet.AddProperty("profile_guided", proptools.Bool(p.DexPreoptProfileGuided))
1146	}
1147
1148	// Do not copy anything else to the snapshot.
1149	if memberType.onlyCopyJarToSnapshot {
1150		return
1151	}
1152
1153	aidlIncludeDirs := p.AidlIncludeDirs
1154	if len(aidlIncludeDirs) != 0 {
1155		sdkModuleContext := ctx.SdkModuleContext()
1156		for _, dir := range aidlIncludeDirs {
1157			// TODO(jiyong): copy parcelable declarations only
1158			aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
1159			for _, file := range aidlFiles {
1160				builder.CopyToSnapshot(android.PathForSource(sdkModuleContext, file), filepath.Join(aidlIncludeDir, file))
1161			}
1162		}
1163
1164		// TODO(b/151933053) - add aidl include dirs property
1165	}
1166}
1167
1168// java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
1169//
1170// By default, a java_library has a single variant that produces a `.jar` file containing `.class` files that were
1171// compiled against the device bootclasspath.  This jar is not suitable for installing on a device, but can be used
1172// as a `static_libs` dependency of another module.
1173//
1174// Specifying `installable: true` will product a `.jar` file containing `classes.dex` files, suitable for installing on
1175// a device.
1176//
1177// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
1178// compiled against the host bootclasspath.
1179func LibraryFactory() android.Module {
1180	module := &Library{}
1181
1182	module.addHostAndDeviceProperties()
1183	module.AddProperties(&module.sourceProperties)
1184
1185	module.initModuleAndImport(module)
1186
1187	android.InitApexModule(module)
1188	InitJavaModule(module, android.HostAndDeviceSupported)
1189	return module
1190}
1191
1192// java_library_static is an obsolete alias for java_library.
1193func LibraryStaticFactory() android.Module {
1194	return LibraryFactory()
1195}
1196
1197// java_library_host builds and links sources into a `.jar` file for the host.
1198//
1199// A java_library_host has a single variant that produces a `.jar` file containing `.class` files that were
1200// compiled against the host bootclasspath.
1201func LibraryHostFactory() android.Module {
1202	module := &Library{}
1203
1204	module.addHostProperties()
1205
1206	module.Module.properties.Installable = proptools.BoolPtr(true)
1207
1208	android.InitApexModule(module)
1209	InitJavaModule(module, android.HostSupported)
1210	return module
1211}
1212
1213//
1214// Java Tests
1215//
1216
1217// Test option struct.
1218type TestOptions struct {
1219	android.CommonTestOptions
1220
1221	// a list of extra test configuration files that should be installed with the module.
1222	Extra_test_configs []string `android:"path,arch_variant"`
1223
1224	// Extra <option> tags to add to the auto generated test xml file. The "key"
1225	// is optional in each of these.
1226	Tradefed_options []tradefed.Option
1227
1228	// Extra <option> tags to add to the auto generated test xml file under the test runner, e.g., AndroidJunitTest.
1229	// The "key" is optional in each of these.
1230	Test_runner_options []tradefed.Option
1231}
1232
1233type testProperties struct {
1234	// list of compatibility suites (for example "cts", "vts") that the module should be
1235	// installed into.
1236	Test_suites []string `android:"arch_variant"`
1237
1238	// the name of the test configuration (for example "AndroidTest.xml") that should be
1239	// installed with the module.
1240	Test_config *string `android:"path,arch_variant"`
1241
1242	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
1243	// should be installed with the module.
1244	Test_config_template *string `android:"path,arch_variant"`
1245
1246	// list of files or filegroup modules that provide data that should be installed alongside
1247	// the test
1248	Data []string `android:"path"`
1249
1250	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
1251	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
1252	// explicitly.
1253	Auto_gen_config *bool
1254
1255	// Add parameterized mainline modules to auto generated test config. The options will be
1256	// handled by TradeFed to do downloading and installing the specified modules on the device.
1257	Test_mainline_modules []string
1258
1259	// Test options.
1260	Test_options TestOptions
1261
1262	// Names of modules containing JNI libraries that should be installed alongside the test.
1263	Jni_libs []string
1264
1265	// Install the test into a folder named for the module in all test suites.
1266	Per_testcase_directory *bool
1267}
1268
1269type hostTestProperties struct {
1270	// list of native binary modules that should be installed alongside the test
1271	Data_native_bins []string `android:"arch_variant"`
1272
1273	// list of device binary modules that should be installed alongside the test
1274	// This property only adds the first variant of the dependency
1275	Data_device_bins_first []string `android:"arch_variant"`
1276
1277	// list of device binary modules that should be installed alongside the test
1278	// This property adds 64bit AND 32bit variants of the dependency
1279	Data_device_bins_both []string `android:"arch_variant"`
1280
1281	// list of device binary modules that should be installed alongside the test
1282	// This property only adds 64bit variants of the dependency
1283	Data_device_bins_64 []string `android:"arch_variant"`
1284
1285	// list of device binary modules that should be installed alongside the test
1286	// This property adds 32bit variants of the dependency if available, or else
1287	// defaults to the 64bit variant
1288	Data_device_bins_prefer32 []string `android:"arch_variant"`
1289
1290	// list of device binary modules that should be installed alongside the test
1291	// This property only adds 32bit variants of the dependency
1292	Data_device_bins_32 []string `android:"arch_variant"`
1293}
1294
1295type testHelperLibraryProperties struct {
1296	// list of compatibility suites (for example "cts", "vts") that the module should be
1297	// installed into.
1298	Test_suites []string `android:"arch_variant"`
1299
1300	// Install the test into a folder named for the module in all test suites.
1301	Per_testcase_directory *bool
1302}
1303
1304type prebuiltTestProperties struct {
1305	// list of compatibility suites (for example "cts", "vts") that the module should be
1306	// installed into.
1307	Test_suites []string `android:"arch_variant"`
1308
1309	// the name of the test configuration (for example "AndroidTest.xml") that should be
1310	// installed with the module.
1311	Test_config *string `android:"path,arch_variant"`
1312}
1313
1314type Test struct {
1315	Library
1316
1317	testProperties testProperties
1318
1319	testConfig       android.Path
1320	extraTestConfigs android.Paths
1321	data             android.Paths
1322}
1323
1324type TestHost struct {
1325	Test
1326
1327	testHostProperties hostTestProperties
1328}
1329
1330type TestHelperLibrary struct {
1331	Library
1332
1333	testHelperLibraryProperties testHelperLibraryProperties
1334}
1335
1336type JavaTestImport struct {
1337	Import
1338
1339	prebuiltTestProperties prebuiltTestProperties
1340
1341	testConfig android.Path
1342	dexJarFile android.Path
1343}
1344
1345func (j *Test) InstallInTestcases() bool {
1346	// Host java tests install into $(HOST_OUT_JAVA_LIBRARIES), and then are copied into
1347	// testcases by base_rules.mk.
1348	return !j.Host()
1349}
1350
1351func (j *TestHelperLibrary) InstallInTestcases() bool {
1352	return true
1353}
1354
1355func (j *JavaTestImport) InstallInTestcases() bool {
1356	return true
1357}
1358
1359func (j *TestHost) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool {
1360	return ctx.DeviceConfig().NativeCoverageEnabled()
1361}
1362
1363func (j *TestHost) addDataDeviceBinsDeps(ctx android.BottomUpMutatorContext) {
1364	if len(j.testHostProperties.Data_device_bins_first) > 0 {
1365		deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
1366		ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_first...)
1367	}
1368
1369	var maybeAndroid32Target *android.Target
1370	var maybeAndroid64Target *android.Target
1371	android32TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib32")
1372	android64TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib64")
1373	if len(android32TargetList) > 0 {
1374		maybeAndroid32Target = &android32TargetList[0]
1375	}
1376	if len(android64TargetList) > 0 {
1377		maybeAndroid64Target = &android64TargetList[0]
1378	}
1379
1380	if len(j.testHostProperties.Data_device_bins_both) > 0 {
1381		if maybeAndroid32Target == nil && maybeAndroid64Target == nil {
1382			ctx.PropertyErrorf("data_device_bins_both", "no device targets available. Targets: %q", ctx.Config().Targets)
1383			return
1384		}
1385		if maybeAndroid32Target != nil {
1386			ctx.AddFarVariationDependencies(
1387				maybeAndroid32Target.Variations(),
1388				dataDeviceBinsTag,
1389				j.testHostProperties.Data_device_bins_both...,
1390			)
1391		}
1392		if maybeAndroid64Target != nil {
1393			ctx.AddFarVariationDependencies(
1394				maybeAndroid64Target.Variations(),
1395				dataDeviceBinsTag,
1396				j.testHostProperties.Data_device_bins_both...,
1397			)
1398		}
1399	}
1400
1401	if len(j.testHostProperties.Data_device_bins_prefer32) > 0 {
1402		if maybeAndroid32Target != nil {
1403			ctx.AddFarVariationDependencies(
1404				maybeAndroid32Target.Variations(),
1405				dataDeviceBinsTag,
1406				j.testHostProperties.Data_device_bins_prefer32...,
1407			)
1408		} else {
1409			if maybeAndroid64Target == nil {
1410				ctx.PropertyErrorf("data_device_bins_prefer32", "no device targets available. Targets: %q", ctx.Config().Targets)
1411				return
1412			}
1413			ctx.AddFarVariationDependencies(
1414				maybeAndroid64Target.Variations(),
1415				dataDeviceBinsTag,
1416				j.testHostProperties.Data_device_bins_prefer32...,
1417			)
1418		}
1419	}
1420
1421	if len(j.testHostProperties.Data_device_bins_32) > 0 {
1422		if maybeAndroid32Target == nil {
1423			ctx.PropertyErrorf("data_device_bins_32", "cannot find 32bit device target. Targets: %q", ctx.Config().Targets)
1424			return
1425		}
1426		deviceVariations := maybeAndroid32Target.Variations()
1427		ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_32...)
1428	}
1429
1430	if len(j.testHostProperties.Data_device_bins_64) > 0 {
1431		if maybeAndroid64Target == nil {
1432			ctx.PropertyErrorf("data_device_bins_64", "cannot find 64bit device target. Targets: %q", ctx.Config().Targets)
1433			return
1434		}
1435		deviceVariations := maybeAndroid64Target.Variations()
1436		ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_64...)
1437	}
1438}
1439
1440func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) {
1441	if len(j.testHostProperties.Data_native_bins) > 0 {
1442		for _, target := range ctx.MultiTargets() {
1443			ctx.AddVariationDependencies(target.Variations(), dataNativeBinsTag, j.testHostProperties.Data_native_bins...)
1444		}
1445	}
1446
1447	if len(j.testProperties.Jni_libs) > 0 {
1448		for _, target := range ctx.MultiTargets() {
1449			sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
1450			ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, j.testProperties.Jni_libs...)
1451		}
1452	}
1453
1454	j.addDataDeviceBinsDeps(ctx)
1455	j.deps(ctx)
1456}
1457
1458func (j *TestHost) AddExtraResource(p android.Path) {
1459	j.extraResources = append(j.extraResources, p)
1460}
1461
1462func (j *TestHost) dataDeviceBins() []string {
1463	ret := make([]string, 0,
1464		len(j.testHostProperties.Data_device_bins_first)+
1465			len(j.testHostProperties.Data_device_bins_both)+
1466			len(j.testHostProperties.Data_device_bins_prefer32)+
1467			len(j.testHostProperties.Data_device_bins_32)+
1468			len(j.testHostProperties.Data_device_bins_64),
1469	)
1470
1471	ret = append(ret, j.testHostProperties.Data_device_bins_first...)
1472	ret = append(ret, j.testHostProperties.Data_device_bins_both...)
1473	ret = append(ret, j.testHostProperties.Data_device_bins_prefer32...)
1474	ret = append(ret, j.testHostProperties.Data_device_bins_32...)
1475	ret = append(ret, j.testHostProperties.Data_device_bins_64...)
1476
1477	return ret
1478}
1479
1480func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1481	var configs []tradefed.Config
1482	dataDeviceBins := j.dataDeviceBins()
1483	if len(dataDeviceBins) > 0 {
1484		// add Tradefed configuration to push device bins to device for testing
1485		remoteDir := filepath.Join("/data/local/tests/unrestricted/", j.Name())
1486		options := []tradefed.Option{{Name: "cleanup", Value: "true"}}
1487		for _, bin := range dataDeviceBins {
1488			fullPath := filepath.Join(remoteDir, bin)
1489			options = append(options, tradefed.Option{Name: "push-file", Key: bin, Value: fullPath})
1490		}
1491		configs = append(configs, tradefed.Object{
1492			Type:    "target_preparer",
1493			Class:   "com.android.tradefed.targetprep.PushFilePreparer",
1494			Options: options,
1495		})
1496	}
1497
1498	j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
1499	android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
1500	android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
1501		InstalledFiles:      j.data,
1502		OutputFile:          j.outputFile,
1503		TestConfig:          j.testConfig,
1504		RequiredModuleNames: j.RequiredModuleNames(),
1505		TestSuites:          j.testProperties.Test_suites,
1506		IsHost:              true,
1507		LocalSdkVersion:     j.sdkVersion.String(),
1508		IsUnitTest:          Bool(j.testProperties.Test_options.Unit_test),
1509	})
1510}
1511
1512func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1513	j.generateAndroidBuildActionsWithConfig(ctx, nil)
1514	android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
1515}
1516
1517func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) {
1518	if j.testProperties.Test_options.Unit_test == nil && ctx.Host() {
1519		// TODO(b/): Clean temporary heuristic to avoid unexpected onboarding.
1520		defaultUnitTest := !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites)
1521		j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest)
1522	}
1523	j.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
1524		TestConfigProp:          j.testProperties.Test_config,
1525		TestConfigTemplateProp:  j.testProperties.Test_config_template,
1526		TestSuites:              j.testProperties.Test_suites,
1527		Config:                  configs,
1528		OptionsForAutogenerated: j.testProperties.Test_options.Tradefed_options,
1529		TestRunnerOptions:       j.testProperties.Test_options.Test_runner_options,
1530		AutoGenConfig:           j.testProperties.Auto_gen_config,
1531		UnitTest:                j.testProperties.Test_options.Unit_test,
1532		DeviceTemplate:          "${JavaTestConfigTemplate}",
1533		HostTemplate:            "${JavaHostTestConfigTemplate}",
1534		HostUnitTestTemplate:    "${JavaHostUnitTestConfigTemplate}",
1535	})
1536
1537	j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
1538
1539	j.extraTestConfigs = android.PathsForModuleSrc(ctx, j.testProperties.Test_options.Extra_test_configs)
1540
1541	ctx.VisitDirectDepsWithTag(dataNativeBinsTag, func(dep android.Module) {
1542		j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
1543	})
1544
1545	ctx.VisitDirectDepsWithTag(dataDeviceBinsTag, func(dep android.Module) {
1546		j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
1547	})
1548
1549	ctx.VisitDirectDepsWithTag(jniLibTag, func(dep android.Module) {
1550		sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider)
1551		if sharedLibInfo.SharedLibrary != nil {
1552			// Copy to an intermediate output directory to append "lib[64]" to the path,
1553			// so that it's compatible with the default rpath values.
1554			var relPath string
1555			if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
1556				relPath = filepath.Join("lib64", sharedLibInfo.SharedLibrary.Base())
1557			} else {
1558				relPath = filepath.Join("lib", sharedLibInfo.SharedLibrary.Base())
1559			}
1560			relocatedLib := android.PathForModuleOut(ctx, "relocated").Join(ctx, relPath)
1561			ctx.Build(pctx, android.BuildParams{
1562				Rule:   android.Cp,
1563				Input:  sharedLibInfo.SharedLibrary,
1564				Output: relocatedLib,
1565			})
1566			j.data = append(j.data, relocatedLib)
1567		} else {
1568			ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
1569		}
1570	})
1571
1572	j.Library.GenerateAndroidBuildActions(ctx)
1573}
1574
1575func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1576	j.Library.GenerateAndroidBuildActions(ctx)
1577}
1578
1579func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1580	j.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
1581		TestConfigProp:       j.prebuiltTestProperties.Test_config,
1582		TestSuites:           j.prebuiltTestProperties.Test_suites,
1583		DeviceTemplate:       "${JavaTestConfigTemplate}",
1584		HostTemplate:         "${JavaHostTestConfigTemplate}",
1585		HostUnitTestTemplate: "${JavaHostUnitTestConfigTemplate}",
1586	})
1587
1588	j.Import.GenerateAndroidBuildActions(ctx)
1589}
1590
1591type testSdkMemberType struct {
1592	android.SdkMemberTypeBase
1593}
1594
1595func (mt *testSdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
1596	ctx.AddVariationDependencies(nil, dependencyTag, names...)
1597}
1598
1599func (mt *testSdkMemberType) IsInstance(module android.Module) bool {
1600	_, ok := module.(*Test)
1601	return ok
1602}
1603
1604func (mt *testSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
1605	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_test_import")
1606}
1607
1608func (mt *testSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
1609	return &testSdkMemberProperties{}
1610}
1611
1612type testSdkMemberProperties struct {
1613	android.SdkMemberPropertiesBase
1614
1615	JarToExport android.Path
1616	TestConfig  android.Path
1617}
1618
1619func (p *testSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
1620	test := variant.(*Test)
1621
1622	implementationJars := test.ImplementationJars()
1623	if len(implementationJars) != 1 {
1624		panic(fmt.Errorf("there must be only one implementation jar from %q", test.Name()))
1625	}
1626
1627	p.JarToExport = implementationJars[0]
1628	p.TestConfig = test.testConfig
1629}
1630
1631func (p *testSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
1632	builder := ctx.SnapshotBuilder()
1633
1634	exportedJar := p.JarToExport
1635	if exportedJar != nil {
1636		snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(ctx, p.OsPrefix(), ctx.Name())
1637		builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
1638
1639		propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
1640	}
1641
1642	testConfig := p.TestConfig
1643	if testConfig != nil {
1644		snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.OsPrefix(), ctx.Name(), testConfigSuffix)
1645		builder.CopyToSnapshot(testConfig, snapshotRelativeTestConfigPath)
1646		propertySet.AddProperty("test_config", snapshotRelativeTestConfigPath)
1647	}
1648}
1649
1650// java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and
1651// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
1652//
1653// By default, a java_test has a single variant that produces a `.jar` file containing `classes.dex` files that were
1654// compiled against the device bootclasspath.
1655//
1656// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
1657// compiled against the host bootclasspath.
1658func TestFactory() android.Module {
1659	module := &Test{}
1660
1661	module.addHostAndDeviceProperties()
1662	module.AddProperties(&module.testProperties)
1663
1664	module.Module.properties.Installable = proptools.BoolPtr(true)
1665	module.Module.dexpreopter.isTest = true
1666	module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
1667	module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
1668	module.Module.sourceProperties.Top_level_test_target = true
1669
1670	InitJavaModule(module, android.HostAndDeviceSupported)
1671	return module
1672}
1673
1674// java_test_helper_library creates a java library and makes sure that it is added to the appropriate test suite.
1675func TestHelperLibraryFactory() android.Module {
1676	module := &TestHelperLibrary{}
1677
1678	module.addHostAndDeviceProperties()
1679	module.AddProperties(&module.testHelperLibraryProperties)
1680
1681	module.Module.properties.Installable = proptools.BoolPtr(true)
1682	module.Module.dexpreopter.isTest = true
1683	module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
1684	module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
1685
1686	InitJavaModule(module, android.HostAndDeviceSupported)
1687	return module
1688}
1689
1690// java_test_import imports one or more `.jar` files into the build graph as if they were built by a java_test module
1691// and makes sure that it is added to the appropriate test suite.
1692//
1693// By default, a java_test_import has a single variant that expects a `.jar` file containing `.class` files that were
1694// compiled against an Android classpath.
1695//
1696// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1697// for host modules.
1698func JavaTestImportFactory() android.Module {
1699	module := &JavaTestImport{}
1700
1701	module.AddProperties(
1702		&module.Import.properties,
1703		&module.prebuiltTestProperties)
1704
1705	module.Import.properties.Installable = proptools.BoolPtr(true)
1706
1707	android.InitPrebuiltModule(module, &module.properties.Jars)
1708	android.InitApexModule(module)
1709	InitJavaModule(module, android.HostAndDeviceSupported)
1710	return module
1711}
1712
1713// java_test_host builds a and links sources into a `.jar` file for the host, and creates an `AndroidTest.xml` file to
1714// allow running the test with `atest` or a `TEST_MAPPING` file.
1715//
1716// A java_test_host has a single variant that produces a `.jar` file containing `.class` files that were
1717// compiled against the host bootclasspath.
1718func TestHostFactory() android.Module {
1719	module := &TestHost{}
1720
1721	module.addHostProperties()
1722	module.AddProperties(&module.testProperties)
1723	module.AddProperties(&module.testHostProperties)
1724
1725	InitTestHost(
1726		module,
1727		proptools.BoolPtr(true),
1728		nil,
1729		nil)
1730
1731	InitJavaModuleMultiTargets(module, android.HostSupported)
1732
1733	return module
1734}
1735
1736func InitTestHost(th *TestHost, installable *bool, testSuites []string, autoGenConfig *bool) {
1737	th.properties.Installable = installable
1738	th.testProperties.Auto_gen_config = autoGenConfig
1739	th.testProperties.Test_suites = testSuites
1740	th.sourceProperties.Test_only = proptools.BoolPtr(true)
1741	th.sourceProperties.Top_level_test_target = true
1742}
1743
1744//
1745// Java Binaries (.jar file plus wrapper script)
1746//
1747
1748type binaryProperties struct {
1749	// installable script to execute the resulting jar
1750	Wrapper *string `android:"path,arch_variant"`
1751
1752	// Name of the class containing main to be inserted into the manifest as Main-Class.
1753	Main_class *string
1754
1755	// Names of modules containing JNI libraries that should be installed alongside the host
1756	// variant of the binary.
1757	Jni_libs []string `android:"arch_variant"`
1758}
1759
1760type Binary struct {
1761	Library
1762
1763	binaryProperties binaryProperties
1764
1765	isWrapperVariant bool
1766
1767	wrapperFile android.Path
1768	binaryFile  android.InstallPath
1769}
1770
1771func (j *Binary) HostToolPath() android.OptionalPath {
1772	return android.OptionalPathForPath(j.binaryFile)
1773}
1774
1775func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1776	j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
1777
1778	if ctx.Arch().ArchType == android.Common {
1779		// Compile the jar
1780		if j.binaryProperties.Main_class != nil {
1781			if j.properties.Manifest != nil {
1782				ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
1783			}
1784			manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
1785			GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
1786			j.overrideManifest = android.OptionalPathForPath(manifestFile)
1787		}
1788
1789		j.Library.GenerateAndroidBuildActions(ctx)
1790	} else {
1791		// Handle the binary wrapper
1792		j.isWrapperVariant = true
1793
1794		if j.binaryProperties.Wrapper != nil {
1795			j.wrapperFile = android.PathForModuleSrc(ctx, *j.binaryProperties.Wrapper)
1796		} else {
1797			if ctx.Windows() {
1798				ctx.PropertyErrorf("wrapper", "wrapper is required for Windows")
1799			}
1800
1801			if ctx.Device() {
1802				// device binary should have a main_class property if it does not
1803				// have a specific wrapper, so that a default wrapper can
1804				// be generated for it.
1805				if j.binaryProperties.Main_class == nil {
1806					ctx.PropertyErrorf("main_class", "main_class property "+
1807						"is required for device binary if no default wrapper is assigned")
1808				} else {
1809					wrapper := android.PathForModuleOut(ctx, ctx.ModuleName()+".sh")
1810					jarName := j.Stem() + ".jar"
1811					partition := j.PartitionTag(ctx.DeviceConfig())
1812					ctx.Build(pctx, android.BuildParams{
1813						Rule:   deviceBinaryWrapper,
1814						Output: wrapper,
1815						Args: map[string]string{
1816							"jar_name":   jarName,
1817							"partition":  partition,
1818							"main_class": String(j.binaryProperties.Main_class),
1819						},
1820					})
1821					j.wrapperFile = wrapper
1822				}
1823			} else {
1824				j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
1825			}
1826		}
1827
1828		ext := ""
1829		if ctx.Windows() {
1830			ext = ".bat"
1831		}
1832
1833		// The host installation rules make the installed wrapper depend on all the dependencies
1834		// of the wrapper variant, which will include the common variant's jar file and any JNI
1835		// libraries.  This is verified by TestBinary.
1836		j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
1837			ctx.ModuleName()+ext, j.wrapperFile)
1838	}
1839}
1840
1841func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
1842	if ctx.Arch().ArchType == android.Common {
1843		j.deps(ctx)
1844	}
1845	if ctx.Arch().ArchType != android.Common {
1846		// These dependencies ensure the host installation rules will install the jar file and
1847		// the jni libraries when the wrapper is installed.
1848		ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
1849		ctx.AddVariationDependencies(
1850			[]blueprint.Variation{{Mutator: "arch", Variation: android.CommonArch.String()}},
1851			binaryInstallTag, ctx.ModuleName())
1852	}
1853}
1854
1855// java_binary builds a `.jar` file and a shell script that executes it for the device, and possibly for the host
1856// as well.
1857//
1858// By default, a java_binary has a single variant that produces a `.jar` file containing `classes.dex` files that were
1859// compiled against the device bootclasspath.
1860//
1861// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
1862// compiled against the host bootclasspath.
1863func BinaryFactory() android.Module {
1864	module := &Binary{}
1865
1866	module.addHostAndDeviceProperties()
1867	module.AddProperties(&module.binaryProperties, &module.sourceProperties)
1868
1869	module.Module.properties.Installable = proptools.BoolPtr(true)
1870
1871	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst)
1872	android.InitDefaultableModule(module)
1873
1874	return module
1875}
1876
1877// java_binary_host builds a `.jar` file and a shell script that executes it for the host.
1878//
1879// A java_binary_host has a single variant that produces a `.jar` file containing `.class` files that were
1880// compiled against the host bootclasspath.
1881func BinaryHostFactory() android.Module {
1882	module := &Binary{}
1883
1884	module.addHostProperties()
1885	module.AddProperties(&module.binaryProperties)
1886
1887	module.Module.properties.Installable = proptools.BoolPtr(true)
1888
1889	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst)
1890	android.InitDefaultableModule(module)
1891	return module
1892}
1893
1894type JavaApiContribution struct {
1895	android.ModuleBase
1896	android.DefaultableModuleBase
1897	embeddableInModuleAndImport
1898
1899	properties struct {
1900		// name of the API surface
1901		Api_surface *string
1902
1903		// relative path to the API signature text file
1904		Api_file *string `android:"path"`
1905	}
1906}
1907
1908func ApiContributionFactory() android.Module {
1909	module := &JavaApiContribution{}
1910	android.InitAndroidModule(module)
1911	android.InitDefaultableModule(module)
1912	module.AddProperties(&module.properties)
1913	module.initModuleAndImport(module)
1914	return module
1915}
1916
1917type JavaApiImportInfo struct {
1918	ApiFile    android.Path
1919	ApiSurface string
1920}
1921
1922var JavaApiImportProvider = blueprint.NewProvider[JavaApiImportInfo]()
1923
1924func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1925	var apiFile android.Path = nil
1926	if apiFileString := ap.properties.Api_file; apiFileString != nil {
1927		apiFile = android.PathForModuleSrc(ctx, String(apiFileString))
1928	}
1929
1930	android.SetProvider(ctx, JavaApiImportProvider, JavaApiImportInfo{
1931		ApiFile:    apiFile,
1932		ApiSurface: proptools.String(ap.properties.Api_surface),
1933	})
1934}
1935
1936type ApiLibrary struct {
1937	android.ModuleBase
1938	android.DefaultableModuleBase
1939
1940	hiddenAPI
1941	dexer
1942	embeddableInModuleAndImport
1943
1944	properties JavaApiLibraryProperties
1945
1946	stubsSrcJar               android.WritablePath
1947	stubsJar                  android.WritablePath
1948	stubsJarWithoutStaticLibs android.WritablePath
1949	extractedSrcJar           android.WritablePath
1950	// .dex of stubs, used for hiddenapi processing
1951	dexJarFile OptionalDexJarPath
1952
1953	validationPaths android.Paths
1954
1955	stubsType StubsType
1956
1957	aconfigProtoFiles android.Paths
1958}
1959
1960type JavaApiLibraryProperties struct {
1961	// name of the API surface
1962	Api_surface *string
1963
1964	// list of Java API contribution modules that consists this API surface
1965	// This is a list of Soong modules
1966	Api_contributions []string
1967
1968	// List of flags to be passed to the javac compiler to generate jar file
1969	Javacflags []string
1970
1971	// List of shared java libs that this module has dependencies to and
1972	// should be passed as classpath in javac invocation
1973	Libs []string
1974
1975	// List of java libs that this module has static dependencies to and will be
1976	// merge zipped after metalava invocation
1977	Static_libs []string
1978
1979	// Java Api library to provide the full API surface stub jar file.
1980	// If this property is set, the stub jar of this module is created by
1981	// extracting the compiled class files provided by the
1982	// full_api_surface_stub module.
1983	Full_api_surface_stub *string
1984
1985	// Version of previously released API file for compatibility check.
1986	Previous_api *string `android:"path"`
1987
1988	// java_system_modules module providing the jar to be added to the
1989	// bootclasspath when compiling the stubs.
1990	// The jar will also be passed to metalava as a classpath to
1991	// generate compilable stubs.
1992	System_modules *string
1993
1994	// If true, the module runs validation on the API signature files provided
1995	// by the modules passed via api_contributions by checking if the files are
1996	// in sync with the source Java files. However, the environment variable
1997	// DISABLE_STUB_VALIDATION has precedence over this property.
1998	Enable_validation *bool
1999
2000	// Type of stubs the module should generate. Must be one of "everything", "runtime" or
2001	// "exportable". Defaults to "everything".
2002	// - "everything" stubs include all non-flagged apis and flagged apis, regardless of the state
2003	// of the flag.
2004	// - "runtime" stubs include all non-flagged apis and flagged apis that are ENABLED or
2005	// READ_WRITE, and all other flagged apis are stripped.
2006	// - "exportable" stubs include all non-flagged apis and flagged apis that are ENABLED and
2007	// READ_ONLY, and all other flagged apis are stripped.
2008	Stubs_type *string
2009
2010	// List of aconfig_declarations module names that the stubs generated in this module
2011	// depend on.
2012	Aconfig_declarations []string
2013}
2014
2015func ApiLibraryFactory() android.Module {
2016	module := &ApiLibrary{}
2017	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
2018	module.AddProperties(&module.properties)
2019	module.initModuleAndImport(module)
2020	android.InitDefaultableModule(module)
2021	return module
2022}
2023
2024func (al *ApiLibrary) ApiSurface() *string {
2025	return al.properties.Api_surface
2026}
2027
2028func (al *ApiLibrary) StubsJar() android.Path {
2029	return al.stubsJar
2030}
2031
2032func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
2033	srcs android.Paths, homeDir android.WritablePath,
2034	classpath android.Paths) *android.RuleBuilderCommand {
2035	rule.Command().Text("rm -rf").Flag(homeDir.String())
2036	rule.Command().Text("mkdir -p").Flag(homeDir.String())
2037
2038	cmd := rule.Command()
2039	cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
2040
2041	if metalavaUseRbe(ctx) {
2042		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
2043		execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
2044		labels := map[string]string{"type": "tool", "name": "metalava"}
2045
2046		pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
2047		rule.Rewrapper(&remoteexec.REParams{
2048			Labels:          labels,
2049			ExecStrategy:    execStrategy,
2050			ToolchainInputs: []string{config.JavaCmd(ctx).String()},
2051			Platform:        map[string]string{remoteexec.PoolKey: pool},
2052		})
2053	}
2054
2055	cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
2056		Flag(config.JavacVmFlags).
2057		Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
2058		FlagWithInputList("--source-files ", srcs, " ")
2059
2060	cmd.Flag("--color").
2061		Flag("--quiet").
2062		Flag("--include-annotations").
2063		// The flag makes nullability issues as warnings rather than errors by replacing
2064		// @Nullable/@NonNull in the listed packages APIs with @RecentlyNullable/@RecentlyNonNull,
2065		// and these packages are meant to have everything annotated
2066		// @RecentlyNullable/@RecentlyNonNull.
2067		FlagWithArg("--force-convert-to-warning-nullability-annotations ", "+*:-android.*:+android.icu.*:-dalvik.*").
2068		FlagWithArg("--repeat-errors-max ", "10").
2069		FlagWithArg("--hide ", "UnresolvedImport").
2070		FlagWithArg("--hide ", "InvalidNullabilityOverride").
2071		FlagWithArg("--hide ", "ChangedDefault")
2072
2073	if len(classpath) == 0 {
2074		// The main purpose of the `--api-class-resolution api` option is to force metalava to ignore
2075		// classes on the classpath when an API file contains missing classes. However, as this command
2076		// does not specify `--classpath` this is not needed for that. However, this is also used as a
2077		// signal to the special metalava code for generating stubs from text files that it needs to add
2078		// some additional items into the API (e.g. default constructors).
2079		cmd.FlagWithArg("--api-class-resolution ", "api")
2080	} else {
2081		cmd.FlagWithArg("--api-class-resolution ", "api:classpath")
2082		cmd.FlagWithInputList("--classpath ", classpath, ":")
2083	}
2084
2085	return cmd
2086}
2087
2088func (al *ApiLibrary) HeaderJars() android.Paths {
2089	return android.Paths{al.stubsJar}
2090}
2091
2092func (al *ApiLibrary) OutputDirAndDeps() (android.Path, android.Paths) {
2093	return nil, nil
2094}
2095
2096func (al *ApiLibrary) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
2097	if stubsDir.Valid() {
2098		cmd.FlagWithArg("--stubs ", stubsDir.String())
2099	}
2100}
2101
2102func (al *ApiLibrary) addValidation(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, validationPaths android.Paths) {
2103	for _, validationPath := range validationPaths {
2104		cmd.Validation(validationPath)
2105	}
2106}
2107
2108// This method extracts the stub class files from the stub jar file provided
2109// from full_api_surface_stub module instead of compiling the srcjar generated from invoking metalava.
2110// This method is used because metalava can generate compilable from-text stubs only when
2111// the codebase encompasses all classes listed in the input API text file, and a class can extend
2112// a class that is not within the same API domain.
2113func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, fullApiSurfaceStubJar android.Path) {
2114	classFilesList := android.PathForModuleOut(ctx, "metalava", "classes.txt")
2115	unzippedSrcJarDir := android.PathForModuleOut(ctx, "metalava", "unzipDir")
2116
2117	rule.Command().
2118		BuiltTool("list_files").
2119		Text(stubsDir.String()).
2120		FlagWithOutput("--out ", classFilesList).
2121		FlagWithArg("--extensions ", ".java").
2122		FlagWithArg("--root ", unzippedSrcJarDir.String()).
2123		Flag("--classes")
2124
2125	rule.Command().
2126		Text("unzip").
2127		Flag("-q").
2128		Input(fullApiSurfaceStubJar).
2129		FlagWithArg("-d ", unzippedSrcJarDir.String())
2130
2131	rule.Command().
2132		BuiltTool("soong_zip").
2133		Flag("-jar").
2134		Flag("-write_if_changed").
2135		Flag("-ignore_missing_files").
2136		Flag("-quiet").
2137		FlagWithArg("-C ", unzippedSrcJarDir.String()).
2138		FlagWithInput("-l ", classFilesList).
2139		FlagWithOutput("-o ", al.stubsJarWithoutStaticLibs)
2140}
2141
2142func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
2143	apiContributions := al.properties.Api_contributions
2144	addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") &&
2145		!ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") &&
2146		proptools.BoolDefault(al.properties.Enable_validation, true)
2147	for _, apiContributionName := range apiContributions {
2148		ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
2149
2150		// Add the java_api_contribution module generating droidstubs module
2151		// as dependency when validation adding conditions are met and
2152		// the java_api_contribution module name has ".api.contribution" suffix.
2153		// All droidstubs-generated modules possess the suffix in the name,
2154		// but there is no such guarantee for tests.
2155		if addValidations {
2156			if strings.HasSuffix(apiContributionName, ".api.contribution") {
2157				ctx.AddDependency(ctx.Module(), metalavaCurrentApiTimestampTag, strings.TrimSuffix(apiContributionName, ".api.contribution"))
2158			} else {
2159				ctx.ModuleErrorf("Validation is enabled for module %s but a "+
2160					"current timestamp provider is not found for the api "+
2161					"contribution %s",
2162					ctx.ModuleName(),
2163					apiContributionName,
2164				)
2165			}
2166		}
2167	}
2168	ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...)
2169	ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...)
2170	if al.properties.Full_api_surface_stub != nil {
2171		ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Full_api_surface_stub))
2172	}
2173	if al.properties.System_modules != nil {
2174		ctx.AddVariationDependencies(nil, systemModulesTag, String(al.properties.System_modules))
2175	}
2176	for _, aconfigDeclarationsName := range al.properties.Aconfig_declarations {
2177		ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationsName)
2178	}
2179}
2180
2181// Map where key is the api scope name and value is the int value
2182// representing the order of the api scope, narrowest to the widest
2183var scopeOrderMap = AllApiScopes.MapToIndex(
2184	func(s *apiScope) string { return s.name })
2185
2186func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo {
2187	for _, srcFileInfo := range srcFilesInfo {
2188		if srcFileInfo.ApiSurface == "" {
2189			ctx.ModuleErrorf("Api surface not defined for the associated api file %s", srcFileInfo.ApiFile)
2190		}
2191	}
2192	sort.Slice(srcFilesInfo, func(i, j int) bool {
2193		return scopeOrderMap[srcFilesInfo[i].ApiSurface] < scopeOrderMap[srcFilesInfo[j].ApiSurface]
2194	})
2195
2196	return srcFilesInfo
2197}
2198
2199var validstubsType = []StubsType{Everything, Runtime, Exportable}
2200
2201func (al *ApiLibrary) validateProperties(ctx android.ModuleContext) {
2202	if al.properties.Stubs_type == nil {
2203		ctx.ModuleErrorf("java_api_library module type must specify stubs_type property.")
2204	} else {
2205		al.stubsType = StringToStubsType(proptools.String(al.properties.Stubs_type))
2206	}
2207
2208	if !android.InList(al.stubsType, validstubsType) {
2209		ctx.PropertyErrorf("stubs_type", "%s is not a valid stubs_type property value. "+
2210			"Must be one of %s.", proptools.String(al.properties.Stubs_type), validstubsType)
2211	}
2212}
2213
2214func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2215	al.validateProperties(ctx)
2216
2217	rule := android.NewRuleBuilder(pctx, ctx)
2218
2219	rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
2220		android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
2221		SandboxInputs()
2222
2223	stubsDir := android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
2224	rule.Command().Text("rm -rf").Text(stubsDir.String())
2225	rule.Command().Text("mkdir -p").Text(stubsDir.String())
2226
2227	homeDir := android.PathForModuleOut(ctx, "metalava", "home")
2228
2229	var srcFilesInfo []JavaApiImportInfo
2230	var classPaths android.Paths
2231	var staticLibs android.Paths
2232	var depApiSrcsStubsJar android.Path
2233	var systemModulesPaths android.Paths
2234	ctx.VisitDirectDeps(func(dep android.Module) {
2235		tag := ctx.OtherModuleDependencyTag(dep)
2236		switch tag {
2237		case javaApiContributionTag:
2238			provider, _ := android.OtherModuleProvider(ctx, dep, JavaApiImportProvider)
2239			if provider.ApiFile == nil && !ctx.Config().AllowMissingDependencies() {
2240				ctx.ModuleErrorf("Error: %s has an empty api file.", dep.Name())
2241			}
2242			srcFilesInfo = append(srcFilesInfo, provider)
2243		case libTag:
2244			provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
2245			classPaths = append(classPaths, provider.HeaderJars...)
2246		case staticLibTag:
2247			provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
2248			staticLibs = append(staticLibs, provider.HeaderJars...)
2249		case depApiSrcsTag:
2250			provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
2251			depApiSrcsStubsJar = provider.HeaderJars[0]
2252		case systemModulesTag:
2253			module := dep.(SystemModulesProvider)
2254			systemModulesPaths = append(systemModulesPaths, module.HeaderJars()...)
2255		case metalavaCurrentApiTimestampTag:
2256			if currentApiTimestampProvider, ok := dep.(currentApiTimestampProvider); ok {
2257				al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp())
2258			}
2259		case aconfigDeclarationTag:
2260			if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
2261				al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPath)
2262			} else if provider, ok := android.OtherModuleProvider(ctx, dep, android.CodegenInfoProvider); ok {
2263				al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPaths...)
2264			} else {
2265				ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+
2266					"module type is allowed for flags_packages property, but %s is neither "+
2267					"of these supported module types",
2268					dep.Name(),
2269				)
2270			}
2271		}
2272	})
2273
2274	srcFilesInfo = al.sortApiFilesByApiScope(ctx, srcFilesInfo)
2275	var srcFiles android.Paths
2276	for _, srcFileInfo := range srcFilesInfo {
2277		srcFiles = append(srcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String()))
2278	}
2279
2280	if srcFiles == nil && !ctx.Config().AllowMissingDependencies() {
2281		ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
2282	}
2283
2284	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, systemModulesPaths)
2285
2286	al.stubsFlags(ctx, cmd, stubsDir)
2287
2288	migratingNullability := String(al.properties.Previous_api) != ""
2289	if migratingNullability {
2290		previousApi := android.PathForModuleSrc(ctx, String(al.properties.Previous_api))
2291		cmd.FlagWithInput("--migrate-nullness ", previousApi)
2292	}
2293
2294	al.addValidation(ctx, cmd, al.validationPaths)
2295
2296	generateRevertAnnotationArgs(ctx, cmd, al.stubsType, al.aconfigProtoFiles)
2297
2298	al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
2299	al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar")
2300	al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
2301
2302	if depApiSrcsStubsJar != nil {
2303		al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsJar)
2304	}
2305	rule.Command().
2306		BuiltTool("soong_zip").
2307		Flag("-write_if_changed").
2308		Flag("-jar").
2309		FlagWithOutput("-o ", al.stubsSrcJar).
2310		FlagWithArg("-C ", stubsDir.String()).
2311		FlagWithArg("-D ", stubsDir.String())
2312
2313	rule.Build("metalava", "metalava merged text")
2314
2315	if depApiSrcsStubsJar == nil {
2316		var flags javaBuilderFlags
2317		flags.javaVersion = getStubsJavaVersion()
2318		flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
2319		flags.classpath = classpath(classPaths)
2320		flags.bootClasspath = classpath(systemModulesPaths)
2321
2322		annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar")
2323
2324		TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
2325			android.Paths{al.stubsSrcJar}, annoSrcJar, flags, android.Paths{})
2326	}
2327
2328	builder := android.NewRuleBuilder(pctx, ctx)
2329	builder.Command().
2330		BuiltTool("merge_zips").
2331		Output(al.stubsJar).
2332		Inputs(android.Paths{al.stubsJarWithoutStaticLibs}).
2333		Inputs(staticLibs)
2334	builder.Build("merge_zips", "merge jar files")
2335
2336	// compile stubs to .dex for hiddenapi processing
2337	dexParams := &compileDexParams{
2338		flags:         javaBuilderFlags{},
2339		sdkVersion:    al.SdkVersion(ctx),
2340		minSdkVersion: al.MinSdkVersion(ctx),
2341		classesJar:    al.stubsJar,
2342		jarName:       ctx.ModuleName() + ".jar",
2343	}
2344	dexOutputFile, _ := al.dexer.compileDex(ctx, dexParams)
2345	uncompressed := true
2346	al.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), al.stubsJar, &uncompressed)
2347	dexOutputFile = al.hiddenAPIEncodeDex(ctx, dexOutputFile)
2348	al.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
2349
2350	ctx.Phony(ctx.ModuleName(), al.stubsJar)
2351
2352	android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
2353		HeaderJars:                     android.PathsIfNonNil(al.stubsJar),
2354		ImplementationAndResourcesJars: android.PathsIfNonNil(al.stubsJar),
2355		ImplementationJars:             android.PathsIfNonNil(al.stubsJar),
2356		AidlIncludeDirs:                android.Paths{},
2357		StubsLinkType:                  Stubs,
2358		// No aconfig libraries on api libraries
2359	})
2360}
2361
2362func (al *ApiLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
2363	return al.dexJarFile
2364}
2365
2366func (al *ApiLibrary) DexJarInstallPath() android.Path {
2367	return al.dexJarFile.Path()
2368}
2369
2370func (al *ApiLibrary) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
2371	return nil
2372}
2373
2374// java_api_library constitutes the sdk, and does not build against one
2375func (al *ApiLibrary) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
2376	return android.SdkSpecNone
2377}
2378
2379// java_api_library is always at "current". Return FutureApiLevel
2380func (al *ApiLibrary) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
2381	return android.FutureApiLevel
2382}
2383
2384// implement the following interfaces for hiddenapi processing
2385var _ hiddenAPIModule = (*ApiLibrary)(nil)
2386var _ UsesLibraryDependency = (*ApiLibrary)(nil)
2387
2388//
2389// Java prebuilts
2390//
2391
2392type ImportProperties struct {
2393	Jars []string `android:"path,arch_variant"`
2394
2395	// The version of the SDK that the source prebuilt file was built against. Defaults to the
2396	// current version if not specified.
2397	Sdk_version *string
2398
2399	// The minimum version of the SDK that this module supports. Defaults to sdk_version if not
2400	// specified.
2401	Min_sdk_version *string
2402
2403	// The max sdk version placeholder used to replace maxSdkVersion attributes on permission
2404	// and uses-permission tags in manifest_fixer.
2405	Replace_max_sdk_version_placeholder *string
2406
2407	Installable *bool
2408
2409	// If not empty, classes are restricted to the specified packages and their sub-packages.
2410	Permitted_packages []string
2411
2412	// List of shared java libs that this module has dependencies to
2413	Libs []string
2414
2415	// List of static java libs that this module has dependencies to
2416	Static_libs []string
2417
2418	// List of files to remove from the jar file(s)
2419	Exclude_files []string
2420
2421	// List of directories to remove from the jar file(s)
2422	Exclude_dirs []string
2423
2424	// if set to true, run Jetifier against .jar file. Defaults to false.
2425	Jetifier *bool
2426
2427	// set the name of the output
2428	Stem *string
2429
2430	Aidl struct {
2431		// directories that should be added as include directories for any aidl sources of modules
2432		// that depend on this module, as well as to aidl for this module.
2433		Export_include_dirs []string
2434	}
2435
2436	// Name of the source soong module that gets shadowed by this prebuilt
2437	// If unspecified, follows the naming convention that the source module of
2438	// the prebuilt is Name() without "prebuilt_" prefix
2439	Source_module_name *string
2440
2441	// Non-nil if this java_import module was dynamically created by a java_sdk_library_import
2442	// The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
2443	// (without any prebuilt_ prefix)
2444	Created_by_java_sdk_library_name *string `blueprint:"mutated"`
2445
2446	// Property signifying whether the module provides stubs jar or not.
2447	Is_stubs_module *bool
2448}
2449
2450type Import struct {
2451	android.ModuleBase
2452	android.DefaultableModuleBase
2453	android.ApexModuleBase
2454	prebuilt android.Prebuilt
2455
2456	// Functionality common to Module and Import.
2457	embeddableInModuleAndImport
2458
2459	hiddenAPI
2460	dexer
2461	dexpreopter
2462
2463	properties ImportProperties
2464
2465	// output file containing classes.dex and resources
2466	dexJarFile        OptionalDexJarPath
2467	dexJarFileErr     error
2468	dexJarInstallFile android.Path
2469
2470	combinedImplementationFile android.Path
2471	combinedHeaderFile         android.Path
2472	classLoaderContexts        dexpreopt.ClassLoaderContextMap
2473	exportAidlIncludeDirs      android.Paths
2474
2475	hideApexVariantFromMake bool
2476
2477	sdkVersion    android.SdkSpec
2478	minSdkVersion android.ApiLevel
2479
2480	stubsLinkType StubsLinkType
2481}
2482
2483var _ PermittedPackagesForUpdatableBootJars = (*Import)(nil)
2484
2485func (j *Import) PermittedPackagesForUpdatableBootJars() []string {
2486	return j.properties.Permitted_packages
2487}
2488
2489func (j *Import) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
2490	return android.SdkSpecFrom(ctx, String(j.properties.Sdk_version))
2491}
2492
2493func (j *Import) SystemModules() string {
2494	return "none"
2495}
2496
2497func (j *Import) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
2498	if j.properties.Min_sdk_version != nil {
2499		return android.ApiLevelFrom(ctx, *j.properties.Min_sdk_version)
2500	}
2501	return j.SdkVersion(ctx).ApiLevel
2502}
2503
2504func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
2505	if j.properties.Replace_max_sdk_version_placeholder != nil {
2506		return android.ApiLevelFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder)
2507	}
2508	// Default is PrivateApiLevel
2509	return android.SdkSpecPrivate.ApiLevel
2510}
2511
2512func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
2513	return j.SdkVersion(ctx).ApiLevel
2514}
2515
2516func (j *Import) Prebuilt() *android.Prebuilt {
2517	return &j.prebuilt
2518}
2519
2520func (j *Import) PrebuiltSrcs() []string {
2521	return j.properties.Jars
2522}
2523
2524func (j *Import) BaseModuleName() string {
2525	return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
2526}
2527
2528func (j *Import) Name() string {
2529	return j.prebuilt.Name(j.ModuleBase.Name())
2530}
2531
2532func (j *Import) Stem() string {
2533	return proptools.StringDefault(j.properties.Stem, j.BaseModuleName())
2534}
2535
2536func (j *Import) CreatedByJavaSdkLibraryName() *string {
2537	return j.properties.Created_by_java_sdk_library_name
2538}
2539
2540func (a *Import) JacocoReportClassesFile() android.Path {
2541	return nil
2542}
2543
2544func (j *Import) LintDepSets() LintDepSets {
2545	return LintDepSets{}
2546}
2547
2548func (j *Import) getStrictUpdatabilityLinting() bool {
2549	return false
2550}
2551
2552func (j *Import) setStrictUpdatabilityLinting(bool) {
2553}
2554
2555func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
2556	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
2557	ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
2558
2559	if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
2560		sdkDeps(ctx, android.SdkContext(j), j.dexer)
2561	}
2562}
2563
2564func (j *Import) commonBuildActions(ctx android.ModuleContext) {
2565	j.sdkVersion = j.SdkVersion(ctx)
2566	j.minSdkVersion = j.MinSdkVersion(ctx)
2567
2568	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
2569	if !apexInfo.IsForPlatform() {
2570		j.hideApexVariantFromMake = true
2571	}
2572
2573	if ctx.Windows() {
2574		j.HideFromMake()
2575	}
2576
2577	if proptools.Bool(j.properties.Is_stubs_module) {
2578		j.stubsLinkType = Stubs
2579	} else {
2580		j.stubsLinkType = Implementation
2581	}
2582}
2583
2584func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2585	j.commonBuildActions(ctx)
2586
2587	j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
2588
2589	var flags javaBuilderFlags
2590
2591	j.collectTransitiveHeaderJars(ctx)
2592	var staticJars android.Paths
2593	var staticHeaderJars android.Paths
2594	ctx.VisitDirectDeps(func(module android.Module) {
2595		tag := ctx.OtherModuleDependencyTag(module)
2596		if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
2597			switch tag {
2598			case libTag, sdkLibTag:
2599				flags.classpath = append(flags.classpath, dep.HeaderJars...)
2600				flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
2601			case staticLibTag:
2602				flags.classpath = append(flags.classpath, dep.HeaderJars...)
2603				staticJars = append(staticJars, dep.ImplementationAndResourcesJars...)
2604				staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
2605			case bootClasspathTag:
2606				flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...)
2607			}
2608		} else if dep, ok := module.(SdkLibraryDependency); ok {
2609			switch tag {
2610			case libTag, sdkLibTag:
2611				flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
2612			}
2613		}
2614
2615		addCLCFromDep(ctx, module, j.classLoaderContexts)
2616	})
2617
2618	jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
2619	jarName := j.Stem() + ".jar"
2620
2621	// Always pass the input jars to TransformJarsToJar, even if there is only a single jar, we need the output
2622	// file of the module to be named jarName.
2623	outputFile := android.PathForModuleOut(ctx, "combined", jarName)
2624	implementationJars := append(slices.Clone(jars), staticJars...)
2625	TransformJarsToJar(ctx, outputFile, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{},
2626		false, j.properties.Exclude_files, j.properties.Exclude_dirs)
2627
2628	// If no dependencies have separate header jars then there is no need to create a separate
2629	// header jar for this module.
2630	reuseImplementationJarAsHeaderJar := slices.Equal(staticJars, staticHeaderJars)
2631
2632	var headerOutputFile android.ModuleOutPath
2633	if reuseImplementationJarAsHeaderJar {
2634		headerOutputFile = outputFile
2635	} else {
2636		headerJars := append(slices.Clone(jars), staticHeaderJars...)
2637		headerOutputFile = android.PathForModuleOut(ctx, "turbine-combined", jarName)
2638		TransformJarsToJar(ctx, headerOutputFile, "combine prebuilt header jars", headerJars, android.OptionalPath{},
2639			false, j.properties.Exclude_files, j.properties.Exclude_dirs)
2640	}
2641
2642	if Bool(j.properties.Jetifier) {
2643		inputFile := outputFile
2644		outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
2645		TransformJetifier(ctx, outputFile, inputFile)
2646
2647		if !reuseImplementationJarAsHeaderJar {
2648			headerInputFile := headerOutputFile
2649			headerOutputFile = android.PathForModuleOut(ctx, "jetifier-headers", jarName)
2650			TransformJetifier(ctx, headerOutputFile, headerInputFile)
2651		} else {
2652			headerOutputFile = outputFile
2653		}
2654	}
2655
2656	// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource.
2657	// Also strip the relative path from the header output file so that the reuseImplementationJarAsHeaderJar check
2658	// in a module that depends on this module considers them equal.
2659	j.combinedHeaderFile = headerOutputFile.WithoutRel()
2660	j.combinedImplementationFile = outputFile.WithoutRel()
2661
2662	j.maybeInstall(ctx, jarName, outputFile)
2663
2664	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
2665
2666	if ctx.Device() {
2667		// If this is a variant created for a prebuilt_apex then use the dex implementation jar
2668		// obtained from the associated deapexer module.
2669		ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
2670		if ai.ForPrebuiltApex {
2671			// Get the path of the dex implementation jar from the `deapexer` module.
2672			di, err := android.FindDeapexerProviderForModule(ctx)
2673			if err != nil {
2674				// An error was found, possibly due to multiple apexes in the tree that export this library
2675				// Defer the error till a client tries to call DexJarBuildPath
2676				j.dexJarFileErr = err
2677				j.initHiddenAPIError(err)
2678				return
2679			}
2680			dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(j.BaseModuleName())
2681			if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
2682				dexJarFile := makeDexJarPathFromPath(dexOutputPath)
2683				j.dexJarFile = dexJarFile
2684				installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, ApexRootRelativePathToJavaLib(j.BaseModuleName()))
2685				j.dexJarInstallFile = installPath
2686
2687				j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
2688				setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
2689				j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
2690
2691				if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
2692					j.dexpreopter.inputProfilePathOnHost = profilePath
2693				}
2694
2695				// Initialize the hiddenapi structure.
2696				j.initHiddenAPI(ctx, dexJarFile, outputFile, j.dexProperties.Uncompress_dex)
2697			} else {
2698				// This should never happen as a variant for a prebuilt_apex is only created if the
2699				// prebuilt_apex has been configured to export the java library dex file.
2700				ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName())
2701			}
2702		} else if Bool(j.dexProperties.Compile_dex) {
2703			sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
2704			if sdkDep.invalidVersion {
2705				ctx.AddMissingDependencies(sdkDep.bootclasspath)
2706				ctx.AddMissingDependencies(sdkDep.java9Classpath)
2707			} else if sdkDep.useFiles {
2708				// sdkDep.jar is actually equivalent to turbine header.jar.
2709				flags.classpath = append(flags.classpath, sdkDep.jars...)
2710			}
2711
2712			// Dex compilation
2713
2714			j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
2715				ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), android.PathForModuleInstall(ctx, "framework", jarName))
2716			setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
2717			j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
2718
2719			var dexOutputFile android.OutputPath
2720			dexParams := &compileDexParams{
2721				flags:         flags,
2722				sdkVersion:    j.SdkVersion(ctx),
2723				minSdkVersion: j.MinSdkVersion(ctx),
2724				classesJar:    outputFile,
2725				jarName:       jarName,
2726			}
2727
2728			dexOutputFile, _ = j.dexer.compileDex(ctx, dexParams)
2729			if ctx.Failed() {
2730				return
2731			}
2732
2733			// Initialize the hiddenapi structure.
2734			j.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), outputFile, j.dexProperties.Uncompress_dex)
2735
2736			// Encode hidden API flags in dex file.
2737			dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
2738
2739			j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
2740			j.dexJarInstallFile = android.PathForModuleInstall(ctx, "framework", jarName)
2741		}
2742	}
2743
2744	android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
2745		HeaderJars:                     android.PathsIfNonNil(j.combinedHeaderFile),
2746		TransitiveLibsHeaderJars:       j.transitiveLibsHeaderJars,
2747		TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
2748		ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedImplementationFile),
2749		ImplementationJars:             android.PathsIfNonNil(j.combinedImplementationFile),
2750		AidlIncludeDirs:                j.exportAidlIncludeDirs,
2751		StubsLinkType:                  j.stubsLinkType,
2752		// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
2753	})
2754}
2755
2756func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputFile android.Path) {
2757	if !Bool(j.properties.Installable) {
2758		return
2759	}
2760
2761	var installDir android.InstallPath
2762	if ctx.InstallInTestcases() {
2763		var archDir string
2764		if !ctx.Host() {
2765			archDir = ctx.DeviceConfig().DeviceArch()
2766		}
2767		installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
2768	} else {
2769		installDir = android.PathForModuleInstall(ctx, "framework")
2770	}
2771	ctx.InstallFile(installDir, jarName, outputFile)
2772}
2773
2774func (j *Import) OutputFiles(tag string) (android.Paths, error) {
2775	switch tag {
2776	case "", ".jar":
2777		return android.Paths{j.combinedImplementationFile}, nil
2778	default:
2779		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
2780	}
2781}
2782
2783var _ android.OutputFileProducer = (*Import)(nil)
2784
2785func (j *Import) HeaderJars() android.Paths {
2786	return android.PathsIfNonNil(j.combinedHeaderFile)
2787}
2788
2789func (j *Import) ImplementationAndResourcesJars() android.Paths {
2790	return android.PathsIfNonNil(j.combinedImplementationFile)
2791}
2792
2793func (j *Import) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
2794	if j.dexJarFileErr != nil {
2795		ctx.ModuleErrorf(j.dexJarFileErr.Error())
2796	}
2797	return j.dexJarFile
2798}
2799
2800func (j *Import) DexJarInstallPath() android.Path {
2801	return j.dexJarInstallFile
2802}
2803
2804func (j *Import) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
2805	return j.classLoaderContexts
2806}
2807
2808var _ android.ApexModule = (*Import)(nil)
2809
2810// Implements android.ApexModule
2811func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
2812	return j.depIsInSameApex(ctx, dep)
2813}
2814
2815// Implements android.ApexModule
2816func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
2817	sdkVersion android.ApiLevel) error {
2818	sdkVersionSpec := j.SdkVersion(ctx)
2819	minSdkVersion := j.MinSdkVersion(ctx)
2820	if !minSdkVersion.Specified() {
2821		return fmt.Errorf("min_sdk_version is not specified")
2822	}
2823	// If the module is compiling against core (via sdk_version), skip comparison check.
2824	if sdkVersionSpec.Kind == android.SdkCore {
2825		return nil
2826	}
2827	if minSdkVersion.GreaterThan(sdkVersion) {
2828		return fmt.Errorf("newer SDK(%v)", minSdkVersion)
2829	}
2830	return nil
2831}
2832
2833// requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or
2834// java_sdk_library_import with the specified base module name requires to be exported from a
2835// prebuilt_apex/apex_set.
2836func requiredFilesFromPrebuiltApexForImport(name string, d *dexpreopter) []string {
2837	dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(name)
2838	// Add the dex implementation jar to the set of exported files.
2839	files := []string{
2840		dexJarFileApexRootRelative,
2841	}
2842	if BoolDefault(d.importDexpreoptProperties.Dex_preopt.Profile_guided, false) {
2843		files = append(files, dexJarFileApexRootRelative+".prof")
2844	}
2845	return files
2846}
2847
2848// ApexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
2849// the java library with the specified name.
2850func ApexRootRelativePathToJavaLib(name string) string {
2851	return filepath.Join("javalib", name+".jar")
2852}
2853
2854var _ android.RequiredFilesFromPrebuiltApex = (*Import)(nil)
2855
2856func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []string {
2857	name := j.BaseModuleName()
2858	return requiredFilesFromPrebuiltApexForImport(name, &j.dexpreopter)
2859}
2860
2861func (j *Import) UseProfileGuidedDexpreopt() bool {
2862	return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
2863}
2864
2865// Add compile time check for interface implementation
2866var _ android.IDEInfo = (*Import)(nil)
2867var _ android.IDECustomizedModuleName = (*Import)(nil)
2868
2869// Collect information for opening IDE project files in java/jdeps.go.
2870
2871func (j *Import) IDEInfo(dpInfo *android.IdeInfo) {
2872	dpInfo.Jars = append(dpInfo.Jars, j.PrebuiltSrcs()...)
2873}
2874
2875func (j *Import) IDECustomizedModuleName() string {
2876	// TODO(b/113562217): Extract the base module name from the Import name, often the Import name
2877	// has a prefix "prebuilt_". Remove the prefix explicitly if needed until we find a better
2878	// solution to get the Import name.
2879	return android.RemoveOptionalPrebuiltPrefix(j.Name())
2880}
2881
2882var _ android.PrebuiltInterface = (*Import)(nil)
2883
2884func (j *Import) IsInstallable() bool {
2885	return Bool(j.properties.Installable)
2886}
2887
2888var _ DexpreopterInterface = (*Import)(nil)
2889
2890// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library module.
2891//
2892// By default, a java_import has a single variant that expects a `.jar` file containing `.class` files that were
2893// compiled against an Android classpath.
2894//
2895// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
2896// for host modules.
2897func ImportFactory() android.Module {
2898	module := &Import{}
2899
2900	module.AddProperties(
2901		&module.properties,
2902		&module.dexer.dexProperties,
2903		&module.importDexpreoptProperties,
2904	)
2905
2906	module.initModuleAndImport(module)
2907
2908	module.dexProperties.Optimize.EnabledByDefault = false
2909
2910	android.InitPrebuiltModule(module, &module.properties.Jars)
2911	android.InitApexModule(module)
2912	InitJavaModule(module, android.HostAndDeviceSupported)
2913	return module
2914}
2915
2916// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library_host
2917// module.
2918//
2919// A java_import_host has a single variant that expects a `.jar` file containing `.class` files that were
2920// compiled against a host bootclasspath.
2921func ImportFactoryHost() android.Module {
2922	module := &Import{}
2923
2924	module.AddProperties(&module.properties)
2925
2926	android.InitPrebuiltModule(module, &module.properties.Jars)
2927	android.InitApexModule(module)
2928	InitJavaModule(module, android.HostSupported)
2929	return module
2930}
2931
2932// dex_import module
2933
2934type DexImportProperties struct {
2935	Jars []string `android:"path"`
2936
2937	// set the name of the output
2938	Stem *string
2939}
2940
2941type DexImport struct {
2942	android.ModuleBase
2943	android.DefaultableModuleBase
2944	android.ApexModuleBase
2945	prebuilt android.Prebuilt
2946
2947	properties DexImportProperties
2948
2949	dexJarFile OptionalDexJarPath
2950
2951	dexpreopter
2952
2953	hideApexVariantFromMake bool
2954}
2955
2956func (j *DexImport) Prebuilt() *android.Prebuilt {
2957	return &j.prebuilt
2958}
2959
2960func (j *DexImport) PrebuiltSrcs() []string {
2961	return j.properties.Jars
2962}
2963
2964func (j *DexImport) Name() string {
2965	return j.prebuilt.Name(j.ModuleBase.Name())
2966}
2967
2968func (j *DexImport) Stem() string {
2969	return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
2970}
2971
2972func (a *DexImport) JacocoReportClassesFile() android.Path {
2973	return nil
2974}
2975
2976func (a *DexImport) LintDepSets() LintDepSets {
2977	return LintDepSets{}
2978}
2979
2980func (j *DexImport) IsInstallable() bool {
2981	return true
2982}
2983
2984func (j *DexImport) getStrictUpdatabilityLinting() bool {
2985	return false
2986}
2987
2988func (j *DexImport) setStrictUpdatabilityLinting(bool) {
2989}
2990
2991func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2992	if len(j.properties.Jars) != 1 {
2993		ctx.PropertyErrorf("jars", "exactly one jar must be provided")
2994	}
2995
2996	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
2997	if !apexInfo.IsForPlatform() {
2998		j.hideApexVariantFromMake = true
2999	}
3000
3001	j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
3002		ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
3003	j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &j.dexpreopter)
3004
3005	inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
3006	dexOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar")
3007
3008	if j.dexpreopter.uncompressedDex {
3009		rule := android.NewRuleBuilder(pctx, ctx)
3010
3011		temporary := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar.unaligned")
3012		rule.Temporary(temporary)
3013
3014		// use zip2zip to uncompress classes*.dex files
3015		rule.Command().
3016			BuiltTool("zip2zip").
3017			FlagWithInput("-i ", inputJar).
3018			FlagWithOutput("-o ", temporary).
3019			FlagWithArg("-0 ", "'classes*.dex'")
3020
3021		// use zipalign to align uncompressed classes*.dex files
3022		rule.Command().
3023			BuiltTool("zipalign").
3024			Flag("-f").
3025			Text("4").
3026			Input(temporary).
3027			Output(dexOutputFile)
3028
3029		rule.DeleteTemporaryFiles()
3030
3031		rule.Build("uncompress_dex", "uncompress dex")
3032	} else {
3033		ctx.Build(pctx, android.BuildParams{
3034			Rule:   android.Cp,
3035			Input:  inputJar,
3036			Output: dexOutputFile,
3037		})
3038	}
3039
3040	j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
3041
3042	j.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), dexOutputFile)
3043
3044	if apexInfo.IsForPlatform() {
3045		ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
3046			j.Stem()+".jar", dexOutputFile)
3047	}
3048}
3049
3050func (j *DexImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
3051	return j.dexJarFile
3052}
3053
3054var _ android.ApexModule = (*DexImport)(nil)
3055
3056// Implements android.ApexModule
3057func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
3058	sdkVersion android.ApiLevel) error {
3059	// we don't check prebuilt modules for sdk_version
3060	return nil
3061}
3062
3063// dex_import imports a `.jar` file containing classes.dex files.
3064//
3065// A dex_import module cannot be used as a dependency of a java_* or android_* module, it can only be installed
3066// to the device.
3067func DexImportFactory() android.Module {
3068	module := &DexImport{}
3069
3070	module.AddProperties(&module.properties)
3071
3072	android.InitPrebuiltModule(module, &module.properties.Jars)
3073	android.InitApexModule(module)
3074	InitJavaModule(module, android.DeviceSupported)
3075	return module
3076}
3077
3078// Defaults
3079type Defaults struct {
3080	android.ModuleBase
3081	android.DefaultsModuleBase
3082	android.ApexModuleBase
3083}
3084
3085// java_defaults provides a set of properties that can be inherited by other java or android modules.
3086//
3087// A module can use the properties from a java_defaults module using `defaults: ["defaults_module_name"]`.  Each
3088// property in the defaults module that exists in the depending module will be prepended to the depending module's
3089// value for that property.
3090//
3091// Example:
3092//
3093//	java_defaults {
3094//	    name: "example_defaults",
3095//	    srcs: ["common/**/*.java"],
3096//	    javacflags: ["-Xlint:all"],
3097//	    aaptflags: ["--auto-add-overlay"],
3098//	}
3099//
3100//	java_library {
3101//	    name: "example",
3102//	    defaults: ["example_defaults"],
3103//	    srcs: ["example/**/*.java"],
3104//	}
3105//
3106// is functionally identical to:
3107//
3108//	java_library {
3109//	    name: "example",
3110//	    srcs: [
3111//	        "common/**/*.java",
3112//	        "example/**/*.java",
3113//	    ],
3114//	    javacflags: ["-Xlint:all"],
3115//	}
3116func DefaultsFactory() android.Module {
3117	module := &Defaults{}
3118
3119	module.AddProperties(
3120		&CommonProperties{},
3121		&DeviceProperties{},
3122		&OverridableProperties{},
3123		&DexProperties{},
3124		&DexpreoptProperties{},
3125		&android.ProtoProperties{},
3126		&aaptProperties{},
3127		&androidLibraryProperties{},
3128		&appProperties{},
3129		&appTestProperties{},
3130		&overridableAppProperties{},
3131		&hostTestProperties{},
3132		&testProperties{},
3133		&ImportProperties{},
3134		&AARImportProperties{},
3135		&sdkLibraryProperties{},
3136		&commonToSdkLibraryAndImportProperties{},
3137		&DexImportProperties{},
3138		&android.ApexProperties{},
3139		&RuntimeResourceOverlayProperties{},
3140		&LintProperties{},
3141		&appTestHelperAppProperties{},
3142		&JavaApiLibraryProperties{},
3143		&bootclasspathFragmentProperties{},
3144		&SourceOnlyBootclasspathProperties{},
3145	)
3146
3147	android.InitDefaultsModule(module)
3148	return module
3149}
3150
3151func kytheExtractJavaFactory() android.Singleton {
3152	return &kytheExtractJavaSingleton{}
3153}
3154
3155type kytheExtractJavaSingleton struct {
3156}
3157
3158func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonContext) {
3159	var xrefTargets android.Paths
3160	ctx.VisitAllModules(func(module android.Module) {
3161		if javaModule, ok := module.(xref); ok {
3162			xrefTargets = append(xrefTargets, javaModule.XrefJavaFiles()...)
3163		}
3164	})
3165	// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
3166	if len(xrefTargets) > 0 {
3167		ctx.Phony("xref_java", xrefTargets...)
3168	}
3169}
3170
3171var Bool = proptools.Bool
3172var BoolDefault = proptools.BoolDefault
3173var String = proptools.String
3174var inList = android.InList[string]
3175
3176// Add class loader context (CLC) of a given dependency to the current CLC.
3177func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
3178	clcMap dexpreopt.ClassLoaderContextMap) {
3179
3180	dep, ok := depModule.(UsesLibraryDependency)
3181	if !ok {
3182		return
3183	}
3184
3185	depName := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(depModule))
3186
3187	var sdkLib *string
3188	if lib, ok := depModule.(SdkLibraryDependency); ok && lib.sharedLibrary() {
3189		// A shared SDK library. This should be added as a top-level CLC element.
3190		sdkLib = &depName
3191	} else if ulib, ok := depModule.(ProvidesUsesLib); ok {
3192		// A non-SDK library disguised as an SDK library by the means of `provides_uses_lib`
3193		// property. This should be handled in the same way as a shared SDK library.
3194		sdkLib = ulib.ProvidesUsesLib()
3195	}
3196
3197	depTag := ctx.OtherModuleDependencyTag(depModule)
3198	if IsLibDepTag(depTag) {
3199		// Ok, propagate <uses-library> through non-static library dependencies.
3200	} else if tag, ok := depTag.(usesLibraryDependencyTag); ok && tag.sdkVersion == dexpreopt.AnySdkVersion {
3201		// Ok, propagate <uses-library> through non-compatibility <uses-library> dependencies.
3202	} else if depTag == staticLibTag {
3203		// Propagate <uses-library> through static library dependencies, unless it is a component
3204		// library (such as stubs). Component libraries have a dependency on their SDK library,
3205		// which should not be pulled just because of a static component library.
3206		if sdkLib != nil {
3207			return
3208		}
3209	} else {
3210		// Don't propagate <uses-library> for other dependency tags.
3211		return
3212	}
3213
3214	// If this is an SDK (or SDK-like) library, then it should be added as a node in the CLC tree,
3215	// and its CLC should be added as subtree of that node. Otherwise the library is not a
3216	// <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies
3217	// from its CLC should be added to the current CLC.
3218	if sdkLib != nil {
3219		optional := false
3220		if module, ok := ctx.Module().(ModuleWithUsesLibrary); ok {
3221			if android.InList(*sdkLib, module.UsesLibrary().usesLibraryProperties.Optional_uses_libs) {
3222				optional = true
3223			}
3224		}
3225		clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, optional,
3226			dep.DexJarBuildPath(ctx).PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
3227	} else {
3228		clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
3229	}
3230}
3231
3232func addMissingOptionalUsesLibsFromDep(ctx android.ModuleContext, depModule android.Module,
3233	usesLibrary *usesLibrary) {
3234
3235	dep, ok := depModule.(ModuleWithUsesLibrary)
3236	if !ok {
3237		return
3238	}
3239
3240	for _, lib := range dep.UsesLibrary().usesLibraryProperties.Missing_optional_uses_libs {
3241		if !android.InList(lib, usesLibrary.usesLibraryProperties.Missing_optional_uses_libs) {
3242			usesLibrary.usesLibraryProperties.Missing_optional_uses_libs =
3243				append(usesLibrary.usesLibraryProperties.Missing_optional_uses_libs, lib)
3244		}
3245	}
3246}
3247
3248type JavaApiContributionImport struct {
3249	JavaApiContribution
3250
3251	prebuilt           android.Prebuilt
3252	prebuiltProperties javaApiContributionImportProperties
3253}
3254
3255type javaApiContributionImportProperties struct {
3256	// Name of the source soong module that gets shadowed by this prebuilt
3257	// If unspecified, follows the naming convention that the source module of
3258	// the prebuilt is Name() without "prebuilt_" prefix
3259	Source_module_name *string
3260
3261	// Non-nil if this java_import module was dynamically created by a java_sdk_library_import
3262	// The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
3263	// (without any prebuilt_ prefix)
3264	Created_by_java_sdk_library_name *string `blueprint:"mutated"`
3265}
3266
3267func ApiContributionImportFactory() android.Module {
3268	module := &JavaApiContributionImport{}
3269	android.InitAndroidModule(module)
3270	android.InitDefaultableModule(module)
3271	android.InitPrebuiltModule(module, &[]string{""})
3272	module.AddProperties(&module.properties, &module.prebuiltProperties)
3273	module.AddProperties(&module.sdkLibraryComponentProperties)
3274	return module
3275}
3276
3277func (module *JavaApiContributionImport) Prebuilt() *android.Prebuilt {
3278	return &module.prebuilt
3279}
3280
3281func (module *JavaApiContributionImport) Name() string {
3282	return module.prebuilt.Name(module.ModuleBase.Name())
3283}
3284
3285func (j *JavaApiContributionImport) BaseModuleName() string {
3286	return proptools.StringDefault(j.prebuiltProperties.Source_module_name, j.ModuleBase.Name())
3287}
3288
3289func (j *JavaApiContributionImport) CreatedByJavaSdkLibraryName() *string {
3290	return j.prebuiltProperties.Created_by_java_sdk_library_name
3291}
3292
3293func (ap *JavaApiContributionImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
3294	ap.JavaApiContribution.GenerateAndroidBuildActions(ctx)
3295}
3296