• 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	"strconv"
25	"strings"
26
27	"github.com/google/blueprint"
28	"github.com/google/blueprint/pathtools"
29	"github.com/google/blueprint/proptools"
30
31	"android/soong/android"
32	"android/soong/java/config"
33	"android/soong/tradefed"
34)
35
36func init() {
37	RegisterJavaBuildComponents(android.InitRegistrationContext)
38
39	// Register sdk member types.
40	android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
41
42	android.RegisterSdkMemberType(&librarySdkMemberType{
43		android.SdkMemberTypeBase{
44			PropertyName: "java_libs",
45		},
46		func(j *Library) android.Path {
47			implementationJars := j.ImplementationJars()
48			if len(implementationJars) != 1 {
49				panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
50			}
51
52			return implementationJars[0]
53		},
54	})
55
56	android.RegisterSdkMemberType(&testSdkMemberType{
57		SdkMemberTypeBase: android.SdkMemberTypeBase{
58			PropertyName: "java_tests",
59		},
60	})
61}
62
63func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
64	ctx.RegisterModuleType("java_defaults", DefaultsFactory)
65
66	ctx.RegisterModuleType("java_library", LibraryFactory)
67	ctx.RegisterModuleType("java_library_static", LibraryStaticFactory)
68	ctx.RegisterModuleType("java_library_host", LibraryHostFactory)
69	ctx.RegisterModuleType("java_binary", BinaryFactory)
70	ctx.RegisterModuleType("java_binary_host", BinaryHostFactory)
71	ctx.RegisterModuleType("java_test", TestFactory)
72	ctx.RegisterModuleType("java_test_helper_library", TestHelperLibraryFactory)
73	ctx.RegisterModuleType("java_test_host", TestHostFactory)
74	ctx.RegisterModuleType("java_test_import", JavaTestImportFactory)
75	ctx.RegisterModuleType("java_import", ImportFactory)
76	ctx.RegisterModuleType("java_import_host", ImportFactoryHost)
77	ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
78	ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
79	ctx.RegisterModuleType("dex_import", DexImportFactory)
80
81	ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
82		ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel()
83	})
84
85	ctx.RegisterSingletonType("logtags", LogtagsSingleton)
86	ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
87}
88
89func (j *Module) CheckStableSdkVersion() error {
90	sdkVersion := j.sdkVersion()
91	if sdkVersion.stable() {
92		return nil
93	}
94	return fmt.Errorf("non stable SDK %v", sdkVersion)
95}
96
97func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
98	if j.RequiresStableAPIs(ctx) {
99		if sc, ok := ctx.Module().(sdkContext); ok {
100			if !sc.sdkVersion().specified() {
101				ctx.PropertyErrorf("sdk_version",
102					"sdk_version must have a value when the module is located at vendor or product(only if PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is set).")
103			}
104		}
105	}
106
107	ctx.VisitDirectDeps(func(module android.Module) {
108		tag := ctx.OtherModuleDependencyTag(module)
109		switch module.(type) {
110		// TODO(satayev): cover other types as well, e.g. imports
111		case *Library, *AndroidLibrary:
112			switch tag {
113			case bootClasspathTag, libTag, staticLibTag, java9LibTag:
114				checkLinkType(ctx, j, module.(linkTypeContext), tag.(dependencyTag))
115			}
116		}
117	})
118}
119
120func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
121	if sc, ok := ctx.Module().(sdkContext); ok {
122		usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis)
123		sdkVersionSpecified := sc.sdkVersion().specified()
124		if usePlatformAPI && sdkVersionSpecified {
125			ctx.PropertyErrorf("platform_apis", "platform_apis must be false when sdk_version is not empty.")
126		} else if !usePlatformAPI && !sdkVersionSpecified {
127			ctx.PropertyErrorf("platform_apis", "platform_apis must be true when sdk_version is empty.")
128		}
129
130	}
131}
132
133// TODO:
134// Autogenerated files:
135//  Renderscript
136// Post-jar passes:
137//  Proguard
138// Rmtypedefs
139// DroidDoc
140// Findbugs
141
142type CompilerProperties struct {
143	// list of source files used to compile the Java module.  May be .java, .logtags, .proto,
144	// or .aidl files.
145	Srcs []string `android:"path,arch_variant"`
146
147	// list of source files that should not be used to build the Java module.
148	// This is most useful in the arch/multilib variants to remove non-common files
149	Exclude_srcs []string `android:"path,arch_variant"`
150
151	// list of directories containing Java resources
152	Java_resource_dirs []string `android:"arch_variant"`
153
154	// list of directories that should be excluded from java_resource_dirs
155	Exclude_java_resource_dirs []string `android:"arch_variant"`
156
157	// list of files to use as Java resources
158	Java_resources []string `android:"path,arch_variant"`
159
160	// list of files that should be excluded from java_resources and java_resource_dirs
161	Exclude_java_resources []string `android:"path,arch_variant"`
162
163	// list of module-specific flags that will be used for javac compiles
164	Javacflags []string `android:"arch_variant"`
165
166	// list of module-specific flags that will be used for kotlinc compiles
167	Kotlincflags []string `android:"arch_variant"`
168
169	// list of of java libraries that will be in the classpath
170	Libs []string `android:"arch_variant"`
171
172	// list of java libraries that will be compiled into the resulting jar
173	Static_libs []string `android:"arch_variant"`
174
175	// manifest file to be included in resulting jar
176	Manifest *string `android:"path"`
177
178	// if not blank, run jarjar using the specified rules file
179	Jarjar_rules *string `android:"path,arch_variant"`
180
181	// If not blank, set the java version passed to javac as -source and -target
182	Java_version *string
183
184	// If set to true, allow this module to be dexed and installed on devices.  Has no
185	// effect on host modules, which are always considered installable.
186	Installable *bool
187
188	// If set to true, include sources used to compile the module in to the final jar
189	Include_srcs *bool
190
191	// If not empty, classes are restricted to the specified packages and their sub-packages.
192	// This restriction is checked after applying jarjar rules and including static libs.
193	Permitted_packages []string
194
195	// List of modules to use as annotation processors
196	Plugins []string
197
198	// List of modules to export to libraries that directly depend on this library as annotation processors
199	Exported_plugins []string
200
201	// The number of Java source entries each Javac instance can process
202	Javac_shard_size *int64
203
204	// Add host jdk tools.jar to bootclasspath
205	Use_tools_jar *bool
206
207	Openjdk9 struct {
208		// List of source files that should only be used when passing -source 1.9 or higher
209		Srcs []string `android:"path"`
210
211		// List of javac flags that should only be used when passing -source 1.9 or higher
212		Javacflags []string
213	}
214
215	// When compiling language level 9+ .java code in packages that are part of
216	// a system module, patch_module names the module that your sources and
217	// dependencies should be patched into. The Android runtime currently
218	// doesn't implement the JEP 261 module system so this option is only
219	// supported at compile time. It should only be needed to compile tests in
220	// packages that exist in libcore and which are inconvenient to move
221	// elsewhere.
222	Patch_module *string `android:"arch_variant"`
223
224	Jacoco struct {
225		// List of classes to include for instrumentation with jacoco to collect coverage
226		// information at runtime when building with coverage enabled.  If unset defaults to all
227		// classes.
228		// Supports '*' as the last character of an entry in the list as a wildcard match.
229		// If preceded by '.' it matches all classes in the package and subpackages, otherwise
230		// it matches classes in the package that have the class name as a prefix.
231		Include_filter []string
232
233		// List of classes to exclude from instrumentation with jacoco to collect coverage
234		// information at runtime when building with coverage enabled.  Overrides classes selected
235		// by the include_filter property.
236		// Supports '*' as the last character of an entry in the list as a wildcard match.
237		// If preceded by '.' it matches all classes in the package and subpackages, otherwise
238		// it matches classes in the package that have the class name as a prefix.
239		Exclude_filter []string
240	}
241
242	Errorprone struct {
243		// List of javac flags that should only be used when running errorprone.
244		Javacflags []string
245	}
246
247	Proto struct {
248		// List of extra options that will be passed to the proto generator.
249		Output_params []string
250	}
251
252	Instrument bool `blueprint:"mutated"`
253
254	// List of files to include in the META-INF/services folder of the resulting jar.
255	Services []string `android:"path,arch_variant"`
256
257	// If true, package the kotlin stdlib into the jar.  Defaults to true.
258	Static_kotlin_stdlib *bool `android:"arch_variant"`
259}
260
261type CompilerDeviceProperties struct {
262	// list of module-specific flags that will be used for dex compiles
263	Dxflags []string `android:"arch_variant"`
264
265	// if not blank, set to the version of the sdk to compile against.
266	// Defaults to compiling against the current platform.
267	Sdk_version *string
268
269	// if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
270	// Defaults to sdk_version if not set.
271	Min_sdk_version *string
272
273	// if not blank, set the targetSdkVersion in the AndroidManifest.xml.
274	// Defaults to sdk_version if not set.
275	Target_sdk_version *string
276
277	// Whether to compile against the platform APIs instead of an SDK.
278	// If true, then sdk_version must be empty. The value of this field
279	// is ignored when module's type isn't android_app.
280	Platform_apis *bool
281
282	Aidl struct {
283		// Top level directories to pass to aidl tool
284		Include_dirs []string
285
286		// Directories rooted at the Android.bp file to pass to aidl tool
287		Local_include_dirs []string
288
289		// directories that should be added as include directories for any aidl sources of modules
290		// that depend on this module, as well as to aidl for this module.
291		Export_include_dirs []string
292
293		// whether to generate traces (for systrace) for this interface
294		Generate_traces *bool
295
296		// whether to generate Binder#GetTransaction name method.
297		Generate_get_transaction_name *bool
298	}
299
300	// If true, export a copy of the module as a -hostdex module for host testing.
301	Hostdex *bool
302
303	Target struct {
304		Hostdex struct {
305			// Additional required dependencies to add to -hostdex modules.
306			Required []string
307		}
308	}
309
310	// If set to true, compile dex regardless of installable.  Defaults to false.
311	Compile_dex *bool
312
313	Optimize struct {
314		// If false, disable all optimization.  Defaults to true for android_app and android_test
315		// modules, false for java_library and java_test modules.
316		Enabled *bool
317		// True if the module containing this has it set by default.
318		EnabledByDefault bool `blueprint:"mutated"`
319
320		// If true, optimize for size by removing unused code.  Defaults to true for apps,
321		// false for libraries and tests.
322		Shrink *bool
323
324		// If true, optimize bytecode.  Defaults to false.
325		Optimize *bool
326
327		// If true, obfuscate bytecode.  Defaults to false.
328		Obfuscate *bool
329
330		// If true, do not use the flag files generated by aapt that automatically keep
331		// classes referenced by the app manifest.  Defaults to false.
332		No_aapt_flags *bool
333
334		// Flags to pass to proguard.
335		Proguard_flags []string
336
337		// Specifies the locations of files containing proguard flags.
338		Proguard_flags_files []string `android:"path"`
339	}
340
341	// When targeting 1.9 and above, override the modules to use with --system,
342	// otherwise provides defaults libraries to add to the bootclasspath.
343	System_modules *string
344
345	// The name of the module as used in build configuration.
346	//
347	// Allows a library to separate its actual name from the name used in
348	// build configuration, e.g.ctx.Config().BootJars().
349	ConfigurationName *string `blueprint:"mutated"`
350
351	// set the name of the output
352	Stem *string
353
354	// Keep the data uncompressed. We always need uncompressed dex for execution,
355	// so this might actually save space by avoiding storing the same data twice.
356	// This defaults to reasonable value based on module and should not be set.
357	// It exists only to support ART tests.
358	Uncompress_dex *bool
359
360	IsSDKLibrary bool `blueprint:"mutated"`
361
362	// If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
363	// Defaults to false.
364	V4_signature *bool
365}
366
367func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool {
368	return BoolDefault(me.Optimize.Enabled, me.Optimize.EnabledByDefault)
369}
370
371// Functionality common to Module and Import
372//
373// It is embedded in Module so its functionality can be used by methods in Module
374// but it is currently only initialized by Import and Library.
375type embeddableInModuleAndImport struct {
376
377	// Functionality related to this being used as a component of a java_sdk_library.
378	EmbeddableSdkLibraryComponent
379}
380
381func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) {
382	e.initSdkLibraryComponent(moduleBase)
383}
384
385// Module/Import's DepIsInSameApex(...) delegates to this method.
386//
387// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with
388// the one provided by ApexModuleBase.
389func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
390	// dependencies other than the static linkage are all considered crossing APEX boundary
391	if staticLibTag == ctx.OtherModuleDependencyTag(dep) {
392		return true
393	}
394	return false
395}
396
397// Module contains the properties and members used by all java module types
398type Module struct {
399	android.ModuleBase
400	android.DefaultableModuleBase
401	android.ApexModuleBase
402	android.SdkBase
403
404	// Functionality common to Module and Import.
405	embeddableInModuleAndImport
406
407	properties       CompilerProperties
408	protoProperties  android.ProtoProperties
409	deviceProperties CompilerDeviceProperties
410
411	// jar file containing header classes including static library dependencies, suitable for
412	// inserting into the bootclasspath/classpath of another compile
413	headerJarFile android.Path
414
415	// jar file containing implementation classes including static library dependencies but no
416	// resources
417	implementationJarFile android.Path
418
419	// jar file containing only resources including from static library dependencies
420	resourceJar android.Path
421
422	// args and dependencies to package source files into a srcjar
423	srcJarArgs []string
424	srcJarDeps android.Paths
425
426	// jar file containing implementation classes and resources including static library
427	// dependencies
428	implementationAndResourcesJar android.Path
429
430	// output file containing classes.dex and resources
431	dexJarFile android.Path
432
433	// output file that contains classes.dex if it should be in the output file
434	maybeStrippedDexJarFile android.Path
435
436	// output file containing uninstrumented classes that will be instrumented by jacoco
437	jacocoReportClassesFile android.Path
438
439	// output file containing mapping of obfuscated names
440	proguardDictionary android.Path
441
442	// output file of the module, which may be a classes jar or a dex jar
443	outputFile       android.Path
444	extraOutputFiles android.Paths
445
446	exportAidlIncludeDirs android.Paths
447
448	logtagsSrcs android.Paths
449
450	// installed file for binary dependency
451	installFile android.Path
452
453	// list of .java files and srcjars that was passed to javac
454	compiledJavaSrcs android.Paths
455	compiledSrcJars  android.Paths
456
457	// list of extra progurad flag files
458	extraProguardFlagFiles android.Paths
459
460	// manifest file to use instead of properties.Manifest
461	overrideManifest android.OptionalPath
462
463	// list of SDK lib names that this java module is exporting
464	exportedSdkLibs []string
465
466	// list of plugins that this java module is exporting
467	exportedPluginJars android.Paths
468
469	// list of plugins that this java module is exporting
470	exportedPluginClasses []string
471
472	// list of source files, collected from srcFiles with unique java and all kt files,
473	// will be used by android.IDEInfo struct
474	expandIDEInfoCompiledSrcs []string
475
476	// expanded Jarjar_rules
477	expandJarjarRules android.Path
478
479	// list of additional targets for checkbuild
480	additionalCheckedModules android.Paths
481
482	// Extra files generated by the module type to be added as java resources.
483	extraResources android.Paths
484
485	hiddenAPI
486	dexpreopter
487	linter
488
489	// list of the xref extraction files
490	kytheFiles android.Paths
491
492	distFile android.Path
493}
494
495func (j *Module) addHostProperties() {
496	j.AddProperties(
497		&j.properties,
498		&j.protoProperties,
499	)
500}
501
502func (j *Module) addHostAndDeviceProperties() {
503	j.addHostProperties()
504	j.AddProperties(
505		&j.deviceProperties,
506		&j.dexpreoptProperties,
507		&j.linter.properties,
508	)
509}
510
511func (j *Module) OutputFiles(tag string) (android.Paths, error) {
512	switch tag {
513	case "":
514		return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil
515	case ".jar":
516		return android.Paths{j.implementationAndResourcesJar}, nil
517	case ".proguard_map":
518		return android.Paths{j.proguardDictionary}, nil
519	default:
520		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
521	}
522}
523
524var _ android.OutputFileProducer = (*Module)(nil)
525
526// Methods that need to be implemented for a module that is added to apex java_libs property.
527type ApexDependency interface {
528	HeaderJars() android.Paths
529	ImplementationAndResourcesJars() android.Paths
530}
531
532type Dependency interface {
533	ApexDependency
534	ImplementationJars() android.Paths
535	ResourceJars() android.Paths
536	DexJar() android.Path
537	AidlIncludeDirs() android.Paths
538	ExportedSdkLibs() []string
539	ExportedPlugins() (android.Paths, []string)
540	SrcJarArgs() ([]string, android.Paths)
541	BaseModuleName() string
542	JacocoReportClassesFile() android.Path
543}
544
545type xref interface {
546	XrefJavaFiles() android.Paths
547}
548
549func (j *Module) XrefJavaFiles() android.Paths {
550	return j.kytheFiles
551}
552
553func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
554	android.InitAndroidArchModule(module, hod, android.MultilibCommon)
555	android.InitDefaultableModule(module)
556}
557
558type dependencyTag struct {
559	blueprint.BaseDependencyTag
560	name string
561}
562
563type jniDependencyTag struct {
564	blueprint.BaseDependencyTag
565}
566
567func IsJniDepTag(depTag blueprint.DependencyTag) bool {
568	_, ok := depTag.(*jniDependencyTag)
569	return ok
570}
571
572var (
573	staticLibTag          = dependencyTag{name: "staticlib"}
574	libTag                = dependencyTag{name: "javalib"}
575	java9LibTag           = dependencyTag{name: "java9lib"}
576	pluginTag             = dependencyTag{name: "plugin"}
577	exportedPluginTag     = dependencyTag{name: "exported-plugin"}
578	bootClasspathTag      = dependencyTag{name: "bootclasspath"}
579	systemModulesTag      = dependencyTag{name: "system modules"}
580	frameworkResTag       = dependencyTag{name: "framework-res"}
581	kotlinStdlibTag       = dependencyTag{name: "kotlin-stdlib"}
582	kotlinAnnotationsTag  = dependencyTag{name: "kotlin-annotations"}
583	proguardRaiseTag      = dependencyTag{name: "proguard-raise"}
584	certificateTag        = dependencyTag{name: "certificate"}
585	instrumentationForTag = dependencyTag{name: "instrumentation_for"}
586	usesLibTag            = dependencyTag{name: "uses-library"}
587	extraLintCheckTag     = dependencyTag{name: "extra-lint-check"}
588)
589
590func IsLibDepTag(depTag blueprint.DependencyTag) bool {
591	return depTag == libTag
592}
593
594func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool {
595	return depTag == staticLibTag
596}
597
598type sdkDep struct {
599	useModule, useFiles, useDefaultLibs, invalidVersion bool
600
601	// The modules that will be added to the bootclasspath when targeting 1.8 or lower
602	bootclasspath []string
603
604	// The default system modules to use. Will be an empty string if no system
605	// modules are to be used.
606	systemModules string
607
608	// The modules that will be added ot the classpath when targeting 1.9 or higher
609	java9Classpath []string
610
611	frameworkResModule string
612
613	jars android.Paths
614	aidl android.OptionalPath
615
616	noStandardLibs, noFrameworksLibs bool
617}
618
619func (s sdkDep) hasStandardLibs() bool {
620	return !s.noStandardLibs
621}
622
623func (s sdkDep) hasFrameworkLibs() bool {
624	return !s.noStandardLibs && !s.noFrameworksLibs
625}
626
627type jniLib struct {
628	name           string
629	path           android.Path
630	target         android.Target
631	coverageFile   android.OptionalPath
632	unstrippedFile android.Path
633}
634
635func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {
636	return j.properties.Instrument &&
637		ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") &&
638		ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir())
639}
640
641func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
642	return j.shouldInstrument(ctx) &&
643		(ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_STATIC") ||
644			ctx.Config().UnbundledBuild())
645}
646
647func (j *Module) sdkVersion() sdkSpec {
648	return sdkSpecFrom(String(j.deviceProperties.Sdk_version))
649}
650
651func (j *Module) systemModules() string {
652	return proptools.String(j.deviceProperties.System_modules)
653}
654
655func (j *Module) minSdkVersion() sdkSpec {
656	if j.deviceProperties.Min_sdk_version != nil {
657		return sdkSpecFrom(*j.deviceProperties.Min_sdk_version)
658	}
659	return j.sdkVersion()
660}
661
662func (j *Module) targetSdkVersion() sdkSpec {
663	if j.deviceProperties.Target_sdk_version != nil {
664		return sdkSpecFrom(*j.deviceProperties.Target_sdk_version)
665	}
666	return j.sdkVersion()
667}
668
669func (j *Module) MinSdkVersion() string {
670	return j.minSdkVersion().version.String()
671}
672
673func (j *Module) AvailableFor(what string) bool {
674	if what == android.AvailableToPlatform && Bool(j.deviceProperties.Hostdex) {
675		// Exception: for hostdex: true libraries, the platform variant is created
676		// even if it's not marked as available to platform. In that case, the platform
677		// variant is used only for the hostdex and not installed to the device.
678		return true
679	}
680	return j.ApexModuleBase.AvailableFor(what)
681}
682
683func (j *Module) deps(ctx android.BottomUpMutatorContext) {
684	if ctx.Device() {
685		j.linter.deps(ctx)
686
687		sdkDep := decodeSdkDep(ctx, sdkContext(j))
688		if sdkDep.useDefaultLibs {
689			ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...)
690			ctx.AddVariationDependencies(nil, systemModulesTag, config.DefaultSystemModules)
691			if sdkDep.hasFrameworkLibs() {
692				ctx.AddVariationDependencies(nil, libTag, config.DefaultLibraries...)
693			}
694		} else if sdkDep.useModule {
695			ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
696			ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
697			if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
698				ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...)
699				ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...)
700			}
701		}
702		if sdkDep.systemModules != "" {
703			ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
704		}
705	}
706
707	syspropPublicStubs := syspropPublicStubs(ctx.Config())
708
709	// rewriteSyspropLibs validates if a java module can link against platform's sysprop_library,
710	// and redirects dependency to public stub depending on the link type.
711	rewriteSyspropLibs := func(libs []string, prop string) []string {
712		// make a copy
713		ret := android.CopyOf(libs)
714
715		for idx, lib := range libs {
716			stub, ok := syspropPublicStubs[lib]
717
718			if !ok {
719				continue
720			}
721
722			linkType, _ := j.getLinkType(ctx.ModuleName())
723			// only platform modules can use internal props
724			if linkType != javaPlatform {
725				ret[idx] = stub
726			}
727		}
728
729		return ret
730	}
731
732	ctx.AddVariationDependencies(nil, libTag, rewriteSyspropLibs(j.properties.Libs, "libs")...)
733	ctx.AddVariationDependencies(nil, staticLibTag, rewriteSyspropLibs(j.properties.Static_libs, "static_libs")...)
734
735	ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
736	ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)
737
738	android.ProtoDeps(ctx, &j.protoProperties)
739	if j.hasSrcExt(".proto") {
740		protoDeps(ctx, &j.protoProperties)
741	}
742
743	if j.hasSrcExt(".kt") {
744		// TODO(ccross): move this to a mutator pass that can tell if generated sources contain
745		// Kotlin files
746		ctx.AddVariationDependencies(nil, kotlinStdlibTag,
747			"kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8")
748		if len(j.properties.Plugins) > 0 {
749			ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations")
750		}
751	}
752
753	// Framework libraries need special handling in static coverage builds: they should not have
754	// static dependency on jacoco, otherwise there would be multiple conflicting definitions of
755	// the same jacoco classes coming from different bootclasspath jars.
756	if inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
757		if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
758			j.properties.Instrument = true
759		}
760	} else if j.shouldInstrumentStatic(ctx) {
761		ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
762	}
763}
764
765func hasSrcExt(srcs []string, ext string) bool {
766	for _, src := range srcs {
767		if filepath.Ext(src) == ext {
768			return true
769		}
770	}
771
772	return false
773}
774
775func (j *Module) hasSrcExt(ext string) bool {
776	return hasSrcExt(j.properties.Srcs, ext)
777}
778
779func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
780	aidlIncludeDirs android.Paths) (string, android.Paths) {
781
782	aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs)
783	aidlIncludes = append(aidlIncludes,
784		android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)...)
785	aidlIncludes = append(aidlIncludes,
786		android.PathsForSource(ctx, j.deviceProperties.Aidl.Include_dirs)...)
787
788	var flags []string
789	var deps android.Paths
790
791	if aidlPreprocess.Valid() {
792		flags = append(flags, "-p"+aidlPreprocess.String())
793		deps = append(deps, aidlPreprocess.Path())
794	} else if len(aidlIncludeDirs) > 0 {
795		flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
796	}
797
798	if len(j.exportAidlIncludeDirs) > 0 {
799		flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
800	}
801
802	if len(aidlIncludes) > 0 {
803		flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
804	}
805
806	flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
807	if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
808		flags = append(flags, "-I"+src.String())
809	}
810
811	if Bool(j.deviceProperties.Aidl.Generate_traces) {
812		flags = append(flags, "-t")
813	}
814
815	if Bool(j.deviceProperties.Aidl.Generate_get_transaction_name) {
816		flags = append(flags, "--transaction_names")
817	}
818
819	return strings.Join(flags, " "), deps
820}
821
822type deps struct {
823	classpath          classpath
824	java9Classpath     classpath
825	bootClasspath      classpath
826	processorPath      classpath
827	processorClasses   []string
828	staticJars         android.Paths
829	staticHeaderJars   android.Paths
830	staticResourceJars android.Paths
831	aidlIncludeDirs    android.Paths
832	srcs               android.Paths
833	srcJars            android.Paths
834	systemModules      *systemModules
835	aidlPreprocess     android.OptionalPath
836	kotlinStdlib       android.Paths
837	kotlinAnnotations  android.Paths
838
839	disableTurbine bool
840}
841
842func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
843	for _, f := range dep.Srcs() {
844		if f.Ext() != ".jar" {
845			ctx.ModuleErrorf("genrule %q must generate files ending with .jar to be used as a libs or static_libs dependency",
846				ctx.OtherModuleName(dep.(blueprint.Module)))
847		}
848	}
849}
850
851type linkType int
852
853const (
854	// TODO(jiyong) rename these for better readability. Make the allowed
855	// and disallowed link types explicit
856	javaCore linkType = iota
857	javaSdk
858	javaSystem
859	javaModule
860	javaSystemServer
861	javaPlatform
862)
863
864type linkTypeContext interface {
865	android.Module
866	getLinkType(name string) (ret linkType, stubs bool)
867}
868
869func (m *Module) getLinkType(name string) (ret linkType, stubs bool) {
870	switch name {
871	case "core.current.stubs", "core.platform.api.stubs", "stub-annotations",
872		"private-stub-annotations-jar", "core-lambda-stubs", "core-generated-annotation-stubs":
873		return javaCore, true
874	case "android_stubs_current":
875		return javaSdk, true
876	case "android_system_stubs_current":
877		return javaSystem, true
878	case "android_module_lib_stubs_current":
879		return javaModule, true
880	case "android_system_server_stubs_current":
881		return javaSystemServer, true
882	case "android_test_stubs_current":
883		return javaSystem, true
884	}
885
886	if stub, linkType := moduleStubLinkType(name); stub {
887		return linkType, true
888	}
889
890	ver := m.sdkVersion()
891	switch ver.kind {
892	case sdkCore:
893		return javaCore, false
894	case sdkSystem:
895		return javaSystem, false
896	case sdkPublic:
897		return javaSdk, false
898	case sdkModule:
899		return javaModule, false
900	case sdkSystemServer:
901		return javaSystemServer, false
902	case sdkPrivate, sdkNone, sdkCorePlatform, sdkTest:
903		return javaPlatform, false
904	}
905
906	if !ver.valid() {
907		panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
908	}
909	return javaSdk, false
910}
911
912func checkLinkType(ctx android.ModuleContext, from *Module, to linkTypeContext, tag dependencyTag) {
913	if ctx.Host() {
914		return
915	}
916
917	myLinkType, stubs := from.getLinkType(ctx.ModuleName())
918	if stubs {
919		return
920	}
921	otherLinkType, _ := to.getLinkType(ctx.OtherModuleName(to))
922	commonMessage := "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source."
923
924	switch myLinkType {
925	case javaCore:
926		if otherLinkType != javaCore {
927			ctx.ModuleErrorf("compiles against core Java API, but dependency %q is compiling against non-core Java APIs."+commonMessage,
928				ctx.OtherModuleName(to))
929		}
930		break
931	case javaSdk:
932		if otherLinkType != javaCore && otherLinkType != javaSdk {
933			ctx.ModuleErrorf("compiles against Android API, but dependency %q is compiling against non-public Android API."+commonMessage,
934				ctx.OtherModuleName(to))
935		}
936		break
937	case javaSystem:
938		if otherLinkType == javaPlatform || otherLinkType == javaModule || otherLinkType == javaSystemServer {
939			ctx.ModuleErrorf("compiles against system API, but dependency %q is compiling against private API."+commonMessage,
940				ctx.OtherModuleName(to))
941		}
942		break
943	case javaModule:
944		if otherLinkType == javaPlatform || otherLinkType == javaSystemServer {
945			ctx.ModuleErrorf("compiles against module API, but dependency %q is compiling against private API."+commonMessage,
946				ctx.OtherModuleName(to))
947		}
948		break
949	case javaSystemServer:
950		if otherLinkType == javaPlatform {
951			ctx.ModuleErrorf("compiles against system server API, but dependency %q is compiling against private API."+commonMessage,
952				ctx.OtherModuleName(to))
953		}
954		break
955	case javaPlatform:
956		// no restriction on link-type
957		break
958	}
959}
960
961func (j *Module) collectDeps(ctx android.ModuleContext) deps {
962	var deps deps
963
964	if ctx.Device() {
965		sdkDep := decodeSdkDep(ctx, sdkContext(j))
966		if sdkDep.invalidVersion {
967			ctx.AddMissingDependencies(sdkDep.bootclasspath)
968			ctx.AddMissingDependencies(sdkDep.java9Classpath)
969		} else if sdkDep.useFiles {
970			// sdkDep.jar is actually equivalent to turbine header.jar.
971			deps.classpath = append(deps.classpath, sdkDep.jars...)
972			deps.aidlPreprocess = sdkDep.aidl
973		} else {
974			deps.aidlPreprocess = sdkDep.aidl
975		}
976	}
977
978	// If this is a component library (stubs, etc.) for a java_sdk_library then
979	// add the name of that java_sdk_library to the exported sdk libs to make sure
980	// that, if necessary, a <uses-library> element for that java_sdk_library is
981	// added to the Android manifest.
982	j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...)
983
984	ctx.VisitDirectDeps(func(module android.Module) {
985		otherName := ctx.OtherModuleName(module)
986		tag := ctx.OtherModuleDependencyTag(module)
987
988		if _, ok := tag.(*jniDependencyTag); ok {
989			// Handled by AndroidApp.collectAppDeps
990			return
991		}
992		if tag == certificateTag {
993			// Handled by AndroidApp.collectAppDeps
994			return
995		}
996
997		switch dep := module.(type) {
998		case SdkLibraryDependency:
999			switch tag {
1000			case libTag:
1001				deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
1002				// names of sdk libs that are directly depended are exported
1003				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.OptionalImplicitSdkLibrary()...)
1004			case staticLibTag:
1005				ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
1006			}
1007		case Dependency:
1008			switch tag {
1009			case bootClasspathTag:
1010				deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
1011			case libTag, instrumentationForTag:
1012				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
1013				// sdk lib names from dependencies are re-exported
1014				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
1015				deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
1016				pluginJars, pluginClasses := dep.ExportedPlugins()
1017				addPlugins(&deps, pluginJars, pluginClasses...)
1018			case java9LibTag:
1019				deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars()...)
1020			case staticLibTag:
1021				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
1022				deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...)
1023				deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
1024				deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
1025				// sdk lib names from dependencies are re-exported
1026				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
1027				deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
1028				pluginJars, pluginClasses := dep.ExportedPlugins()
1029				addPlugins(&deps, pluginJars, pluginClasses...)
1030			case pluginTag:
1031				if plugin, ok := dep.(*Plugin); ok {
1032					if plugin.pluginProperties.Processor_class != nil {
1033						addPlugins(&deps, plugin.ImplementationAndResourcesJars(), *plugin.pluginProperties.Processor_class)
1034					} else {
1035						addPlugins(&deps, plugin.ImplementationAndResourcesJars())
1036					}
1037					deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api)
1038				} else {
1039					ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
1040				}
1041			case exportedPluginTag:
1042				if plugin, ok := dep.(*Plugin); ok {
1043					if plugin.pluginProperties.Generates_api != nil && *plugin.pluginProperties.Generates_api {
1044						ctx.PropertyErrorf("exported_plugins", "Cannot export plugins with generates_api = true, found %v", otherName)
1045					}
1046					j.exportedPluginJars = append(j.exportedPluginJars, plugin.ImplementationAndResourcesJars()...)
1047					if plugin.pluginProperties.Processor_class != nil {
1048						j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.pluginProperties.Processor_class)
1049					}
1050				} else {
1051					ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
1052				}
1053			case kotlinStdlibTag:
1054				deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars()...)
1055			case kotlinAnnotationsTag:
1056				deps.kotlinAnnotations = dep.HeaderJars()
1057			}
1058
1059		case android.SourceFileProducer:
1060			switch tag {
1061			case libTag:
1062				checkProducesJars(ctx, dep)
1063				deps.classpath = append(deps.classpath, dep.Srcs()...)
1064			case staticLibTag:
1065				checkProducesJars(ctx, dep)
1066				deps.classpath = append(deps.classpath, dep.Srcs()...)
1067				deps.staticJars = append(deps.staticJars, dep.Srcs()...)
1068				deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
1069			}
1070		default:
1071			switch tag {
1072			case bootClasspathTag:
1073				// If a system modules dependency has been added to the bootclasspath
1074				// then add its libs to the bootclasspath.
1075				sm := module.(SystemModulesProvider)
1076				deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...)
1077
1078			case systemModulesTag:
1079				if deps.systemModules != nil {
1080					panic("Found two system module dependencies")
1081				}
1082				sm := module.(SystemModulesProvider)
1083				outputDir, outputDeps := sm.OutputDirAndDeps()
1084				deps.systemModules = &systemModules{outputDir, outputDeps}
1085			}
1086		}
1087	})
1088
1089	j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
1090
1091	return deps
1092}
1093
1094func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
1095	deps.processorPath = append(deps.processorPath, pluginJars...)
1096	deps.processorClasses = append(deps.processorClasses, pluginClasses...)
1097}
1098
1099func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) javaVersion {
1100	if javaVersion != "" {
1101		return normalizeJavaVersion(ctx, javaVersion)
1102	} else if ctx.Device() {
1103		return sdkContext.sdkVersion().defaultJavaLanguageVersion(ctx)
1104	} else {
1105		return JAVA_VERSION_9
1106	}
1107}
1108
1109type javaVersion int
1110
1111const (
1112	JAVA_VERSION_UNSUPPORTED = 0
1113	JAVA_VERSION_6           = 6
1114	JAVA_VERSION_7           = 7
1115	JAVA_VERSION_8           = 8
1116	JAVA_VERSION_9           = 9
1117)
1118
1119func (v javaVersion) String() string {
1120	switch v {
1121	case JAVA_VERSION_6:
1122		return "1.6"
1123	case JAVA_VERSION_7:
1124		return "1.7"
1125	case JAVA_VERSION_8:
1126		return "1.8"
1127	case JAVA_VERSION_9:
1128		return "1.9"
1129	default:
1130		return "unsupported"
1131	}
1132}
1133
1134// Returns true if javac targeting this version uses system modules instead of a bootclasspath.
1135func (v javaVersion) usesJavaModules() bool {
1136	return v >= 9
1137}
1138
1139func normalizeJavaVersion(ctx android.BaseModuleContext, javaVersion string) javaVersion {
1140	switch javaVersion {
1141	case "1.6", "6":
1142		return JAVA_VERSION_6
1143	case "1.7", "7":
1144		return JAVA_VERSION_7
1145	case "1.8", "8":
1146		return JAVA_VERSION_8
1147	case "1.9", "9":
1148		return JAVA_VERSION_9
1149	case "10", "11":
1150		ctx.PropertyErrorf("java_version", "Java language levels above 9 are not supported")
1151		return JAVA_VERSION_UNSUPPORTED
1152	default:
1153		ctx.PropertyErrorf("java_version", "Unrecognized Java language level")
1154		return JAVA_VERSION_UNSUPPORTED
1155	}
1156}
1157
1158func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaBuilderFlags {
1159
1160	var flags javaBuilderFlags
1161
1162	// javaVersion flag.
1163	flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
1164
1165	// javac flags.
1166	javacFlags := j.properties.Javacflags
1167	if flags.javaVersion.usesJavaModules() {
1168		javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
1169	}
1170	if ctx.Config().MinimizeJavaDebugInfo() {
1171		// Override the -g flag passed globally to remove local variable debug info to reduce
1172		// disk and memory usage.
1173		javacFlags = append(javacFlags, "-g:source,lines")
1174	}
1175	javacFlags = append(javacFlags, "-Xlint:-dep-ann")
1176
1177	if ctx.Config().RunErrorProne() {
1178		if config.ErrorProneClasspath == nil {
1179			ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
1180		}
1181
1182		errorProneFlags := []string{
1183			"-Xplugin:ErrorProne",
1184			"${config.ErrorProneChecks}",
1185		}
1186		errorProneFlags = append(errorProneFlags, j.properties.Errorprone.Javacflags...)
1187
1188		flags.errorProneExtraJavacFlags = "${config.ErrorProneFlags} " +
1189			"'" + strings.Join(errorProneFlags, " ") + "'"
1190		flags.errorProneProcessorPath = classpath(android.PathsForSource(ctx, config.ErrorProneClasspath))
1191	}
1192
1193	// classpath
1194	flags.bootClasspath = append(flags.bootClasspath, deps.bootClasspath...)
1195	flags.classpath = append(flags.classpath, deps.classpath...)
1196	flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...)
1197	flags.processorPath = append(flags.processorPath, deps.processorPath...)
1198
1199	flags.processors = append(flags.processors, deps.processorClasses...)
1200	flags.processors = android.FirstUniqueStrings(flags.processors)
1201
1202	if len(flags.bootClasspath) == 0 && ctx.Host() && !flags.javaVersion.usesJavaModules() &&
1203		decodeSdkDep(ctx, sdkContext(j)).hasStandardLibs() {
1204		// Give host-side tools a version of OpenJDK's standard libraries
1205		// close to what they're targeting. As of Dec 2017, AOSP is only
1206		// bundling OpenJDK 8 and 9, so nothing < 8 is available.
1207		//
1208		// When building with OpenJDK 8, the following should have no
1209		// effect since those jars would be available by default.
1210		//
1211		// When building with OpenJDK 9 but targeting a version < 1.8,
1212		// putting them on the bootclasspath means that:
1213		// a) code can't (accidentally) refer to OpenJDK 9 specific APIs
1214		// b) references to existing APIs are not reinterpreted in an
1215		//    OpenJDK 9-specific way, eg. calls to subclasses of
1216		//    java.nio.Buffer as in http://b/70862583
1217		java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
1218		flags.bootClasspath = append(flags.bootClasspath,
1219			android.PathForSource(ctx, java8Home, "jre/lib/jce.jar"),
1220			android.PathForSource(ctx, java8Home, "jre/lib/rt.jar"))
1221		if Bool(j.properties.Use_tools_jar) {
1222			flags.bootClasspath = append(flags.bootClasspath,
1223				android.PathForSource(ctx, java8Home, "lib/tools.jar"))
1224		}
1225	}
1226
1227	if j.properties.Patch_module != nil && flags.javaVersion.usesJavaModules() {
1228		// Manually specify build directory in case it is not under the repo root.
1229		// (javac doesn't seem to expand into symbolc links when searching for patch-module targets, so
1230		// just adding a symlink under the root doesn't help.)
1231		patchPaths := ".:" + ctx.Config().BuildDir()
1232		classPath := flags.classpath.FormJavaClassPath("")
1233		if classPath != "" {
1234			patchPaths += ":" + classPath
1235		}
1236		javacFlags = append(javacFlags, "--patch-module="+String(j.properties.Patch_module)+"="+patchPaths)
1237	}
1238
1239	// systemModules
1240	flags.systemModules = deps.systemModules
1241
1242	// aidl flags.
1243	flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
1244
1245	if len(javacFlags) > 0 {
1246		// optimization.
1247		ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
1248		flags.javacFlags = "$javacFlags"
1249	}
1250
1251	return flags
1252}
1253
1254func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
1255	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
1256
1257	deps := j.collectDeps(ctx)
1258	flags := j.collectBuilderFlags(ctx, deps)
1259
1260	if flags.javaVersion.usesJavaModules() {
1261		j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...)
1262	}
1263	srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
1264	if hasSrcExt(srcFiles.Strings(), ".proto") {
1265		flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
1266	}
1267
1268	srcFiles = j.genSources(ctx, srcFiles, flags)
1269
1270	srcJars := srcFiles.FilterByExt(".srcjar")
1271	srcJars = append(srcJars, deps.srcJars...)
1272	if aaptSrcJar != nil {
1273		srcJars = append(srcJars, aaptSrcJar)
1274	}
1275
1276	if j.properties.Jarjar_rules != nil {
1277		j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
1278	}
1279
1280	jarName := ctx.ModuleName() + ".jar"
1281
1282	javaSrcFiles := srcFiles.FilterByExt(".java")
1283	var uniqueSrcFiles android.Paths
1284	set := make(map[string]bool)
1285	for _, v := range javaSrcFiles {
1286		if _, found := set[v.String()]; !found {
1287			set[v.String()] = true
1288			uniqueSrcFiles = append(uniqueSrcFiles, v)
1289		}
1290	}
1291
1292	// Collect .java files for AIDEGen
1293	j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
1294
1295	var kotlinJars android.Paths
1296
1297	if srcFiles.HasExt(".kt") {
1298		// user defined kotlin flags.
1299		kotlincFlags := j.properties.Kotlincflags
1300		CheckKotlincFlags(ctx, kotlincFlags)
1301
1302		// If there are kotlin files, compile them first but pass all the kotlin and java files
1303		// kotlinc will use the java files to resolve types referenced by the kotlin files, but
1304		// won't emit any classes for them.
1305		kotlincFlags = append(kotlincFlags, "-no-stdlib")
1306		if ctx.Device() {
1307			kotlincFlags = append(kotlincFlags, "-no-jdk")
1308		}
1309		if len(kotlincFlags) > 0 {
1310			// optimization.
1311			ctx.Variable(pctx, "kotlincFlags", strings.Join(kotlincFlags, " "))
1312			flags.kotlincFlags += "$kotlincFlags"
1313		}
1314
1315		var kotlinSrcFiles android.Paths
1316		kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...)
1317		kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...)
1318
1319		// Collect .kt files for AIDEGen
1320		j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...)
1321
1322		flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
1323		flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
1324
1325		flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
1326		flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
1327
1328		if len(flags.processorPath) > 0 {
1329			// Use kapt for annotation processing
1330			kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
1331			kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
1332			kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, srcJars, flags)
1333			srcJars = append(srcJars, kaptSrcJar)
1334			kotlinJars = append(kotlinJars, kaptResJar)
1335			// Disable annotation processing in javac, it's already been handled by kapt
1336			flags.processorPath = nil
1337			flags.processors = nil
1338		}
1339
1340		kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
1341		kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, srcJars, flags)
1342		if ctx.Failed() {
1343			return
1344		}
1345
1346		// Make javac rule depend on the kotlinc rule
1347		flags.classpath = append(flags.classpath, kotlinJar)
1348
1349		kotlinJars = append(kotlinJars, kotlinJar)
1350		// Jar kotlin classes into the final jar after javac
1351		if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
1352			kotlinJars = append(kotlinJars, deps.kotlinStdlib...)
1353		}
1354	}
1355
1356	jars := append(android.Paths(nil), kotlinJars...)
1357
1358	// Store the list of .java files that was passed to javac
1359	j.compiledJavaSrcs = uniqueSrcFiles
1360	j.compiledSrcJars = srcJars
1361
1362	enable_sharding := false
1363	var headerJarFileWithoutJarjar android.Path
1364	if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
1365		if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
1366			enable_sharding = true
1367			// Formerly, there was a check here that prevented annotation processors
1368			// from being used when sharding was enabled, as some annotation processors
1369			// do not function correctly in sharded environments. It was removed to
1370			// allow for the use of annotation processors that do function correctly
1371			// with sharding enabled. See: b/77284273.
1372		}
1373		headerJarFileWithoutJarjar, j.headerJarFile =
1374			j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
1375		if ctx.Failed() {
1376			return
1377		}
1378	}
1379	if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
1380		var extraJarDeps android.Paths
1381		if ctx.Config().RunErrorProne() {
1382			// If error-prone is enabled, add an additional rule to compile the java files into
1383			// a separate set of classes (so that they don't overwrite the normal ones and require
1384			// a rebuild when error-prone is turned off).
1385			// TODO(ccross): Once we always compile with javac9 we may be able to conditionally
1386			//    enable error-prone without affecting the output class files.
1387			errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
1388			RunErrorProne(ctx, errorprone, uniqueSrcFiles, srcJars, flags)
1389			extraJarDeps = append(extraJarDeps, errorprone)
1390		}
1391
1392		if enable_sharding {
1393			flags.classpath = append(flags.classpath, headerJarFileWithoutJarjar)
1394			shardSize := int(*(j.properties.Javac_shard_size))
1395			var shardSrcs []android.Paths
1396			if len(uniqueSrcFiles) > 0 {
1397				shardSrcs = android.ShardPaths(uniqueSrcFiles, shardSize)
1398				for idx, shardSrc := range shardSrcs {
1399					classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
1400						nil, flags, extraJarDeps)
1401					jars = append(jars, classes)
1402				}
1403			}
1404			if len(srcJars) > 0 {
1405				classes := j.compileJavaClasses(ctx, jarName, len(shardSrcs),
1406					nil, srcJars, flags, extraJarDeps)
1407				jars = append(jars, classes)
1408			}
1409		} else {
1410			classes := j.compileJavaClasses(ctx, jarName, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps)
1411			jars = append(jars, classes)
1412		}
1413		if ctx.Failed() {
1414			return
1415		}
1416	}
1417
1418	j.srcJarArgs, j.srcJarDeps = resourcePathsToJarArgs(srcFiles), srcFiles
1419
1420	var includeSrcJar android.WritablePath
1421	if Bool(j.properties.Include_srcs) {
1422		includeSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+".srcjar")
1423		TransformResourcesToJar(ctx, includeSrcJar, j.srcJarArgs, j.srcJarDeps)
1424	}
1425
1426	dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs,
1427		j.properties.Exclude_java_resource_dirs, j.properties.Exclude_java_resources)
1428	fileArgs, fileDeps := ResourceFilesToJarArgs(ctx, j.properties.Java_resources, j.properties.Exclude_java_resources)
1429	extraArgs, extraDeps := resourcePathsToJarArgs(j.extraResources), j.extraResources
1430
1431	var resArgs []string
1432	var resDeps android.Paths
1433
1434	resArgs = append(resArgs, dirArgs...)
1435	resDeps = append(resDeps, dirDeps...)
1436
1437	resArgs = append(resArgs, fileArgs...)
1438	resDeps = append(resDeps, fileDeps...)
1439
1440	resArgs = append(resArgs, extraArgs...)
1441	resDeps = append(resDeps, extraDeps...)
1442
1443	if len(resArgs) > 0 {
1444		resourceJar := android.PathForModuleOut(ctx, "res", jarName)
1445		TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps)
1446		j.resourceJar = resourceJar
1447		if ctx.Failed() {
1448			return
1449		}
1450	}
1451
1452	var resourceJars android.Paths
1453	if j.resourceJar != nil {
1454		resourceJars = append(resourceJars, j.resourceJar)
1455	}
1456	if Bool(j.properties.Include_srcs) {
1457		resourceJars = append(resourceJars, includeSrcJar)
1458	}
1459	resourceJars = append(resourceJars, deps.staticResourceJars...)
1460
1461	if len(resourceJars) > 1 {
1462		combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
1463		TransformJarsToJar(ctx, combinedJar, "for resources", resourceJars, android.OptionalPath{},
1464			false, nil, nil)
1465		j.resourceJar = combinedJar
1466	} else if len(resourceJars) == 1 {
1467		j.resourceJar = resourceJars[0]
1468	}
1469
1470	if len(deps.staticJars) > 0 {
1471		jars = append(jars, deps.staticJars...)
1472	}
1473
1474	manifest := j.overrideManifest
1475	if !manifest.Valid() && j.properties.Manifest != nil {
1476		manifest = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *j.properties.Manifest))
1477	}
1478
1479	services := android.PathsForModuleSrc(ctx, j.properties.Services)
1480	if len(services) > 0 {
1481		servicesJar := android.PathForModuleOut(ctx, "services", jarName)
1482		var zipargs []string
1483		for _, file := range services {
1484			serviceFile := file.String()
1485			zipargs = append(zipargs, "-C", filepath.Dir(serviceFile), "-f", serviceFile)
1486		}
1487		rule := zip
1488		args := map[string]string{
1489			"jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "),
1490		}
1491		if ctx.Config().IsEnvTrue("RBE_ZIP") {
1492			rule = zipRE
1493			args["implicits"] = strings.Join(services.Strings(), ",")
1494		}
1495		ctx.Build(pctx, android.BuildParams{
1496			Rule:      rule,
1497			Output:    servicesJar,
1498			Implicits: services,
1499			Args:      args,
1500		})
1501		jars = append(jars, servicesJar)
1502	}
1503
1504	// Combine the classes built from sources, any manifests, and any static libraries into
1505	// classes.jar. If there is only one input jar this step will be skipped.
1506	var outputFile android.ModuleOutPath
1507
1508	if len(jars) == 1 && !manifest.Valid() {
1509		if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok {
1510			// Optimization: skip the combine step if there is nothing to do
1511			// TODO(ccross): this leaves any module-info.class files, but those should only come from
1512			// prebuilt dependencies until we support modules in the platform build, so there shouldn't be
1513			// any if len(jars) == 1.
1514			outputFile = moduleOutPath
1515		} else {
1516			combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
1517			ctx.Build(pctx, android.BuildParams{
1518				Rule:   android.Cp,
1519				Input:  jars[0],
1520				Output: combinedJar,
1521			})
1522			outputFile = combinedJar
1523		}
1524	} else {
1525		combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
1526		TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest,
1527			false, nil, nil)
1528		outputFile = combinedJar
1529	}
1530
1531	// jarjar implementation jar if necessary
1532	if j.expandJarjarRules != nil {
1533		// Transform classes.jar into classes-jarjar.jar
1534		jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName)
1535		TransformJarJar(ctx, jarjarFile, outputFile, j.expandJarjarRules)
1536		outputFile = jarjarFile
1537
1538		// jarjar resource jar if necessary
1539		if j.resourceJar != nil {
1540			resourceJarJarFile := android.PathForModuleOut(ctx, "res-jarjar", jarName)
1541			TransformJarJar(ctx, resourceJarJarFile, j.resourceJar, j.expandJarjarRules)
1542			j.resourceJar = resourceJarJarFile
1543		}
1544
1545		if ctx.Failed() {
1546			return
1547		}
1548	}
1549
1550	// Check package restrictions if necessary.
1551	if len(j.properties.Permitted_packages) > 0 {
1552		// Check packages and copy to package-checked file.
1553		pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp")
1554		CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages)
1555		j.additionalCheckedModules = append(j.additionalCheckedModules, pkgckFile)
1556
1557		if ctx.Failed() {
1558			return
1559		}
1560	}
1561
1562	j.implementationJarFile = outputFile
1563	if j.headerJarFile == nil {
1564		j.headerJarFile = j.implementationJarFile
1565	}
1566
1567	// Force enable the instrumentation for java code that is built for APEXes ...
1568	// except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
1569	// doesn't make sense)
1570	isJacocoAgent := ctx.ModuleName() == "jacocoagent"
1571	if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !isJacocoAgent && !j.IsForPlatform() {
1572		j.properties.Instrument = true
1573	}
1574
1575	if j.shouldInstrument(ctx) {
1576		outputFile = j.instrument(ctx, flags, outputFile, jarName)
1577	}
1578
1579	// merge implementation jar with resources if necessary
1580	implementationAndResourcesJar := outputFile
1581	if j.resourceJar != nil {
1582		jars := android.Paths{j.resourceJar, implementationAndResourcesJar}
1583		combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
1584		TransformJarsToJar(ctx, combinedJar, "for resources", jars, manifest,
1585			false, nil, nil)
1586		implementationAndResourcesJar = combinedJar
1587	}
1588
1589	j.implementationAndResourcesJar = implementationAndResourcesJar
1590
1591	// Enable dex compilation for the APEX variants, unless it is disabled explicitly
1592	if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !j.IsForPlatform() {
1593		if j.deviceProperties.Compile_dex == nil {
1594			j.deviceProperties.Compile_dex = proptools.BoolPtr(true)
1595		}
1596		if j.deviceProperties.Hostdex == nil {
1597			j.deviceProperties.Hostdex = proptools.BoolPtr(true)
1598		}
1599	}
1600
1601	if ctx.Device() && j.hasCode(ctx) &&
1602		(Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
1603		// Dex compilation
1604		var dexOutputFile android.ModuleOutPath
1605		dexOutputFile = j.compileDex(ctx, flags, outputFile, jarName)
1606		if ctx.Failed() {
1607			return
1608		}
1609
1610		configurationName := j.ConfigurationName()
1611		primary := configurationName == ctx.ModuleName()
1612
1613		// Hidden API CSV generation and dex encoding
1614		dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, configurationName, primary, dexOutputFile, j.implementationJarFile,
1615			proptools.Bool(j.deviceProperties.Uncompress_dex))
1616
1617		// merge dex jar with resources if necessary
1618		if j.resourceJar != nil {
1619			jars := android.Paths{dexOutputFile, j.resourceJar}
1620			combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
1621			TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
1622				false, nil, nil)
1623			if *j.deviceProperties.Uncompress_dex {
1624				combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName)
1625				TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
1626				dexOutputFile = combinedAlignedJar
1627			} else {
1628				dexOutputFile = combinedJar
1629			}
1630		}
1631
1632		j.dexJarFile = dexOutputFile
1633
1634		// Dexpreopting
1635		dexOutputFile = j.dexpreopt(ctx, dexOutputFile)
1636
1637		j.maybeStrippedDexJarFile = dexOutputFile
1638
1639		outputFile = dexOutputFile
1640
1641		if ctx.Failed() {
1642			return
1643		}
1644	} else {
1645		outputFile = implementationAndResourcesJar
1646	}
1647
1648	if ctx.Device() {
1649		lintSDKVersionString := func(sdkSpec sdkSpec) string {
1650			if v := sdkSpec.version; v.isNumbered() {
1651				return v.String()
1652			} else {
1653				return ctx.Config().DefaultAppTargetSdk()
1654			}
1655		}
1656
1657		j.linter.name = ctx.ModuleName()
1658		j.linter.srcs = srcFiles
1659		j.linter.srcJars = srcJars
1660		j.linter.classpath = append(append(android.Paths(nil), flags.bootClasspath...), flags.classpath...)
1661		j.linter.classes = j.implementationJarFile
1662		j.linter.minSdkVersion = lintSDKVersionString(j.minSdkVersion())
1663		j.linter.targetSdkVersion = lintSDKVersionString(j.targetSdkVersion())
1664		j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion())
1665		j.linter.javaLanguageLevel = flags.javaVersion.String()
1666		j.linter.kotlinLanguageLevel = "1.3"
1667		if j.ApexName() != "" && ctx.Config().UnbundledBuild() {
1668			j.linter.buildModuleReportZip = true
1669		}
1670		j.linter.lint(ctx)
1671	}
1672
1673	ctx.CheckbuildFile(outputFile)
1674
1675	// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
1676	j.outputFile = outputFile.WithoutRel()
1677}
1678
1679func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, idx int,
1680	srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath {
1681
1682	kzipName := pathtools.ReplaceExtension(jarName, "kzip")
1683	if idx >= 0 {
1684		kzipName = strings.TrimSuffix(jarName, filepath.Ext(jarName)) + strconv.Itoa(idx) + ".kzip"
1685		jarName += strconv.Itoa(idx)
1686	}
1687
1688	classes := android.PathForModuleOut(ctx, "javac", jarName)
1689	TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, flags, extraJarDeps)
1690
1691	if ctx.Config().EmitXrefRules() {
1692		extractionFile := android.PathForModuleOut(ctx, kzipName)
1693		emitXrefRule(ctx, extractionFile, idx, srcFiles, srcJars, flags, extraJarDeps)
1694		j.kytheFiles = append(j.kytheFiles, extractionFile)
1695	}
1696
1697	return classes
1698}
1699
1700// Check for invalid kotlinc flags. Only use this for flags explicitly passed by the user,
1701// since some of these flags may be used internally.
1702func CheckKotlincFlags(ctx android.ModuleContext, flags []string) {
1703	for _, flag := range flags {
1704		flag = strings.TrimSpace(flag)
1705
1706		if !strings.HasPrefix(flag, "-") {
1707			ctx.PropertyErrorf("kotlincflags", "Flag `%s` must start with `-`", flag)
1708		} else if strings.HasPrefix(flag, "-Xintellij-plugin-root") {
1709			ctx.PropertyErrorf("kotlincflags",
1710				"Bad flag: `%s`, only use internal compiler for consistency.", flag)
1711		} else if inList(flag, config.KotlincIllegalFlags) {
1712			ctx.PropertyErrorf("kotlincflags", "Flag `%s` already used by build system", flag)
1713		} else if flag == "-include-runtime" {
1714			ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, do not include runtime.", flag)
1715		} else {
1716			args := strings.Split(flag, " ")
1717			if args[0] == "-kotlin-home" {
1718				ctx.PropertyErrorf("kotlincflags",
1719					"Bad flag: `%s`, kotlin home already set to default (path to kotlinc in the repo).", flag)
1720			}
1721		}
1722	}
1723}
1724
1725func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
1726	deps deps, flags javaBuilderFlags, jarName string,
1727	extraJars android.Paths) (headerJar, jarjarHeaderJar android.Path) {
1728
1729	var jars android.Paths
1730	if len(srcFiles) > 0 || len(srcJars) > 0 {
1731		// Compile java sources into turbine.jar.
1732		turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
1733		TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
1734		if ctx.Failed() {
1735			return nil, nil
1736		}
1737		jars = append(jars, turbineJar)
1738	}
1739
1740	jars = append(jars, extraJars...)
1741
1742	// Combine any static header libraries into classes-header.jar. If there is only
1743	// one input jar this step will be skipped.
1744	jars = append(jars, deps.staticHeaderJars...)
1745
1746	// we cannot skip the combine step for now if there is only one jar
1747	// since we have to strip META-INF/TRANSITIVE dir from turbine.jar
1748	combinedJar := android.PathForModuleOut(ctx, "turbine-combined", jarName)
1749	TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{},
1750		false, nil, []string{"META-INF/TRANSITIVE"})
1751	headerJar = combinedJar
1752	jarjarHeaderJar = combinedJar
1753
1754	if j.expandJarjarRules != nil {
1755		// Transform classes.jar into classes-jarjar.jar
1756		jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName)
1757		TransformJarJar(ctx, jarjarFile, headerJar, j.expandJarjarRules)
1758		jarjarHeaderJar = jarjarFile
1759		if ctx.Failed() {
1760			return nil, nil
1761		}
1762	}
1763
1764	return headerJar, jarjarHeaderJar
1765}
1766
1767func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
1768	classesJar android.Path, jarName string) android.ModuleOutPath {
1769
1770	specs := j.jacocoModuleToZipCommand(ctx)
1771
1772	jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName)
1773	instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName)
1774
1775	jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs)
1776
1777	j.jacocoReportClassesFile = jacocoReportClassesFile
1778
1779	return instrumentedJar
1780}
1781
1782var _ Dependency = (*Module)(nil)
1783
1784func (j *Module) HeaderJars() android.Paths {
1785	if j.headerJarFile == nil {
1786		return nil
1787	}
1788	return android.Paths{j.headerJarFile}
1789}
1790
1791func (j *Module) ImplementationJars() android.Paths {
1792	if j.implementationJarFile == nil {
1793		return nil
1794	}
1795	return android.Paths{j.implementationJarFile}
1796}
1797
1798func (j *Module) DexJar() android.Path {
1799	return j.dexJarFile
1800}
1801
1802func (j *Module) ResourceJars() android.Paths {
1803	if j.resourceJar == nil {
1804		return nil
1805	}
1806	return android.Paths{j.resourceJar}
1807}
1808
1809func (j *Module) ImplementationAndResourcesJars() android.Paths {
1810	if j.implementationAndResourcesJar == nil {
1811		return nil
1812	}
1813	return android.Paths{j.implementationAndResourcesJar}
1814}
1815
1816func (j *Module) AidlIncludeDirs() android.Paths {
1817	// exportAidlIncludeDirs is type android.Paths already
1818	return j.exportAidlIncludeDirs
1819}
1820
1821func (j *Module) ExportedSdkLibs() []string {
1822	// exportedSdkLibs is type []string
1823	return j.exportedSdkLibs
1824}
1825
1826func (j *Module) ExportedPlugins() (android.Paths, []string) {
1827	return j.exportedPluginJars, j.exportedPluginClasses
1828}
1829
1830func (j *Module) SrcJarArgs() ([]string, android.Paths) {
1831	return j.srcJarArgs, j.srcJarDeps
1832}
1833
1834var _ logtagsProducer = (*Module)(nil)
1835
1836func (j *Module) logtags() android.Paths {
1837	return j.logtagsSrcs
1838}
1839
1840// Collect information for opening IDE project files in java/jdeps.go.
1841func (j *Module) IDEInfo(dpInfo *android.IdeInfo) {
1842	dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
1843	dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
1844	dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
1845	dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
1846	if j.expandJarjarRules != nil {
1847		dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
1848	}
1849}
1850
1851func (j *Module) CompilerDeps() []string {
1852	jdeps := []string{}
1853	jdeps = append(jdeps, j.properties.Libs...)
1854	jdeps = append(jdeps, j.properties.Static_libs...)
1855	return jdeps
1856}
1857
1858func (j *Module) hasCode(ctx android.ModuleContext) bool {
1859	srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
1860	return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0
1861}
1862
1863func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
1864	return j.depIsInSameApex(ctx, dep)
1865}
1866
1867func (j *Module) Stem() string {
1868	return proptools.StringDefault(j.deviceProperties.Stem, j.Name())
1869}
1870
1871func (j *Module) ConfigurationName() string {
1872	return proptools.StringDefault(j.deviceProperties.ConfigurationName, j.BaseModuleName())
1873}
1874
1875func (j *Module) JacocoReportClassesFile() android.Path {
1876	return j.jacocoReportClassesFile
1877}
1878
1879func (j *Module) IsInstallable() bool {
1880	return Bool(j.properties.Installable)
1881}
1882
1883//
1884// Java libraries (.jar file)
1885//
1886
1887type LibraryProperties struct {
1888	Dist struct {
1889		// The tag of the output of this module that should be output.
1890		Tag *string `android:"arch_variant"`
1891	} `android:"arch_variant"`
1892}
1893
1894type Library struct {
1895	Module
1896
1897	libraryProperties LibraryProperties
1898
1899	InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
1900}
1901
1902// Provides access to the list of permitted packages from updatable boot jars.
1903type PermittedPackagesForUpdatableBootJars interface {
1904	PermittedPackagesForUpdatableBootJars() []string
1905}
1906
1907var _ PermittedPackagesForUpdatableBootJars = (*Library)(nil)
1908
1909func (j *Library) PermittedPackagesForUpdatableBootJars() []string {
1910	return j.properties.Permitted_packages
1911}
1912
1913func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool {
1914	// Store uncompressed (and aligned) any dex files from jars in APEXes.
1915	if am, ok := ctx.Module().(android.ApexModule); ok && !am.IsForPlatform() {
1916		return true
1917	}
1918
1919	// Store uncompressed (and do not strip) dex files from boot class path jars.
1920	if inList(ctx.ModuleName(), ctx.Config().BootJars()) {
1921		return true
1922	}
1923
1924	// Store uncompressed dex files that are preopted on /system.
1925	if !dexpreopter.dexpreoptDisabled(ctx) && (ctx.Host() || !odexOnSystemOther(ctx, dexpreopter.installPath)) {
1926		return true
1927	}
1928	if ctx.Config().UncompressPrivAppDex() &&
1929		inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules()) {
1930		return true
1931	}
1932
1933	return false
1934}
1935
1936func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1937	j.checkSdkVersions(ctx)
1938	j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
1939	j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
1940	if j.deviceProperties.Uncompress_dex == nil {
1941		// If the value was not force-set by the user, use reasonable default based on the module.
1942		j.deviceProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
1943	}
1944	j.dexpreopter.uncompressedDex = *j.deviceProperties.Uncompress_dex
1945	j.compile(ctx, nil)
1946
1947	exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform()
1948	if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex {
1949		var extraInstallDeps android.Paths
1950		if j.InstallMixin != nil {
1951			extraInstallDeps = j.InstallMixin(ctx, j.outputFile)
1952		}
1953		j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
1954			j.Stem()+".jar", j.outputFile, extraInstallDeps...)
1955	}
1956
1957	// Verify Dist.Tag is set to a supported output
1958	if j.libraryProperties.Dist.Tag != nil {
1959		distFiles, err := j.OutputFiles(*j.libraryProperties.Dist.Tag)
1960		if err != nil {
1961			ctx.PropertyErrorf("dist.tag", "%s", err.Error())
1962		}
1963		j.distFile = distFiles[0]
1964	}
1965}
1966
1967func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
1968	j.deps(ctx)
1969}
1970
1971const (
1972	aidlIncludeDir   = "aidl"
1973	javaDir          = "java"
1974	jarFileSuffix    = ".jar"
1975	testConfigSuffix = "-AndroidTest.xml"
1976)
1977
1978// path to the jar file of a java library. Relative to <sdk_root>/<api_dir>
1979func sdkSnapshotFilePathForJar(osPrefix, name string) string {
1980	return sdkSnapshotFilePathForMember(osPrefix, name, jarFileSuffix)
1981}
1982
1983func sdkSnapshotFilePathForMember(osPrefix, name string, suffix string) string {
1984	return filepath.Join(javaDir, osPrefix, name+suffix)
1985}
1986
1987type librarySdkMemberType struct {
1988	android.SdkMemberTypeBase
1989
1990	// Function to retrieve the appropriate output jar (implementation or header) from
1991	// the library.
1992	jarToExportGetter func(j *Library) android.Path
1993}
1994
1995func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
1996	mctx.AddVariationDependencies(nil, dependencyTag, names...)
1997}
1998
1999func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
2000	_, ok := module.(*Library)
2001	return ok
2002}
2003
2004func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
2005	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_import")
2006}
2007
2008func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
2009	return &librarySdkMemberProperties{}
2010}
2011
2012type librarySdkMemberProperties struct {
2013	android.SdkMemberPropertiesBase
2014
2015	JarToExport     android.Path `android:"arch_variant"`
2016	AidlIncludeDirs android.Paths
2017}
2018
2019func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
2020	j := variant.(*Library)
2021
2022	p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(j)
2023	p.AidlIncludeDirs = j.AidlIncludeDirs()
2024}
2025
2026func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
2027	builder := ctx.SnapshotBuilder()
2028
2029	exportedJar := p.JarToExport
2030	if exportedJar != nil {
2031		snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), ctx.Name())
2032		builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
2033
2034		propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
2035	}
2036
2037	aidlIncludeDirs := p.AidlIncludeDirs
2038	if len(aidlIncludeDirs) != 0 {
2039		sdkModuleContext := ctx.SdkModuleContext()
2040		for _, dir := range aidlIncludeDirs {
2041			// TODO(jiyong): copy parcelable declarations only
2042			aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
2043			for _, file := range aidlFiles {
2044				builder.CopyToSnapshot(android.PathForSource(sdkModuleContext, file), filepath.Join(aidlIncludeDir, file))
2045			}
2046		}
2047
2048		// TODO(b/151933053) - add aidl include dirs property
2049	}
2050}
2051
2052var javaHeaderLibsSdkMemberType android.SdkMemberType = &librarySdkMemberType{
2053	android.SdkMemberTypeBase{
2054		PropertyName: "java_header_libs",
2055		SupportsSdk:  true,
2056	},
2057	func(j *Library) android.Path {
2058		headerJars := j.HeaderJars()
2059		if len(headerJars) != 1 {
2060			panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
2061		}
2062
2063		return headerJars[0]
2064	},
2065}
2066
2067// java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
2068//
2069// By default, a java_library has a single variant that produces a `.jar` file containing `.class` files that were
2070// compiled against the device bootclasspath.  This jar is not suitable for installing on a device, but can be used
2071// as a `static_libs` dependency of another module.
2072//
2073// Specifying `installable: true` will product a `.jar` file containing `classes.dex` files, suitable for installing on
2074// a device.
2075//
2076// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
2077// compiled against the host bootclasspath.
2078func LibraryFactory() android.Module {
2079	module := &Library{}
2080
2081	module.addHostAndDeviceProperties()
2082	module.AddProperties(&module.libraryProperties)
2083
2084	module.initModuleAndImport(&module.ModuleBase)
2085
2086	android.InitApexModule(module)
2087	android.InitSdkAwareModule(module)
2088	InitJavaModule(module, android.HostAndDeviceSupported)
2089	return module
2090}
2091
2092// java_library_static is an obsolete alias for java_library.
2093func LibraryStaticFactory() android.Module {
2094	return LibraryFactory()
2095}
2096
2097// java_library_host builds and links sources into a `.jar` file for the host.
2098//
2099// A java_library_host has a single variant that produces a `.jar` file containing `.class` files that were
2100// compiled against the host bootclasspath.
2101func LibraryHostFactory() android.Module {
2102	module := &Library{}
2103
2104	module.addHostProperties()
2105
2106	module.Module.properties.Installable = proptools.BoolPtr(true)
2107
2108	android.InitApexModule(module)
2109	InitJavaModule(module, android.HostSupported)
2110	return module
2111}
2112
2113//
2114// Java Tests
2115//
2116
2117type testProperties struct {
2118	// list of compatibility suites (for example "cts", "vts") that the module should be
2119	// installed into.
2120	Test_suites []string `android:"arch_variant"`
2121
2122	// the name of the test configuration (for example "AndroidTest.xml") that should be
2123	// installed with the module.
2124	Test_config *string `android:"path,arch_variant"`
2125
2126	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
2127	// should be installed with the module.
2128	Test_config_template *string `android:"path,arch_variant"`
2129
2130	// list of files or filegroup modules that provide data that should be installed alongside
2131	// the test
2132	Data []string `android:"path"`
2133
2134	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
2135	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
2136	// explicitly.
2137	Auto_gen_config *bool
2138
2139	// Add parameterized mainline modules to auto generated test config. The options will be
2140	// handled by TradeFed to do downloading and installing the specified modules on the device.
2141	Test_mainline_modules []string
2142}
2143
2144type testHelperLibraryProperties struct {
2145	// list of compatibility suites (for example "cts", "vts") that the module should be
2146	// installed into.
2147	Test_suites []string `android:"arch_variant"`
2148}
2149
2150type prebuiltTestProperties struct {
2151	// list of compatibility suites (for example "cts", "vts") that the module should be
2152	// installed into.
2153	Test_suites []string `android:"arch_variant"`
2154
2155	// the name of the test configuration (for example "AndroidTest.xml") that should be
2156	// installed with the module.
2157	Test_config *string `android:"path,arch_variant"`
2158}
2159
2160type Test struct {
2161	Library
2162
2163	testProperties testProperties
2164
2165	testConfig android.Path
2166	data       android.Paths
2167}
2168
2169type TestHelperLibrary struct {
2170	Library
2171
2172	testHelperLibraryProperties testHelperLibraryProperties
2173}
2174
2175type JavaTestImport struct {
2176	Import
2177
2178	prebuiltTestProperties prebuiltTestProperties
2179
2180	testConfig android.Path
2181}
2182
2183func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2184	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
2185		j.testProperties.Test_suites, j.testProperties.Auto_gen_config)
2186	j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
2187
2188	j.Library.GenerateAndroidBuildActions(ctx)
2189}
2190
2191func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2192	j.Library.GenerateAndroidBuildActions(ctx)
2193}
2194
2195func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2196	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.prebuiltTestProperties.Test_config, nil,
2197		j.prebuiltTestProperties.Test_suites, nil)
2198
2199	j.Import.GenerateAndroidBuildActions(ctx)
2200}
2201
2202type testSdkMemberType struct {
2203	android.SdkMemberTypeBase
2204}
2205
2206func (mt *testSdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
2207	mctx.AddVariationDependencies(nil, dependencyTag, names...)
2208}
2209
2210func (mt *testSdkMemberType) IsInstance(module android.Module) bool {
2211	_, ok := module.(*Test)
2212	return ok
2213}
2214
2215func (mt *testSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
2216	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_test_import")
2217}
2218
2219func (mt *testSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
2220	return &testSdkMemberProperties{}
2221}
2222
2223type testSdkMemberProperties struct {
2224	android.SdkMemberPropertiesBase
2225
2226	JarToExport android.Path
2227	TestConfig  android.Path
2228}
2229
2230func (p *testSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
2231	test := variant.(*Test)
2232
2233	implementationJars := test.ImplementationJars()
2234	if len(implementationJars) != 1 {
2235		panic(fmt.Errorf("there must be only one implementation jar from %q", test.Name()))
2236	}
2237
2238	p.JarToExport = implementationJars[0]
2239	p.TestConfig = test.testConfig
2240}
2241
2242func (p *testSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
2243	builder := ctx.SnapshotBuilder()
2244
2245	exportedJar := p.JarToExport
2246	if exportedJar != nil {
2247		snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), ctx.Name())
2248		builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
2249
2250		propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
2251	}
2252
2253	testConfig := p.TestConfig
2254	if testConfig != nil {
2255		snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.OsPrefix(), ctx.Name(), testConfigSuffix)
2256		builder.CopyToSnapshot(testConfig, snapshotRelativeTestConfigPath)
2257		propertySet.AddProperty("test_config", snapshotRelativeTestConfigPath)
2258	}
2259}
2260
2261// java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and
2262// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
2263//
2264// By default, a java_test has a single variant that produces a `.jar` file containing `classes.dex` files that were
2265// compiled against the device bootclasspath.
2266//
2267// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
2268// compiled against the host bootclasspath.
2269func TestFactory() android.Module {
2270	module := &Test{}
2271
2272	module.addHostAndDeviceProperties()
2273	module.AddProperties(&module.testProperties)
2274
2275	module.Module.properties.Installable = proptools.BoolPtr(true)
2276	module.Module.dexpreopter.isTest = true
2277	module.Module.linter.test = true
2278
2279	InitJavaModule(module, android.HostAndDeviceSupported)
2280	return module
2281}
2282
2283// java_test_helper_library creates a java library and makes sure that it is added to the appropriate test suite.
2284func TestHelperLibraryFactory() android.Module {
2285	module := &TestHelperLibrary{}
2286
2287	module.addHostAndDeviceProperties()
2288	module.AddProperties(&module.testHelperLibraryProperties)
2289
2290	module.Module.properties.Installable = proptools.BoolPtr(true)
2291	module.Module.dexpreopter.isTest = true
2292	module.Module.linter.test = true
2293
2294	InitJavaModule(module, android.HostAndDeviceSupported)
2295	return module
2296}
2297
2298// java_test_import imports one or more `.jar` files into the build graph as if they were built by a java_test module
2299// and makes sure that it is added to the appropriate test suite.
2300//
2301// By default, a java_test_import has a single variant that expects a `.jar` file containing `.class` files that were
2302// compiled against an Android classpath.
2303//
2304// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
2305// for host modules.
2306func JavaTestImportFactory() android.Module {
2307	module := &JavaTestImport{}
2308
2309	module.AddProperties(
2310		&module.Import.properties,
2311		&module.prebuiltTestProperties)
2312
2313	module.Import.properties.Installable = proptools.BoolPtr(true)
2314
2315	android.InitPrebuiltModule(module, &module.properties.Jars)
2316	android.InitApexModule(module)
2317	android.InitSdkAwareModule(module)
2318	InitJavaModule(module, android.HostAndDeviceSupported)
2319	return module
2320}
2321
2322// java_test_host builds a and links sources into a `.jar` file for the host, and creates an `AndroidTest.xml` file to
2323// allow running the test with `atest` or a `TEST_MAPPING` file.
2324//
2325// A java_test_host has a single variant that produces a `.jar` file containing `.class` files that were
2326// compiled against the host bootclasspath.
2327func TestHostFactory() android.Module {
2328	module := &Test{}
2329
2330	module.addHostProperties()
2331	module.AddProperties(&module.testProperties)
2332
2333	module.Module.properties.Installable = proptools.BoolPtr(true)
2334
2335	InitJavaModule(module, android.HostSupported)
2336	return module
2337}
2338
2339//
2340// Java Binaries (.jar file plus wrapper script)
2341//
2342
2343type binaryProperties struct {
2344	// installable script to execute the resulting jar
2345	Wrapper *string `android:"path"`
2346
2347	// Name of the class containing main to be inserted into the manifest as Main-Class.
2348	Main_class *string
2349}
2350
2351type Binary struct {
2352	Library
2353
2354	binaryProperties binaryProperties
2355
2356	isWrapperVariant bool
2357
2358	wrapperFile android.Path
2359	binaryFile  android.InstallPath
2360}
2361
2362func (j *Binary) HostToolPath() android.OptionalPath {
2363	return android.OptionalPathForPath(j.binaryFile)
2364}
2365
2366func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2367	if ctx.Arch().ArchType == android.Common {
2368		// Compile the jar
2369		if j.binaryProperties.Main_class != nil {
2370			if j.properties.Manifest != nil {
2371				ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
2372			}
2373			manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
2374			GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
2375			j.overrideManifest = android.OptionalPathForPath(manifestFile)
2376		}
2377
2378		j.Library.GenerateAndroidBuildActions(ctx)
2379	} else {
2380		// Handle the binary wrapper
2381		j.isWrapperVariant = true
2382
2383		if j.binaryProperties.Wrapper != nil {
2384			j.wrapperFile = android.PathForModuleSrc(ctx, *j.binaryProperties.Wrapper)
2385		} else {
2386			j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
2387		}
2388
2389		// Depend on the installed jar so that the wrapper doesn't get executed by
2390		// another build rule before the jar has been installed.
2391		jarFile := ctx.PrimaryModule().(*Binary).installFile
2392
2393		j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
2394			ctx.ModuleName(), j.wrapperFile, jarFile)
2395	}
2396}
2397
2398func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
2399	if ctx.Arch().ArchType == android.Common {
2400		j.deps(ctx)
2401	}
2402}
2403
2404// java_binary builds a `.jar` file and a shell script that executes it for the device, and possibly for the host
2405// as well.
2406//
2407// By default, a java_binary has a single variant that produces a `.jar` file containing `classes.dex` files that were
2408// compiled against the device bootclasspath.
2409//
2410// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
2411// compiled against the host bootclasspath.
2412func BinaryFactory() android.Module {
2413	module := &Binary{}
2414
2415	module.addHostAndDeviceProperties()
2416	module.AddProperties(&module.binaryProperties)
2417
2418	module.Module.properties.Installable = proptools.BoolPtr(true)
2419
2420	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst)
2421	android.InitDefaultableModule(module)
2422	return module
2423}
2424
2425// java_binary_host builds a `.jar` file and a shell script that executes it for the host.
2426//
2427// A java_binary_host has a single variant that produces a `.jar` file containing `.class` files that were
2428// compiled against the host bootclasspath.
2429func BinaryHostFactory() android.Module {
2430	module := &Binary{}
2431
2432	module.addHostProperties()
2433	module.AddProperties(&module.binaryProperties)
2434
2435	module.Module.properties.Installable = proptools.BoolPtr(true)
2436
2437	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst)
2438	android.InitDefaultableModule(module)
2439	return module
2440}
2441
2442//
2443// Java prebuilts
2444//
2445
2446type ImportProperties struct {
2447	Jars []string `android:"path,arch_variant"`
2448
2449	Sdk_version *string
2450
2451	Installable *bool
2452
2453	// List of shared java libs that this module has dependencies to
2454	Libs []string
2455
2456	// List of files to remove from the jar file(s)
2457	Exclude_files []string
2458
2459	// List of directories to remove from the jar file(s)
2460	Exclude_dirs []string
2461
2462	// if set to true, run Jetifier against .jar file. Defaults to false.
2463	Jetifier *bool
2464
2465	// set the name of the output
2466	Stem *string
2467}
2468
2469type Import struct {
2470	android.ModuleBase
2471	android.DefaultableModuleBase
2472	android.ApexModuleBase
2473	prebuilt android.Prebuilt
2474	android.SdkBase
2475
2476	// Functionality common to Module and Import.
2477	embeddableInModuleAndImport
2478
2479	properties ImportProperties
2480
2481	combinedClasspathFile android.Path
2482	exportedSdkLibs       []string
2483}
2484
2485func (j *Import) sdkVersion() sdkSpec {
2486	return sdkSpecFrom(String(j.properties.Sdk_version))
2487}
2488
2489func (j *Import) minSdkVersion() sdkSpec {
2490	return j.sdkVersion()
2491}
2492
2493func (j *Import) MinSdkVersion() string {
2494	return j.minSdkVersion().version.String()
2495}
2496
2497func (j *Import) Prebuilt() *android.Prebuilt {
2498	return &j.prebuilt
2499}
2500
2501func (j *Import) PrebuiltSrcs() []string {
2502	return j.properties.Jars
2503}
2504
2505func (j *Import) Name() string {
2506	return j.prebuilt.Name(j.ModuleBase.Name())
2507}
2508
2509func (j *Import) Stem() string {
2510	return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
2511}
2512
2513func (a *Import) JacocoReportClassesFile() android.Path {
2514	return nil
2515}
2516
2517func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
2518	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
2519}
2520
2521func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2522	jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
2523
2524	jarName := j.Stem() + ".jar"
2525	outputFile := android.PathForModuleOut(ctx, "combined", jarName)
2526	TransformJarsToJar(ctx, outputFile, "for prebuilts", jars, android.OptionalPath{},
2527		false, j.properties.Exclude_files, j.properties.Exclude_dirs)
2528	if Bool(j.properties.Jetifier) {
2529		inputFile := outputFile
2530		outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
2531		TransformJetifier(ctx, outputFile, inputFile)
2532	}
2533	j.combinedClasspathFile = outputFile
2534
2535	// If this is a component library (impl, stubs, etc.) for a java_sdk_library then
2536	// add the name of that java_sdk_library to the exported sdk libs to make sure
2537	// that, if necessary, a <uses-library> element for that java_sdk_library is
2538	// added to the Android manifest.
2539	j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...)
2540
2541	ctx.VisitDirectDeps(func(module android.Module) {
2542		otherName := ctx.OtherModuleName(module)
2543		tag := ctx.OtherModuleDependencyTag(module)
2544
2545		switch dep := module.(type) {
2546		case Dependency:
2547			switch tag {
2548			case libTag, staticLibTag:
2549				// sdk lib names from dependencies are re-exported
2550				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
2551			}
2552		case SdkLibraryDependency:
2553			switch tag {
2554			case libTag:
2555				// names of sdk libs that are directly depended are exported
2556				j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
2557			}
2558		}
2559	})
2560
2561	j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
2562	if Bool(j.properties.Installable) {
2563		ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
2564			jarName, outputFile)
2565	}
2566}
2567
2568var _ Dependency = (*Import)(nil)
2569
2570func (j *Import) HeaderJars() android.Paths {
2571	if j.combinedClasspathFile == nil {
2572		return nil
2573	}
2574	return android.Paths{j.combinedClasspathFile}
2575}
2576
2577func (j *Import) ImplementationJars() android.Paths {
2578	if j.combinedClasspathFile == nil {
2579		return nil
2580	}
2581	return android.Paths{j.combinedClasspathFile}
2582}
2583
2584func (j *Import) ResourceJars() android.Paths {
2585	return nil
2586}
2587
2588func (j *Import) ImplementationAndResourcesJars() android.Paths {
2589	if j.combinedClasspathFile == nil {
2590		return nil
2591	}
2592	return android.Paths{j.combinedClasspathFile}
2593}
2594
2595func (j *Import) DexJar() android.Path {
2596	return nil
2597}
2598
2599func (j *Import) AidlIncludeDirs() android.Paths {
2600	return nil
2601}
2602
2603func (j *Import) ExportedSdkLibs() []string {
2604	return j.exportedSdkLibs
2605}
2606
2607func (j *Import) ExportedPlugins() (android.Paths, []string) {
2608	return nil, nil
2609}
2610
2611func (j *Import) SrcJarArgs() ([]string, android.Paths) {
2612	return nil, nil
2613}
2614
2615func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
2616	return j.depIsInSameApex(ctx, dep)
2617}
2618
2619// Add compile time check for interface implementation
2620var _ android.IDEInfo = (*Import)(nil)
2621var _ android.IDECustomizedModuleName = (*Import)(nil)
2622
2623// Collect information for opening IDE project files in java/jdeps.go.
2624const (
2625	removedPrefix = "prebuilt_"
2626)
2627
2628func (j *Import) IDEInfo(dpInfo *android.IdeInfo) {
2629	dpInfo.Jars = append(dpInfo.Jars, j.PrebuiltSrcs()...)
2630}
2631
2632func (j *Import) IDECustomizedModuleName() string {
2633	// TODO(b/113562217): Extract the base module name from the Import name, often the Import name
2634	// has a prefix "prebuilt_". Remove the prefix explicitly if needed until we find a better
2635	// solution to get the Import name.
2636	name := j.Name()
2637	if strings.HasPrefix(name, removedPrefix) {
2638		name = strings.TrimPrefix(name, removedPrefix)
2639	}
2640	return name
2641}
2642
2643var _ android.PrebuiltInterface = (*Import)(nil)
2644
2645// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library module.
2646//
2647// By default, a java_import has a single variant that expects a `.jar` file containing `.class` files that were
2648// compiled against an Android classpath.
2649//
2650// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
2651// for host modules.
2652func ImportFactory() android.Module {
2653	module := &Import{}
2654
2655	module.AddProperties(&module.properties)
2656
2657	module.initModuleAndImport(&module.ModuleBase)
2658
2659	android.InitPrebuiltModule(module, &module.properties.Jars)
2660	android.InitApexModule(module)
2661	android.InitSdkAwareModule(module)
2662	InitJavaModule(module, android.HostAndDeviceSupported)
2663	return module
2664}
2665
2666// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library_host
2667// module.
2668//
2669// A java_import_host has a single variant that expects a `.jar` file containing `.class` files that were
2670// compiled against a host bootclasspath.
2671func ImportFactoryHost() android.Module {
2672	module := &Import{}
2673
2674	module.AddProperties(&module.properties)
2675
2676	android.InitPrebuiltModule(module, &module.properties.Jars)
2677	android.InitApexModule(module)
2678	InitJavaModule(module, android.HostSupported)
2679	return module
2680}
2681
2682// dex_import module
2683
2684type DexImportProperties struct {
2685	Jars []string `android:"path"`
2686
2687	// set the name of the output
2688	Stem *string
2689}
2690
2691type DexImport struct {
2692	android.ModuleBase
2693	android.DefaultableModuleBase
2694	android.ApexModuleBase
2695	prebuilt android.Prebuilt
2696
2697	properties DexImportProperties
2698
2699	dexJarFile              android.Path
2700	maybeStrippedDexJarFile android.Path
2701
2702	dexpreopter
2703}
2704
2705func (j *DexImport) Prebuilt() *android.Prebuilt {
2706	return &j.prebuilt
2707}
2708
2709func (j *DexImport) PrebuiltSrcs() []string {
2710	return j.properties.Jars
2711}
2712
2713func (j *DexImport) Name() string {
2714	return j.prebuilt.Name(j.ModuleBase.Name())
2715}
2716
2717func (j *DexImport) Stem() string {
2718	return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
2719}
2720
2721func (a *DexImport) JacocoReportClassesFile() android.Path {
2722	return nil
2723}
2724
2725func (a *DexImport) LintDepSets() LintDepSets {
2726	return LintDepSets{}
2727}
2728
2729func (j *DexImport) IsInstallable() bool {
2730	return true
2731}
2732
2733func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2734	if len(j.properties.Jars) != 1 {
2735		ctx.PropertyErrorf("jars", "exactly one jar must be provided")
2736	}
2737
2738	j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
2739	j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
2740
2741	inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
2742	dexOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar")
2743
2744	if j.dexpreopter.uncompressedDex {
2745		rule := android.NewRuleBuilder()
2746
2747		temporary := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar.unaligned")
2748		rule.Temporary(temporary)
2749
2750		// use zip2zip to uncompress classes*.dex files
2751		rule.Command().
2752			BuiltTool(ctx, "zip2zip").
2753			FlagWithInput("-i ", inputJar).
2754			FlagWithOutput("-o ", temporary).
2755			FlagWithArg("-0 ", "'classes*.dex'")
2756
2757		// use zipalign to align uncompressed classes*.dex files
2758		rule.Command().
2759			BuiltTool(ctx, "zipalign").
2760			Flag("-f").
2761			Text("4").
2762			Input(temporary).
2763			Output(dexOutputFile)
2764
2765		rule.DeleteTemporaryFiles()
2766
2767		rule.Build(pctx, ctx, "uncompress_dex", "uncompress dex")
2768	} else {
2769		ctx.Build(pctx, android.BuildParams{
2770			Rule:   android.Cp,
2771			Input:  inputJar,
2772			Output: dexOutputFile,
2773		})
2774	}
2775
2776	j.dexJarFile = dexOutputFile
2777
2778	dexOutputFile = j.dexpreopt(ctx, dexOutputFile)
2779
2780	j.maybeStrippedDexJarFile = dexOutputFile
2781
2782	if j.IsForPlatform() {
2783		ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
2784			j.Stem()+".jar", dexOutputFile)
2785	}
2786}
2787
2788func (j *DexImport) DexJar() android.Path {
2789	return j.dexJarFile
2790}
2791
2792// dex_import imports a `.jar` file containing classes.dex files.
2793//
2794// A dex_import module cannot be used as a dependency of a java_* or android_* module, it can only be installed
2795// to the device.
2796func DexImportFactory() android.Module {
2797	module := &DexImport{}
2798
2799	module.AddProperties(&module.properties)
2800
2801	android.InitPrebuiltModule(module, &module.properties.Jars)
2802	android.InitApexModule(module)
2803	InitJavaModule(module, android.DeviceSupported)
2804	return module
2805}
2806
2807//
2808// Defaults
2809//
2810type Defaults struct {
2811	android.ModuleBase
2812	android.DefaultsModuleBase
2813	android.ApexModuleBase
2814}
2815
2816// java_defaults provides a set of properties that can be inherited by other java or android modules.
2817//
2818// A module can use the properties from a java_defaults module using `defaults: ["defaults_module_name"]`.  Each
2819// property in the defaults module that exists in the depending module will be prepended to the depending module's
2820// value for that property.
2821//
2822// Example:
2823//
2824//     java_defaults {
2825//         name: "example_defaults",
2826//         srcs: ["common/**/*.java"],
2827//         javacflags: ["-Xlint:all"],
2828//         aaptflags: ["--auto-add-overlay"],
2829//     }
2830//
2831//     java_library {
2832//         name: "example",
2833//         defaults: ["example_defaults"],
2834//         srcs: ["example/**/*.java"],
2835//     }
2836//
2837// is functionally identical to:
2838//
2839//     java_library {
2840//         name: "example",
2841//         srcs: [
2842//             "common/**/*.java",
2843//             "example/**/*.java",
2844//         ],
2845//         javacflags: ["-Xlint:all"],
2846//     }
2847func defaultsFactory() android.Module {
2848	return DefaultsFactory()
2849}
2850
2851func DefaultsFactory() android.Module {
2852	module := &Defaults{}
2853
2854	module.AddProperties(
2855		&CompilerProperties{},
2856		&CompilerDeviceProperties{},
2857		&DexpreoptProperties{},
2858		&android.ProtoProperties{},
2859		&aaptProperties{},
2860		&androidLibraryProperties{},
2861		&appProperties{},
2862		&appTestProperties{},
2863		&overridableAppProperties{},
2864		&ImportProperties{},
2865		&AARImportProperties{},
2866		&sdkLibraryProperties{},
2867		&commonToSdkLibraryAndImportProperties{},
2868		&DexImportProperties{},
2869		&android.ApexProperties{},
2870		&RuntimeResourceOverlayProperties{},
2871		&LintProperties{},
2872	)
2873
2874	android.InitDefaultsModule(module)
2875	return module
2876}
2877
2878func kytheExtractJavaFactory() android.Singleton {
2879	return &kytheExtractJavaSingleton{}
2880}
2881
2882type kytheExtractJavaSingleton struct {
2883}
2884
2885func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonContext) {
2886	var xrefTargets android.Paths
2887	ctx.VisitAllModules(func(module android.Module) {
2888		if javaModule, ok := module.(xref); ok {
2889			xrefTargets = append(xrefTargets, javaModule.XrefJavaFiles()...)
2890		}
2891	})
2892	// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
2893	if len(xrefTargets) > 0 {
2894		ctx.Phony("xref_java", xrefTargets...)
2895	}
2896}
2897
2898var Bool = proptools.Bool
2899var BoolDefault = proptools.BoolDefault
2900var String = proptools.String
2901var inList = android.InList
2902