• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18	"fmt"
19	"path/filepath"
20	"strconv"
21	"strings"
22
23	"android/soong/android"
24	"android/soong/dexpreopt"
25
26	"github.com/google/blueprint"
27	"github.com/google/blueprint/proptools"
28)
29
30type AndroidLibraryDependency interface {
31	ExportPackage() android.Path
32	ExportedProguardFlagFiles() android.Paths
33	ExportedRRODirs() []rroDir
34	ExportedStaticPackages() android.Paths
35	ExportedManifests() android.Paths
36	ExportedAssets() android.OptionalPath
37	SetRROEnforcedForDependent(enforce bool)
38	IsRROEnforced(ctx android.BaseModuleContext) bool
39}
40
41func init() {
42	RegisterAARBuildComponents(android.InitRegistrationContext)
43}
44
45func RegisterAARBuildComponents(ctx android.RegistrationContext) {
46	ctx.RegisterModuleType("android_library_import", AARImportFactory)
47	ctx.RegisterModuleType("android_library", AndroidLibraryFactory)
48	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
49		ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
50	})
51}
52
53//
54// AAR (android library)
55//
56
57type androidLibraryProperties struct {
58	BuildAAR bool `blueprint:"mutated"`
59}
60
61type aaptProperties struct {
62	// flags passed to aapt when creating the apk
63	Aaptflags []string
64
65	// include all resource configurations, not just the product-configured
66	// ones.
67	Aapt_include_all_resources *bool
68
69	// list of directories relative to the Blueprints file containing assets.
70	// Defaults to ["assets"] if a directory called assets exists.  Set to []
71	// to disable the default.
72	Asset_dirs []string
73
74	// list of directories relative to the Blueprints file containing
75	// Android resources.  Defaults to ["res"] if a directory called res exists.
76	// Set to [] to disable the default.
77	Resource_dirs []string
78
79	// list of zip files containing Android resources.
80	Resource_zips []string `android:"path"`
81
82	// path to AndroidManifest.xml.  If unset, defaults to "AndroidManifest.xml".
83	Manifest *string `android:"path"`
84
85	// paths to additional manifest files to merge with main manifest.
86	Additional_manifests []string `android:"path"`
87
88	// do not include AndroidManifest from dependent libraries
89	Dont_merge_manifests *bool
90
91	// true if RRO is enforced for any of the dependent modules
92	RROEnforcedForDependent bool `blueprint:"mutated"`
93}
94
95type aapt struct {
96	aaptSrcJar              android.Path
97	exportPackage           android.Path
98	manifestPath            android.Path
99	transitiveManifestPaths android.Paths
100	proguardOptionsFile     android.Path
101	rroDirs                 []rroDir
102	rTxt                    android.Path
103	extraAaptPackagesFile   android.Path
104	mergedManifestFile      android.Path
105	noticeFile              android.OptionalPath
106	assetPackage            android.OptionalPath
107	isLibrary               bool
108	useEmbeddedNativeLibs   bool
109	useEmbeddedDex          bool
110	usesNonSdkApis          bool
111	hasNoCode               bool
112	LoggingParent           string
113	resourceFiles           android.Paths
114
115	splitNames []string
116	splits     []split
117
118	aaptProperties aaptProperties
119}
120
121type split struct {
122	name   string
123	suffix string
124	path   android.Path
125}
126
127// Propagate RRO enforcement flag to static lib dependencies transitively.
128func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) {
129	m := ctx.Module()
130	if d, ok := m.(AndroidLibraryDependency); ok && d.IsRROEnforced(ctx) {
131		ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
132			if a, ok := d.(AndroidLibraryDependency); ok {
133				a.SetRROEnforcedForDependent(true)
134			}
135		})
136	}
137}
138
139func (a *aapt) ExportPackage() android.Path {
140	return a.exportPackage
141}
142
143func (a *aapt) ExportedRRODirs() []rroDir {
144	return a.rroDirs
145}
146
147func (a *aapt) ExportedManifests() android.Paths {
148	return a.transitiveManifestPaths
149}
150
151func (a *aapt) ExportedAssets() android.OptionalPath {
152	return a.assetPackage
153}
154
155func (a *aapt) SetRROEnforcedForDependent(enforce bool) {
156	a.aaptProperties.RROEnforcedForDependent = enforce
157}
158
159func (a *aapt) IsRROEnforced(ctx android.BaseModuleContext) bool {
160	// True if RRO is enforced for this module or...
161	return ctx.Config().EnforceRROForModule(ctx.ModuleName()) ||
162		// if RRO is enforced for any of its dependents.
163		a.aaptProperties.RROEnforcedForDependent
164}
165
166func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkContext,
167	manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
168	resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
169
170	hasVersionCode := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-code")
171	hasVersionName := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-name")
172
173	// Flags specified in Android.bp
174	linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
175
176	linkFlags = append(linkFlags, "--no-static-lib-packages")
177
178	// Find implicit or explicit asset and resource dirs
179	assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
180	resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res")
181	resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips)
182
183	// Glob directories into lists of paths
184	for _, dir := range resourceDirs {
185		resDirs = append(resDirs, globbedResourceDir{
186			dir:   dir,
187			files: androidResourceGlob(ctx, dir),
188		})
189		resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, a, dir)
190		overlayDirs = append(overlayDirs, resOverlayDirs...)
191		rroDirs = append(rroDirs, resRRODirs...)
192	}
193
194	var assetDeps android.Paths
195	for i, dir := range assetDirs {
196		// Add a dependency on every file in the asset directory.  This ensures the aapt2
197		// rule will be rerun if one of the files in the asset directory is modified.
198		assetDeps = append(assetDeps, androidResourceGlob(ctx, dir)...)
199
200		// Add a dependency on a file that contains a list of all the files in the asset directory.
201		// This ensures the aapt2 rule will be run if a file is removed from the asset directory,
202		// or a file is added whose timestamp is older than the output of aapt2.
203		assetFileListFile := android.PathForModuleOut(ctx, "asset_dir_globs", strconv.Itoa(i)+".glob")
204		androidResourceGlobList(ctx, dir, assetFileListFile)
205		assetDeps = append(assetDeps, assetFileListFile)
206	}
207
208	assetDirStrings := assetDirs.Strings()
209	if a.noticeFile.Valid() {
210		assetDirStrings = append(assetDirStrings, filepath.Dir(a.noticeFile.Path().String()))
211		assetDeps = append(assetDeps, a.noticeFile.Path())
212	}
213
214	linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
215	linkDeps = append(linkDeps, manifestPath)
216
217	linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirStrings, "-A "))
218	linkDeps = append(linkDeps, assetDeps...)
219
220	// SDK version flags
221	minSdkVersion, err := sdkContext.MinSdkVersion(ctx).EffectiveVersionString(ctx)
222	if err != nil {
223		ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
224	}
225
226	linkFlags = append(linkFlags, "--min-sdk-version "+minSdkVersion)
227	linkFlags = append(linkFlags, "--target-sdk-version "+minSdkVersion)
228
229	// Version code
230	if !hasVersionCode {
231		linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion().String())
232	}
233
234	if !hasVersionName {
235		var versionName string
236		if ctx.ModuleName() == "framework-res" {
237			// Some builds set AppsDefaultVersionName() to include the build number ("O-123456").  aapt2 copies the
238			// version name of framework-res into app manifests as compileSdkVersionCodename, which confuses things
239			// if it contains the build number.  Use the PlatformVersionName instead.
240			versionName = ctx.Config().PlatformVersionName()
241		} else {
242			versionName = ctx.Config().AppsDefaultVersionName()
243		}
244		versionName = proptools.NinjaEscape(versionName)
245		linkFlags = append(linkFlags, "--version-name ", versionName)
246	}
247
248	linkFlags, compileFlags = android.FilterList(linkFlags, []string{"--legacy"})
249
250	// Always set --pseudo-localize, it will be stripped out later for release
251	// builds that don't want it.
252	compileFlags = append(compileFlags, "--pseudo-localize")
253
254	return compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resourceZips
255}
256
257func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkDep sdkDep) {
258	if sdkDep.frameworkResModule != "" {
259		ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule)
260	}
261}
262
263var extractAssetsRule = pctx.AndroidStaticRule("extractAssets",
264	blueprint.RuleParams{
265		Command:     `${config.Zip2ZipCmd} -i ${in} -o ${out} "assets/**/*"`,
266		CommandDeps: []string{"${config.Zip2ZipCmd}"},
267	})
268
269func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkContext,
270	classLoaderContexts dexpreopt.ClassLoaderContextMap, extraLinkFlags ...string) {
271
272	transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags :=
273		aaptLibs(ctx, sdkContext, classLoaderContexts)
274
275	// App manifest file
276	manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
277	manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
278
279	manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, classLoaderContexts,
280		a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode,
281		a.LoggingParent)
282
283	// Add additional manifest files to transitive manifests.
284	additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
285	a.transitiveManifestPaths = append(android.Paths{manifestPath}, additionalManifests...)
286	a.transitiveManifestPaths = append(a.transitiveManifestPaths, transitiveStaticLibManifests...)
287
288	if len(a.transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) {
289		a.mergedManifestFile = manifestMerger(ctx, a.transitiveManifestPaths[0], a.transitiveManifestPaths[1:], a.isLibrary)
290		if !a.isLibrary {
291			// Only use the merged manifest for applications.  For libraries, the transitive closure of manifests
292			// will be propagated to the final application and merged there.  The merged manifest for libraries is
293			// only passed to Make, which can't handle transitive dependencies.
294			manifestPath = a.mergedManifestFile
295		}
296	} else {
297		a.mergedManifestFile = manifestPath
298	}
299
300	compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, sdkContext, manifestPath)
301
302	rroDirs = append(rroDirs, staticRRODirs...)
303	linkFlags = append(linkFlags, libFlags...)
304	linkDeps = append(linkDeps, libDeps...)
305	linkFlags = append(linkFlags, extraLinkFlags...)
306	if a.isLibrary {
307		linkFlags = append(linkFlags, "--static-lib")
308	}
309
310	packageRes := android.PathForModuleOut(ctx, "package-res.apk")
311	// the subdir "android" is required to be filtered by package names
312	srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar")
313	proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
314	rTxt := android.PathForModuleOut(ctx, "R.txt")
315	// This file isn't used by Soong, but is generated for exporting
316	extraPackages := android.PathForModuleOut(ctx, "extra_packages")
317
318	var compiledResDirs []android.Paths
319	for _, dir := range resDirs {
320		a.resourceFiles = append(a.resourceFiles, dir.files...)
321		compiledResDirs = append(compiledResDirs, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths())
322	}
323
324	for i, zip := range resZips {
325		flata := android.PathForModuleOut(ctx, fmt.Sprintf("reszip.%d.flata", i))
326		aapt2CompileZip(ctx, flata, zip, "", compileFlags)
327		compiledResDirs = append(compiledResDirs, android.Paths{flata})
328	}
329
330	var compiledRes, compiledOverlay android.Paths
331
332	compiledOverlay = append(compiledOverlay, transitiveStaticLibs...)
333
334	if len(transitiveStaticLibs) > 0 {
335		// If we are using static android libraries, every source file becomes an overlay.
336		// This is to emulate old AAPT behavior which simulated library support.
337		for _, compiledResDir := range compiledResDirs {
338			compiledOverlay = append(compiledOverlay, compiledResDir...)
339		}
340	} else if a.isLibrary {
341		// Otherwise, for a static library we treat all the resources equally with no overlay.
342		for _, compiledResDir := range compiledResDirs {
343			compiledRes = append(compiledRes, compiledResDir...)
344		}
345	} else if len(compiledResDirs) > 0 {
346		// Without static libraries, the first directory is our directory, which can then be
347		// overlaid by the rest.
348		compiledRes = append(compiledRes, compiledResDirs[0]...)
349		for _, compiledResDir := range compiledResDirs[1:] {
350			compiledOverlay = append(compiledOverlay, compiledResDir...)
351		}
352	}
353
354	for _, dir := range overlayDirs {
355		compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()...)
356	}
357
358	var splitPackages android.WritablePaths
359	var splits []split
360
361	for _, s := range a.splitNames {
362		suffix := strings.Replace(s, ",", "_", -1)
363		path := android.PathForModuleOut(ctx, "package_"+suffix+".apk")
364		linkFlags = append(linkFlags, "--split", path.String()+":"+s)
365		splitPackages = append(splitPackages, path)
366		splits = append(splits, split{
367			name:   s,
368			suffix: suffix,
369			path:   path,
370		})
371	}
372
373	aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
374		linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages)
375
376	// Extract assets from the resource package output so that they can be used later in aapt2link
377	// for modules that depend on this one.
378	if android.PrefixInList(linkFlags, "-A ") || len(assetPackages) > 0 {
379		assets := android.PathForModuleOut(ctx, "assets.zip")
380		ctx.Build(pctx, android.BuildParams{
381			Rule:        extractAssetsRule,
382			Input:       packageRes,
383			Output:      assets,
384			Description: "extract assets from built resource file",
385		})
386		a.assetPackage = android.OptionalPathForPath(assets)
387	}
388
389	a.aaptSrcJar = srcJar
390	a.exportPackage = packageRes
391	a.manifestPath = manifestPath
392	a.proguardOptionsFile = proguardOptionsFile
393	a.rroDirs = rroDirs
394	a.extraAaptPackagesFile = extraPackages
395	a.rTxt = rTxt
396	a.splits = splits
397}
398
399// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
400func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) (
401	transitiveStaticLibs, transitiveStaticLibManifests android.Paths, staticRRODirs []rroDir, assets, deps android.Paths, flags []string) {
402
403	var sharedLibs android.Paths
404
405	if classLoaderContexts == nil {
406		// Not all callers need to compute class loader context, those who don't just pass nil.
407		// Create a temporary class loader context here (it will be computed, but not used).
408		classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
409	}
410
411	sdkDep := decodeSdkDep(ctx, sdkContext)
412	if sdkDep.useFiles {
413		sharedLibs = append(sharedLibs, sdkDep.jars...)
414	}
415
416	ctx.VisitDirectDeps(func(module android.Module) {
417		depTag := ctx.OtherModuleDependencyTag(module)
418
419		var exportPackage android.Path
420		aarDep, _ := module.(AndroidLibraryDependency)
421		if aarDep != nil {
422			exportPackage = aarDep.ExportPackage()
423		}
424
425		switch depTag {
426		case instrumentationForTag:
427			// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
428		case libTag:
429			if exportPackage != nil {
430				sharedLibs = append(sharedLibs, exportPackage)
431			}
432		case frameworkResTag:
433			if exportPackage != nil {
434				sharedLibs = append(sharedLibs, exportPackage)
435			}
436		case staticLibTag:
437			if exportPackage != nil {
438				transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
439				transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
440				transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
441				if aarDep.ExportedAssets().Valid() {
442					assets = append(assets, aarDep.ExportedAssets().Path())
443				}
444
445			outer:
446				for _, d := range aarDep.ExportedRRODirs() {
447					for _, e := range staticRRODirs {
448						if d.path == e.path {
449							continue outer
450						}
451					}
452					staticRRODirs = append(staticRRODirs, d)
453				}
454			}
455		}
456
457		addCLCFromDep(ctx, module, classLoaderContexts)
458	})
459
460	deps = append(deps, sharedLibs...)
461	deps = append(deps, transitiveStaticLibs...)
462
463	if len(transitiveStaticLibs) > 0 {
464		flags = append(flags, "--auto-add-overlay")
465	}
466
467	for _, sharedLib := range sharedLibs {
468		flags = append(flags, "-I "+sharedLib.String())
469	}
470
471	transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
472	transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
473
474	return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags
475}
476
477type AndroidLibrary struct {
478	Library
479	aapt
480
481	androidLibraryProperties androidLibraryProperties
482
483	aarFile android.WritablePath
484
485	exportedProguardFlagFiles android.Paths
486	exportedStaticPackages    android.Paths
487}
488
489func (a *AndroidLibrary) ExportedProguardFlagFiles() android.Paths {
490	return a.exportedProguardFlagFiles
491}
492
493func (a *AndroidLibrary) ExportedStaticPackages() android.Paths {
494	return a.exportedStaticPackages
495}
496
497var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
498
499func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
500	a.Module.deps(ctx)
501	sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
502	if sdkDep.hasFrameworkLibs() {
503		a.aapt.deps(ctx, sdkDep)
504	}
505}
506
507func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
508	a.aapt.isLibrary = true
509	a.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
510	a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts)
511
512	a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
513
514	ctx.CheckbuildFile(a.proguardOptionsFile)
515	ctx.CheckbuildFile(a.exportPackage)
516	ctx.CheckbuildFile(a.aaptSrcJar)
517
518	// apps manifests are handled by aapt, don't let Module see them
519	a.properties.Manifest = nil
520
521	a.linter.mergedManifest = a.aapt.mergedManifestFile
522	a.linter.manifest = a.aapt.manifestPath
523	a.linter.resources = a.aapt.resourceFiles
524
525	a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
526		a.proguardOptionsFile)
527
528	a.Module.compile(ctx, a.aaptSrcJar)
529
530	a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar")
531	var res android.Paths
532	if a.androidLibraryProperties.BuildAAR {
533		BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
534		ctx.CheckbuildFile(a.aarFile)
535	}
536
537	a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles,
538		android.PathsForModuleSrc(ctx, a.dexProperties.Optimize.Proguard_flags_files)...)
539	ctx.VisitDirectDeps(func(m android.Module) {
540		if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
541			a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
542			a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportPackage())
543			a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportedStaticPackages()...)
544		}
545	})
546
547	a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
548	a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
549}
550
551// android_library builds and links sources into a `.jar` file for the device along with Android resources.
552//
553// An android_library has a single variant that produces a `.jar` file containing `.class` files that were
554// compiled against the device bootclasspath, along with a `package-res.apk` file containing  Android resources compiled
555// with aapt2.  This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of
556// an android_app module.
557func AndroidLibraryFactory() android.Module {
558	module := &AndroidLibrary{}
559
560	module.Module.addHostAndDeviceProperties()
561	module.AddProperties(
562		&module.aaptProperties,
563		&module.androidLibraryProperties)
564
565	module.androidLibraryProperties.BuildAAR = true
566	module.Module.linter.library = true
567
568	android.InitApexModule(module)
569	InitJavaModule(module, android.DeviceSupported)
570	return module
571}
572
573//
574// AAR (android library) prebuilts
575//
576
577type AARImportProperties struct {
578	Aars []string `android:"path"`
579
580	Sdk_version     *string
581	Min_sdk_version *string
582
583	Static_libs []string
584	Libs        []string
585
586	// if set to true, run Jetifier against .aar file. Defaults to false.
587	Jetifier *bool
588}
589
590type AARImport struct {
591	android.ModuleBase
592	android.DefaultableModuleBase
593	android.ApexModuleBase
594	prebuilt android.Prebuilt
595
596	// Functionality common to Module and Import.
597	embeddableInModuleAndImport
598
599	properties AARImportProperties
600
601	classpathFile         android.WritablePath
602	proguardFlags         android.WritablePath
603	exportPackage         android.WritablePath
604	extraAaptPackagesFile android.WritablePath
605	manifest              android.WritablePath
606
607	exportedStaticPackages android.Paths
608
609	hideApexVariantFromMake bool
610
611	aarPath android.Path
612
613	sdkVersion    android.SdkSpec
614	minSdkVersion android.SdkSpec
615}
616
617var _ android.OutputFileProducer = (*AARImport)(nil)
618
619// For OutputFileProducer interface
620func (a *AARImport) OutputFiles(tag string) (android.Paths, error) {
621	switch tag {
622	case ".aar":
623		return []android.Path{a.aarPath}, nil
624	case "":
625		return []android.Path{a.classpathFile}, nil
626	default:
627		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
628	}
629}
630
631func (a *AARImport) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
632	return android.SdkSpecFrom(ctx, String(a.properties.Sdk_version))
633}
634
635func (a *AARImport) SystemModules() string {
636	return ""
637}
638
639func (a *AARImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
640	if a.properties.Min_sdk_version != nil {
641		return android.SdkSpecFrom(ctx, *a.properties.Min_sdk_version)
642	}
643	return a.SdkVersion(ctx)
644}
645
646func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
647	return a.SdkVersion(ctx)
648}
649
650func (a *AARImport) javaVersion() string {
651	return ""
652}
653
654var _ AndroidLibraryDependency = (*AARImport)(nil)
655
656func (a *AARImport) ExportPackage() android.Path {
657	return a.exportPackage
658}
659
660func (a *AARImport) ExportedProguardFlagFiles() android.Paths {
661	return android.Paths{a.proguardFlags}
662}
663
664func (a *AARImport) ExportedRRODirs() []rroDir {
665	return nil
666}
667
668func (a *AARImport) ExportedStaticPackages() android.Paths {
669	return a.exportedStaticPackages
670}
671
672func (a *AARImport) ExportedManifests() android.Paths {
673	return android.Paths{a.manifest}
674}
675
676// TODO(jungjw): Decide whether we want to implement this.
677func (a *AARImport) ExportedAssets() android.OptionalPath {
678	return android.OptionalPath{}
679}
680
681// RRO enforcement is not available on aar_import since its RRO dirs are not
682// exported.
683func (a *AARImport) SetRROEnforcedForDependent(enforce bool) {
684}
685
686// RRO enforcement is not available on aar_import since its RRO dirs are not
687// exported.
688func (a *AARImport) IsRROEnforced(ctx android.BaseModuleContext) bool {
689	return false
690}
691
692func (a *AARImport) Prebuilt() *android.Prebuilt {
693	return &a.prebuilt
694}
695
696func (a *AARImport) Name() string {
697	return a.prebuilt.Name(a.ModuleBase.Name())
698}
699
700func (a *AARImport) JacocoReportClassesFile() android.Path {
701	return nil
702}
703
704func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
705	if !ctx.Config().AlwaysUsePrebuiltSdks() {
706		sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
707		if sdkDep.useModule && sdkDep.frameworkResModule != "" {
708			ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule)
709		}
710	}
711
712	ctx.AddVariationDependencies(nil, libTag, a.properties.Libs...)
713	ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...)
714}
715
716// Unzip an AAR into its constituent files and directories.  Any files in Outputs that don't exist in the AAR will be
717// touched to create an empty file. The res directory is not extracted, as it will be extracted in its own rule.
718var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
719	blueprint.RuleParams{
720		Command: `rm -rf $outDir && mkdir -p $outDir && ` +
721			`unzip -qoDD -d $outDir $in && rm -rf $outDir/res && touch $out && ` +
722			`${config.MergeZipsCmd} $combinedClassesJar $$(ls $outDir/classes.jar 2> /dev/null) $$(ls $outDir/libs/*.jar 2> /dev/null)`,
723		CommandDeps: []string{"${config.MergeZipsCmd}"},
724	},
725	"outDir", "combinedClassesJar")
726
727func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
728	if len(a.properties.Aars) != 1 {
729		ctx.PropertyErrorf("aars", "exactly one aar is required")
730		return
731	}
732
733	a.sdkVersion = a.SdkVersion(ctx)
734	a.minSdkVersion = a.MinSdkVersion(ctx)
735
736	a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
737
738	aarName := ctx.ModuleName() + ".aar"
739	a.aarPath = android.PathForModuleSrc(ctx, a.properties.Aars[0])
740
741	if Bool(a.properties.Jetifier) {
742		inputFile := a.aarPath
743		a.aarPath = android.PathForModuleOut(ctx, "jetifier", aarName)
744		TransformJetifier(ctx, a.aarPath.(android.WritablePath), inputFile)
745	}
746
747	extractedAARDir := android.PathForModuleOut(ctx, "aar")
748	a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar")
749	a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
750	a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml")
751
752	ctx.Build(pctx, android.BuildParams{
753		Rule:        unzipAAR,
754		Input:       a.aarPath,
755		Outputs:     android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest},
756		Description: "unzip AAR",
757		Args: map[string]string{
758			"outDir":             extractedAARDir.String(),
759			"combinedClassesJar": a.classpathFile.String(),
760		},
761	})
762
763	// Always set --pseudo-localize, it will be stripped out later for release
764	// builds that don't want it.
765	compileFlags := []string{"--pseudo-localize"}
766	compiledResDir := android.PathForModuleOut(ctx, "flat-res")
767	flata := compiledResDir.Join(ctx, "gen_res.flata")
768	aapt2CompileZip(ctx, flata, a.aarPath, "res", compileFlags)
769
770	a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
771	// the subdir "android" is required to be filtered by package names
772	srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar")
773	proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
774	rTxt := android.PathForModuleOut(ctx, "R.txt")
775	a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages")
776
777	var linkDeps android.Paths
778
779	linkFlags := []string{
780		"--static-lib",
781		"--no-static-lib-packages",
782		"--auto-add-overlay",
783	}
784
785	linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
786	linkDeps = append(linkDeps, a.manifest)
787
788	transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags :=
789		aaptLibs(ctx, android.SdkContext(a), nil)
790
791	_ = staticLibManifests
792	_ = staticRRODirs
793
794	linkDeps = append(linkDeps, libDeps...)
795	linkFlags = append(linkFlags, libFlags...)
796
797	overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)
798
799	aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
800		linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil)
801
802	ctx.SetProvider(JavaInfoProvider, JavaInfo{
803		HeaderJars:                     android.PathsIfNonNil(a.classpathFile),
804		ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
805		ImplementationJars:             android.PathsIfNonNil(a.classpathFile),
806	})
807}
808
809func (a *AARImport) HeaderJars() android.Paths {
810	return android.Paths{a.classpathFile}
811}
812
813func (a *AARImport) ImplementationAndResourcesJars() android.Paths {
814	return android.Paths{a.classpathFile}
815}
816
817func (a *AARImport) DexJarBuildPath() android.Path {
818	return nil
819}
820
821func (a *AARImport) DexJarInstallPath() android.Path {
822	return nil
823}
824
825func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
826	return nil
827}
828
829var _ android.ApexModule = (*AARImport)(nil)
830
831// Implements android.ApexModule
832func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
833	return a.depIsInSameApex(ctx, dep)
834}
835
836// Implements android.ApexModule
837func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
838	sdkVersion android.ApiLevel) error {
839	return nil
840}
841
842var _ android.PrebuiltInterface = (*Import)(nil)
843
844// android_library_import imports an `.aar` file into the build graph as if it was built with android_library.
845//
846// This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of
847// an android_app module.
848func AARImportFactory() android.Module {
849	module := &AARImport{}
850
851	module.AddProperties(&module.properties)
852
853	android.InitPrebuiltModule(module, &module.properties.Aars)
854	android.InitApexModule(module)
855	InitJavaModule(module, android.DeviceSupported)
856	return module
857}
858