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