• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	"strings"
25
26	"android/soong/bazel"
27
28	"github.com/google/blueprint"
29	"github.com/google/blueprint/proptools"
30
31	"android/soong/android"
32	"android/soong/cc"
33	"android/soong/dexpreopt"
34	"android/soong/java/config"
35	"android/soong/tradefed"
36)
37
38func init() {
39	registerJavaBuildComponents(android.InitRegistrationContext)
40
41	RegisterJavaSdkMemberTypes()
42}
43
44func registerJavaBuildComponents(ctx android.RegistrationContext) {
45	ctx.RegisterModuleType("java_defaults", DefaultsFactory)
46
47	ctx.RegisterModuleType("java_library", LibraryFactory)
48	ctx.RegisterModuleType("java_library_static", LibraryStaticFactory)
49	ctx.RegisterModuleType("java_library_host", LibraryHostFactory)
50	ctx.RegisterModuleType("java_binary", BinaryFactory)
51	ctx.RegisterModuleType("java_binary_host", BinaryHostFactory)
52	ctx.RegisterModuleType("java_test", TestFactory)
53	ctx.RegisterModuleType("java_test_helper_library", TestHelperLibraryFactory)
54	ctx.RegisterModuleType("java_test_host", TestHostFactory)
55	ctx.RegisterModuleType("java_test_import", JavaTestImportFactory)
56	ctx.RegisterModuleType("java_import", ImportFactory)
57	ctx.RegisterModuleType("java_import_host", ImportFactoryHost)
58	ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
59	ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
60	ctx.RegisterModuleType("dex_import", DexImportFactory)
61
62	// This mutator registers dependencies on dex2oat for modules that should be
63	// dexpreopted. This is done late when the final variants have been
64	// established, to not get the dependencies split into the wrong variants and
65	// to support the checks in dexpreoptDisabled().
66	ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
67		ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel()
68	})
69
70	ctx.RegisterSingletonType("logtags", LogtagsSingleton)
71	ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
72}
73
74func RegisterJavaSdkMemberTypes() {
75	// Register sdk member types.
76	android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
77	android.RegisterSdkMemberType(javaLibsSdkMemberType)
78	android.RegisterSdkMemberType(javaBootLibsSdkMemberType)
79	android.RegisterSdkMemberType(javaSystemserverLibsSdkMemberType)
80	android.RegisterSdkMemberType(javaTestSdkMemberType)
81}
82
83var (
84	// Supports adding java header libraries to module_exports and sdk.
85	javaHeaderLibsSdkMemberType = &librarySdkMemberType{
86		android.SdkMemberTypeBase{
87			PropertyName: "java_header_libs",
88			SupportsSdk:  true,
89		},
90		func(_ android.SdkMemberContext, j *Library) android.Path {
91			headerJars := j.HeaderJars()
92			if len(headerJars) != 1 {
93				panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
94			}
95
96			return headerJars[0]
97		},
98		sdkSnapshotFilePathForJar,
99		copyEverythingToSnapshot,
100	}
101
102	// Export implementation classes jar as part of the sdk.
103	exportImplementationClassesJar = func(_ android.SdkMemberContext, j *Library) android.Path {
104		implementationJars := j.ImplementationAndResourcesJars()
105		if len(implementationJars) != 1 {
106			panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
107		}
108		return implementationJars[0]
109	}
110
111	// Supports adding java implementation libraries to module_exports but not sdk.
112	javaLibsSdkMemberType = &librarySdkMemberType{
113		android.SdkMemberTypeBase{
114			PropertyName: "java_libs",
115		},
116		exportImplementationClassesJar,
117		sdkSnapshotFilePathForJar,
118		copyEverythingToSnapshot,
119	}
120
121	snapshotRequiresImplementationJar = func(ctx android.SdkMemberContext) bool {
122		// In the S build the build will break if updatable-media does not provide a full implementation
123		// jar. That issue was fixed in Tiramisu by b/229932396.
124		if ctx.IsTargetBuildBeforeTiramisu() && ctx.Name() == "updatable-media" {
125			return true
126		}
127
128		return false
129	}
130
131	// Supports adding java boot libraries to module_exports and sdk.
132	//
133	// The build has some implicit dependencies (via the boot jars configuration) on a number of
134	// modules, e.g. core-oj, apache-xml, that are part of the java boot class path and which are
135	// provided by mainline modules (e.g. art, conscrypt, runtime-i18n) but which are not otherwise
136	// used outside those mainline modules.
137	//
138	// As they are not needed outside the mainline modules adding them to the sdk/module-exports as
139	// either java_libs, or java_header_libs would end up exporting more information than was strictly
140	// necessary. The java_boot_libs property to allow those modules to be exported as part of the
141	// sdk/module_exports without exposing any unnecessary information.
142	javaBootLibsSdkMemberType = &librarySdkMemberType{
143		android.SdkMemberTypeBase{
144			PropertyName: "java_boot_libs",
145			SupportsSdk:  true,
146		},
147		func(ctx android.SdkMemberContext, j *Library) android.Path {
148			if snapshotRequiresImplementationJar(ctx) {
149				return exportImplementationClassesJar(ctx, j)
150			}
151
152			// Java boot libs are only provided in the SDK to provide access to their dex implementation
153			// jar for use by dexpreopting and boot jars package check. They do not need to provide an
154			// actual implementation jar but the java_import will need a file that exists so just copy an
155			// empty file. Any attempt to use that file as a jar will cause a build error.
156			return ctx.SnapshotBuilder().EmptyFile()
157		},
158		func(ctx android.SdkMemberContext, osPrefix, name string) string {
159			if snapshotRequiresImplementationJar(ctx) {
160				return sdkSnapshotFilePathForJar(ctx, osPrefix, name)
161			}
162
163			// Create a special name for the implementation jar to try and provide some useful information
164			// to a developer that attempts to compile against this.
165			// TODO(b/175714559): Provide a proper error message in Soong not ninja.
166			return filepath.Join(osPrefix, "java_boot_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix)
167		},
168		onlyCopyJarToSnapshot,
169	}
170
171	// Supports adding java systemserver libraries to module_exports and sdk.
172	//
173	// The build has some implicit dependencies (via the systemserver jars configuration) on a number
174	// of modules that are part of the java systemserver classpath and which are provided by mainline
175	// modules but which are not otherwise used outside those mainline modules.
176	//
177	// As they are not needed outside the mainline modules adding them to the sdk/module-exports as
178	// either java_libs, or java_header_libs would end up exporting more information than was strictly
179	// necessary. The java_systemserver_libs property to allow those modules to be exported as part of
180	// the sdk/module_exports without exposing any unnecessary information.
181	javaSystemserverLibsSdkMemberType = &librarySdkMemberType{
182		android.SdkMemberTypeBase{
183			PropertyName: "java_systemserver_libs",
184			SupportsSdk:  true,
185
186			// This was only added in Tiramisu.
187			SupportedBuildReleaseSpecification: "Tiramisu+",
188		},
189		func(ctx android.SdkMemberContext, j *Library) android.Path {
190			// Java systemserver libs are only provided in the SDK to provide access to their dex
191			// implementation jar for use by dexpreopting. They do not need to provide an actual
192			// implementation jar but the java_import will need a file that exists so just copy an empty
193			// file. Any attempt to use that file as a jar will cause a build error.
194			return ctx.SnapshotBuilder().EmptyFile()
195		},
196		func(_ android.SdkMemberContext, osPrefix, name string) string {
197			// Create a special name for the implementation jar to try and provide some useful information
198			// to a developer that attempts to compile against this.
199			// TODO(b/175714559): Provide a proper error message in Soong not ninja.
200			return filepath.Join(osPrefix, "java_systemserver_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix)
201		},
202		onlyCopyJarToSnapshot,
203	}
204
205	// Supports adding java test libraries to module_exports but not sdk.
206	javaTestSdkMemberType = &testSdkMemberType{
207		SdkMemberTypeBase: android.SdkMemberTypeBase{
208			PropertyName: "java_tests",
209		},
210	}
211)
212
213// JavaInfo contains information about a java module for use by modules that depend on it.
214type JavaInfo struct {
215	// HeaderJars is a list of jars that can be passed as the javac classpath in order to link
216	// against this module.  If empty, ImplementationJars should be used instead.
217	HeaderJars android.Paths
218
219	// ImplementationAndResourceJars is a list of jars that contain the implementations of classes
220	// in the module as well as any resources included in the module.
221	ImplementationAndResourcesJars android.Paths
222
223	// ImplementationJars is a list of jars that contain the implementations of classes in the
224	//module.
225	ImplementationJars android.Paths
226
227	// ResourceJars is a list of jars that contain the resources included in the module.
228	ResourceJars android.Paths
229
230	// AidlIncludeDirs is a list of directories that should be passed to the aidl tool when
231	// depending on this module.
232	AidlIncludeDirs android.Paths
233
234	// SrcJarArgs is a list of arguments to pass to soong_zip to package the sources of this
235	// module.
236	SrcJarArgs []string
237
238	// SrcJarDeps is a list of paths to depend on when packaging the sources of this module.
239	SrcJarDeps android.Paths
240
241	// ExportedPlugins is a list of paths that should be used as annotation processors for any
242	// module that depends on this module.
243	ExportedPlugins android.Paths
244
245	// ExportedPluginClasses is a list of classes that should be run as annotation processors for
246	// any module that depends on this module.
247	ExportedPluginClasses []string
248
249	// ExportedPluginDisableTurbine is true if this module's annotation processors generate APIs,
250	// requiring disbling turbine for any modules that depend on it.
251	ExportedPluginDisableTurbine bool
252
253	// JacocoReportClassesFile is the path to a jar containing uninstrumented classes that will be
254	// instrumented by jacoco.
255	JacocoReportClassesFile android.Path
256}
257
258var JavaInfoProvider = blueprint.NewProvider(JavaInfo{})
259
260// SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to
261// the sysprop implementation library.
262type SyspropPublicStubInfo struct {
263	// JavaInfo is the JavaInfoProvider of the sysprop public stub library that corresponds to
264	// the sysprop implementation library.
265	JavaInfo JavaInfo
266}
267
268var SyspropPublicStubInfoProvider = blueprint.NewProvider(SyspropPublicStubInfo{})
269
270// Methods that need to be implemented for a module that is added to apex java_libs property.
271type ApexDependency interface {
272	HeaderJars() android.Paths
273	ImplementationAndResourcesJars() android.Paths
274}
275
276// Provides build path and install path to DEX jars.
277type UsesLibraryDependency interface {
278	DexJarBuildPath() OptionalDexJarPath
279	DexJarInstallPath() android.Path
280	ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
281}
282
283// TODO(jungjw): Move this to kythe.go once it's created.
284type xref interface {
285	XrefJavaFiles() android.Paths
286}
287
288func (j *Module) XrefJavaFiles() android.Paths {
289	return j.kytheFiles
290}
291
292type dependencyTag struct {
293	blueprint.BaseDependencyTag
294	name string
295
296	// True if the dependency is relinked at runtime.
297	runtimeLinked bool
298
299	// True if the dependency is a toolchain, for example an annotation processor.
300	toolchain bool
301}
302
303// installDependencyTag is a dependency tag that is annotated to cause the installed files of the
304// dependency to be installed when the parent module is installed.
305type installDependencyTag struct {
306	blueprint.BaseDependencyTag
307	android.InstallAlwaysNeededDependencyTag
308	name string
309}
310
311func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
312	if d.runtimeLinked {
313		return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
314	} else if d.toolchain {
315		return []android.LicenseAnnotation{android.LicenseAnnotationToolchain}
316	}
317	return nil
318}
319
320var _ android.LicenseAnnotationsDependencyTag = dependencyTag{}
321
322type usesLibraryDependencyTag struct {
323	dependencyTag
324
325	// SDK version in which the library appared as a standalone library.
326	sdkVersion int
327
328	// If the dependency is optional or required.
329	optional bool
330
331	// Whether this is an implicit dependency inferred by Soong, or an explicit one added via
332	// `uses_libs`/`optional_uses_libs` properties.
333	implicit bool
334}
335
336func makeUsesLibraryDependencyTag(sdkVersion int, optional bool, implicit bool) usesLibraryDependencyTag {
337	return usesLibraryDependencyTag{
338		dependencyTag: dependencyTag{
339			name:          fmt.Sprintf("uses-library-%d", sdkVersion),
340			runtimeLinked: true,
341		},
342		sdkVersion: sdkVersion,
343		optional:   optional,
344		implicit:   implicit,
345	}
346}
347
348func IsJniDepTag(depTag blueprint.DependencyTag) bool {
349	return depTag == jniLibTag
350}
351
352var (
353	dataNativeBinsTag       = dependencyTag{name: "dataNativeBins"}
354	dataDeviceBinsTag       = dependencyTag{name: "dataDeviceBins"}
355	staticLibTag            = dependencyTag{name: "staticlib"}
356	libTag                  = dependencyTag{name: "javalib", runtimeLinked: true}
357	java9LibTag             = dependencyTag{name: "java9lib", runtimeLinked: true}
358	pluginTag               = dependencyTag{name: "plugin", toolchain: true}
359	errorpronePluginTag     = dependencyTag{name: "errorprone-plugin", toolchain: true}
360	exportedPluginTag       = dependencyTag{name: "exported-plugin", toolchain: true}
361	bootClasspathTag        = dependencyTag{name: "bootclasspath", runtimeLinked: true}
362	systemModulesTag        = dependencyTag{name: "system modules", runtimeLinked: true}
363	frameworkResTag         = dependencyTag{name: "framework-res"}
364	kotlinStdlibTag         = dependencyTag{name: "kotlin-stdlib", runtimeLinked: true}
365	kotlinAnnotationsTag    = dependencyTag{name: "kotlin-annotations", runtimeLinked: true}
366	kotlinPluginTag         = dependencyTag{name: "kotlin-plugin", toolchain: true}
367	proguardRaiseTag        = dependencyTag{name: "proguard-raise"}
368	certificateTag          = dependencyTag{name: "certificate"}
369	instrumentationForTag   = dependencyTag{name: "instrumentation_for"}
370	extraLintCheckTag       = dependencyTag{name: "extra-lint-check", toolchain: true}
371	jniLibTag               = dependencyTag{name: "jnilib", runtimeLinked: true}
372	syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
373	jniInstallTag           = installDependencyTag{name: "jni install"}
374	binaryInstallTag        = installDependencyTag{name: "binary install"}
375)
376
377func IsLibDepTag(depTag blueprint.DependencyTag) bool {
378	return depTag == libTag
379}
380
381func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool {
382	return depTag == staticLibTag
383}
384
385type sdkDep struct {
386	useModule, useFiles, invalidVersion bool
387
388	// The modules that will be added to the bootclasspath when targeting 1.8 or lower
389	bootclasspath []string
390
391	// The default system modules to use. Will be an empty string if no system
392	// modules are to be used.
393	systemModules string
394
395	// The modules that will be added to the classpath regardless of the Java language level targeted
396	classpath []string
397
398	// The modules that will be added ot the classpath when targeting 1.9 or higher
399	// (normally these will be on the bootclasspath when targeting 1.8 or lower)
400	java9Classpath []string
401
402	frameworkResModule string
403
404	jars android.Paths
405	aidl android.OptionalPath
406
407	noStandardLibs, noFrameworksLibs bool
408}
409
410func (s sdkDep) hasStandardLibs() bool {
411	return !s.noStandardLibs
412}
413
414func (s sdkDep) hasFrameworkLibs() bool {
415	return !s.noStandardLibs && !s.noFrameworksLibs
416}
417
418type jniLib struct {
419	name           string
420	path           android.Path
421	target         android.Target
422	coverageFile   android.OptionalPath
423	unstrippedFile android.Path
424}
425
426func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) {
427	sdkDep := decodeSdkDep(ctx, sdkContext)
428	if sdkDep.useModule {
429		ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
430		ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
431		ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...)
432		if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
433			ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries...)
434		}
435		if d.effectiveOptimizeEnabled() && sdkDep.hasFrameworkLibs() {
436			ctx.AddVariationDependencies(nil, proguardRaiseTag, config.FrameworkLibraries...)
437		}
438	}
439	if sdkDep.systemModules != "" {
440		ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
441	}
442}
443
444type deps struct {
445	// bootClasspath is the list of jars that form the boot classpath (generally the java.* and
446	// android.* classes) for tools that still use it.  javac targeting 1.9 or higher uses
447	// systemModules and java9Classpath instead.
448	bootClasspath classpath
449
450	// classpath is the list of jars that form the classpath for javac and kotlinc rules.  It
451	// contains header jars for all static and non-static dependencies.
452	classpath classpath
453
454	// dexClasspath is the list of jars that form the classpath for d8 and r8 rules.  It contains
455	// header jars for all non-static dependencies.  Static dependencies have already been
456	// combined into the program jar.
457	dexClasspath classpath
458
459	// java9Classpath is the list of jars that will be added to the classpath when targeting
460	// 1.9 or higher.  It generally contains the android.* classes, while the java.* classes
461	// are provided by systemModules.
462	java9Classpath classpath
463
464	processorPath           classpath
465	errorProneProcessorPath classpath
466	processorClasses        []string
467	staticJars              android.Paths
468	staticHeaderJars        android.Paths
469	staticResourceJars      android.Paths
470	aidlIncludeDirs         android.Paths
471	srcs                    android.Paths
472	srcJars                 android.Paths
473	systemModules           *systemModules
474	aidlPreprocess          android.OptionalPath
475	kotlinStdlib            android.Paths
476	kotlinAnnotations       android.Paths
477	kotlinPlugins           android.Paths
478
479	disableTurbine bool
480}
481
482func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
483	for _, f := range dep.Srcs() {
484		if f.Ext() != ".jar" {
485			ctx.ModuleErrorf("genrule %q must generate files ending with .jar to be used as a libs or static_libs dependency",
486				ctx.OtherModuleName(dep.(blueprint.Module)))
487		}
488	}
489}
490
491func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext android.SdkContext) javaVersion {
492	if javaVersion != "" {
493		return normalizeJavaVersion(ctx, javaVersion)
494	} else if ctx.Device() {
495		return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion(ctx))
496	} else {
497		return JAVA_VERSION_11
498	}
499}
500
501type javaVersion int
502
503const (
504	JAVA_VERSION_UNSUPPORTED = 0
505	JAVA_VERSION_6           = 6
506	JAVA_VERSION_7           = 7
507	JAVA_VERSION_8           = 8
508	JAVA_VERSION_9           = 9
509	JAVA_VERSION_11          = 11
510)
511
512func (v javaVersion) String() string {
513	switch v {
514	case JAVA_VERSION_6:
515		return "1.6"
516	case JAVA_VERSION_7:
517		return "1.7"
518	case JAVA_VERSION_8:
519		return "1.8"
520	case JAVA_VERSION_9:
521		return "1.9"
522	case JAVA_VERSION_11:
523		return "11"
524	default:
525		return "unsupported"
526	}
527}
528
529func (v javaVersion) StringForKotlinc() string {
530	// $ ./external/kotlinc/bin/kotlinc -jvm-target foo
531	// error: unknown JVM target version: foo
532	// Supported versions: 1.6, 1.8, 9, 10, 11, 12, 13, 14, 15, 16, 17
533	switch v {
534	case JAVA_VERSION_7:
535		return "1.6"
536	case JAVA_VERSION_9:
537		return "9"
538	default:
539		return v.String()
540	}
541}
542
543// Returns true if javac targeting this version uses system modules instead of a bootclasspath.
544func (v javaVersion) usesJavaModules() bool {
545	return v >= 9
546}
547
548func normalizeJavaVersion(ctx android.BaseModuleContext, javaVersion string) javaVersion {
549	switch javaVersion {
550	case "1.6", "6":
551		return JAVA_VERSION_6
552	case "1.7", "7":
553		return JAVA_VERSION_7
554	case "1.8", "8":
555		return JAVA_VERSION_8
556	case "1.9", "9":
557		return JAVA_VERSION_9
558	case "11":
559		return JAVA_VERSION_11
560	case "10":
561		ctx.PropertyErrorf("java_version", "Java language levels 10 is not supported")
562		return JAVA_VERSION_UNSUPPORTED
563	default:
564		ctx.PropertyErrorf("java_version", "Unrecognized Java language level")
565		return JAVA_VERSION_UNSUPPORTED
566	}
567}
568
569//
570// Java libraries (.jar file)
571//
572
573type Library struct {
574	Module
575
576	InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
577}
578
579var _ android.ApexModule = (*Library)(nil)
580
581// Provides access to the list of permitted packages from apex boot jars.
582type PermittedPackagesForUpdatableBootJars interface {
583	PermittedPackagesForUpdatableBootJars() []string
584}
585
586var _ PermittedPackagesForUpdatableBootJars = (*Library)(nil)
587
588func (j *Library) PermittedPackagesForUpdatableBootJars() []string {
589	return j.properties.Permitted_packages
590}
591
592func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool {
593	// Store uncompressed (and aligned) any dex files from jars in APEXes.
594	if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
595		return true
596	}
597
598	// Store uncompressed (and do not strip) dex files from boot class path jars.
599	if inList(ctx.ModuleName(), ctx.Config().BootJars()) {
600		return true
601	}
602
603	// Store uncompressed dex files that are preopted on /system.
604	if !dexpreopter.dexpreoptDisabled(ctx) && (ctx.Host() || !dexpreopter.odexOnSystemOther(ctx, dexpreopter.installPath)) {
605		return true
606	}
607	if ctx.Config().UncompressPrivAppDex() &&
608		inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules()) {
609		return true
610	}
611
612	return false
613}
614
615// Sets `dexer.dexProperties.Uncompress_dex` to the proper value.
616func setUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter, dexer *dexer) {
617	if dexer.dexProperties.Uncompress_dex == nil {
618		// If the value was not force-set by the user, use reasonable default based on the module.
619		dexer.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, dexpreopter))
620	}
621}
622
623func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
624	j.sdkVersion = j.SdkVersion(ctx)
625	j.minSdkVersion = j.MinSdkVersion(ctx)
626	j.maxSdkVersion = j.MaxSdkVersion(ctx)
627
628	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
629	if !apexInfo.IsForPlatform() {
630		j.hideApexVariantFromMake = true
631	}
632
633	j.checkSdkVersions(ctx)
634	j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
635		ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
636	j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
637	setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
638	j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
639	j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
640	j.compile(ctx, nil)
641
642	// Collect the module directory for IDE info in java/jdeps.go.
643	j.modulePaths = append(j.modulePaths, ctx.ModuleDir())
644
645	exclusivelyForApex := !apexInfo.IsForPlatform()
646	if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex {
647		var extraInstallDeps android.Paths
648		if j.InstallMixin != nil {
649			extraInstallDeps = j.InstallMixin(ctx, j.outputFile)
650		}
651		hostDexNeeded := Bool(j.deviceProperties.Hostdex) && !ctx.Host()
652		if hostDexNeeded {
653			j.hostdexInstallFile = ctx.InstallFile(
654				android.PathForHostDexInstall(ctx, "framework"),
655				j.Stem()+"-hostdex.jar", j.outputFile)
656		}
657		var installDir android.InstallPath
658		if ctx.InstallInTestcases() {
659			var archDir string
660			if !ctx.Host() {
661				archDir = ctx.DeviceConfig().DeviceArch()
662			}
663			installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
664		} else {
665			installDir = android.PathForModuleInstall(ctx, "framework")
666		}
667		j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
668	}
669}
670
671func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
672	j.deps(ctx)
673	j.usesLibrary.deps(ctx, false)
674}
675
676const (
677	aidlIncludeDir   = "aidl"
678	javaDir          = "java"
679	jarFileSuffix    = ".jar"
680	testConfigSuffix = "-AndroidTest.xml"
681)
682
683// path to the jar file of a java library. Relative to <sdk_root>/<api_dir>
684func sdkSnapshotFilePathForJar(_ android.SdkMemberContext, osPrefix, name string) string {
685	return sdkSnapshotFilePathForMember(osPrefix, name, jarFileSuffix)
686}
687
688func sdkSnapshotFilePathForMember(osPrefix, name string, suffix string) string {
689	return filepath.Join(javaDir, osPrefix, name+suffix)
690}
691
692type librarySdkMemberType struct {
693	android.SdkMemberTypeBase
694
695	// Function to retrieve the appropriate output jar (implementation or header) from
696	// the library.
697	jarToExportGetter func(ctx android.SdkMemberContext, j *Library) android.Path
698
699	// Function to compute the snapshot relative path to which the named library's
700	// jar should be copied.
701	snapshotPathGetter func(ctx android.SdkMemberContext, osPrefix, name string) string
702
703	// True if only the jar should be copied to the snapshot, false if the jar plus any additional
704	// files like aidl files should also be copied.
705	onlyCopyJarToSnapshot bool
706}
707
708const (
709	onlyCopyJarToSnapshot    = true
710	copyEverythingToSnapshot = false
711)
712
713func (mt *librarySdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
714	ctx.AddVariationDependencies(nil, dependencyTag, names...)
715}
716
717func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
718	_, ok := module.(*Library)
719	return ok
720}
721
722func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
723	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_import")
724}
725
726func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
727	return &librarySdkMemberProperties{}
728}
729
730type librarySdkMemberProperties struct {
731	android.SdkMemberPropertiesBase
732
733	JarToExport     android.Path `android:"arch_variant"`
734	AidlIncludeDirs android.Paths
735
736	// The list of permitted packages that need to be passed to the prebuilts as they are used to
737	// create the updatable-bcp-packages.txt file.
738	PermittedPackages []string
739}
740
741func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
742	j := variant.(*Library)
743
744	p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(ctx, j)
745
746	p.AidlIncludeDirs = j.AidlIncludeDirs()
747
748	p.PermittedPackages = j.PermittedPackagesForUpdatableBootJars()
749}
750
751func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
752	builder := ctx.SnapshotBuilder()
753
754	memberType := ctx.MemberType().(*librarySdkMemberType)
755
756	exportedJar := p.JarToExport
757	if exportedJar != nil {
758		// Delegate the creation of the snapshot relative path to the member type.
759		snapshotRelativeJavaLibPath := memberType.snapshotPathGetter(ctx, p.OsPrefix(), ctx.Name())
760
761		// Copy the exported jar to the snapshot.
762		builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
763
764		propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
765	}
766
767	if len(p.PermittedPackages) > 0 {
768		propertySet.AddProperty("permitted_packages", p.PermittedPackages)
769	}
770
771	// Do not copy anything else to the snapshot.
772	if memberType.onlyCopyJarToSnapshot {
773		return
774	}
775
776	aidlIncludeDirs := p.AidlIncludeDirs
777	if len(aidlIncludeDirs) != 0 {
778		sdkModuleContext := ctx.SdkModuleContext()
779		for _, dir := range aidlIncludeDirs {
780			// TODO(jiyong): copy parcelable declarations only
781			aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
782			for _, file := range aidlFiles {
783				builder.CopyToSnapshot(android.PathForSource(sdkModuleContext, file), filepath.Join(aidlIncludeDir, file))
784			}
785		}
786
787		// TODO(b/151933053) - add aidl include dirs property
788	}
789}
790
791// java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
792//
793// By default, a java_library has a single variant that produces a `.jar` file containing `.class` files that were
794// compiled against the device bootclasspath.  This jar is not suitable for installing on a device, but can be used
795// as a `static_libs` dependency of another module.
796//
797// Specifying `installable: true` will product a `.jar` file containing `classes.dex` files, suitable for installing on
798// a device.
799//
800// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
801// compiled against the host bootclasspath.
802func LibraryFactory() android.Module {
803	module := &Library{}
804
805	module.addHostAndDeviceProperties()
806
807	module.initModuleAndImport(module)
808
809	android.InitApexModule(module)
810	android.InitSdkAwareModule(module)
811	android.InitBazelModule(module)
812	InitJavaModule(module, android.HostAndDeviceSupported)
813	return module
814}
815
816// java_library_static is an obsolete alias for java_library.
817func LibraryStaticFactory() android.Module {
818	return LibraryFactory()
819}
820
821// java_library_host builds and links sources into a `.jar` file for the host.
822//
823// A java_library_host has a single variant that produces a `.jar` file containing `.class` files that were
824// compiled against the host bootclasspath.
825func LibraryHostFactory() android.Module {
826	module := &Library{}
827
828	module.addHostProperties()
829
830	module.Module.properties.Installable = proptools.BoolPtr(true)
831
832	android.InitApexModule(module)
833	android.InitSdkAwareModule(module)
834	android.InitBazelModule(module)
835	InitJavaModule(module, android.HostSupported)
836	return module
837}
838
839//
840// Java Tests
841//
842
843// Test option struct.
844type TestOptions struct {
845	// a list of extra test configuration files that should be installed with the module.
846	Extra_test_configs []string `android:"path,arch_variant"`
847
848	// If the test is a hostside(no device required) unittest that shall be run during presubmit check.
849	Unit_test *bool
850}
851
852type testProperties struct {
853	// list of compatibility suites (for example "cts", "vts") that the module should be
854	// installed into.
855	Test_suites []string `android:"arch_variant"`
856
857	// the name of the test configuration (for example "AndroidTest.xml") that should be
858	// installed with the module.
859	Test_config *string `android:"path,arch_variant"`
860
861	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
862	// should be installed with the module.
863	Test_config_template *string `android:"path,arch_variant"`
864
865	// list of files or filegroup modules that provide data that should be installed alongside
866	// the test
867	Data []string `android:"path"`
868
869	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
870	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
871	// explicitly.
872	Auto_gen_config *bool
873
874	// Add parameterized mainline modules to auto generated test config. The options will be
875	// handled by TradeFed to do downloading and installing the specified modules on the device.
876	Test_mainline_modules []string
877
878	// Test options.
879	Test_options TestOptions
880
881	// Names of modules containing JNI libraries that should be installed alongside the test.
882	Jni_libs []string
883
884	// Install the test into a folder named for the module in all test suites.
885	Per_testcase_directory *bool
886}
887
888type hostTestProperties struct {
889	// list of native binary modules that should be installed alongside the test
890	Data_native_bins []string `android:"arch_variant"`
891
892	// list of device binary modules that should be installed alongside the test
893	// This property only adds the first variant of the dependency
894	Data_device_bins_first []string `android:"arch_variant"`
895
896	// list of device binary modules that should be installed alongside the test
897	// This property adds 64bit AND 32bit variants of the dependency
898	Data_device_bins_both []string `android:"arch_variant"`
899
900	// list of device binary modules that should be installed alongside the test
901	// This property only adds 64bit variants of the dependency
902	Data_device_bins_64 []string `android:"arch_variant"`
903
904	// list of device binary modules that should be installed alongside the test
905	// This property adds 32bit variants of the dependency if available, or else
906	// defaults to the 64bit variant
907	Data_device_bins_prefer32 []string `android:"arch_variant"`
908
909	// list of device binary modules that should be installed alongside the test
910	// This property only adds 32bit variants of the dependency
911	Data_device_bins_32 []string `android:"arch_variant"`
912}
913
914type testHelperLibraryProperties struct {
915	// list of compatibility suites (for example "cts", "vts") that the module should be
916	// installed into.
917	Test_suites []string `android:"arch_variant"`
918
919	// Install the test into a folder named for the module in all test suites.
920	Per_testcase_directory *bool
921}
922
923type prebuiltTestProperties struct {
924	// list of compatibility suites (for example "cts", "vts") that the module should be
925	// installed into.
926	Test_suites []string `android:"arch_variant"`
927
928	// the name of the test configuration (for example "AndroidTest.xml") that should be
929	// installed with the module.
930	Test_config *string `android:"path,arch_variant"`
931}
932
933type Test struct {
934	Library
935
936	testProperties testProperties
937
938	testConfig       android.Path
939	extraTestConfigs android.Paths
940	data             android.Paths
941}
942
943type TestHost struct {
944	Test
945
946	testHostProperties hostTestProperties
947}
948
949type TestHelperLibrary struct {
950	Library
951
952	testHelperLibraryProperties testHelperLibraryProperties
953}
954
955type JavaTestImport struct {
956	Import
957
958	prebuiltTestProperties prebuiltTestProperties
959
960	testConfig android.Path
961	dexJarFile android.Path
962}
963
964func (j *Test) InstallInTestcases() bool {
965	// Host java tests install into $(HOST_OUT_JAVA_LIBRARIES), and then are copied into
966	// testcases by base_rules.mk.
967	return !j.Host()
968}
969
970func (j *TestHelperLibrary) InstallInTestcases() bool {
971	return true
972}
973
974func (j *JavaTestImport) InstallInTestcases() bool {
975	return true
976}
977
978func (j *TestHost) addDataDeviceBinsDeps(ctx android.BottomUpMutatorContext) {
979	if len(j.testHostProperties.Data_device_bins_first) > 0 {
980		deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
981		ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_first...)
982	}
983
984	var maybeAndroid32Target *android.Target
985	var maybeAndroid64Target *android.Target
986	android32TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib32")
987	android64TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib64")
988	if len(android32TargetList) > 0 {
989		maybeAndroid32Target = &android32TargetList[0]
990	}
991	if len(android64TargetList) > 0 {
992		maybeAndroid64Target = &android64TargetList[0]
993	}
994
995	if len(j.testHostProperties.Data_device_bins_both) > 0 {
996		if maybeAndroid32Target == nil && maybeAndroid64Target == nil {
997			ctx.PropertyErrorf("data_device_bins_both", "no device targets available. Targets: %q", ctx.Config().Targets)
998			return
999		}
1000		if maybeAndroid32Target != nil {
1001			ctx.AddFarVariationDependencies(
1002				maybeAndroid32Target.Variations(),
1003				dataDeviceBinsTag,
1004				j.testHostProperties.Data_device_bins_both...,
1005			)
1006		}
1007		if maybeAndroid64Target != nil {
1008			ctx.AddFarVariationDependencies(
1009				maybeAndroid64Target.Variations(),
1010				dataDeviceBinsTag,
1011				j.testHostProperties.Data_device_bins_both...,
1012			)
1013		}
1014	}
1015
1016	if len(j.testHostProperties.Data_device_bins_prefer32) > 0 {
1017		if maybeAndroid32Target != nil {
1018			ctx.AddFarVariationDependencies(
1019				maybeAndroid32Target.Variations(),
1020				dataDeviceBinsTag,
1021				j.testHostProperties.Data_device_bins_prefer32...,
1022			)
1023		} else {
1024			if maybeAndroid64Target == nil {
1025				ctx.PropertyErrorf("data_device_bins_prefer32", "no device targets available. Targets: %q", ctx.Config().Targets)
1026				return
1027			}
1028			ctx.AddFarVariationDependencies(
1029				maybeAndroid64Target.Variations(),
1030				dataDeviceBinsTag,
1031				j.testHostProperties.Data_device_bins_prefer32...,
1032			)
1033		}
1034	}
1035
1036	if len(j.testHostProperties.Data_device_bins_32) > 0 {
1037		if maybeAndroid32Target == nil {
1038			ctx.PropertyErrorf("data_device_bins_32", "cannot find 32bit device target. Targets: %q", ctx.Config().Targets)
1039			return
1040		}
1041		deviceVariations := maybeAndroid32Target.Variations()
1042		ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_32...)
1043	}
1044
1045	if len(j.testHostProperties.Data_device_bins_64) > 0 {
1046		if maybeAndroid64Target == nil {
1047			ctx.PropertyErrorf("data_device_bins_64", "cannot find 64bit device target. Targets: %q", ctx.Config().Targets)
1048			return
1049		}
1050		deviceVariations := maybeAndroid64Target.Variations()
1051		ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_64...)
1052	}
1053}
1054
1055func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) {
1056	if len(j.testHostProperties.Data_native_bins) > 0 {
1057		for _, target := range ctx.MultiTargets() {
1058			ctx.AddVariationDependencies(target.Variations(), dataNativeBinsTag, j.testHostProperties.Data_native_bins...)
1059		}
1060	}
1061
1062	if len(j.testProperties.Jni_libs) > 0 {
1063		for _, target := range ctx.MultiTargets() {
1064			sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
1065			ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, j.testProperties.Jni_libs...)
1066		}
1067	}
1068
1069	j.addDataDeviceBinsDeps(ctx)
1070
1071	j.deps(ctx)
1072}
1073
1074func (j *TestHost) AddExtraResource(p android.Path) {
1075	j.extraResources = append(j.extraResources, p)
1076}
1077
1078func (j *TestHost) dataDeviceBins() []string {
1079	ret := make([]string, 0,
1080		len(j.testHostProperties.Data_device_bins_first)+
1081			len(j.testHostProperties.Data_device_bins_both)+
1082			len(j.testHostProperties.Data_device_bins_prefer32)+
1083			len(j.testHostProperties.Data_device_bins_32)+
1084			len(j.testHostProperties.Data_device_bins_64),
1085	)
1086
1087	ret = append(ret, j.testHostProperties.Data_device_bins_first...)
1088	ret = append(ret, j.testHostProperties.Data_device_bins_both...)
1089	ret = append(ret, j.testHostProperties.Data_device_bins_prefer32...)
1090	ret = append(ret, j.testHostProperties.Data_device_bins_32...)
1091	ret = append(ret, j.testHostProperties.Data_device_bins_64...)
1092
1093	return ret
1094}
1095
1096func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1097	var configs []tradefed.Config
1098	dataDeviceBins := j.dataDeviceBins()
1099	if len(dataDeviceBins) > 0 {
1100		// add Tradefed configuration to push device bins to device for testing
1101		remoteDir := filepath.Join("/data/local/tests/unrestricted/", j.Name())
1102		options := []tradefed.Option{{Name: "cleanup", Value: "true"}}
1103		for _, bin := range dataDeviceBins {
1104			fullPath := filepath.Join(remoteDir, bin)
1105			options = append(options, tradefed.Option{Name: "push-file", Key: bin, Value: fullPath})
1106		}
1107		configs = append(configs, tradefed.Object{
1108			Type:    "target_preparer",
1109			Class:   "com.android.tradefed.targetprep.PushFilePreparer",
1110			Options: options,
1111		})
1112	}
1113
1114	j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
1115}
1116
1117func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1118	j.generateAndroidBuildActionsWithConfig(ctx, nil)
1119}
1120
1121func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) {
1122	if j.testProperties.Test_options.Unit_test == nil && ctx.Host() {
1123		// TODO(b/): Clean temporary heuristic to avoid unexpected onboarding.
1124		defaultUnitTest := !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites)
1125		j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest)
1126	}
1127
1128	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
1129		j.testProperties.Test_suites, configs, j.testProperties.Auto_gen_config, j.testProperties.Test_options.Unit_test)
1130
1131	j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
1132
1133	j.extraTestConfigs = android.PathsForModuleSrc(ctx, j.testProperties.Test_options.Extra_test_configs)
1134
1135	ctx.VisitDirectDepsWithTag(dataNativeBinsTag, func(dep android.Module) {
1136		j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
1137	})
1138
1139	ctx.VisitDirectDepsWithTag(dataDeviceBinsTag, func(dep android.Module) {
1140		j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
1141	})
1142
1143	ctx.VisitDirectDepsWithTag(jniLibTag, func(dep android.Module) {
1144		sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
1145		if sharedLibInfo.SharedLibrary != nil {
1146			// Copy to an intermediate output directory to append "lib[64]" to the path,
1147			// so that it's compatible with the default rpath values.
1148			var relPath string
1149			if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
1150				relPath = filepath.Join("lib64", sharedLibInfo.SharedLibrary.Base())
1151			} else {
1152				relPath = filepath.Join("lib", sharedLibInfo.SharedLibrary.Base())
1153			}
1154			relocatedLib := android.PathForModuleOut(ctx, "relocated").Join(ctx, relPath)
1155			ctx.Build(pctx, android.BuildParams{
1156				Rule:   android.Cp,
1157				Input:  sharedLibInfo.SharedLibrary,
1158				Output: relocatedLib,
1159			})
1160			j.data = append(j.data, relocatedLib)
1161		} else {
1162			ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
1163		}
1164	})
1165
1166	j.Library.GenerateAndroidBuildActions(ctx)
1167}
1168
1169func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1170	j.Library.GenerateAndroidBuildActions(ctx)
1171}
1172
1173func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1174	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.prebuiltTestProperties.Test_config, nil,
1175		j.prebuiltTestProperties.Test_suites, nil, nil, nil)
1176
1177	j.Import.GenerateAndroidBuildActions(ctx)
1178}
1179
1180type testSdkMemberType struct {
1181	android.SdkMemberTypeBase
1182}
1183
1184func (mt *testSdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
1185	ctx.AddVariationDependencies(nil, dependencyTag, names...)
1186}
1187
1188func (mt *testSdkMemberType) IsInstance(module android.Module) bool {
1189	_, ok := module.(*Test)
1190	return ok
1191}
1192
1193func (mt *testSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
1194	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_test_import")
1195}
1196
1197func (mt *testSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
1198	return &testSdkMemberProperties{}
1199}
1200
1201type testSdkMemberProperties struct {
1202	android.SdkMemberPropertiesBase
1203
1204	JarToExport android.Path
1205	TestConfig  android.Path
1206}
1207
1208func (p *testSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
1209	test := variant.(*Test)
1210
1211	implementationJars := test.ImplementationJars()
1212	if len(implementationJars) != 1 {
1213		panic(fmt.Errorf("there must be only one implementation jar from %q", test.Name()))
1214	}
1215
1216	p.JarToExport = implementationJars[0]
1217	p.TestConfig = test.testConfig
1218}
1219
1220func (p *testSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
1221	builder := ctx.SnapshotBuilder()
1222
1223	exportedJar := p.JarToExport
1224	if exportedJar != nil {
1225		snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(ctx, p.OsPrefix(), ctx.Name())
1226		builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
1227
1228		propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
1229	}
1230
1231	testConfig := p.TestConfig
1232	if testConfig != nil {
1233		snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.OsPrefix(), ctx.Name(), testConfigSuffix)
1234		builder.CopyToSnapshot(testConfig, snapshotRelativeTestConfigPath)
1235		propertySet.AddProperty("test_config", snapshotRelativeTestConfigPath)
1236	}
1237}
1238
1239// java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and
1240// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
1241//
1242// By default, a java_test has a single variant that produces a `.jar` file containing `classes.dex` files that were
1243// compiled against the device bootclasspath.
1244//
1245// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
1246// compiled against the host bootclasspath.
1247func TestFactory() android.Module {
1248	module := &Test{}
1249
1250	module.addHostAndDeviceProperties()
1251	module.AddProperties(&module.testProperties)
1252
1253	module.Module.properties.Installable = proptools.BoolPtr(true)
1254	module.Module.dexpreopter.isTest = true
1255	module.Module.linter.test = true
1256
1257	android.InitSdkAwareModule(module)
1258	InitJavaModule(module, android.HostAndDeviceSupported)
1259	return module
1260}
1261
1262// java_test_helper_library creates a java library and makes sure that it is added to the appropriate test suite.
1263func TestHelperLibraryFactory() android.Module {
1264	module := &TestHelperLibrary{}
1265
1266	module.addHostAndDeviceProperties()
1267	module.AddProperties(&module.testHelperLibraryProperties)
1268
1269	module.Module.properties.Installable = proptools.BoolPtr(true)
1270	module.Module.dexpreopter.isTest = true
1271	module.Module.linter.test = true
1272
1273	InitJavaModule(module, android.HostAndDeviceSupported)
1274	return module
1275}
1276
1277// java_test_import imports one or more `.jar` files into the build graph as if they were built by a java_test module
1278// and makes sure that it is added to the appropriate test suite.
1279//
1280// By default, a java_test_import has a single variant that expects a `.jar` file containing `.class` files that were
1281// compiled against an Android classpath.
1282//
1283// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1284// for host modules.
1285func JavaTestImportFactory() android.Module {
1286	module := &JavaTestImport{}
1287
1288	module.AddProperties(
1289		&module.Import.properties,
1290		&module.prebuiltTestProperties)
1291
1292	module.Import.properties.Installable = proptools.BoolPtr(true)
1293
1294	android.InitPrebuiltModule(module, &module.properties.Jars)
1295	android.InitApexModule(module)
1296	android.InitSdkAwareModule(module)
1297	InitJavaModule(module, android.HostAndDeviceSupported)
1298	return module
1299}
1300
1301// java_test_host builds a and links sources into a `.jar` file for the host, and creates an `AndroidTest.xml` file to
1302// allow running the test with `atest` or a `TEST_MAPPING` file.
1303//
1304// A java_test_host has a single variant that produces a `.jar` file containing `.class` files that were
1305// compiled against the host bootclasspath.
1306func TestHostFactory() android.Module {
1307	module := &TestHost{}
1308
1309	module.addHostProperties()
1310	module.AddProperties(&module.testProperties)
1311	module.AddProperties(&module.testHostProperties)
1312
1313	InitTestHost(
1314		module,
1315		proptools.BoolPtr(true),
1316		nil,
1317		nil)
1318
1319	InitJavaModuleMultiTargets(module, android.HostSupported)
1320
1321	return module
1322}
1323
1324func InitTestHost(th *TestHost, installable *bool, testSuites []string, autoGenConfig *bool) {
1325	th.properties.Installable = installable
1326	th.testProperties.Auto_gen_config = autoGenConfig
1327	th.testProperties.Test_suites = testSuites
1328}
1329
1330//
1331// Java Binaries (.jar file plus wrapper script)
1332//
1333
1334type binaryProperties struct {
1335	// installable script to execute the resulting jar
1336	Wrapper *string `android:"path,arch_variant"`
1337
1338	// Name of the class containing main to be inserted into the manifest as Main-Class.
1339	Main_class *string
1340
1341	// Names of modules containing JNI libraries that should be installed alongside the host
1342	// variant of the binary.
1343	Jni_libs []string `android:"arch_variant"`
1344}
1345
1346type Binary struct {
1347	Library
1348
1349	binaryProperties binaryProperties
1350
1351	isWrapperVariant bool
1352
1353	wrapperFile android.Path
1354	binaryFile  android.InstallPath
1355}
1356
1357func (j *Binary) HostToolPath() android.OptionalPath {
1358	return android.OptionalPathForPath(j.binaryFile)
1359}
1360
1361func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1362	if ctx.Arch().ArchType == android.Common {
1363		// Compile the jar
1364		if j.binaryProperties.Main_class != nil {
1365			if j.properties.Manifest != nil {
1366				ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
1367			}
1368			manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
1369			GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
1370			j.overrideManifest = android.OptionalPathForPath(manifestFile)
1371		}
1372
1373		j.Library.GenerateAndroidBuildActions(ctx)
1374	} else {
1375		// Handle the binary wrapper
1376		j.isWrapperVariant = true
1377
1378		if j.binaryProperties.Wrapper != nil {
1379			j.wrapperFile = android.PathForModuleSrc(ctx, *j.binaryProperties.Wrapper)
1380		} else {
1381			if ctx.Windows() {
1382				ctx.PropertyErrorf("wrapper", "wrapper is required for Windows")
1383			}
1384
1385			j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
1386		}
1387
1388		ext := ""
1389		if ctx.Windows() {
1390			ext = ".bat"
1391		}
1392
1393		// The host installation rules make the installed wrapper depend on all the dependencies
1394		// of the wrapper variant, which will include the common variant's jar file and any JNI
1395		// libraries.  This is verified by TestBinary.
1396		j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
1397			ctx.ModuleName()+ext, j.wrapperFile)
1398	}
1399}
1400
1401func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
1402	if ctx.Arch().ArchType == android.Common || ctx.BazelConversionMode() {
1403		j.deps(ctx)
1404	}
1405	if ctx.Arch().ArchType != android.Common || ctx.BazelConversionMode() {
1406		// These dependencies ensure the host installation rules will install the jar file and
1407		// the jni libraries when the wrapper is installed.
1408		ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
1409		ctx.AddVariationDependencies(
1410			[]blueprint.Variation{{Mutator: "arch", Variation: android.CommonArch.String()}},
1411			binaryInstallTag, ctx.ModuleName())
1412	}
1413}
1414
1415// java_binary builds a `.jar` file and a shell script that executes it for the device, and possibly for the host
1416// as well.
1417//
1418// By default, a java_binary has a single variant that produces a `.jar` file containing `classes.dex` files that were
1419// compiled against the device bootclasspath.
1420//
1421// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
1422// compiled against the host bootclasspath.
1423func BinaryFactory() android.Module {
1424	module := &Binary{}
1425
1426	module.addHostAndDeviceProperties()
1427	module.AddProperties(&module.binaryProperties)
1428
1429	module.Module.properties.Installable = proptools.BoolPtr(true)
1430
1431	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst)
1432	android.InitDefaultableModule(module)
1433	android.InitBazelModule(module)
1434
1435	return module
1436}
1437
1438// java_binary_host builds a `.jar` file and a shell script that executes it for the host.
1439//
1440// A java_binary_host has a single variant that produces a `.jar` file containing `.class` files that were
1441// compiled against the host bootclasspath.
1442func BinaryHostFactory() android.Module {
1443	module := &Binary{}
1444
1445	module.addHostProperties()
1446	module.AddProperties(&module.binaryProperties)
1447
1448	module.Module.properties.Installable = proptools.BoolPtr(true)
1449
1450	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst)
1451	android.InitDefaultableModule(module)
1452	android.InitBazelModule(module)
1453	return module
1454}
1455
1456//
1457// Java prebuilts
1458//
1459
1460type ImportProperties struct {
1461	Jars []string `android:"path,arch_variant"`
1462
1463	// The version of the SDK that the source prebuilt file was built against. Defaults to the
1464	// current version if not specified.
1465	Sdk_version *string
1466
1467	// The minimum version of the SDK that this module supports. Defaults to sdk_version if not
1468	// specified.
1469	Min_sdk_version *string
1470
1471	Installable *bool
1472
1473	// If not empty, classes are restricted to the specified packages and their sub-packages.
1474	Permitted_packages []string
1475
1476	// List of shared java libs that this module has dependencies to
1477	Libs []string
1478
1479	// List of files to remove from the jar file(s)
1480	Exclude_files []string
1481
1482	// List of directories to remove from the jar file(s)
1483	Exclude_dirs []string
1484
1485	// if set to true, run Jetifier against .jar file. Defaults to false.
1486	Jetifier *bool
1487
1488	// set the name of the output
1489	Stem *string
1490
1491	Aidl struct {
1492		// directories that should be added as include directories for any aidl sources of modules
1493		// that depend on this module, as well as to aidl for this module.
1494		Export_include_dirs []string
1495	}
1496}
1497
1498type Import struct {
1499	android.ModuleBase
1500	android.DefaultableModuleBase
1501	android.ApexModuleBase
1502	android.BazelModuleBase
1503	prebuilt android.Prebuilt
1504	android.SdkBase
1505
1506	// Functionality common to Module and Import.
1507	embeddableInModuleAndImport
1508
1509	hiddenAPI
1510	dexer
1511	dexpreopter
1512
1513	properties ImportProperties
1514
1515	// output file containing classes.dex and resources
1516	dexJarFile        OptionalDexJarPath
1517	dexJarInstallFile android.Path
1518
1519	combinedClasspathFile android.Path
1520	classLoaderContexts   dexpreopt.ClassLoaderContextMap
1521	exportAidlIncludeDirs android.Paths
1522
1523	hideApexVariantFromMake bool
1524
1525	sdkVersion    android.SdkSpec
1526	minSdkVersion android.SdkSpec
1527}
1528
1529var _ PermittedPackagesForUpdatableBootJars = (*Import)(nil)
1530
1531func (j *Import) PermittedPackagesForUpdatableBootJars() []string {
1532	return j.properties.Permitted_packages
1533}
1534
1535func (j *Import) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
1536	return android.SdkSpecFrom(ctx, String(j.properties.Sdk_version))
1537}
1538
1539func (j *Import) SystemModules() string {
1540	return "none"
1541}
1542
1543func (j *Import) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
1544	if j.properties.Min_sdk_version != nil {
1545		return android.SdkSpecFrom(ctx, *j.properties.Min_sdk_version)
1546	}
1547	return j.SdkVersion(ctx)
1548}
1549
1550func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
1551	return j.SdkVersion(ctx)
1552}
1553
1554func (j *Import) Prebuilt() *android.Prebuilt {
1555	return &j.prebuilt
1556}
1557
1558func (j *Import) PrebuiltSrcs() []string {
1559	return j.properties.Jars
1560}
1561
1562func (j *Import) Name() string {
1563	return j.prebuilt.Name(j.ModuleBase.Name())
1564}
1565
1566func (j *Import) Stem() string {
1567	return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
1568}
1569
1570func (a *Import) JacocoReportClassesFile() android.Path {
1571	return nil
1572}
1573
1574func (j *Import) LintDepSets() LintDepSets {
1575	return LintDepSets{}
1576}
1577
1578func (j *Import) getStrictUpdatabilityLinting() bool {
1579	return false
1580}
1581
1582func (j *Import) setStrictUpdatabilityLinting(bool) {
1583}
1584
1585func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
1586	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
1587
1588	if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
1589		sdkDeps(ctx, android.SdkContext(j), j.dexer)
1590	}
1591}
1592
1593func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1594	j.sdkVersion = j.SdkVersion(ctx)
1595	j.minSdkVersion = j.MinSdkVersion(ctx)
1596
1597	if !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() {
1598		j.hideApexVariantFromMake = true
1599	}
1600
1601	if ctx.Windows() {
1602		j.HideFromMake()
1603	}
1604
1605	jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
1606
1607	jarName := j.Stem() + ".jar"
1608	outputFile := android.PathForModuleOut(ctx, "combined", jarName)
1609	TransformJarsToJar(ctx, outputFile, "for prebuilts", jars, android.OptionalPath{},
1610		false, j.properties.Exclude_files, j.properties.Exclude_dirs)
1611	if Bool(j.properties.Jetifier) {
1612		inputFile := outputFile
1613		outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
1614		TransformJetifier(ctx, outputFile, inputFile)
1615	}
1616	j.combinedClasspathFile = outputFile
1617	j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
1618
1619	var flags javaBuilderFlags
1620
1621	ctx.VisitDirectDeps(func(module android.Module) {
1622		tag := ctx.OtherModuleDependencyTag(module)
1623
1624		if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
1625			dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
1626			switch tag {
1627			case libTag:
1628				flags.classpath = append(flags.classpath, dep.HeaderJars...)
1629				flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
1630			case staticLibTag:
1631				flags.classpath = append(flags.classpath, dep.HeaderJars...)
1632			case bootClasspathTag:
1633				flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...)
1634			}
1635		} else if dep, ok := module.(SdkLibraryDependency); ok {
1636			switch tag {
1637			case libTag:
1638				flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
1639			}
1640		}
1641
1642		addCLCFromDep(ctx, module, j.classLoaderContexts)
1643	})
1644
1645	if Bool(j.properties.Installable) {
1646		var installDir android.InstallPath
1647		if ctx.InstallInTestcases() {
1648			var archDir string
1649			if !ctx.Host() {
1650				archDir = ctx.DeviceConfig().DeviceArch()
1651			}
1652			installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
1653		} else {
1654			installDir = android.PathForModuleInstall(ctx, "framework")
1655		}
1656		ctx.InstallFile(installDir, jarName, outputFile)
1657	}
1658
1659	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
1660
1661	if ctx.Device() {
1662		// If this is a variant created for a prebuilt_apex then use the dex implementation jar
1663		// obtained from the associated deapexer module.
1664		ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
1665		if ai.ForPrebuiltApex {
1666			// Get the path of the dex implementation jar from the `deapexer` module.
1667			di := android.FindDeapexerProviderForModule(ctx)
1668			if di == nil {
1669				return // An error has been reported by FindDeapexerProviderForModule.
1670			}
1671			if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(j.BaseModuleName())); dexOutputPath != nil {
1672				dexJarFile := makeDexJarPathFromPath(dexOutputPath)
1673				j.dexJarFile = dexJarFile
1674				installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName()))
1675				j.dexJarInstallFile = installPath
1676
1677				j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath)
1678				setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
1679				j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
1680				j.dexpreopt(ctx, dexOutputPath)
1681
1682				// Initialize the hiddenapi structure.
1683				j.initHiddenAPI(ctx, dexJarFile, outputFile, j.dexProperties.Uncompress_dex)
1684			} else {
1685				// This should never happen as a variant for a prebuilt_apex is only created if the
1686				// prebuilt_apex has been configured to export the java library dex file.
1687				ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName())
1688			}
1689		} else if Bool(j.dexProperties.Compile_dex) {
1690			sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
1691			if sdkDep.invalidVersion {
1692				ctx.AddMissingDependencies(sdkDep.bootclasspath)
1693				ctx.AddMissingDependencies(sdkDep.java9Classpath)
1694			} else if sdkDep.useFiles {
1695				// sdkDep.jar is actually equivalent to turbine header.jar.
1696				flags.classpath = append(flags.classpath, sdkDep.jars...)
1697			}
1698
1699			// Dex compilation
1700
1701			j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
1702				ctx, android.PathForModuleInstall(ctx, "framework", jarName))
1703			setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
1704			j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
1705
1706			var dexOutputFile android.OutputPath
1707			dexOutputFile = j.dexer.compileDex(ctx, flags, j.MinSdkVersion(ctx), outputFile, jarName)
1708			if ctx.Failed() {
1709				return
1710			}
1711
1712			// Initialize the hiddenapi structure.
1713			j.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), outputFile, j.dexProperties.Uncompress_dex)
1714
1715			// Encode hidden API flags in dex file.
1716			dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
1717
1718			j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
1719			j.dexJarInstallFile = android.PathForModuleInstall(ctx, "framework", jarName)
1720		}
1721	}
1722
1723	ctx.SetProvider(JavaInfoProvider, JavaInfo{
1724		HeaderJars:                     android.PathsIfNonNil(j.combinedClasspathFile),
1725		ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile),
1726		ImplementationJars:             android.PathsIfNonNil(j.combinedClasspathFile),
1727		AidlIncludeDirs:                j.exportAidlIncludeDirs,
1728	})
1729}
1730
1731func (j *Import) OutputFiles(tag string) (android.Paths, error) {
1732	switch tag {
1733	case "", ".jar":
1734		return android.Paths{j.combinedClasspathFile}, nil
1735	default:
1736		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1737	}
1738}
1739
1740var _ android.OutputFileProducer = (*Import)(nil)
1741
1742func (j *Import) HeaderJars() android.Paths {
1743	if j.combinedClasspathFile == nil {
1744		return nil
1745	}
1746	return android.Paths{j.combinedClasspathFile}
1747}
1748
1749func (j *Import) ImplementationAndResourcesJars() android.Paths {
1750	if j.combinedClasspathFile == nil {
1751		return nil
1752	}
1753	return android.Paths{j.combinedClasspathFile}
1754}
1755
1756func (j *Import) DexJarBuildPath() OptionalDexJarPath {
1757	return j.dexJarFile
1758}
1759
1760func (j *Import) DexJarInstallPath() android.Path {
1761	return j.dexJarInstallFile
1762}
1763
1764func (j *Import) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
1765	return j.classLoaderContexts
1766}
1767
1768var _ android.ApexModule = (*Import)(nil)
1769
1770// Implements android.ApexModule
1771func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
1772	return j.depIsInSameApex(ctx, dep)
1773}
1774
1775// Implements android.ApexModule
1776func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
1777	sdkVersion android.ApiLevel) error {
1778	sdkSpec := j.MinSdkVersion(ctx)
1779	if !sdkSpec.Specified() {
1780		return fmt.Errorf("min_sdk_version is not specified")
1781	}
1782	if sdkSpec.Kind == android.SdkCore {
1783		return nil
1784	}
1785	if sdkSpec.ApiLevel.GreaterThan(sdkVersion) {
1786		return fmt.Errorf("newer SDK(%v)", sdkSpec.ApiLevel)
1787	}
1788	return nil
1789}
1790
1791// requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or
1792// java_sdk_library_import with the specified base module name requires to be exported from a
1793// prebuilt_apex/apex_set.
1794func requiredFilesFromPrebuiltApexForImport(name string) []string {
1795	// Add the dex implementation jar to the set of exported files.
1796	return []string{
1797		apexRootRelativePathToJavaLib(name),
1798	}
1799}
1800
1801// apexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
1802// the java library with the specified name.
1803func apexRootRelativePathToJavaLib(name string) string {
1804	return filepath.Join("javalib", name+".jar")
1805}
1806
1807var _ android.RequiredFilesFromPrebuiltApex = (*Import)(nil)
1808
1809func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []string {
1810	name := j.BaseModuleName()
1811	return requiredFilesFromPrebuiltApexForImport(name)
1812}
1813
1814// Add compile time check for interface implementation
1815var _ android.IDEInfo = (*Import)(nil)
1816var _ android.IDECustomizedModuleName = (*Import)(nil)
1817
1818// Collect information for opening IDE project files in java/jdeps.go.
1819
1820func (j *Import) IDEInfo(dpInfo *android.IdeInfo) {
1821	dpInfo.Jars = append(dpInfo.Jars, j.PrebuiltSrcs()...)
1822}
1823
1824func (j *Import) IDECustomizedModuleName() string {
1825	// TODO(b/113562217): Extract the base module name from the Import name, often the Import name
1826	// has a prefix "prebuilt_". Remove the prefix explicitly if needed until we find a better
1827	// solution to get the Import name.
1828	return android.RemoveOptionalPrebuiltPrefix(j.Name())
1829}
1830
1831var _ android.PrebuiltInterface = (*Import)(nil)
1832
1833func (j *Import) IsInstallable() bool {
1834	return Bool(j.properties.Installable)
1835}
1836
1837var _ DexpreopterInterface = (*Import)(nil)
1838
1839// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library module.
1840//
1841// By default, a java_import has a single variant that expects a `.jar` file containing `.class` files that were
1842// compiled against an Android classpath.
1843//
1844// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1845// for host modules.
1846func ImportFactory() android.Module {
1847	module := &Import{}
1848
1849	module.AddProperties(
1850		&module.properties,
1851		&module.dexer.dexProperties,
1852	)
1853
1854	module.initModuleAndImport(module)
1855
1856	module.dexProperties.Optimize.EnabledByDefault = false
1857
1858	android.InitPrebuiltModule(module, &module.properties.Jars)
1859	android.InitApexModule(module)
1860	android.InitSdkAwareModule(module)
1861	android.InitBazelModule(module)
1862	InitJavaModule(module, android.HostAndDeviceSupported)
1863	return module
1864}
1865
1866// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library_host
1867// module.
1868//
1869// A java_import_host has a single variant that expects a `.jar` file containing `.class` files that were
1870// compiled against a host bootclasspath.
1871func ImportFactoryHost() android.Module {
1872	module := &Import{}
1873
1874	module.AddProperties(&module.properties)
1875
1876	android.InitPrebuiltModule(module, &module.properties.Jars)
1877	android.InitApexModule(module)
1878	android.InitBazelModule(module)
1879	InitJavaModule(module, android.HostSupported)
1880	return module
1881}
1882
1883// dex_import module
1884
1885type DexImportProperties struct {
1886	Jars []string `android:"path"`
1887
1888	// set the name of the output
1889	Stem *string
1890}
1891
1892type DexImport struct {
1893	android.ModuleBase
1894	android.DefaultableModuleBase
1895	android.ApexModuleBase
1896	prebuilt android.Prebuilt
1897
1898	properties DexImportProperties
1899
1900	dexJarFile OptionalDexJarPath
1901
1902	dexpreopter
1903
1904	hideApexVariantFromMake bool
1905}
1906
1907func (j *DexImport) Prebuilt() *android.Prebuilt {
1908	return &j.prebuilt
1909}
1910
1911func (j *DexImport) PrebuiltSrcs() []string {
1912	return j.properties.Jars
1913}
1914
1915func (j *DexImport) Name() string {
1916	return j.prebuilt.Name(j.ModuleBase.Name())
1917}
1918
1919func (j *DexImport) Stem() string {
1920	return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
1921}
1922
1923func (a *DexImport) JacocoReportClassesFile() android.Path {
1924	return nil
1925}
1926
1927func (a *DexImport) LintDepSets() LintDepSets {
1928	return LintDepSets{}
1929}
1930
1931func (j *DexImport) IsInstallable() bool {
1932	return true
1933}
1934
1935func (j *DexImport) getStrictUpdatabilityLinting() bool {
1936	return false
1937}
1938
1939func (j *DexImport) setStrictUpdatabilityLinting(bool) {
1940}
1941
1942func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1943	if len(j.properties.Jars) != 1 {
1944		ctx.PropertyErrorf("jars", "exactly one jar must be provided")
1945	}
1946
1947	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
1948	if !apexInfo.IsForPlatform() {
1949		j.hideApexVariantFromMake = true
1950	}
1951
1952	j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
1953		ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
1954	j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
1955
1956	inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
1957	dexOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar")
1958
1959	if j.dexpreopter.uncompressedDex {
1960		rule := android.NewRuleBuilder(pctx, ctx)
1961
1962		temporary := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar.unaligned")
1963		rule.Temporary(temporary)
1964
1965		// use zip2zip to uncompress classes*.dex files
1966		rule.Command().
1967			BuiltTool("zip2zip").
1968			FlagWithInput("-i ", inputJar).
1969			FlagWithOutput("-o ", temporary).
1970			FlagWithArg("-0 ", "'classes*.dex'")
1971
1972		// use zipalign to align uncompressed classes*.dex files
1973		rule.Command().
1974			BuiltTool("zipalign").
1975			Flag("-f").
1976			Text("4").
1977			Input(temporary).
1978			Output(dexOutputFile)
1979
1980		rule.DeleteTemporaryFiles()
1981
1982		rule.Build("uncompress_dex", "uncompress dex")
1983	} else {
1984		ctx.Build(pctx, android.BuildParams{
1985			Rule:   android.Cp,
1986			Input:  inputJar,
1987			Output: dexOutputFile,
1988		})
1989	}
1990
1991	j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
1992
1993	j.dexpreopt(ctx, dexOutputFile)
1994
1995	if apexInfo.IsForPlatform() {
1996		ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
1997			j.Stem()+".jar", dexOutputFile)
1998	}
1999}
2000
2001func (j *DexImport) DexJarBuildPath() OptionalDexJarPath {
2002	return j.dexJarFile
2003}
2004
2005var _ android.ApexModule = (*DexImport)(nil)
2006
2007// Implements android.ApexModule
2008func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
2009	sdkVersion android.ApiLevel) error {
2010	// we don't check prebuilt modules for sdk_version
2011	return nil
2012}
2013
2014// dex_import imports a `.jar` file containing classes.dex files.
2015//
2016// A dex_import module cannot be used as a dependency of a java_* or android_* module, it can only be installed
2017// to the device.
2018func DexImportFactory() android.Module {
2019	module := &DexImport{}
2020
2021	module.AddProperties(&module.properties)
2022
2023	android.InitPrebuiltModule(module, &module.properties.Jars)
2024	android.InitApexModule(module)
2025	InitJavaModule(module, android.DeviceSupported)
2026	return module
2027}
2028
2029//
2030// Defaults
2031//
2032type Defaults struct {
2033	android.ModuleBase
2034	android.DefaultsModuleBase
2035	android.ApexModuleBase
2036}
2037
2038// java_defaults provides a set of properties that can be inherited by other java or android modules.
2039//
2040// A module can use the properties from a java_defaults module using `defaults: ["defaults_module_name"]`.  Each
2041// property in the defaults module that exists in the depending module will be prepended to the depending module's
2042// value for that property.
2043//
2044// Example:
2045//
2046//     java_defaults {
2047//         name: "example_defaults",
2048//         srcs: ["common/**/*.java"],
2049//         javacflags: ["-Xlint:all"],
2050//         aaptflags: ["--auto-add-overlay"],
2051//     }
2052//
2053//     java_library {
2054//         name: "example",
2055//         defaults: ["example_defaults"],
2056//         srcs: ["example/**/*.java"],
2057//     }
2058//
2059// is functionally identical to:
2060//
2061//     java_library {
2062//         name: "example",
2063//         srcs: [
2064//             "common/**/*.java",
2065//             "example/**/*.java",
2066//         ],
2067//         javacflags: ["-Xlint:all"],
2068//     }
2069func DefaultsFactory() android.Module {
2070	module := &Defaults{}
2071
2072	module.AddProperties(
2073		&CommonProperties{},
2074		&DeviceProperties{},
2075		&OverridableDeviceProperties{},
2076		&DexProperties{},
2077		&DexpreoptProperties{},
2078		&android.ProtoProperties{},
2079		&aaptProperties{},
2080		&androidLibraryProperties{},
2081		&appProperties{},
2082		&appTestProperties{},
2083		&overridableAppProperties{},
2084		&testProperties{},
2085		&ImportProperties{},
2086		&AARImportProperties{},
2087		&sdkLibraryProperties{},
2088		&commonToSdkLibraryAndImportProperties{},
2089		&DexImportProperties{},
2090		&android.ApexProperties{},
2091		&RuntimeResourceOverlayProperties{},
2092		&LintProperties{},
2093		&appTestHelperAppProperties{},
2094	)
2095
2096	android.InitDefaultsModule(module)
2097	return module
2098}
2099
2100func kytheExtractJavaFactory() android.Singleton {
2101	return &kytheExtractJavaSingleton{}
2102}
2103
2104type kytheExtractJavaSingleton struct {
2105}
2106
2107func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonContext) {
2108	var xrefTargets android.Paths
2109	ctx.VisitAllModules(func(module android.Module) {
2110		if javaModule, ok := module.(xref); ok {
2111			xrefTargets = append(xrefTargets, javaModule.XrefJavaFiles()...)
2112		}
2113	})
2114	// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
2115	if len(xrefTargets) > 0 {
2116		ctx.Phony("xref_java", xrefTargets...)
2117	}
2118}
2119
2120var Bool = proptools.Bool
2121var BoolDefault = proptools.BoolDefault
2122var String = proptools.String
2123var inList = android.InList
2124
2125// Add class loader context (CLC) of a given dependency to the current CLC.
2126func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
2127	clcMap dexpreopt.ClassLoaderContextMap) {
2128
2129	dep, ok := depModule.(UsesLibraryDependency)
2130	if !ok {
2131		return
2132	}
2133
2134	depName := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(depModule))
2135
2136	var sdkLib *string
2137	if lib, ok := depModule.(SdkLibraryDependency); ok && lib.sharedLibrary() {
2138		// A shared SDK library. This should be added as a top-level CLC element.
2139		sdkLib = &depName
2140	} else if ulib, ok := depModule.(ProvidesUsesLib); ok {
2141		// A non-SDK library disguised as an SDK library by the means of `provides_uses_lib`
2142		// property. This should be handled in the same way as a shared SDK library.
2143		sdkLib = ulib.ProvidesUsesLib()
2144	}
2145
2146	depTag := ctx.OtherModuleDependencyTag(depModule)
2147	if depTag == libTag {
2148		// Ok, propagate <uses-library> through non-static library dependencies.
2149	} else if tag, ok := depTag.(usesLibraryDependencyTag); ok &&
2150		tag.sdkVersion == dexpreopt.AnySdkVersion && tag.implicit {
2151		// Ok, propagate <uses-library> through non-compatibility implicit <uses-library>
2152		// dependencies.
2153	} else if depTag == staticLibTag {
2154		// Propagate <uses-library> through static library dependencies, unless it is a component
2155		// library (such as stubs). Component libraries have a dependency on their SDK library,
2156		// which should not be pulled just because of a static component library.
2157		if sdkLib != nil {
2158			return
2159		}
2160	} else {
2161		// Don't propagate <uses-library> for other dependency tags.
2162		return
2163	}
2164
2165	// If this is an SDK (or SDK-like) library, then it should be added as a node in the CLC tree,
2166	// and its CLC should be added as subtree of that node. Otherwise the library is not a
2167	// <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies
2168	// from its CLC should be added to the current CLC.
2169	if sdkLib != nil {
2170		clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, true,
2171			dep.DexJarBuildPath().PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
2172	} else {
2173		clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
2174	}
2175}
2176
2177type javaCommonAttributes struct {
2178	Srcs      bazel.LabelListAttribute
2179	Plugins   bazel.LabelListAttribute
2180	Javacopts bazel.StringListAttribute
2181}
2182
2183type javaDependencyLabels struct {
2184	// Dependencies which DO NOT contribute to the API visible to upstream dependencies.
2185	Deps bazel.LabelListAttribute
2186	// Dependencies which DO contribute to the API visible to upstream dependencies.
2187	StaticDeps bazel.LabelListAttribute
2188}
2189
2190// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules
2191// and also separates dependencies into dynamic dependencies and static dependencies.
2192// Each corresponding Bazel target type, can have a different method for handling
2193// dynamic vs. static dependencies, and so these are returned to the calling function.
2194type eventLogTagsAttributes struct {
2195	Srcs bazel.LabelListAttribute
2196}
2197
2198func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) {
2199	var srcs bazel.LabelListAttribute
2200	archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
2201	for axis, configToProps := range archVariantProps {
2202		for config, _props := range configToProps {
2203			if archProps, ok := _props.(*CommonProperties); ok {
2204				archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Srcs, archProps.Exclude_srcs)
2205				srcs.SetSelectValue(axis, config, archSrcs)
2206			}
2207		}
2208	}
2209
2210	javaSrcPartition := "java"
2211	protoSrcPartition := "proto"
2212	logtagSrcPartition := "logtag"
2213	srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
2214		javaSrcPartition:   bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
2215		logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
2216		protoSrcPartition:  android.ProtoSrcLabelPartition,
2217	})
2218
2219	javaSrcs := srcPartitions[javaSrcPartition]
2220
2221	var logtagsSrcs bazel.LabelList
2222	if !srcPartitions[logtagSrcPartition].IsEmpty() {
2223		logtagsLibName := m.Name() + "_logtags"
2224		logtagsSrcs = bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}})
2225		ctx.CreateBazelTargetModule(
2226			bazel.BazelTargetModuleProperties{
2227				Rule_class:        "event_log_tags",
2228				Bzl_load_location: "//build/make/tools:event_log_tags.bzl",
2229			},
2230			android.CommonAttributes{Name: logtagsLibName},
2231			&eventLogTagsAttributes{
2232				Srcs: srcPartitions[logtagSrcPartition],
2233			},
2234		)
2235	}
2236	javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs))
2237
2238	var javacopts []string
2239	if m.properties.Javacflags != nil {
2240		javacopts = append(javacopts, m.properties.Javacflags...)
2241	}
2242	epEnabled := m.properties.Errorprone.Enabled
2243	//TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
2244	if Bool(epEnabled) {
2245		javacopts = append(javacopts, m.properties.Errorprone.Javacflags...)
2246	}
2247
2248	commonAttrs := &javaCommonAttributes{
2249		Srcs: javaSrcs,
2250		Plugins: bazel.MakeLabelListAttribute(
2251			android.BazelLabelForModuleDeps(ctx, m.properties.Plugins),
2252		),
2253		Javacopts: bazel.MakeStringListAttribute(javacopts),
2254	}
2255
2256	depLabels := &javaDependencyLabels{}
2257
2258	var deps bazel.LabelList
2259	if m.properties.Libs != nil {
2260		deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Libs))
2261	}
2262
2263	var staticDeps bazel.LabelList
2264	if m.properties.Static_libs != nil {
2265		staticDeps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Static_libs))
2266	}
2267
2268	protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])
2269	// Soong does not differentiate between a java_library and the Bazel equivalent of
2270	// a java_proto_library + proto_library pair. Instead, in Soong proto sources are
2271	// listed directly in the srcs of a java_library, and the classes produced
2272	// by protoc are included directly in the resulting JAR. Thus upstream dependencies
2273	// that depend on a java_library with proto sources can link directly to the protobuf API,
2274	// and so this should be a static dependency.
2275	staticDeps.Add(protoDepLabel)
2276
2277	depLabels.Deps = bazel.MakeLabelListAttribute(deps)
2278	depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
2279
2280	return commonAttrs, depLabels
2281}
2282
2283type javaLibraryAttributes struct {
2284	*javaCommonAttributes
2285	Deps    bazel.LabelListAttribute
2286	Exports bazel.LabelListAttribute
2287}
2288
2289func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
2290	commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx)
2291
2292	deps := depLabels.Deps
2293	if !commonAttrs.Srcs.IsEmpty() {
2294		deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
2295
2296		sdkVersion := m.SdkVersion(ctx)
2297		if sdkVersion.Kind == android.SdkPublic && sdkVersion.ApiLevel == android.FutureApiLevel {
2298			// TODO(b/220869005) remove forced dependency on current public android.jar
2299			deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import"))
2300		}
2301	} else if !depLabels.Deps.IsEmpty() {
2302		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
2303	}
2304
2305	attrs := &javaLibraryAttributes{
2306		javaCommonAttributes: commonAttrs,
2307		Deps:                 deps,
2308		Exports:              depLabels.StaticDeps,
2309	}
2310
2311	props := bazel.BazelTargetModuleProperties{
2312		Rule_class:        "java_library",
2313		Bzl_load_location: "//build/bazel/rules/java:library.bzl",
2314	}
2315
2316	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
2317}
2318
2319type javaBinaryHostAttributes struct {
2320	*javaCommonAttributes
2321	Deps         bazel.LabelListAttribute
2322	Runtime_deps bazel.LabelListAttribute
2323	Main_class   string
2324	Jvm_flags    bazel.StringListAttribute
2325}
2326
2327// JavaBinaryHostBp2Build is for java_binary_host bp2build.
2328func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
2329	commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx)
2330
2331	deps := depLabels.Deps
2332	deps.Append(depLabels.StaticDeps)
2333	if m.binaryProperties.Jni_libs != nil {
2334		deps.Append(bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs)))
2335	}
2336
2337	var runtimeDeps bazel.LabelListAttribute
2338	if commonAttrs.Srcs.IsEmpty() {
2339		// if there are no sources, then the dependencies can only be used at runtime
2340		runtimeDeps = deps
2341		deps = bazel.LabelListAttribute{}
2342	}
2343
2344	mainClass := ""
2345	if m.binaryProperties.Main_class != nil {
2346		mainClass = *m.binaryProperties.Main_class
2347	}
2348	if m.properties.Manifest != nil {
2349		mainClassInManifest, err := android.GetMainClassInManifest(ctx.Config(), android.PathForModuleSrc(ctx, *m.properties.Manifest).String())
2350		if err != nil {
2351			return
2352		}
2353		mainClass = mainClassInManifest
2354	}
2355
2356	attrs := &javaBinaryHostAttributes{
2357		javaCommonAttributes: commonAttrs,
2358		Deps:                 deps,
2359		Runtime_deps:         runtimeDeps,
2360		Main_class:           mainClass,
2361	}
2362
2363	// Attribute jvm_flags
2364	if m.binaryProperties.Jni_libs != nil {
2365		jniLibPackages := map[string]bool{}
2366		for _, jniLibLabel := range android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs).Includes {
2367			jniLibPackage := jniLibLabel.Label
2368			indexOfColon := strings.Index(jniLibLabel.Label, ":")
2369			if indexOfColon > 0 {
2370				// JNI lib from other package
2371				jniLibPackage = jniLibLabel.Label[2:indexOfColon]
2372			} else if indexOfColon == 0 {
2373				// JNI lib in the same package of java_binary
2374				packageOfCurrentModule := m.GetBazelLabel(ctx, m)
2375				jniLibPackage = packageOfCurrentModule[2:strings.Index(packageOfCurrentModule, ":")]
2376			}
2377			if _, inMap := jniLibPackages[jniLibPackage]; !inMap {
2378				jniLibPackages[jniLibPackage] = true
2379			}
2380		}
2381		jniLibPaths := []string{}
2382		for jniLibPackage, _ := range jniLibPackages {
2383			// See cs/f:.*/third_party/bazel/.*java_stub_template.txt for the use of RUNPATH
2384			jniLibPaths = append(jniLibPaths, "$${RUNPATH}"+jniLibPackage)
2385		}
2386		attrs.Jvm_flags = bazel.MakeStringListAttribute([]string{"-Djava.library.path=" + strings.Join(jniLibPaths, ":")})
2387	}
2388
2389	props := bazel.BazelTargetModuleProperties{
2390		Rule_class: "java_binary",
2391	}
2392
2393	// Create the BazelTargetModule.
2394	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
2395}
2396
2397type bazelJavaImportAttributes struct {
2398	Jars bazel.LabelListAttribute
2399}
2400
2401// java_import bp2Build converter.
2402func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
2403	var jars bazel.LabelListAttribute
2404	archVariantProps := i.GetArchVariantProperties(ctx, &ImportProperties{})
2405	for axis, configToProps := range archVariantProps {
2406		for config, _props := range configToProps {
2407			if archProps, ok := _props.(*ImportProperties); ok {
2408				archJars := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Jars, []string(nil))
2409				jars.SetSelectValue(axis, config, archJars)
2410			}
2411		}
2412	}
2413
2414	attrs := &bazelJavaImportAttributes{
2415		Jars: jars,
2416	}
2417	props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"}
2418
2419	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: android.RemoveOptionalPrebuiltPrefix(i.Name())}, attrs)
2420
2421}
2422