• 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 implementations for android_app, android_test, and some more
18// related module types, including their override variants.
19
20import (
21	"fmt"
22	"path/filepath"
23	"strings"
24
25	"github.com/google/blueprint"
26	"github.com/google/blueprint/depset"
27	"github.com/google/blueprint/proptools"
28
29	"android/soong/android"
30	"android/soong/cc"
31	"android/soong/dexpreopt"
32	"android/soong/tradefed"
33)
34
35func init() {
36	RegisterAppBuildComponents(android.InitRegistrationContext)
37	pctx.HostBinToolVariable("ModifyAllowlistCmd", "modify_permissions_allowlist")
38}
39
40var (
41	modifyAllowlist = pctx.AndroidStaticRule("modifyAllowlist",
42		blueprint.RuleParams{
43			Command:     "${ModifyAllowlistCmd} $in $packageName $out",
44			CommandDeps: []string{"${ModifyAllowlistCmd}"},
45		}, "packageName")
46)
47
48type FlagsPackages struct {
49	// Paths to the aconfig dump output text files that are consumed by aapt2
50	AconfigTextFiles android.Paths
51}
52
53var FlagsPackagesProvider = blueprint.NewProvider[FlagsPackages]()
54
55func RegisterAppBuildComponents(ctx android.RegistrationContext) {
56	ctx.RegisterModuleType("android_app", AndroidAppFactory)
57	ctx.RegisterModuleType("android_test", AndroidTestFactory)
58	ctx.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
59	ctx.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
60	ctx.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
61	ctx.RegisterModuleType("override_android_test", OverrideAndroidTestModuleFactory)
62}
63
64type AppInfo struct {
65	// Updatable is set to the value of the updatable property
66	Updatable bool
67
68	// TestHelperApp is true if the module is a android_test_helper_app
69	TestHelperApp bool
70
71	// EmbeddedJNILibs is the list of paths to JNI libraries that were embedded in the APK.
72	EmbeddedJNILibs android.Paths
73
74	MergedManifestFile android.Path
75
76	Prebuilt                      bool
77	AppSet                        bool
78	Privileged                    bool
79	OutputFile                    android.Path
80	InstallApkName                string
81	JacocoReportClassesFile       android.Path
82	Certificate                   Certificate
83	PrivAppAllowlist              android.OptionalPath
84	OverriddenManifestPackageName *string
85	ApkCertsFile                  android.Path
86}
87
88var AppInfoProvider = blueprint.NewProvider[*AppInfo]()
89
90// AndroidManifest.xml merging
91// package splits
92
93type appProperties struct {
94	// Names of extra android_app_certificate modules to sign the apk with in the form ":module".
95	Additional_certificates []string
96
97	// If set, create package-export.apk, which other packages can
98	// use to get PRODUCT-agnostic resource data like IDs and type definitions.
99	Export_package_resources *bool
100
101	// Specifies that this app should be installed to the priv-app directory,
102	// where the system will grant it additional privileges not available to
103	// normal apps.
104	Privileged *bool
105
106	// list of resource labels to generate individual resource packages
107	Package_splits []string
108
109	// list of native libraries that will be provided in or alongside the resulting jar
110	Jni_libs proptools.Configurable[[]string] `android:"arch_variant"`
111
112	// if true, use JNI libraries that link against platform APIs even if this module sets
113	// sdk_version.
114	Jni_uses_platform_apis *bool
115
116	// if true, use JNI libraries that link against SDK APIs even if this module does not set
117	// sdk_version.
118	Jni_uses_sdk_apis *bool
119
120	// STL library to use for JNI libraries.
121	Stl *string `android:"arch_variant"`
122
123	// Store native libraries uncompressed in the APK and set the android:extractNativeLibs="false" manifest
124	// flag so that they are used from inside the APK at runtime.  Defaults to true for android_test modules unless
125	// sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to true for
126	// android_app modules that are embedded to APEXes, defaults to false for other module types where the native
127	// libraries are generally preinstalled outside the APK.
128	Use_embedded_native_libs *bool
129
130	// Store dex files uncompressed in the APK and set the android:useEmbeddedDex="true" manifest attribute so that
131	// they are used from inside the APK at runtime.
132	Use_embedded_dex *bool
133
134	// Forces native libraries to always be packaged into the APK,
135	// Use_embedded_native_libs still selects whether they are stored uncompressed and aligned or compressed.
136	// True for android_test* modules.
137	AlwaysPackageNativeLibs bool `blueprint:"mutated"`
138
139	// If set, find and merge all NOTICE files that this module and its dependencies have and store
140	// it in the APK as an asset.
141	Embed_notices *bool
142
143	// cc.Coverage related properties
144	PreventInstall    bool `blueprint:"mutated"`
145	IsCoverageVariant bool `blueprint:"mutated"`
146
147	// It can be set to test the behaviour of default target sdk version.
148	// Only required when updatable: false. It is an error if updatable: true and this is false.
149	Enforce_default_target_sdk_version *bool
150
151	// If set, the targetSdkVersion for the target is set to the latest default API level.
152	// This would be by default false, unless updatable: true or
153	// enforce_default_target_sdk_version: true in which case this defaults to true.
154	EnforceDefaultTargetSdkVersion bool `blueprint:"mutated"`
155
156	// Whether this app is considered mainline updatable or not. When set to true, this will enforce
157	// additional rules to make sure an app can safely be updated. Default is false.
158	// Prefer using other specific properties if build behaviour must be changed; avoid using this
159	// flag for anything but neverallow rules (unless the behaviour change is invisible to owners).
160	Updatable *bool
161
162	// Specifies the file that contains the allowlist for this app.
163	Privapp_allowlist *string `android:"path"`
164
165	// If set, create an RRO package which contains only resources having PRODUCT_CHARACTERISTICS
166	// and install the RRO package to /product partition, instead of passing --product argument
167	// to aapt2. Default is false.
168	// Setting this will make this APK identical to all targets, regardless of
169	// PRODUCT_CHARACTERISTICS.
170	Generate_product_characteristics_rro *bool
171
172	ProductCharacteristicsRROPackageName        *string `blueprint:"mutated"`
173	ProductCharacteristicsRROManifestModuleName *string `blueprint:"mutated"`
174}
175
176// android_app properties that can be overridden by override_android_app
177type overridableAppProperties struct {
178	// The name of a certificate in the default certificate directory, blank to use the default product certificate,
179	// or an android_app_certificate module name in the form ":module".
180	Certificate proptools.Configurable[string] `android:"replace_instead_of_append"`
181
182	// Name of the signing certificate lineage file or filegroup module.
183	Lineage *string `android:"path"`
184
185	// For overriding the --rotation-min-sdk-version property of apksig
186	RotationMinSdkVersion *string
187
188	// the package name of this app. The package name in the manifest file is used if one was not given.
189	Package_name proptools.Configurable[string]
190
191	// the logging parent of this app.
192	Logging_parent *string
193
194	// Whether to rename the package in resources to the override name rather than the base name. Defaults to true.
195	Rename_resources_package *bool
196
197	// Names of modules to be overridden. Listed modules can only be other binaries
198	// (in Make or Soong).
199	// This does not completely prevent installation of the overridden binaries, but if both
200	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
201	// from PRODUCT_PACKAGES.
202	Overrides []string
203}
204
205type AndroidApp struct {
206	Library
207	aapt
208	android.OverridableModuleBase
209
210	certificate Certificate
211
212	appProperties appProperties
213
214	overridableAppProperties overridableAppProperties
215
216	jniLibs                  []jniLib
217	installPathForJNISymbols android.Path
218	embeddedJniLibs          bool
219	jniCoverageOutputs       android.Paths
220
221	bundleFile android.Path
222
223	// the install APK name is normally the same as the module name, but can be overridden with PRODUCT_PACKAGE_NAME_OVERRIDES.
224	installApkName string
225
226	installDir android.InstallPath
227
228	onDeviceDir string
229
230	additionalAaptFlags []string
231
232	overriddenManifestPackageName string
233
234	android.ApexBundleDepsInfo
235
236	javaApiUsedByOutputFile android.ModuleOutPath
237
238	privAppAllowlist android.OptionalPath
239
240	requiredModuleNames []string
241}
242
243func (a *AndroidApp) IsInstallable() bool {
244	return Bool(a.properties.Installable)
245}
246
247func (a *AndroidApp) ResourcesNodeDepSet() depset.DepSet[*resourcesNode] {
248	return a.aapt.resourcesNodesDepSet
249}
250
251func (a *AndroidApp) OutputFile() android.Path {
252	return a.outputFile
253}
254
255func (a *AndroidApp) Certificate() Certificate {
256	return a.certificate
257}
258
259func (a *AndroidApp) JniCoverageOutputs() android.Paths {
260	return a.jniCoverageOutputs
261}
262
263func (a *AndroidApp) PrivAppAllowlist() android.OptionalPath {
264	return a.privAppAllowlist
265}
266
267var _ AndroidLibraryDependency = (*AndroidApp)(nil)
268
269type Certificate struct {
270	Pem, Key  android.Path
271	presigned bool
272}
273
274var PresignedCertificate = Certificate{presigned: true}
275
276func (c Certificate) AndroidMkString() string {
277	if c.presigned {
278		return "PRESIGNED"
279	} else {
280		return c.Pem.String()
281	}
282}
283
284func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
285	if String(a.appProperties.Stl) == "c++_shared" && !a.SdkVersion(ctx).Specified() {
286		ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
287	}
288
289	sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
290	a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
291	a.Module.deps(ctx)
292	if sdkDep.hasFrameworkLibs() {
293		a.aapt.deps(ctx, sdkDep)
294	}
295
296	usesSDK := a.SdkVersion(ctx).Specified() && a.SdkVersion(ctx).Kind != android.SdkCorePlatform
297
298	if usesSDK && Bool(a.appProperties.Jni_uses_sdk_apis) {
299		ctx.PropertyErrorf("jni_uses_sdk_apis",
300			"can only be set for modules that do not set sdk_version")
301	} else if !usesSDK && Bool(a.appProperties.Jni_uses_platform_apis) {
302		ctx.PropertyErrorf("jni_uses_platform_apis",
303			"can only be set for modules that set sdk_version")
304	}
305
306	for _, jniTarget := range ctx.MultiTargets() {
307		variation := append(jniTarget.Variations(),
308			blueprint.Variation{Mutator: "link", Variation: "shared"})
309
310		// Test whether to use the SDK variant or the non-SDK variant of JNI dependencies.
311		// Many factors are considered here.
312		// 1. Basically, the selection follows whether the app has sdk_version set or not.
313		jniUsesSdkVariant := usesSDK
314		// 2. However, jni_uses_platform_apis and jni_uses_sdk_apis can override it
315		if Bool(a.appProperties.Jni_uses_sdk_apis) {
316			jniUsesSdkVariant = true
317		}
318		if Bool(a.appProperties.Jni_uses_platform_apis) {
319			jniUsesSdkVariant = false
320		}
321		// 3. Then the use of SDK variant is again prohibited for the following cases:
322		// 3.1. the app is shipped on unbundled partitions like vendor. Since the entire
323		// partition (not only the app) is considered unbudled, there's no need to use the
324		// SDK variant.
325		// 3.2. the app doesn't support embedding the JNI libs
326		if a.RequiresStableAPIs(ctx) || !a.shouldEmbedJnis(ctx) {
327			jniUsesSdkVariant = false
328		}
329		if jniUsesSdkVariant {
330			variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
331		}
332
333		// Use the installable dep tag when the JNIs are not embedded
334		var tag dependencyTag
335		if a.shouldEmbedJnis(ctx) {
336			tag = jniLibTag
337		} else {
338			tag = jniInstallTag
339		}
340		ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs.GetOrDefault(ctx, nil)...)
341	}
342	for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
343		ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
344	}
345}
346
347func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
348	cert := android.SrcIsModule(a.getCertString(ctx))
349	if cert != "" {
350		ctx.AddDependency(ctx.Module(), certificateTag, cert)
351	}
352
353	if a.appProperties.Privapp_allowlist != nil && !Bool(a.appProperties.Privileged) {
354		// There are a few uids that are explicitly considered privileged regardless of their
355		// app's location. Bluetooth is one such app. It should arguably be moved to priv-app,
356		// but for now, allow it not to be in priv-app.
357		privilegedBecauseOfUid := ctx.ModuleName() == "Bluetooth"
358		if !privilegedBecauseOfUid {
359			ctx.PropertyErrorf("privapp_allowlist", "privileged must be set in order to use privapp_allowlist (with a few exceptions)")
360		}
361	}
362
363	for _, cert := range a.appProperties.Additional_certificates {
364		cert = android.SrcIsModule(cert)
365		if cert != "" {
366			ctx.AddDependency(ctx.Module(), certificateTag, cert)
367		} else {
368			ctx.PropertyErrorf("additional_certificates",
369				`must be names of android_app_certificate modules in the form ":module"`)
370		}
371	}
372}
373
374// TODO(b/156476221): Remove this allowlist
375var (
376	missingMinSdkVersionMtsAllowlist = []string{
377		"CellBroadcastReceiverGoogleUnitTests",
378		"CellBroadcastReceiverUnitTests",
379		"CtsBatterySavingTestCases",
380		"CtsDeviceAndProfileOwnerApp23",
381		"CtsDeviceAndProfileOwnerApp30",
382		"CtsIntentSenderApp",
383		"CtsJobSchedulerTestCases",
384		"CtsMimeMapTestCases",
385		"CtsTareTestCases",
386		"LibStatsPullTests",
387		"MediaProviderClientTests",
388		"TeleServiceTests",
389		"TestExternalImsServiceApp",
390		"TestSmsRetrieverApp",
391		"TetheringPrivilegedTests",
392	}
393)
394
395func checkMinSdkVersionMts(ctx android.ModuleContext, minSdkVersion android.ApiLevel) {
396	if includedInMts(ctx.Module()) && !minSdkVersion.Specified() && !android.InList(ctx.ModuleName(), missingMinSdkVersionMtsAllowlist) {
397		ctx.PropertyErrorf("min_sdk_version", "min_sdk_version is a required property for tests included in MTS")
398	}
399}
400
401func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
402	checkMinSdkVersionMts(ctx, a.MinSdkVersion(ctx))
403	applicationId := a.appTestHelperAppProperties.Manifest_values.ApplicationId
404	if applicationId != nil {
405		packageName := a.overridableAppProperties.Package_name.Get(ctx)
406		if packageName.IsPresent() {
407			ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.")
408		}
409		a.aapt.manifestValues.applicationId = *applicationId
410	}
411	a.generateAndroidBuildActions(ctx)
412	android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
413		TestOnly: true,
414	})
415	appInfo := &AppInfo{
416		Updatable:     Bool(a.appProperties.Updatable),
417		TestHelperApp: true,
418	}
419	setCommonAppInfo(appInfo, a)
420	android.SetProvider(ctx, AppInfoProvider, appInfo)
421
422	moduleInfoJSON := ctx.ModuleInfoJSON()
423	moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests")
424	if len(a.appTestHelperAppProperties.Test_suites) > 0 {
425		moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, a.appTestHelperAppProperties.Test_suites...)
426	} else {
427		moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
428	}
429
430	android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
431		TestSuites: a.appTestHelperAppProperties.Test_suites,
432	})
433}
434
435func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
436	a.checkAppSdkVersions(ctx)
437	a.checkEmbedJnis(ctx)
438	a.generateAndroidBuildActions(ctx)
439	a.generateJavaUsedByApex(ctx)
440
441	var embeddedJniLibs []android.Path
442
443	if a.embeddedJniLibs {
444		for _, jni := range a.jniLibs {
445			embeddedJniLibs = append(embeddedJniLibs, jni.path)
446		}
447	}
448	overriddenName := a.OverriddenManifestPackageName()
449	appInfo := &AppInfo{
450		Updatable:                     Bool(a.appProperties.Updatable),
451		TestHelperApp:                 false,
452		EmbeddedJNILibs:               embeddedJniLibs,
453		MergedManifestFile:            a.mergedManifest,
454		OverriddenManifestPackageName: &overriddenName,
455	}
456	setCommonAppInfo(appInfo, a)
457	android.SetProvider(ctx, AppInfoProvider, appInfo)
458
459	a.requiredModuleNames = a.getRequiredModuleNames(ctx)
460
461	if a.dexer.proguardDictionary.Valid() {
462		android.SetProvider(ctx, ProguardProvider, ProguardInfo{
463			ModuleName:         ctx.ModuleName(),
464			Class:              "APPS",
465			ProguardDictionary: a.dexer.proguardDictionary.Path(),
466			ProguardUsageZip:   a.dexer.proguardUsageZip.Path(),
467			ClassesJar:         a.implementationAndResourcesJar,
468		})
469	}
470}
471
472func (a *AndroidApp) getRequiredModuleNames(ctx android.ModuleContext) []string {
473	var required []string
474	if proptools.Bool(a.appProperties.Generate_product_characteristics_rro) {
475		required = []string{a.productCharacteristicsRROPackageName()}
476	}
477	// Install the vendor overlay variant if this app is installed.
478	if len(filterRRO(a.rroDirsDepSet, device)) > 0 {
479		required = append(required, AutogeneratedRroModuleName(ctx, ctx.Module().Name(), "vendor"))
480	}
481	// Install the product overlay variant if this app is installed.
482	if len(filterRRO(a.rroDirsDepSet, product)) > 0 {
483		required = append(required, AutogeneratedRroModuleName(ctx, ctx.Module().Name(), "product"))
484	}
485	return required
486}
487
488func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
489	if a.Updatable() {
490		if !a.SdkVersion(ctx).Stable() {
491			ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.SdkVersion(ctx))
492		}
493		if String(a.overridableProperties.Min_sdk_version) == "" {
494			ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.")
495		}
496
497		if minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx); err == nil {
498			a.checkJniLibsSdkVersion(ctx, minSdkVersion)
499			android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
500		} else {
501			ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
502		}
503
504		if !BoolDefault(a.appProperties.Enforce_default_target_sdk_version, true) {
505			ctx.PropertyErrorf("enforce_default_target_sdk_version", "Updatable apps must enforce default target sdk version")
506		}
507		// TODO(b/227460469) after all the modules removes the target sdk version, throw an error if the target sdk version is explicitly set.
508		if a.deviceProperties.Target_sdk_version == nil {
509			a.SetEnforceDefaultTargetSdkVersion(true)
510		}
511	}
512
513	a.checkPlatformAPI(ctx)
514	a.checkSdkVersions(ctx)
515}
516
517// Ensures that use_embedded_native_libs are set for apk-in-apex
518func (a *AndroidApp) checkEmbedJnis(ctx android.BaseModuleContext) {
519	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
520	apkInApex := !apexInfo.IsForPlatform()
521	hasJnis := len(a.appProperties.Jni_libs.GetOrDefault(ctx, nil)) > 0
522
523	if apkInApex && hasJnis && !Bool(a.appProperties.Use_embedded_native_libs) {
524		ctx.ModuleErrorf("APK in APEX should have use_embedded_native_libs: true")
525	}
526}
527
528// If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it.
529// This check is enforced for "updatable" APKs (including APK-in-APEX).
530func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) {
531	// It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType()
532	ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
533		if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) {
534			return
535		}
536		if _, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); !ok {
537			panic(fmt.Errorf("jni dependency is not a cc module: %v", m))
538		}
539		commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoProvider)
540		if !ok {
541			panic(fmt.Errorf("jni dependency doesn't have CommonModuleInfo provider: %v", m))
542		}
543		// The domain of cc.sdk_version is "current" and <number>
544		// We can rely on android.SdkSpec to convert it to <number> so that "current" is
545		// handled properly regardless of sdk finalization.
546		ver := ""
547		if !commonInfo.MinSdkVersion.IsPlatform {
548			ver = commonInfo.MinSdkVersion.ApiLevel.String()
549		}
550		jniSdkVersion, err := android.SdkSpecFrom(ctx, ver).EffectiveVersion(ctx)
551		if err != nil || minSdkVersion.LessThan(jniSdkVersion) {
552			ctx.OtherModuleErrorf(m, "min_sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)",
553				ver, minSdkVersion, ctx.ModuleName())
554			return
555		}
556
557	})
558}
559
560// Returns true if the native libraries should be stored in the APK uncompressed and the
561// extractNativeLibs application flag should be set to false in the manifest.
562func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool {
563	minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx)
564	if err != nil {
565		ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.MinSdkVersion(ctx), err)
566	}
567
568	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
569	return (minSdkVersion.FinalOrFutureInt() >= 23 && Bool(a.appProperties.Use_embedded_native_libs)) ||
570		!apexInfo.IsForPlatform()
571}
572
573// Returns whether this module should have the dex file stored uncompressed in the APK.
574func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool {
575	if Bool(a.appProperties.Use_embedded_dex) {
576		return true
577	}
578
579	// Uncompress dex in APKs of privileged apps (even for unbundled builds, they may
580	// be preinstalled as prebuilts).
581	if ctx.Config().UncompressPrivAppDex() && a.Privileged() {
582		return true
583	}
584
585	if ctx.Config().UnbundledBuild() {
586		return false
587	}
588
589	return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter)
590}
591
592func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
593	return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
594		Bool(a.appProperties.Updatable) ||
595		a.appProperties.AlwaysPackageNativeLibs
596}
597
598func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string {
599	aaptFlags := []string{"--rename-manifest-package " + packageName}
600	if renameResourcesPackage {
601		// Required to rename the package name in the resources table.
602		aaptFlags = append(aaptFlags, "--rename-resources-package "+packageName)
603	}
604	return aaptFlags
605}
606
607func (a *AndroidApp) OverriddenManifestPackageName() string {
608	return a.overriddenManifestPackageName
609}
610
611func (a *AndroidApp) renameResourcesPackage() bool {
612	return proptools.BoolDefault(a.overridableAppProperties.Rename_resources_package, true)
613}
614
615func getAconfigFilePaths(ctx android.ModuleContext) (aconfigTextFilePaths android.Paths) {
616	ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
617		tag := ctx.OtherModuleDependencyTag(dep)
618		switch tag {
619		case staticLibTag, rroDepTag:
620			if flagPackages, ok := android.OtherModuleProvider(ctx, dep, FlagsPackagesProvider); ok {
621				aconfigTextFilePaths = append(aconfigTextFilePaths, flagPackages.AconfigTextFiles...)
622			}
623
624		case aconfigDeclarationTag:
625			if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
626				aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath)
627			} else {
628				ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
629					"flags_packages property, but %s is not aconfig_declarations module type",
630					dep.Name(),
631				)
632			}
633		}
634	})
635
636	return android.FirstUniquePaths(aconfigTextFilePaths)
637}
638
639func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
640	usePlatformAPI := proptools.Bool(a.Module.deviceProperties.Platform_apis)
641	if ctx.Module().(android.SdkContext).SdkVersion(ctx).Kind == android.SdkModule {
642		usePlatformAPI = true
643	}
644	a.aapt.usesNonSdkApis = usePlatformAPI
645
646	// Ask manifest_fixer to add or update the application element indicating this app has no code.
647	a.aapt.hasNoCode = !a.hasCode(ctx)
648
649	aaptLinkFlags := []string{}
650
651	// Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
652	autogenerateRRO := proptools.Bool(a.appProperties.Generate_product_characteristics_rro)
653	hasProduct := android.PrefixInList(a.aaptProperties.Aaptflags, "--product")
654	characteristics := ctx.Config().ProductAAPTCharacteristics()
655	if !autogenerateRRO && !hasProduct && len(characteristics) > 0 && characteristics != "default" {
656		aaptLinkFlags = append(aaptLinkFlags, "--product", characteristics)
657	}
658
659	if !Bool(a.aaptProperties.Aapt_include_all_resources) {
660		// Product AAPT config
661		for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
662			aaptLinkFlags = append(aaptLinkFlags, "-c", aaptConfig)
663		}
664
665		// Product AAPT preferred config
666		if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
667			aaptLinkFlags = append(aaptLinkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
668		}
669	}
670
671	manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
672	packageNameProp := a.overridableAppProperties.Package_name.Get(ctx)
673	if overridden || packageNameProp.IsPresent() {
674		// The product override variable has a priority over the package_name property.
675		if !overridden {
676			manifestPackageName = packageNameProp.Get()
677		}
678		aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, a.renameResourcesPackage())...)
679		a.overriddenManifestPackageName = manifestPackageName
680	}
681
682	aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...)
683
684	a.aapt.splitNames = a.appProperties.Package_splits
685	a.aapt.LoggingParent = String(a.overridableAppProperties.Logging_parent)
686	if a.Updatable() {
687		if override := ctx.Config().Getenv("OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION"); override != "" {
688			a.aapt.defaultManifestVersion = override
689		} else {
690			a.aapt.defaultManifestVersion = ctx.Config().ReleaseDefaultUpdatableModuleVersion()
691		}
692	}
693
694	// Use non final ids if we are doing optimized shrinking and are using R8.
695	nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled(ctx)
696
697	aconfigTextFilePaths := getAconfigFilePaths(ctx)
698
699	a.aapt.buildActions(ctx,
700		aaptBuildActionOptions{
701			sdkContext:                     android.SdkContext(a),
702			classLoaderContexts:            a.classLoaderContexts,
703			excludedLibs:                   a.usesLibraryProperties.Exclude_uses_libs,
704			enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(),
705			forceNonFinalResourceIDs:       nonFinalIds,
706			extraLinkFlags:                 aaptLinkFlags,
707			aconfigTextFiles:               aconfigTextFilePaths,
708			usesLibrary:                    &a.usesLibrary,
709		},
710	)
711
712	// apps manifests are handled by aapt, don't let Module see them
713	a.properties.Manifest = nil
714
715	android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{
716		AconfigTextFiles: aconfigTextFilePaths,
717	})
718}
719
720func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) {
721	var staticLibProguardFlagFiles android.Paths
722	ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
723		depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
724		staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.UnconditionallyExportedProguardFlags.ToList()...)
725		if ctx.OtherModuleDependencyTag(m) == staticLibTag {
726			staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.ProguardFlagsFiles.ToList()...)
727		}
728	})
729
730	staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
731
732	a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...)
733	if !(a.dexProperties.optimizedResourceShrinkingEnabled(ctx)) {
734		// When using the optimized shrinking the R8 enqueuer will traverse the xml files that become
735		// live for code references and (transitively) mark these as live.
736		// In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now
737		// dead code alive)
738		a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile)
739	}
740}
741
742func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath {
743	var installDir string
744	if ctx.ModuleName() == "framework-res" {
745		// framework-res.apk is installed as system/framework/framework-res.apk
746		installDir = "framework"
747	} else if a.Privileged() {
748		installDir = filepath.Join("priv-app", a.installApkName)
749	} else {
750		installDir = filepath.Join("app", a.installApkName)
751	}
752
753	return android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
754}
755
756func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, android.Path, *JavaInfo) {
757	a.dexpreopter.installPath = a.installPath(ctx)
758	a.dexpreopter.isApp = true
759	if a.dexProperties.Uncompress_dex == nil {
760		// If the value was not force-set by the user, use reasonable default based on the module.
761		a.dexProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
762	}
763	a.dexpreopter.uncompressedDex = *a.dexProperties.Uncompress_dex
764	a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries(ctx)
765	a.dexpreopter.classLoaderContexts = a.classLoaderContexts
766	a.dexpreopter.manifestFile = a.mergedManifestFile
767	a.dexpreopter.preventInstall = a.appProperties.PreventInstall
768
769	var packageResources = a.exportPackage
770
771	javaInfo := &JavaInfo{}
772	if ctx.ModuleName() != "framework-res" {
773		if a.dexProperties.resourceShrinkingEnabled(ctx) {
774			protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk")
775			aapt2Convert(ctx, protoFile, packageResources, "proto")
776			a.dexer.resourcesInput = android.OptionalPathForPath(protoFile)
777		}
778
779		var extraSrcJars android.Paths
780		var extraClasspathJars android.Paths
781		var extraCombinedJars android.Paths
782		if a.useResourceProcessorBusyBox(ctx) {
783			// When building an app with ResourceProcessorBusyBox enabled ResourceProcessorBusyBox has already
784			// created R.class files that provide IDs for resources in busybox/R.jar.  Pass that file in the
785			// classpath when compiling everything else, and add it to the final classes jar.
786			extraClasspathJars = android.Paths{a.aapt.rJar}
787			extraCombinedJars = android.Paths{a.aapt.rJar}
788		} else {
789			// When building an app without ResourceProcessorBusyBox the aapt2 rule creates R.srcjar containing
790			// R.java files for the app's package and the packages from all transitive static android_library
791			// dependencies.  Compile the srcjar alongside the rest of the sources.
792			extraSrcJars = android.Paths{a.aapt.aaptSrcJar}
793		}
794
795		javaInfo = a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil)
796		if a.dexProperties.resourceShrinkingEnabled(ctx) {
797			binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk")
798			aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary")
799			packageResources = binaryResources
800		}
801	}
802
803	return a.dexJarFile.PathOrNil(), packageResources, javaInfo
804}
805
806func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, prebuiltJniPackages android.Paths, ctx android.ModuleContext) android.WritablePath {
807	var jniJarFile android.WritablePath
808	if len(jniLibs) > 0 || len(prebuiltJniPackages) > 0 {
809		a.jniLibs = jniLibs
810		if a.shouldEmbedJnis(ctx) {
811			jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
812			a.installPathForJNISymbols = a.installPath(ctx)
813			TransformJniLibsToJar(ctx, jniJarFile, jniLibs, prebuiltJniPackages, a.useEmbeddedNativeLibs(ctx))
814			for _, jni := range jniLibs {
815				if jni.coverageFile.Valid() {
816					// Only collect coverage for the first target arch if this is a multilib target.
817					// TODO(jungjw): Ideally, we want to collect both reports, but that would cause coverage
818					// data file path collisions since the current coverage file path format doesn't contain
819					// arch-related strings. This is fine for now though; the code coverage team doesn't use
820					// multi-arch targets such as test_suite_* for coverage collections yet.
821					//
822					// Work with the team to come up with a new format that handles multilib modules properly
823					// and change this.
824					if len(ctx.Config().Targets[android.Android]) == 1 ||
825						ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType == jni.target.Arch.ArchType {
826						a.jniCoverageOutputs = append(a.jniCoverageOutputs, jni.coverageFile.Path())
827					}
828				}
829			}
830			a.embeddedJniLibs = true
831		}
832	}
833	return jniJarFile
834}
835
836func (a *AndroidApp) JNISymbolsInstalls(installPath string) android.RuleBuilderInstalls {
837	var jniSymbols android.RuleBuilderInstalls
838	for _, jniLib := range a.jniLibs {
839		if jniLib.unstrippedFile != nil {
840			jniSymbols = append(jniSymbols, android.RuleBuilderInstall{
841				From: jniLib.unstrippedFile,
842				To:   filepath.Join(installPath, targetToJniDir(jniLib.target), jniLib.unstrippedFile.Base()),
843			})
844		}
845	}
846	return jniSymbols
847}
848
849// Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it
850// isn't a cert module reference. Also checks and enforces system cert restriction if applicable.
851func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate,
852	ctx android.ModuleContext) (mainCertificate Certificate, allCertificates []Certificate) {
853	if android.SrcIsModule(certPropValue) == "" {
854		var mainCert Certificate
855		if certPropValue != "" {
856			defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
857			mainCert = Certificate{
858				Pem: defaultDir.Join(ctx, certPropValue+".x509.pem"),
859				Key: defaultDir.Join(ctx, certPropValue+".pk8"),
860			}
861		} else {
862			pem, key := ctx.Config().DefaultAppCertificate(ctx)
863			mainCert = Certificate{
864				Pem: pem,
865				Key: key,
866			}
867		}
868		certificates = append([]Certificate{mainCert}, certificates...)
869	}
870
871	if len(certificates) > 0 {
872		mainCertificate = certificates[0]
873	} else {
874		// This can be reached with an empty certificate list if AllowMissingDependencies is set
875		// and the certificate property for this module is a module reference to a missing module.
876		if !ctx.Config().AllowMissingDependencies() && len(ctx.GetMissingDependencies()) > 0 {
877			panic("Should only get here if AllowMissingDependencies set and there are missing dependencies")
878		}
879		// Set a certificate to avoid panics later when accessing it.
880		mainCertificate = Certificate{
881			Key: android.PathForModuleOut(ctx, "missing.pk8"),
882			Pem: android.PathForModuleOut(ctx, "missing.x509.pem"),
883		}
884	}
885
886	if !m.Platform() {
887		certPath := mainCertificate.Pem.String()
888		systemCertPath := ctx.Config().DefaultAppCertificateDir(ctx).String()
889		if strings.HasPrefix(certPath, systemCertPath) {
890			enforceSystemCert := ctx.Config().EnforceSystemCertificate()
891			allowed := ctx.Config().EnforceSystemCertificateAllowList()
892
893			if enforceSystemCert && !inList(m.Name(), allowed) {
894				ctx.PropertyErrorf("certificate", "The module in product partition cannot be signed with certificate in system.")
895			}
896		}
897	}
898
899	return mainCertificate, certificates
900}
901
902func (a *AndroidApp) InstallApkName() string {
903	return a.installApkName
904}
905
906func (a *AndroidApp) createPrivappAllowlist(ctx android.ModuleContext) android.Path {
907	if a.appProperties.Privapp_allowlist == nil {
908		return nil
909	}
910
911	isOverrideApp := a.GetOverriddenBy() != ""
912	if !isOverrideApp {
913		// if this is not an override, we don't need to rewrite the existing privapp allowlist
914		return android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist)
915	}
916
917	packageNameProp := a.overridableAppProperties.Package_name.Get(ctx)
918	if packageNameProp.IsEmpty() {
919		ctx.PropertyErrorf("privapp_allowlist", "package_name must be set to use privapp_allowlist")
920	}
921
922	packageName := packageNameProp.Get()
923	fileName := "privapp_allowlist_" + packageName + ".xml"
924	outPath := android.PathForModuleOut(ctx, fileName)
925	ctx.Build(pctx, android.BuildParams{
926		Rule:   modifyAllowlist,
927		Input:  android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist),
928		Output: outPath,
929		Args: map[string]string{
930			"packageName": packageName,
931		},
932	})
933	return outPath
934}
935
936func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
937	var apkDeps android.Paths
938
939	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
940	if !apexInfo.IsForPlatform() {
941		a.hideApexVariantFromMake = true
942	}
943
944	a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
945	a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
946
947	// Unlike installApkName, a.stem should respect base module name for override_android_app.
948	// Therefore, use ctx.ModuleName() instead of a.Name().
949	a.stem = proptools.StringDefault(a.overridableProperties.Stem, ctx.ModuleName())
950
951	// Check if the install APK name needs to be overridden.
952	// Both android_app and override_android_app module are expected to possess
953	// its module bound apk path. However, override_android_app inherits ctx.ModuleName()
954	// from the base module. Therefore, use a.Name() which represents
955	// the module name for both android_app and override_android_app.
956	a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(
957		proptools.StringDefault(a.overridableProperties.Stem, a.Name()))
958
959	if ctx.ModuleName() == "framework-res" {
960		// framework-res.apk is installed as system/framework/framework-res.apk
961		a.installDir = android.PathForModuleInstall(ctx, "framework")
962	} else if a.Privileged() {
963		a.installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName)
964	} else if ctx.InstallInTestcases() {
965		a.installDir = android.PathForModuleInstall(ctx, a.installApkName, ctx.DeviceConfig().DeviceArch())
966	} else {
967		a.installDir = android.PathForModuleInstall(ctx, "app", a.installApkName)
968	}
969	a.onDeviceDir = android.InstallPathToOnDevicePath(ctx, a.installDir)
970
971	a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
972	if a.usesLibrary.shouldDisableDexpreopt {
973		a.dexpreopter.disableDexpreopt()
974	}
975
976	var noticeAssetPath android.WritablePath
977	if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
978		// The rule to create the notice file can't be generated yet, as the final output path
979		// for the apk isn't known yet.  Add the path where the notice file will be generated to the
980		// aapt rules now before calling aaptBuildActions, the rule to create the notice file will
981		// be generated later.
982		noticeAssetPath = android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
983		a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath)
984	}
985
986	// For apps targeting latest target_sdk_version
987	if Bool(a.appProperties.Enforce_default_target_sdk_version) {
988		a.SetEnforceDefaultTargetSdkVersion(true)
989	}
990
991	// Process all building blocks, from AAPT to certificates.
992	a.aaptBuildActions(ctx)
993	// The decision to enforce <uses-library> checks is made before adding implicit SDK libraries.
994	a.usesLibrary.freezeEnforceUsesLibraries(ctx)
995
996	// Check that the <uses-library> list is coherent with the manifest.
997	if a.usesLibrary.enforceUsesLibraries(ctx) {
998		manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(
999			ctx, a.mergedManifestFile, &a.classLoaderContexts)
1000		apkDeps = append(apkDeps, manifestCheckFile)
1001	}
1002
1003	a.proguardBuildActions(ctx)
1004
1005	a.linter.mergedManifest = a.aapt.mergedManifestFile
1006	a.linter.manifest = a.aapt.manifestPath
1007	a.linter.resources = a.aapt.resourceFiles
1008	a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps()
1009
1010	dexJarFile, packageResources, javaInfo := a.dexBuildActions(ctx)
1011
1012	// No need to check the SDK version of the JNI deps unless we embed them
1013	checkNativeSdkVersion := a.shouldEmbedJnis(ctx) && !Bool(a.appProperties.Jni_uses_platform_apis)
1014	jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), checkNativeSdkVersion)
1015	jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx)
1016
1017	if ctx.Failed() {
1018		return
1019	}
1020
1021	a.certificate, certificates = processMainCert(a.ModuleBase, a.getCertString(ctx), certificates, ctx)
1022
1023	// Build a final signed app package.
1024	packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk")
1025	v4SigningRequested := Bool(a.Module.deviceProperties.V4_signature)
1026	var v4SignatureFile android.WritablePath = nil
1027	if v4SigningRequested {
1028		v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+".apk.idsig")
1029	}
1030	var lineageFile android.Path
1031	if lineage := String(a.overridableAppProperties.Lineage); lineage != "" {
1032		lineageFile = android.PathForModuleSrc(ctx, lineage)
1033	}
1034	rotationMinSdkVersion := String(a.overridableAppProperties.RotationMinSdkVersion)
1035
1036	CreateAndSignAppPackage(ctx, packageFile, packageResources, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
1037	a.outputFile = packageFile
1038	if v4SigningRequested {
1039		a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
1040	}
1041
1042	if a.aapt.noticeFile.Valid() {
1043		// Generating the notice file rule has to be here after a.outputFile is known.
1044		noticeFile := android.PathForModuleOut(ctx, "NOTICE.html.gz")
1045		android.BuildNoticeHtmlOutputFromLicenseMetadata(
1046			ctx, noticeFile, "", "",
1047			[]string{
1048				a.installDir.String() + "/",
1049				android.PathForModuleInstall(ctx).String() + "/",
1050				a.outputFile.String(),
1051			})
1052		builder := android.NewRuleBuilder(pctx, ctx)
1053		builder.Command().Text("cp").
1054			Input(noticeFile).
1055			Output(noticeAssetPath)
1056		builder.Build("notice_dir", "Building notice dir")
1057	}
1058
1059	for _, split := range a.aapt.splits {
1060		// Sign the split APKs
1061		packageFile := android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk")
1062		if v4SigningRequested {
1063			v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig")
1064		}
1065		CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
1066		a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
1067		if v4SigningRequested {
1068			a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
1069		}
1070	}
1071
1072	// Build an app bundle.
1073	bundleFile := android.PathForModuleOut(ctx, "base.zip")
1074	BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile)
1075	a.bundleFile = bundleFile
1076
1077	allowlist := a.createPrivappAllowlist(ctx)
1078	if allowlist != nil {
1079		a.privAppAllowlist = android.OptionalPathForPath(allowlist)
1080	}
1081
1082	// Install the app package.
1083	shouldInstallAppPackage := (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() && !a.appProperties.PreventInstall
1084	if shouldInstallAppPackage {
1085		if a.privAppAllowlist.Valid() {
1086			allowlistInstallPath := android.PathForModuleInstall(ctx, "etc", "permissions")
1087			allowlistInstallFilename := a.installApkName + ".xml"
1088			ctx.InstallFile(allowlistInstallPath, allowlistInstallFilename, a.privAppAllowlist.Path())
1089		}
1090
1091		var extraInstalledPaths android.InstallPaths
1092		for _, extra := range a.extraOutputFiles {
1093			installed := ctx.InstallFile(a.installDir, extra.Base(), extra)
1094			extraInstalledPaths = append(extraInstalledPaths, installed)
1095		}
1096		// If we don't embed jni libs, make sure that those are installed along with the
1097		// app, and also place symlinks to the installed paths under the lib/<arch>
1098		// directory of the app installation directory. ex:
1099		// /system/app/MyApp/lib/arm64/libfoo.so -> /system/lib64/libfoo.so
1100		if !a.embeddedJniLibs {
1101			for _, jniLib := range jniLibs {
1102				archStr := jniLib.target.Arch.ArchType.String()
1103				symlinkDir := a.installDir.Join(ctx, "lib", archStr)
1104				for _, installedLib := range jniLib.installPaths {
1105					// install the symlink itself
1106					symlinkName := installedLib.Base()
1107					symlinkTarget := android.InstallPathToOnDevicePath(ctx, installedLib)
1108					ctx.InstallAbsoluteSymlink(symlinkDir, symlinkName, symlinkTarget)
1109				}
1110			}
1111		}
1112		ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...)
1113	}
1114
1115	ctx.CheckbuildFile(a.outputFile)
1116
1117	a.buildAppDependencyInfo(ctx)
1118
1119	providePrebuiltInfo(ctx,
1120		prebuiltInfoProps{
1121			baseModuleName: a.BaseModuleName(),
1122			isPrebuilt:     false,
1123		},
1124	)
1125
1126	if javaInfo != nil {
1127		javaInfo.OutputFile = a.outputFile
1128		setExtraJavaInfo(ctx, a, javaInfo)
1129		android.SetProvider(ctx, JavaInfoProvider, javaInfo)
1130	}
1131
1132	android.SetProvider(ctx, android.ApexBundleDepsDataProvider, android.ApexBundleDepsData{
1133		FlatListPath: a.FlatListPath(),
1134		Updatable:    a.Updatable(),
1135	})
1136
1137	moduleInfoJSON := ctx.ModuleInfoJSON()
1138	moduleInfoJSON.Class = []string{"APPS"}
1139	if !a.embeddedJniLibs {
1140		for _, jniLib := range a.jniLibs {
1141			moduleInfoJSON.ExtraRequired = append(moduleInfoJSON.ExtraRequired, jniLib.name)
1142		}
1143	}
1144
1145	a.setOutputFiles(ctx)
1146
1147	buildComplianceMetadata(ctx)
1148}
1149
1150func (a *AndroidApp) setOutputFiles(ctx android.ModuleContext) {
1151	ctx.SetOutputFiles([]android.Path{a.proguardOptionsFile}, ".aapt.proguardOptionsFile")
1152	if a.aaptSrcJar != nil {
1153		ctx.SetOutputFiles([]android.Path{a.aaptSrcJar}, ".aapt.srcjar")
1154	}
1155	if a.rJar != nil {
1156		ctx.SetOutputFiles([]android.Path{a.rJar}, ".aapt.jar")
1157	}
1158	ctx.SetOutputFiles([]android.Path{a.outputFile}, ".apk")
1159	ctx.SetOutputFiles([]android.Path{a.exportPackage}, ".export-package.apk")
1160	ctx.SetOutputFiles([]android.Path{a.aapt.manifestPath}, ".manifest.xml")
1161	setOutputFiles(ctx, a.Library.Module)
1162}
1163
1164type appDepsInterface interface {
1165	SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
1166	MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
1167	RequiresStableAPIs(ctx android.BaseModuleContext) bool
1168}
1169
1170func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
1171	shouldCollectRecursiveNativeDeps bool,
1172	checkNativeSdkVersion bool) ([]jniLib, android.Paths, []Certificate) {
1173
1174	if checkNativeSdkVersion {
1175		checkNativeSdkVersion = app.SdkVersion(ctx).Specified() &&
1176			app.SdkVersion(ctx).Kind != android.SdkCorePlatform && !app.RequiresStableAPIs(ctx)
1177	}
1178	jniLib, prebuiltJniPackages := collectJniDeps(ctx, shouldCollectRecursiveNativeDeps,
1179		checkNativeSdkVersion, func(parent, child android.ModuleProxy) bool {
1180			apkInApex := ctx.Module().(android.ApexModule).NotInPlatform()
1181			childLinkable, _ := android.OtherModuleProvider(ctx, child, cc.LinkableInfoProvider)
1182			parentIsLinkable := false
1183			if android.EqualModules(ctx.Module(), parent) {
1184				parentLinkable, _ := ctx.Module().(cc.LinkableInterface)
1185				parentIsLinkable = parentLinkable != nil
1186			} else {
1187				_, parentIsLinkable = android.OtherModuleProvider(ctx, parent, cc.LinkableInfoProvider)
1188			}
1189			useStubsOfDep := childLinkable.IsStubs
1190			if apkInApex && parentIsLinkable {
1191				// APK-in-APEX
1192				// If the parent is a linkable interface, use stubs if the dependency edge crosses an apex boundary.
1193				useStubsOfDep = useStubsOfDep || (childLinkable.HasStubsVariants && cc.ShouldUseStubForApex(ctx, parent, child))
1194			}
1195			return !childLinkable.IsNdk && !useStubsOfDep
1196		})
1197
1198	var certificates []Certificate
1199
1200	var directImplementationDeps android.Paths
1201	var transitiveImplementationDeps []depset.DepSet[android.Path]
1202	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
1203		otherName := ctx.OtherModuleName(module)
1204		tag := ctx.OtherModuleDependencyTag(module)
1205
1206		if tag == certificateTag {
1207			if dep, ok := android.OtherModuleProvider(ctx, module, AndroidAppCertificateInfoProvider); ok {
1208				certificates = append(certificates, dep.Certificate)
1209			} else {
1210				ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
1211			}
1212		}
1213
1214		if IsJniDepTag(tag) {
1215			directImplementationDeps = append(directImplementationDeps, android.OutputFileForModule(ctx, module, ""))
1216			if info, ok := android.OtherModuleProvider(ctx, module, cc.ImplementationDepInfoProvider); ok {
1217				transitiveImplementationDeps = append(transitiveImplementationDeps, info.ImplementationDeps)
1218			}
1219		}
1220	})
1221	android.SetProvider(ctx, cc.ImplementationDepInfoProvider, &cc.ImplementationDepInfo{
1222		ImplementationDeps: depset.New(depset.PREORDER, directImplementationDeps, transitiveImplementationDeps),
1223	})
1224
1225	return jniLib, prebuiltJniPackages, certificates
1226}
1227
1228func collectJniDeps(ctx android.ModuleContext,
1229	shouldCollectRecursiveNativeDeps bool,
1230	checkNativeSdkVersion bool,
1231	filter func(parent, child android.ModuleProxy) bool) ([]jniLib, android.Paths) {
1232	var jniLibs []jniLib
1233	var prebuiltJniPackages android.Paths
1234	seenModulePaths := make(map[string]bool)
1235
1236	ctx.WalkDepsProxy(func(module, parent android.ModuleProxy) bool {
1237		if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
1238			return false
1239		}
1240		otherName := ctx.OtherModuleName(module)
1241		tag := ctx.OtherModuleDependencyTag(module)
1242
1243		if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) {
1244			if dep, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
1245				if filter != nil && !filter(parent, module) {
1246					return false
1247				}
1248
1249				lib := dep.OutputFile
1250				if lib.Valid() {
1251					path := lib.Path()
1252					if seenModulePaths[path.String()] {
1253						return false
1254					}
1255					seenModulePaths[path.String()] = true
1256
1257					commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
1258					if checkNativeSdkVersion && commonInfo.SdkVersion == "" {
1259						ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not",
1260							otherName)
1261					}
1262
1263					jniLibs = append(jniLibs, jniLib{
1264						name:           ctx.OtherModuleName(module),
1265						path:           path,
1266						target:         commonInfo.Target,
1267						coverageFile:   dep.CoverageOutputFile,
1268						unstrippedFile: dep.UnstrippedOutputFile,
1269						partition:      dep.Partition,
1270						installPaths:   android.OtherModuleProviderOrDefault(ctx, module, android.InstallFilesProvider).InstallFiles,
1271					})
1272				} else if ctx.Config().AllowMissingDependencies() {
1273					ctx.AddMissingDependencies([]string{otherName})
1274				} else {
1275					ctx.ModuleErrorf("dependency %q missing output file", otherName)
1276				}
1277			} else {
1278				ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName)
1279			}
1280
1281			return shouldCollectRecursiveNativeDeps
1282		}
1283
1284		if info, ok := android.OtherModuleProvider(ctx, module, JniPackageProvider); ok {
1285			prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
1286		}
1287
1288		return false
1289	})
1290
1291	return jniLibs, prebuiltJniPackages
1292}
1293
1294func (a *AndroidApp) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) {
1295	ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
1296		// TODO(ccross): Should this use android.DepIsInSameApex?  Right now it is applying the android app
1297		// heuristics to every transitive dependency, when it should probably be using the heuristics of the
1298		// immediate parent.
1299		isExternal := !a.GetDepInSameApexChecker().OutgoingDepIsInSameApex(ctx.OtherModuleDependencyTag(child))
1300		if am, ok := android.OtherModuleProvider(ctx, child, android.CommonModuleInfoProvider); ok && am.IsApexModule {
1301			if !do(ctx, parent, child, isExternal) {
1302				return false
1303			}
1304		}
1305		return !isExternal
1306	})
1307}
1308
1309func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) {
1310	if ctx.Host() {
1311		return
1312	}
1313
1314	depsInfo := android.DepNameToDepInfoMap{}
1315	a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
1316		depName := to.Name()
1317
1318		// Skip dependencies that are only available to APEXes; they are developed with updatability
1319		// in mind and don't need manual approval.
1320		if android.OtherModulePointerProviderOrDefault(ctx, to, android.CommonModuleInfoProvider).NotAvailableForPlatform {
1321			return true
1322		}
1323
1324		if info, exist := depsInfo[depName]; exist {
1325			info.From = append(info.From, from.Name())
1326			info.IsExternal = info.IsExternal && externalDep
1327			depsInfo[depName] = info
1328		} else {
1329			toMinSdkVersion := "(no version)"
1330			if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoProvider); ok &&
1331				!info.MinSdkVersion.IsPlatform && info.MinSdkVersion.ApiLevel != nil {
1332				toMinSdkVersion = info.MinSdkVersion.ApiLevel.String()
1333			}
1334			depsInfo[depName] = android.ApexModuleDepInfo{
1335				To:            depName,
1336				From:          []string{from.Name()},
1337				IsExternal:    externalDep,
1338				MinSdkVersion: toMinSdkVersion,
1339			}
1340		}
1341		return true
1342	})
1343
1344	a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).String(), depsInfo)
1345}
1346
1347func (a *AndroidApp) enforceDefaultTargetSdkVersion() bool {
1348	return a.appProperties.EnforceDefaultTargetSdkVersion
1349}
1350
1351func (a *AndroidApp) SetEnforceDefaultTargetSdkVersion(val bool) {
1352	a.appProperties.EnforceDefaultTargetSdkVersion = val
1353}
1354
1355func (a *AndroidApp) Updatable() bool {
1356	return Bool(a.appProperties.Updatable)
1357}
1358
1359func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string {
1360	certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
1361	if overridden {
1362		return ":" + certificate
1363	}
1364	return a.overridableAppProperties.Certificate.GetOrDefault(ctx, "")
1365}
1366
1367func (m *AndroidApp) GetDepInSameApexChecker() android.DepInSameApexChecker {
1368	return AppDepInSameApexChecker{}
1369}
1370
1371type AppDepInSameApexChecker struct {
1372	android.BaseDepInSameApexChecker
1373}
1374
1375func (m AppDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
1376	if IsJniDepTag(tag) {
1377		return true
1378	}
1379	return depIsInSameApex(tag)
1380}
1381
1382func (a *AndroidApp) Privileged() bool {
1383	return Bool(a.appProperties.Privileged)
1384}
1385
1386func (a *AndroidApp) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool {
1387	return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled()
1388}
1389
1390func (a *AndroidApp) SetPreventInstall() {
1391	a.appProperties.PreventInstall = true
1392}
1393
1394func (a *AndroidApp) MarkAsCoverageVariant(coverage bool) {
1395	a.appProperties.IsCoverageVariant = coverage
1396}
1397
1398func (a *AndroidApp) EnableCoverageIfNeeded() {}
1399
1400var _ cc.Coverage = (*AndroidApp)(nil)
1401
1402func (a *AndroidApp) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
1403	a.Library.IDEInfo(ctx, dpInfo)
1404	a.aapt.IDEInfo(ctx, dpInfo)
1405}
1406
1407func (a *AndroidApp) productCharacteristicsRROPackageName() string {
1408	return proptools.String(a.appProperties.ProductCharacteristicsRROPackageName)
1409}
1410
1411func (a *AndroidApp) productCharacteristicsRROManifestModuleName() string {
1412	return proptools.String(a.appProperties.ProductCharacteristicsRROManifestModuleName)
1413}
1414
1415// android_app compiles sources and Android resources into an Android application package `.apk` file.
1416func AndroidAppFactory() android.Module {
1417	module := &AndroidApp{}
1418
1419	module.Module.dexProperties.Optimize.EnabledByDefault = true
1420	module.Module.dexProperties.Optimize.Shrink = proptools.BoolPtr(true)
1421	module.Module.dexProperties.Optimize.Proguard_compatibility = proptools.BoolPtr(false)
1422
1423	module.Module.properties.Instrument = true
1424	module.Module.properties.Supports_static_instrumentation = true
1425	module.Module.properties.Installable = proptools.BoolPtr(true)
1426
1427	module.addHostAndDeviceProperties()
1428	module.AddProperties(
1429		&module.aaptProperties,
1430		&module.appProperties,
1431		&module.overridableAppProperties,
1432		&module.Library.sourceProperties)
1433
1434	module.usesLibrary.enforce = true
1435
1436	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
1437	android.InitDefaultableModule(module)
1438	android.InitOverridableModule(module, &module.overridableAppProperties.Overrides)
1439	android.InitApexModule(module)
1440
1441	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
1442		a := ctx.Module().(*AndroidApp)
1443
1444		characteristics := ctx.Config().ProductAAPTCharacteristics()
1445		if characteristics == "default" || characteristics == "" {
1446			module.appProperties.Generate_product_characteristics_rro = nil
1447			// no need to create RRO
1448			return
1449		}
1450
1451		if !proptools.Bool(module.appProperties.Generate_product_characteristics_rro) {
1452			return
1453		}
1454
1455		rroPackageName := a.Name() + "__" + strings.ReplaceAll(characteristics, ",", "_") + "__auto_generated_characteristics_rro"
1456		rroManifestName := rroPackageName + "_manifest"
1457
1458		a.appProperties.ProductCharacteristicsRROPackageName = proptools.StringPtr(rroPackageName)
1459		a.appProperties.ProductCharacteristicsRROManifestModuleName = proptools.StringPtr(rroManifestName)
1460
1461		rroManifestProperties := struct {
1462			Name  *string
1463			Tools []string
1464			Out   []string
1465			Srcs  []string
1466			Cmd   *string
1467		}{
1468			Name:  proptools.StringPtr(rroManifestName),
1469			Tools: []string{"characteristics_rro_generator", "aapt2"},
1470			Out:   []string{"AndroidManifest.xml"},
1471			Srcs:  []string{":" + a.Name() + "{.apk}"},
1472			Cmd:   proptools.StringPtr("$(location characteristics_rro_generator) $$($(location aapt2) dump packagename $(in)) $(out)"),
1473		}
1474		ctx.CreateModule(GenRuleFactory, &rroManifestProperties)
1475
1476		rroProperties := struct {
1477			Name           *string
1478			Filter_product *string
1479			Aaptflags      []string
1480			Manifest       *string
1481			Resource_dirs  proptools.Configurable[[]string]
1482			Flags_packages []string
1483		}{
1484			Name:           proptools.StringPtr(rroPackageName),
1485			Filter_product: proptools.StringPtr(characteristics),
1486			Aaptflags:      []string{"--auto-add-overlay"},
1487			Manifest:       proptools.StringPtr(":" + rroManifestName),
1488			Resource_dirs:  a.aaptProperties.Resource_dirs,
1489			Flags_packages: a.aaptProperties.Flags_packages,
1490		}
1491		if !Bool(a.aaptProperties.Aapt_include_all_resources) {
1492			for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
1493				rroProperties.Aaptflags = append(rroProperties.Aaptflags, "-c", aaptConfig)
1494			}
1495		}
1496		ctx.CreateModule(RuntimeResourceOverlayFactory, &rroProperties)
1497
1498	})
1499
1500	module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
1501		createInternalRuntimeOverlays(ctx, module.ModuleBase)
1502	})
1503
1504	return module
1505}
1506
1507func AutogeneratedRroModuleName(ctx android.EarlyModuleContext, moduleName, partition string) string {
1508	return fmt.Sprintf("%s__%s__auto_generated_rro_%s", moduleName, ctx.Config().DeviceProduct(), partition)
1509}
1510
1511type createModuleContext interface {
1512	android.EarlyModuleContext
1513	CreateModule(android.ModuleFactory, ...interface{}) android.Module
1514}
1515
1516func createInternalRuntimeOverlays(ctx createModuleContext, a android.ModuleBase) {
1517	if !ctx.Config().HasDeviceProduct() {
1518		return
1519	}
1520	// vendor
1521	vendorOverlayProps := struct {
1522		Name                *string
1523		Base                *string
1524		Vendor              *bool
1525		Product_specific    *bool
1526		System_ext_specific *bool
1527		Manifest            *string
1528		Sdk_version         *string
1529		Compile_multilib    *string
1530		Enabled             proptools.Configurable[bool]
1531	}{
1532		Name:                proptools.StringPtr(AutogeneratedRroModuleName(ctx, a.Name(), "vendor")),
1533		Base:                proptools.StringPtr(a.Name()),
1534		Vendor:              proptools.BoolPtr(true),
1535		Product_specific:    proptools.BoolPtr(false),
1536		System_ext_specific: proptools.BoolPtr(false),
1537		Manifest:            proptools.StringPtr(":" + a.Name() + "{.manifest.xml}"),
1538		Sdk_version:         proptools.StringPtr("current"),
1539		Compile_multilib:    proptools.StringPtr("first"),
1540		Enabled:             a.EnabledProperty().Clone(),
1541	}
1542	ctx.CreateModule(AutogenRuntimeResourceOverlayFactory, &vendorOverlayProps)
1543
1544	// product
1545	productOverlayProps := struct {
1546		Name                *string
1547		Base                *string
1548		Vendor              *bool
1549		Proprietary         *bool
1550		Soc_specific        *bool
1551		Product_specific    *bool
1552		System_ext_specific *bool
1553		Manifest            *string
1554		Sdk_version         *string
1555		Compile_multilib    *string
1556		Enabled             proptools.Configurable[bool]
1557	}{
1558		Name:                proptools.StringPtr(AutogeneratedRroModuleName(ctx, a.Name(), "product")),
1559		Base:                proptools.StringPtr(a.Name()),
1560		Vendor:              proptools.BoolPtr(false),
1561		Proprietary:         proptools.BoolPtr(false),
1562		Soc_specific:        proptools.BoolPtr(false),
1563		Product_specific:    proptools.BoolPtr(true),
1564		System_ext_specific: proptools.BoolPtr(false),
1565		Manifest:            proptools.StringPtr(":" + a.Name() + "{.manifest.xml}"),
1566		Sdk_version:         proptools.StringPtr("current"),
1567		Compile_multilib:    proptools.StringPtr("first"),
1568		Enabled:             a.EnabledProperty().Clone(),
1569	}
1570	ctx.CreateModule(AutogenRuntimeResourceOverlayFactory, &productOverlayProps)
1571}
1572
1573// A dictionary of values to be overridden in the manifest.
1574type Manifest_values struct {
1575	// Overrides the value of package_name in the manifest
1576	ApplicationId *string
1577}
1578
1579type appTestProperties struct {
1580	// The name of the android_app module that the tests will run against.
1581	Instrumentation_for *string
1582
1583	// If specified, the instrumentation target package name in the manifest is overwritten by it.
1584	Instrumentation_target_package *string
1585
1586	// If specified, the mainline module package name in the test config is overwritten by it.
1587	Mainline_package_name *string
1588
1589	Manifest_values Manifest_values
1590}
1591
1592type AndroidTest struct {
1593	AndroidApp
1594
1595	appTestProperties appTestProperties
1596
1597	testProperties testProperties
1598
1599	testConfig       android.Path
1600	extraTestConfigs android.Paths
1601	data             android.Paths
1602}
1603
1604func (a *AndroidTest) InstallInTestcases() bool {
1605	return true
1606}
1607
1608type androidTestApp interface {
1609	includedInTestSuite(searchPrefix string) bool
1610}
1611
1612func (a *AndroidTest) includedInTestSuite(searchPrefix string) bool {
1613	return android.PrefixInList(a.testProperties.Test_suites, searchPrefix)
1614}
1615
1616func (a *AndroidTestHelperApp) includedInTestSuite(searchPrefix string) bool {
1617	return android.PrefixInList(a.appTestHelperAppProperties.Test_suites, searchPrefix)
1618}
1619
1620func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1621	checkMinSdkVersionMts(ctx, a.MinSdkVersion(ctx))
1622	var configs []tradefed.Config
1623	if a.appTestProperties.Instrumentation_target_package != nil {
1624		a.additionalAaptFlags = append(a.additionalAaptFlags,
1625			"--rename-instrumentation-target-package "+*a.appTestProperties.Instrumentation_target_package)
1626	} else if a.appTestProperties.Instrumentation_for != nil {
1627		// Check if the instrumentation target package is overridden.
1628		manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(*a.appTestProperties.Instrumentation_for)
1629		if overridden {
1630			a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+manifestPackageName)
1631		}
1632	}
1633	applicationId := a.appTestProperties.Manifest_values.ApplicationId
1634	if applicationId != nil {
1635		packageNameProp := a.overridableAppProperties.Package_name.Get(ctx)
1636		if packageNameProp.IsPresent() {
1637			ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.")
1638		}
1639		a.aapt.manifestValues.applicationId = *applicationId
1640	}
1641	a.generateAndroidBuildActions(ctx)
1642
1643	for _, c := range a.testProperties.Test_options.Tradefed_options {
1644		configs = append(configs, c)
1645	}
1646	for _, module := range a.testProperties.Test_mainline_modules {
1647		configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
1648	}
1649
1650	testConfig := tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config,
1651		a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites,
1652		a.testProperties.Auto_gen_config, configs, a.testProperties.Test_options.Test_runner_options)
1653	a.testConfig = a.FixTestConfig(ctx, testConfig)
1654	a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs)
1655	a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
1656	a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_common_data)...)
1657	a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_data)...)
1658	a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_prefer32_data)...)
1659	a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Host_common_data)...)
1660
1661	// Install test deps
1662	if !ctx.Config().KatiEnabled() {
1663		pathInTestCases := android.PathForModuleInstall(ctx, ctx.Module().Name())
1664		if a.testConfig != nil {
1665			ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".config", a.testConfig)
1666		}
1667		dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
1668		if dynamicConfig.Valid() {
1669			ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".dynamic", dynamicConfig.Path())
1670		}
1671		testDeps := append(a.data, a.extraTestConfigs...)
1672		for _, data := range android.SortedUniquePaths(testDeps) {
1673			dataPath := android.DataPath{SrcPath: data}
1674			ctx.InstallTestData(pathInTestCases, []android.DataPath{dataPath})
1675		}
1676	}
1677
1678	android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
1679		TestcaseRelDataFiles:    testcaseRel(a.data),
1680		OutputFile:              a.OutputFile(),
1681		TestConfig:              a.testConfig,
1682		HostRequiredModuleNames: a.HostRequiredModuleNames(),
1683		TestSuites:              a.testProperties.Test_suites,
1684		IsHost:                  false,
1685		LocalCertificate:        a.certificate.AndroidMkString(),
1686		IsUnitTest:              Bool(a.testProperties.Test_options.Unit_test),
1687		MkInclude:               "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
1688		MkAppClass:              "APPS",
1689	})
1690	android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
1691		TestOnly:       true,
1692		TopLevelTarget: true,
1693	})
1694
1695	moduleInfoJSON := ctx.ModuleInfoJSON()
1696	moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests")
1697	if a.testConfig != nil {
1698		moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, a.testConfig.String())
1699	}
1700	moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, a.extraTestConfigs.Strings()...)
1701	if len(a.testProperties.Test_suites) > 0 {
1702		moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, a.testProperties.Test_suites...)
1703	} else {
1704		moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
1705	}
1706
1707	if _, ok := testConfig.(android.WritablePath); ok {
1708		moduleInfoJSON.AutoTestConfig = []string{"true"}
1709	}
1710	moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, a.testProperties.Test_mainline_modules...)
1711
1712	android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
1713		TestSuites: a.testProperties.Test_suites,
1714	})
1715}
1716
1717func testcaseRel(paths android.Paths) []string {
1718	relPaths := []string{}
1719	for _, p := range paths {
1720		relPaths = append(relPaths, p.Rel())
1721	}
1722	return relPaths
1723}
1724
1725func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path {
1726	if testConfig == nil {
1727		return nil
1728	}
1729
1730	fixedConfig := android.PathForModuleOut(ctx, "test_config_fixer", "AndroidTest.xml")
1731	rule := android.NewRuleBuilder(pctx, ctx)
1732	command := rule.Command().BuiltTool("test_config_fixer").Input(testConfig).Output(fixedConfig)
1733	fixNeeded := false
1734
1735	// Auto-generated test config uses `ModuleName` as the APK name. So fix it if it is not the case.
1736	if ctx.ModuleName() != a.installApkName {
1737		fixNeeded = true
1738		command.FlagWithArg("--test-file-name ", a.installApkName+".apk")
1739	}
1740
1741	packageNameProp := a.overridableAppProperties.Package_name.Get(ctx)
1742	if packageNameProp.IsPresent() {
1743		fixNeeded = true
1744		command.FlagWithInput("--manifest ", a.manifestPath).
1745			FlagWithArg("--package-name ", packageNameProp.Get())
1746	}
1747
1748	if a.appTestProperties.Mainline_package_name != nil {
1749		fixNeeded = true
1750		command.FlagWithArg("--mainline-package-name ", *a.appTestProperties.Mainline_package_name)
1751	}
1752
1753	if fixNeeded {
1754		rule.Build("fix_test_config", "fix test config")
1755		return fixedConfig
1756	}
1757	return testConfig
1758}
1759
1760func (a *AndroidTestHelperApp) DepsMutator(ctx android.BottomUpMutatorContext) {
1761	if len(a.ApexProperties.Apex_available) == 0 && ctx.Config().IsEnvTrue("EMMA_API_MAPPER") {
1762		// Instrument the android_test_helper target to log potential API calls at the run time.
1763		// Contact android-xts-infra team before using the environment var EMMA_API_MAPPER.
1764		ctx.AddVariationDependencies(nil, staticLibTag, "apimapper-helper-device-lib")
1765		a.setApiMapper(true)
1766	}
1767	a.AndroidApp.DepsMutator(ctx)
1768}
1769
1770func (a *AndroidTest) DepsMutator(ctx android.BottomUpMutatorContext) {
1771	if len(a.ApexProperties.Apex_available) == 0 && ctx.Config().IsEnvTrue("EMMA_API_MAPPER") {
1772		// Instrument the android_test_helper target to log potential API calls at the run time.
1773		// Contact android-xts-infra team before using the environment var EMMA_API_MAPPER.
1774		ctx.AddVariationDependencies(nil, staticLibTag, "apimapper-helper-device-lib")
1775		a.setApiMapper(true)
1776	}
1777	a.AndroidApp.DepsMutator(ctx)
1778}
1779
1780func (a *AndroidTest) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
1781	a.AndroidApp.OverridablePropertiesDepsMutator(ctx)
1782	if a.appTestProperties.Instrumentation_for != nil {
1783		// The android_app dependency listed in instrumentation_for needs to be added to the classpath for javac,
1784		// but not added to the aapt2 link includes like a normal android_app or android_library dependency, so
1785		// use instrumentationForTag instead of libTag.
1786		ctx.AddVariationDependencies(nil, instrumentationForTag, String(a.appTestProperties.Instrumentation_for))
1787	}
1788}
1789
1790// android_test compiles test sources and Android resources into an Android application package `.apk` file and
1791// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
1792func AndroidTestFactory() android.Module {
1793	module := &AndroidTest{}
1794
1795	module.Module.dexProperties.Optimize.EnabledByDefault = false
1796
1797	module.Module.properties.Instrument = true
1798	module.Module.properties.Supports_static_instrumentation = true
1799	module.Module.properties.Installable = proptools.BoolPtr(true)
1800	module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
1801	module.appProperties.AlwaysPackageNativeLibs = true
1802	module.Module.dexpreopter.isTest = true
1803	module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)
1804
1805	module.addHostAndDeviceProperties()
1806	module.AddProperties(
1807		&module.aaptProperties,
1808		&module.appProperties,
1809		&module.appTestProperties,
1810		&module.overridableAppProperties,
1811		&module.testProperties)
1812
1813	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
1814	android.InitDefaultableModule(module)
1815	android.InitOverridableModule(module, &module.overridableAppProperties.Overrides)
1816
1817	return module
1818}
1819
1820type appTestHelperAppProperties struct {
1821	// list of compatibility suites (for example "cts", "vts") that the module should be
1822	// installed into.
1823	Test_suites []string `android:"arch_variant"`
1824
1825	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
1826	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
1827	// explicitly.
1828	Auto_gen_config *bool
1829
1830	// Install the test into a folder named for the module in all test suites.
1831	Per_testcase_directory *bool
1832
1833	Manifest_values Manifest_values
1834}
1835
1836type AndroidTestHelperApp struct {
1837	AndroidApp
1838
1839	appTestHelperAppProperties appTestHelperAppProperties
1840}
1841
1842func (a *AndroidTestHelperApp) InstallInTestcases() bool {
1843	return true
1844}
1845
1846// android_test_helper_app compiles sources and Android resources into an Android application package `.apk` file that
1847// will be used by tests, but does not produce an `AndroidTest.xml` file so the module will not be run directly as a
1848// test.
1849func AndroidTestHelperAppFactory() android.Module {
1850	module := &AndroidTestHelperApp{}
1851
1852	// TODO(b/192032291): Disable by default after auditing downstream usage.
1853	module.Module.dexProperties.Optimize.EnabledByDefault = true
1854	module.Module.dexProperties.Optimize.Ignore_library_extends_program = proptools.BoolPtr(true)
1855	module.Module.dexProperties.Optimize.Proguard_compatibility = proptools.BoolPtr(false)
1856
1857	module.Module.properties.Installable = proptools.BoolPtr(true)
1858	module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
1859	module.appProperties.AlwaysPackageNativeLibs = true
1860	module.Module.dexpreopter.isTest = true
1861	module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)
1862
1863	module.addHostAndDeviceProperties()
1864	module.AddProperties(
1865		&module.aaptProperties,
1866		&module.appProperties,
1867		&module.appTestHelperAppProperties,
1868		&module.overridableAppProperties)
1869
1870	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
1871	android.InitDefaultableModule(module)
1872	android.InitApexModule(module)
1873	return module
1874}
1875
1876type AndroidAppCertificate struct {
1877	android.ModuleBase
1878
1879	properties  AndroidAppCertificateProperties
1880	Certificate Certificate
1881}
1882
1883type AndroidAppCertificateProperties struct {
1884	// Name of the certificate files.  Extensions .x509.pem and .pk8 will be added to the name.
1885	Certificate *string
1886}
1887
1888type AndroidAppCertificateInfo struct {
1889	Certificate Certificate
1890}
1891
1892var AndroidAppCertificateInfoProvider = blueprint.NewProvider[AndroidAppCertificateInfo]()
1893
1894// android_app_certificate modules can be referenced by the certificates property of android_app modules to select
1895// the signing key.
1896func AndroidAppCertificateFactory() android.Module {
1897	module := &AndroidAppCertificate{}
1898	module.AddProperties(&module.properties)
1899	android.InitAndroidModule(module)
1900	return module
1901}
1902
1903func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1904	cert := String(c.properties.Certificate)
1905	c.Certificate = Certificate{
1906		Pem: android.PathForModuleSrc(ctx, cert+".x509.pem"),
1907		Key: android.PathForModuleSrc(ctx, cert+".pk8"),
1908	}
1909
1910	android.SetProvider(ctx, AndroidAppCertificateInfoProvider, AndroidAppCertificateInfo{
1911		Certificate: c.Certificate,
1912	})
1913}
1914
1915type OverrideAndroidApp struct {
1916	android.ModuleBase
1917	android.OverrideModuleBase
1918}
1919
1920func (i *OverrideAndroidApp) GenerateAndroidBuildActions(_ android.ModuleContext) {
1921	// All the overrides happen in the base module.
1922	// TODO(jungjw): Check the base module type.
1923}
1924
1925// override_android_app is used to create an android_app module based on another android_app by overriding
1926// some of its properties.
1927func OverrideAndroidAppModuleFactory() android.Module {
1928	m := &OverrideAndroidApp{}
1929	m.AddProperties(
1930		&OverridableProperties{},
1931		&overridableAppProperties{},
1932	)
1933
1934	android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
1935	android.InitOverrideModule(m)
1936	android.AddLoadHookWithPriority(m, func(ctx android.LoadHookContext) {
1937		createInternalRuntimeOverlays(ctx, m.ModuleBase)
1938	}, 1) // Run after soong config load hoook
1939
1940	return m
1941}
1942
1943type OverrideAndroidTest struct {
1944	android.ModuleBase
1945	android.OverrideModuleBase
1946}
1947
1948func (i *OverrideAndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1949	// All the overrides happen in the base module.
1950	// TODO(jungjw): Check the base module type.
1951	android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
1952		TestOnly:       true,
1953		TopLevelTarget: true,
1954	})
1955}
1956
1957// override_android_test is used to create an android_app module based on another android_test by overriding
1958// some of its properties.
1959func OverrideAndroidTestModuleFactory() android.Module {
1960	m := &OverrideAndroidTest{}
1961	m.AddProperties(&overridableAppProperties{})
1962	m.AddProperties(&appTestProperties{})
1963
1964	android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
1965	android.InitOverrideModule(m)
1966	return m
1967}
1968
1969type UsesLibraryProperties struct {
1970	// A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file.
1971	Uses_libs proptools.Configurable[[]string]
1972
1973	// A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file with
1974	// required=false.
1975	Optional_uses_libs proptools.Configurable[[]string]
1976
1977	// If true, the list of uses_libs and optional_uses_libs modules must match the AndroidManifest.xml file.  Defaults
1978	// to true if either uses_libs or optional_uses_libs is set.  Will unconditionally default to true in the future.
1979	Enforce_uses_libs *bool
1980
1981	// Optional name of the <uses-library> provided by this module. This is needed for non-SDK
1982	// libraries, because SDK ones are automatically picked up by Soong. The <uses-library> name
1983	// normally is the same as the module name, but there are exceptions.
1984	Provides_uses_lib *string
1985
1986	// A list of shared library names to exclude from the classpath of the APK. Adding a library here
1987	// will prevent it from being used when precompiling the APK and prevent it from being implicitly
1988	// added to the APK's manifest's <uses-library> elements.
1989	//
1990	// Care must be taken when using this as it could result in runtime errors if the APK actually
1991	// uses classes provided by the library and which are not provided in any other way.
1992	//
1993	// This is primarily intended for use by various CTS tests that check the runtime handling of the
1994	// android.test.base shared library (and related libraries) but which depend on some common
1995	// libraries that depend on the android.test.base library. Without this those tests will end up
1996	// with a <uses-library android:name="android.test.base"/> in their manifest which would either
1997	// render the tests worthless (as they would be testing the wrong behavior), or would break the
1998	// test altogether by providing access to classes that the tests were not expecting. Those tests
1999	// provide the android.test.base statically and use jarjar to rename them so they do not collide
2000	// with the classes provided by the android.test.base library.
2001	Exclude_uses_libs []string
2002
2003	// The module names of optional uses-library libraries that are missing from the source tree.
2004	Missing_optional_uses_libs []string `blueprint:"mutated"`
2005}
2006
2007// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the
2008// <uses-library> tags that end up in the manifest of an APK match the ones known to the build system through the
2009// uses_libs and optional_uses_libs properties.  The build system's values are used by dexpreopt to preopt apps
2010// with knowledge of their shared libraries.
2011type usesLibrary struct {
2012	usesLibraryProperties UsesLibraryProperties
2013
2014	// Whether to enforce verify_uses_library check.
2015	enforce bool
2016
2017	// Whether dexpreopt should be disabled
2018	shouldDisableDexpreopt bool
2019}
2020
2021func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps bool) {
2022	if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() {
2023		ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs.GetOrDefault(ctx, nil)...)
2024		presentOptionalUsesLibs := u.presentOptionalUsesLibs(ctx)
2025		ctx.AddVariationDependencies(nil, usesLibOptTag, presentOptionalUsesLibs...)
2026		// Only add these extra dependencies if the module is an app that depends on framework
2027		// libs. This avoids creating a cyclic dependency:
2028		//     e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
2029		if addCompatDeps {
2030			// Dexpreopt needs paths to the dex jars of these libraries in order to construct
2031			// class loader context for dex2oat. Add them as a dependency with a special tag.
2032			ctx.AddVariationDependencies(nil, usesLibCompat29ReqTag, dexpreopt.CompatUsesLibs29...)
2033			ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
2034			ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
2035		}
2036		_, diff, _ := android.ListSetDifference(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil), presentOptionalUsesLibs)
2037		u.usesLibraryProperties.Missing_optional_uses_libs = diff
2038	} else {
2039		ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.usesLibraryProperties.Uses_libs.GetOrDefault(ctx, nil)...)
2040		ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.presentOptionalUsesLibs(ctx)...)
2041	}
2042}
2043
2044// presentOptionalUsesLibs returns optional_uses_libs after filtering out libraries that don't exist in the source tree.
2045func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
2046	optionalUsesLibs := android.FilterListPred(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil), func(s string) bool {
2047		exists := ctx.OtherModuleExists(s)
2048		if !exists && !android.InList(ctx.ModuleName(), ctx.Config().BuildWarningBadOptionalUsesLibsAllowlist()) {
2049			fmt.Printf("Warning: Module '%s' depends on non-existing optional_uses_libs '%s'\n", ctx.ModuleName(), s)
2050		}
2051		return exists
2052	})
2053	return optionalUsesLibs
2054}
2055
2056// Returns a map of module names of shared library dependencies to the paths to their dex jars on
2057// host and on device.
2058func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext) dexpreopt.ClassLoaderContextMap {
2059	clcMap := make(dexpreopt.ClassLoaderContextMap)
2060
2061	// Skip when UnbundledBuild() is true, but UnbundledBuildImage() is false. With
2062	// UnbundledBuildImage() it is necessary to generate dexpreopt.config for post-dexpreopting.
2063	if ctx.Config().UnbundledBuild() && !ctx.Config().UnbundledBuildImage() {
2064		return clcMap
2065	}
2066
2067	ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
2068		tag, isUsesLibTag := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag)
2069		if !isUsesLibTag {
2070			return
2071		}
2072
2073		dep := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(m))
2074
2075		javaInfo, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider)
2076		if !ok {
2077			return
2078		}
2079		// Skip stub libraries. A dependency on the implementation library has been added earlier,
2080		// so it will be added to CLC, but the stub shouldn't be. Stub libraries can be distingushed
2081		// from implementation libraries by their name, which is different as it has a suffix.
2082		if comp := javaInfo.SdkLibraryComponentDependencyInfo; comp != nil {
2083			if impl := comp.OptionalSdkLibraryImplementation; impl != nil && *impl != dep {
2084				return
2085			}
2086		}
2087
2088		if lib := javaInfo.UsesLibraryDependencyInfo; lib != nil {
2089			if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok {
2090				// Skip java_sdk_library dependencies that provide stubs, but not an implementation.
2091				// This will be restricted to optional_uses_libs
2092				if tag == usesLibOptTag && javaInfo.DexJarBuildPath.PathOrNil() == nil {
2093					u.shouldDisableDexpreopt = true
2094					return
2095				}
2096			}
2097			libName := dep
2098			if ulib := javaInfo.ProvidesUsesLibInfo; ulib != nil && ulib.ProvidesUsesLib != nil {
2099				libName = *ulib.ProvidesUsesLib
2100			}
2101			clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
2102				javaInfo.DexJarBuildPath.PathOrNil(), lib.DexJarInstallPath,
2103				lib.ClassLoaderContexts)
2104		} else if ctx.Config().AllowMissingDependencies() {
2105			ctx.AddMissingDependencies([]string{dep})
2106		} else {
2107			ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library", dep)
2108		}
2109	})
2110	return clcMap
2111}
2112
2113// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
2114// properties.  Defaults to true if either of uses_libs or optional_uses_libs is specified.  Will default to true
2115// unconditionally in the future.
2116func (u *usesLibrary) enforceUsesLibraries(ctx android.ModuleContext) bool {
2117	defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs.GetOrDefault(ctx, nil)) > 0 ||
2118		len(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil)) > 0
2119	return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, u.enforce || defaultEnforceUsesLibs)
2120}
2121
2122// Freeze the value of `enforce_uses_libs` based on the current values of `uses_libs` and `optional_uses_libs`.
2123func (u *usesLibrary) freezeEnforceUsesLibraries(ctx android.ModuleContext) {
2124	enforce := u.enforceUsesLibraries(ctx)
2125	u.usesLibraryProperties.Enforce_uses_libs = &enforce
2126}
2127
2128// verifyUsesLibraries checks the <uses-library> tags in the manifest against the ones specified
2129// in the `uses_libs`/`optional_uses_libs` properties. The input can be either an XML manifest, or
2130// an APK with the manifest embedded in it (manifest_check will know which one it is by the file
2131// extension: APKs are supposed to end with '.apk').
2132func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile android.Path,
2133	outputFile android.WritablePath, classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path {
2134
2135	statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
2136
2137	// Disable verify_uses_libraries check if dexpreopt is globally disabled. Without dexpreopt the
2138	// check is not necessary, and although it is good to have, it is difficult to maintain on
2139	// non-linux build platforms where dexpreopt is generally disabled (the check may fail due to
2140	// various unrelated reasons, such as a failure to get manifest from an APK).
2141	global := dexpreopt.GetGlobalConfig(ctx)
2142	if global.DisablePreopt || global.OnlyPreoptArtBootImage {
2143		return inputFile
2144	}
2145
2146	rule := android.NewRuleBuilder(pctx, ctx)
2147	cmd := rule.Command().BuiltTool("manifest_check").
2148		Flag("--enforce-uses-libraries").
2149		Input(inputFile).
2150		FlagWithOutput("--enforce-uses-libraries-status ", statusFile).
2151		FlagWithInput("--aapt ", ctx.Config().HostToolPath(ctx, "aapt2"))
2152
2153	if outputFile != nil {
2154		cmd.FlagWithOutput("-o ", outputFile)
2155	}
2156
2157	if dexpreopt.GetGlobalConfig(ctx).RelaxUsesLibraryCheck {
2158		cmd.Flag("--enforce-uses-libraries-relax")
2159	}
2160
2161	requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs()
2162	for _, lib := range requiredUsesLibs {
2163		cmd.FlagWithArg("--uses-library ", lib)
2164	}
2165	for _, lib := range optionalUsesLibs {
2166		cmd.FlagWithArg("--optional-uses-library ", lib)
2167	}
2168
2169	// Also add missing optional uses libs, as the manifest check expects them.
2170	// Note that what we add here are the module names of those missing libs, not library names, while
2171	// the manifest check actually expects library names. However, the case where a library is missing
2172	// and the module name != the library name is too rare for us to handle.
2173	for _, lib := range u.usesLibraryProperties.Missing_optional_uses_libs {
2174		cmd.FlagWithArg("--missing-optional-uses-library ", lib)
2175	}
2176
2177	rule.Build("verify_uses_libraries", "verify <uses-library>")
2178	return outputFile
2179}
2180
2181// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against
2182// the build system and returns the path to a copy of the manifest.
2183func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path,
2184	classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path {
2185	outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
2186	return u.verifyUsesLibraries(ctx, manifest, outputFile, classLoaderContexts)
2187}
2188
2189// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the build
2190// system and returns the path to a copy of the APK.
2191func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path,
2192	classLoaderContexts *dexpreopt.ClassLoaderContextMap) {
2193	u.verifyUsesLibraries(ctx, apk, nil, classLoaderContexts) // for APKs manifest_check does not write output file
2194}
2195
2196// androidApp is an interface to handle all app modules (android_app, android_app_import, etc.) in
2197// the same way.
2198type androidApp interface {
2199	android.Module
2200	Privileged() bool
2201	InstallApkName() string
2202	OutputFile() android.Path
2203	JacocoReportClassesFile() android.Path
2204	Certificate() Certificate
2205	BaseModuleName() string
2206	PrivAppAllowlist() android.OptionalPath
2207}
2208
2209var _ androidApp = (*AndroidApp)(nil)
2210var _ androidApp = (*AndroidAppImport)(nil)
2211var _ androidApp = (*AndroidTestHelperApp)(nil)
2212
2213func setCommonAppInfo(appInfo *AppInfo, m androidApp) {
2214	appInfo.Privileged = m.Privileged()
2215	appInfo.OutputFile = m.OutputFile()
2216	appInfo.InstallApkName = m.InstallApkName()
2217	appInfo.JacocoReportClassesFile = m.JacocoReportClassesFile()
2218	appInfo.Certificate = m.Certificate()
2219	appInfo.PrivAppAllowlist = m.PrivAppAllowlist()
2220}
2221
2222type AppInfos []AppInfo
2223
2224var AppInfosProvider = blueprint.NewProvider[AppInfos]()
2225