• 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 Android apps.
18
19import (
20	"path/filepath"
21	"sort"
22	"strings"
23
24	"github.com/google/blueprint"
25	"github.com/google/blueprint/proptools"
26
27	"android/soong/android"
28	"android/soong/cc"
29	"android/soong/tradefed"
30)
31
32func init() {
33	android.RegisterModuleType("android_app", AndroidAppFactory)
34	android.RegisterModuleType("android_test", AndroidTestFactory)
35	android.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
36	android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
37	android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
38}
39
40// AndroidManifest.xml merging
41// package splits
42
43type appProperties struct {
44	// Names of extra android_app_certificate modules to sign the apk with in the form ":module".
45	Additional_certificates []string
46
47	// If set, create package-export.apk, which other packages can
48	// use to get PRODUCT-agnostic resource data like IDs and type definitions.
49	Export_package_resources *bool
50
51	// Specifies that this app should be installed to the priv-app directory,
52	// where the system will grant it additional privileges not available to
53	// normal apps.
54	Privileged *bool
55
56	// list of resource labels to generate individual resource packages
57	Package_splits []string
58
59	// Names of modules to be overridden. Listed modules can only be other binaries
60	// (in Make or Soong).
61	// This does not completely prevent installation of the overridden binaries, but if both
62	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
63	// from PRODUCT_PACKAGES.
64	Overrides []string
65
66	// list of native libraries that will be provided in or alongside the resulting jar
67	Jni_libs []string `android:"arch_variant"`
68
69	// Store native libraries uncompressed in the APK and set the android:extractNativeLibs="false" manifest
70	// flag so that they are used from inside the APK at runtime.  Defaults to true for android_test modules unless
71	// sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to false for other
72	// module types where the native libraries are generally preinstalled outside the APK.
73	Use_embedded_native_libs *bool
74
75	// Store dex files uncompressed in the APK and set the android:useEmbeddedDex="true" manifest attribute so that
76	// they are used from inside the APK at runtime.
77	Use_embedded_dex *bool
78
79	// Forces native libraries to always be packaged into the APK,
80	// Use_embedded_native_libs still selects whether they are stored uncompressed and aligned or compressed.
81	// True for android_test* modules.
82	AlwaysPackageNativeLibs bool `blueprint:"mutated"`
83
84	// If set, find and merge all NOTICE files that this module and its dependencies have and store
85	// it in the APK as an asset.
86	Embed_notices *bool
87}
88
89// android_app properties that can be overridden by override_android_app
90type overridableAppProperties struct {
91	// The name of a certificate in the default certificate directory, blank to use the default product certificate,
92	// or an android_app_certificate module name in the form ":module".
93	Certificate *string
94
95	// the package name of this app. The package name in the manifest file is used if one was not given.
96	Package_name *string
97}
98
99type AndroidApp struct {
100	Library
101	aapt
102	android.OverridableModuleBase
103
104	certificate Certificate
105
106	appProperties appProperties
107
108	overridableAppProperties overridableAppProperties
109
110	installJniLibs []jniLib
111
112	bundleFile android.Path
113
114	// the install APK name is normally the same as the module name, but can be overridden with PRODUCT_PACKAGE_NAME_OVERRIDES.
115	installApkName string
116
117	additionalAaptFlags []string
118}
119
120func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
121	return nil
122}
123
124func (a *AndroidApp) ExportedStaticPackages() android.Paths {
125	return nil
126}
127
128var _ AndroidLibraryDependency = (*AndroidApp)(nil)
129
130type Certificate struct {
131	Pem, Key android.Path
132}
133
134func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
135	a.Module.deps(ctx)
136
137	if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
138		a.aapt.deps(ctx, sdkContext(a))
139	}
140
141	for _, jniTarget := range ctx.MultiTargets() {
142		variation := []blueprint.Variation{
143			{Mutator: "arch", Variation: jniTarget.String()},
144			{Mutator: "link", Variation: "shared"},
145		}
146		tag := &jniDependencyTag{
147			target: jniTarget,
148		}
149		ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
150	}
151
152	cert := android.SrcIsModule(a.getCertString(ctx))
153	if cert != "" {
154		ctx.AddDependency(ctx.Module(), certificateTag, cert)
155	}
156
157	for _, cert := range a.appProperties.Additional_certificates {
158		cert = android.SrcIsModule(cert)
159		if cert != "" {
160			ctx.AddDependency(ctx.Module(), certificateTag, cert)
161		} else {
162			ctx.PropertyErrorf("additional_certificates",
163				`must be names of android_app_certificate modules in the form ":module"`)
164		}
165	}
166}
167
168func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
169	a.aapt.uncompressedJNI = a.shouldUncompressJNI(ctx)
170	a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
171	a.generateAndroidBuildActions(ctx)
172}
173
174// shouldUncompressJNI returns true if the native libraries should be stored in the APK uncompressed and the
175// extractNativeLibs application flag should be set to false in the manifest.
176func (a *AndroidApp) shouldUncompressJNI(ctx android.ModuleContext) bool {
177	minSdkVersion, err := sdkVersionToNumber(ctx, a.minSdkVersion())
178	if err != nil {
179		ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.minSdkVersion(), err)
180	}
181
182	return minSdkVersion >= 23 && Bool(a.appProperties.Use_embedded_native_libs)
183}
184
185// Returns whether this module should have the dex file stored uncompressed in the APK.
186func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool {
187	if Bool(a.appProperties.Use_embedded_dex) {
188		return true
189	}
190
191	// Uncompress dex in APKs of privileged apps, and modules used by privileged apps
192	// (even for unbundled builds, they may be preinstalled as prebuilts).
193	if ctx.Config().UncompressPrivAppDex() &&
194		(Bool(a.appProperties.Privileged) ||
195			inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules())) {
196		return true
197	}
198
199	if ctx.Config().UnbundledBuild() {
200		return false
201	}
202
203	// Uncompress if the dex files is preopted on /system.
204	if !a.dexpreopter.dexpreoptDisabled(ctx) && (ctx.Host() || !odexOnSystemOther(ctx, a.dexpreopter.installPath)) {
205		return true
206	}
207
208	return false
209}
210
211func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
212	a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
213
214	aaptLinkFlags := []string{}
215
216	// Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
217	hasProduct := false
218	for _, f := range a.aaptProperties.Aaptflags {
219		if strings.HasPrefix(f, "--product") {
220			hasProduct = true
221			break
222		}
223	}
224	if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
225		aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
226	}
227
228	if !Bool(a.aaptProperties.Aapt_include_all_resources) {
229		// Product AAPT config
230		for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
231			aaptLinkFlags = append(aaptLinkFlags, "-c", aaptConfig)
232		}
233
234		// Product AAPT preferred config
235		if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
236			aaptLinkFlags = append(aaptLinkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
237		}
238	}
239
240	manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
241	if overridden || a.overridableAppProperties.Package_name != nil {
242		// The product override variable has a priority over the package_name property.
243		if !overridden {
244			manifestPackageName = *a.overridableAppProperties.Package_name
245		}
246		aaptLinkFlags = append(aaptLinkFlags, "--rename-manifest-package "+manifestPackageName)
247	}
248
249	aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...)
250
251	a.aapt.splitNames = a.appProperties.Package_splits
252
253	a.aapt.buildActions(ctx, sdkContext(a), aaptLinkFlags...)
254
255	// apps manifests are handled by aapt, don't let Module see them
256	a.properties.Manifest = nil
257}
258
259func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) {
260	var staticLibProguardFlagFiles android.Paths
261	ctx.VisitDirectDeps(func(m android.Module) {
262		if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
263			staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
264		}
265	})
266
267	staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
268
269	a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, staticLibProguardFlagFiles...)
270	a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile)
271}
272
273func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
274
275	var installDir string
276	if ctx.ModuleName() == "framework-res" {
277		// framework-res.apk is installed as system/framework/framework-res.apk
278		installDir = "framework"
279	} else if Bool(a.appProperties.Privileged) {
280		installDir = filepath.Join("priv-app", a.installApkName)
281	} else {
282		installDir = filepath.Join("app", a.installApkName)
283	}
284	a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
285	a.dexpreopter.isInstallable = Bool(a.properties.Installable)
286	a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
287	a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex
288
289	if ctx.ModuleName() != "framework-res" {
290		a.Module.compile(ctx, a.aaptSrcJar)
291	}
292
293	return a.maybeStrippedDexJarFile
294}
295
296func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
297	var jniJarFile android.WritablePath
298	if len(jniLibs) > 0 {
299		embedJni := ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
300			a.appProperties.AlwaysPackageNativeLibs
301		if embedJni {
302			jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
303			TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.shouldUncompressJNI(ctx))
304		} else {
305			a.installJniLibs = jniLibs
306		}
307	}
308	return jniJarFile
309}
310
311func (a *AndroidApp) certificateBuildActions(certificateDeps []Certificate, ctx android.ModuleContext) []Certificate {
312	cert := a.getCertString(ctx)
313	certModule := android.SrcIsModule(cert)
314	if certModule != "" {
315		a.certificate = certificateDeps[0]
316		certificateDeps = certificateDeps[1:]
317	} else if cert != "" {
318		defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
319		a.certificate = Certificate{
320			defaultDir.Join(ctx, cert+".x509.pem"),
321			defaultDir.Join(ctx, cert+".pk8"),
322		}
323	} else {
324		pem, key := ctx.Config().DefaultAppCertificate(ctx)
325		a.certificate = Certificate{pem, key}
326	}
327
328	if !a.Module.Platform() {
329		certPath := a.certificate.Pem.String()
330		systemCertPath := ctx.Config().DefaultAppCertificateDir(ctx).String()
331		if strings.HasPrefix(certPath, systemCertPath) {
332			enforceSystemCert := ctx.Config().EnforceSystemCertificate()
333			whitelist := ctx.Config().EnforceSystemCertificateWhitelist()
334
335			if enforceSystemCert && !inList(a.Module.Name(), whitelist) {
336				ctx.PropertyErrorf("certificate", "The module in product partition cannot be signed with certificate in system.")
337			}
338		}
339	}
340
341	return append([]Certificate{a.certificate}, certificateDeps...)
342}
343
344func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext, installDir android.OutputPath) android.OptionalPath {
345	if !Bool(a.appProperties.Embed_notices) && !ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
346		return android.OptionalPath{}
347	}
348
349	// Collect NOTICE files from all dependencies.
350	seenModules := make(map[android.Module]bool)
351	noticePathSet := make(map[android.Path]bool)
352
353	ctx.WalkDepsBlueprint(func(child blueprint.Module, parent blueprint.Module) bool {
354		if _, ok := child.(android.Module); !ok {
355			return false
356		}
357		module := child.(android.Module)
358		// Have we already seen this?
359		if _, ok := seenModules[module]; ok {
360			return false
361		}
362		seenModules[module] = true
363
364		// Skip host modules.
365		if module.Target().Os.Class == android.Host || module.Target().Os.Class == android.HostCross {
366			return false
367		}
368
369		path := module.NoticeFile()
370		if path.Valid() {
371			noticePathSet[path.Path()] = true
372		}
373		return true
374	})
375
376	// If the app has one, add it too.
377	if a.NoticeFile().Valid() {
378		noticePathSet[a.NoticeFile().Path()] = true
379	}
380
381	if len(noticePathSet) == 0 {
382		return android.OptionalPath{}
383	}
384	var noticePaths []android.Path
385	for path := range noticePathSet {
386		noticePaths = append(noticePaths, path)
387	}
388	sort.Slice(noticePaths, func(i, j int) bool {
389		return noticePaths[i].String() < noticePaths[j].String()
390	})
391	noticeFile := android.BuildNoticeOutput(ctx, installDir, a.installApkName+".apk", noticePaths)
392
393	return android.OptionalPathForPath(noticeFile)
394}
395
396func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
397	// Check if the install APK name needs to be overridden.
398	a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
399
400	var installDir android.OutputPath
401	if ctx.ModuleName() == "framework-res" {
402		// framework-res.apk is installed as system/framework/framework-res.apk
403		installDir = android.PathForModuleInstall(ctx, "framework")
404	} else if Bool(a.appProperties.Privileged) {
405		installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName)
406	} else {
407		installDir = android.PathForModuleInstall(ctx, "app", a.installApkName)
408	}
409
410	a.aapt.noticeFile = a.noticeBuildActions(ctx, installDir)
411
412	// Process all building blocks, from AAPT to certificates.
413	a.aaptBuildActions(ctx)
414
415	a.proguardBuildActions(ctx)
416
417	dexJarFile := a.dexBuildActions(ctx)
418
419	jniLibs, certificateDeps := a.collectAppDeps(ctx)
420	jniJarFile := a.jniBuildActions(jniLibs, ctx)
421
422	if ctx.Failed() {
423		return
424	}
425
426	certificates := a.certificateBuildActions(certificateDeps, ctx)
427
428	// Build a final signed app package.
429	// TODO(jungjw): Consider changing this to installApkName.
430	packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk")
431	CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
432	a.outputFile = packageFile
433
434	for _, split := range a.aapt.splits {
435		// Sign the split APKs
436		packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"_"+split.suffix+".apk")
437		CreateAppPackage(ctx, packageFile, split.path, nil, nil, certificates)
438		a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
439	}
440
441	// Build an app bundle.
442	bundleFile := android.PathForModuleOut(ctx, "base.zip")
443	BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile)
444	a.bundleFile = bundleFile
445
446	// Install the app package.
447	ctx.InstallFile(installDir, a.installApkName+".apk", a.outputFile)
448	for _, split := range a.aapt.splits {
449		ctx.InstallFile(installDir, a.installApkName+"_"+split.suffix+".apk", split.path)
450	}
451}
452
453func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) {
454	var jniLibs []jniLib
455	var certificates []Certificate
456
457	ctx.VisitDirectDeps(func(module android.Module) {
458		otherName := ctx.OtherModuleName(module)
459		tag := ctx.OtherModuleDependencyTag(module)
460
461		if jniTag, ok := tag.(*jniDependencyTag); ok {
462			if dep, ok := module.(*cc.Module); ok {
463				lib := dep.OutputFile()
464				if lib.Valid() {
465					jniLibs = append(jniLibs, jniLib{
466						name:   ctx.OtherModuleName(module),
467						path:   lib.Path(),
468						target: jniTag.target,
469					})
470				} else {
471					ctx.ModuleErrorf("dependency %q missing output file", otherName)
472				}
473			} else {
474				ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName)
475
476			}
477		} else if tag == certificateTag {
478			if dep, ok := module.(*AndroidAppCertificate); ok {
479				certificates = append(certificates, dep.Certificate)
480			} else {
481				ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
482			}
483		}
484	})
485
486	return jniLibs, certificates
487}
488
489func (a *AndroidApp) getCertString(ctx android.BaseContext) string {
490	certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
491	if overridden {
492		return ":" + certificate
493	}
494	return String(a.overridableAppProperties.Certificate)
495}
496
497// android_app compiles sources and Android resources into an Android application package `.apk` file.
498func AndroidAppFactory() android.Module {
499	module := &AndroidApp{}
500
501	module.Module.deviceProperties.Optimize.EnabledByDefault = true
502	module.Module.deviceProperties.Optimize.Shrink = proptools.BoolPtr(true)
503
504	module.Module.properties.Instrument = true
505	module.Module.properties.Installable = proptools.BoolPtr(true)
506
507	module.AddProperties(
508		&module.Module.properties,
509		&module.Module.deviceProperties,
510		&module.Module.dexpreoptProperties,
511		&module.Module.protoProperties,
512		&module.aaptProperties,
513		&module.appProperties,
514		&module.overridableAppProperties)
515
516	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
517		return class == android.Device && ctx.Config().DevicePrefer32BitApps()
518	})
519
520	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
521	android.InitDefaultableModule(module)
522	android.InitOverridableModule(module, &module.appProperties.Overrides)
523
524	return module
525}
526
527type appTestProperties struct {
528	Instrumentation_for *string
529}
530
531type AndroidTest struct {
532	AndroidApp
533
534	appTestProperties appTestProperties
535
536	testProperties testProperties
537
538	testConfig android.Path
539	data       android.Paths
540}
541
542func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
543	// Check if the instrumentation target package is overridden before generating build actions.
544	if a.appTestProperties.Instrumentation_for != nil {
545		manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(*a.appTestProperties.Instrumentation_for)
546		if overridden {
547			a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+manifestPackageName)
548		}
549	}
550	a.generateAndroidBuildActions(ctx)
551
552	a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites)
553	a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
554}
555
556func (a *AndroidTest) DepsMutator(ctx android.BottomUpMutatorContext) {
557	a.AndroidApp.DepsMutator(ctx)
558	if a.appTestProperties.Instrumentation_for != nil {
559		// The android_app dependency listed in instrumentation_for needs to be added to the classpath for javac,
560		// but not added to the aapt2 link includes like a normal android_app or android_library dependency, so
561		// use instrumentationForTag instead of libTag.
562		ctx.AddVariationDependencies(nil, instrumentationForTag, String(a.appTestProperties.Instrumentation_for))
563	}
564}
565
566// android_test compiles test sources and Android resources into an Android application package `.apk` file and
567// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
568func AndroidTestFactory() android.Module {
569	module := &AndroidTest{}
570
571	module.Module.deviceProperties.Optimize.EnabledByDefault = true
572
573	module.Module.properties.Instrument = true
574	module.Module.properties.Installable = proptools.BoolPtr(true)
575	module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
576	module.appProperties.AlwaysPackageNativeLibs = true
577	module.Module.dexpreopter.isTest = true
578
579	module.AddProperties(
580		&module.Module.properties,
581		&module.Module.deviceProperties,
582		&module.Module.dexpreoptProperties,
583		&module.Module.protoProperties,
584		&module.aaptProperties,
585		&module.appProperties,
586		&module.appTestProperties,
587		&module.overridableAppProperties,
588		&module.testProperties)
589
590	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
591	android.InitDefaultableModule(module)
592	return module
593}
594
595type appTestHelperAppProperties struct {
596	// list of compatibility suites (for example "cts", "vts") that the module should be
597	// installed into.
598	Test_suites []string `android:"arch_variant"`
599}
600
601type AndroidTestHelperApp struct {
602	AndroidApp
603
604	appTestHelperAppProperties appTestHelperAppProperties
605}
606
607// android_test_helper_app compiles sources and Android resources into an Android application package `.apk` file that
608// will be used by tests, but does not produce an `AndroidTest.xml` file so the module will not be run directly as a
609// test.
610func AndroidTestHelperAppFactory() android.Module {
611	module := &AndroidTestHelperApp{}
612
613	module.Module.deviceProperties.Optimize.EnabledByDefault = true
614
615	module.Module.properties.Installable = proptools.BoolPtr(true)
616	module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
617	module.appProperties.AlwaysPackageNativeLibs = true
618	module.Module.dexpreopter.isTest = true
619
620	module.AddProperties(
621		&module.Module.properties,
622		&module.Module.deviceProperties,
623		&module.Module.dexpreoptProperties,
624		&module.Module.protoProperties,
625		&module.aaptProperties,
626		&module.appProperties,
627		&module.appTestHelperAppProperties,
628		&module.overridableAppProperties)
629
630	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
631	android.InitDefaultableModule(module)
632	return module
633}
634
635type AndroidAppCertificate struct {
636	android.ModuleBase
637	properties  AndroidAppCertificateProperties
638	Certificate Certificate
639}
640
641type AndroidAppCertificateProperties struct {
642	// Name of the certificate files.  Extensions .x509.pem and .pk8 will be added to the name.
643	Certificate *string
644}
645
646// android_app_certificate modules can be referenced by the certificates property of android_app modules to select
647// the signing key.
648func AndroidAppCertificateFactory() android.Module {
649	module := &AndroidAppCertificate{}
650	module.AddProperties(&module.properties)
651	android.InitAndroidModule(module)
652	return module
653}
654
655func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
656	cert := String(c.properties.Certificate)
657	c.Certificate = Certificate{
658		android.PathForModuleSrc(ctx, cert+".x509.pem"),
659		android.PathForModuleSrc(ctx, cert+".pk8"),
660	}
661}
662
663type OverrideAndroidApp struct {
664	android.ModuleBase
665	android.OverrideModuleBase
666}
667
668func (i *OverrideAndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
669	// All the overrides happen in the base module.
670	// TODO(jungjw): Check the base module type.
671}
672
673// override_android_app is used to create an android_app module based on another android_app by overriding
674// some of its properties.
675func OverrideAndroidAppModuleFactory() android.Module {
676	m := &OverrideAndroidApp{}
677	m.AddProperties(&overridableAppProperties{})
678
679	android.InitAndroidModule(m)
680	android.InitOverrideModule(m)
681	return m
682}
683