xref: /aosp_15_r20/build/soong/apex/apex.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright (C) 2018 The Android Open Source Project
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
15// package apex implements build rules for creating the APEX files which are container for
16// lower-level system components. See https://source.android.com/devices/tech/ota/apex
17package apex
18
19import (
20	"fmt"
21	"path/filepath"
22	"regexp"
23	"slices"
24	"sort"
25	"strings"
26
27	"github.com/google/blueprint"
28	"github.com/google/blueprint/depset"
29	"github.com/google/blueprint/proptools"
30
31	"android/soong/android"
32	"android/soong/bpf"
33	"android/soong/cc"
34	"android/soong/dexpreopt"
35	prebuilt_etc "android/soong/etc"
36	"android/soong/filesystem"
37	"android/soong/java"
38	"android/soong/rust"
39	"android/soong/sh"
40)
41
42func init() {
43	registerApexBuildComponents(android.InitRegistrationContext)
44}
45
46func registerApexBuildComponents(ctx android.RegistrationContext) {
47	ctx.RegisterModuleType("apex", BundleFactory)
48	ctx.RegisterModuleType("apex_test", TestApexBundleFactory)
49	ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
50	ctx.RegisterModuleType("apex_defaults", DefaultsFactory)
51	ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
52	ctx.RegisterModuleType("override_apex", OverrideApexFactory)
53	ctx.RegisterModuleType("apex_set", apexSetFactory)
54
55	ctx.PreDepsMutators(RegisterPreDepsMutators)
56	ctx.PostDepsMutators(RegisterPostDepsMutators)
57}
58
59func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
60	ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).UsesReverseDependencies()
61}
62
63func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
64	ctx.TopDown("apex_info", apexInfoMutator)
65	ctx.BottomUp("apex_unique", apexUniqueVariationsMutator)
66	// Run mark_platform_availability before the apexMutator as the apexMutator needs to know whether
67	// it should create a platform variant.
68	ctx.BottomUp("mark_platform_availability", markPlatformAvailability)
69	ctx.Transition("apex", &apexTransitionMutator{})
70}
71
72type apexBundleProperties struct {
73	// Json manifest file describing meta info of this APEX bundle. Refer to
74	// system/apex/proto/apex_manifest.proto for the schema. Default: "apex_manifest.json"
75	Manifest *string `android:"path"`
76
77	// AndroidManifest.xml file used for the zip container of this APEX bundle. If unspecified,
78	// a default one is automatically generated.
79	AndroidManifest proptools.Configurable[string] `android:"path,replace_instead_of_append"`
80
81	// Determines the file contexts file for setting the security contexts to files in this APEX
82	// bundle. For platform APEXes, this should points to a file under /system/sepolicy Default:
83	// /system/sepolicy/apex/<module_name>_file_contexts.
84	File_contexts *string `android:"path"`
85
86	// By default, file_contexts is amended by force-labelling / and /apex_manifest.pb as system_file
87	// to avoid mistakes. When set as true, no force-labelling.
88	Use_file_contexts_as_is *bool
89
90	// Path to the canned fs config file for customizing file's
91	// uid/gid/mod/capabilities. The content of this file is appended to the
92	// default config, so that the custom entries are preferred. The format is
93	// /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where
94	// path_or_glob is a path or glob pattern for a file or set of files,
95	// uid/gid are numerial values of user ID and group ID, mode is octal value
96	// for the file mode, and cap is hexadecimal value for the capability.
97	Canned_fs_config proptools.Configurable[string] `android:"path,replace_instead_of_append"`
98
99	ApexNativeDependencies
100
101	Multilib apexMultilibProperties
102
103	// List of runtime resource overlays (RROs) that are embedded inside this APEX.
104	Rros []string
105
106	// List of bootclasspath fragments that are embedded inside this APEX bundle.
107	Bootclasspath_fragments proptools.Configurable[[]string]
108
109	// List of systemserverclasspath fragments that are embedded inside this APEX bundle.
110	Systemserverclasspath_fragments proptools.Configurable[[]string]
111
112	// List of java libraries that are embedded inside this APEX bundle.
113	Java_libs []string
114
115	// List of sh binaries that are embedded inside this APEX bundle.
116	Sh_binaries []string
117
118	// List of platform_compat_config files that are embedded inside this APEX bundle.
119	Compat_configs []string
120
121	// List of filesystem images that are embedded inside this APEX bundle.
122	Filesystems []string
123
124	// List of module names which we don't want to add as transitive deps. This can be used as
125	// a workaround when the current implementation collects more than necessary. For example,
126	// Rust binaries with prefer_rlib:true add unnecessary dependencies.
127	Unwanted_transitive_deps []string
128
129	// Whether this APEX is considered updatable or not. When set to true, this will enforce
130	// additional rules for making sure that the APEX is truly updatable. To be updatable,
131	// min_sdk_version should be set as well. This will also disable the size optimizations like
132	// symlinking to the system libs. Default is true.
133	Updatable *bool
134
135	// Marks that this APEX is designed to be updatable in the future, although it's not
136	// updatable yet. This is used to mimic some of the build behaviors that are applied only to
137	// updatable APEXes. Currently, this disables the size optimization, so that the size of
138	// APEX will not increase when the APEX is actually marked as truly updatable. Default is
139	// false.
140	Future_updatable *bool
141
142	// Whether this APEX can use platform APIs or not. Can be set to true only when `updatable:
143	// false`. Default is false.
144	Platform_apis *bool
145
146	// Whether this APEX is installable to one of the partitions like system, vendor, etc.
147	// Default: true.
148	Installable *bool
149
150	// The type of filesystem to use. Either 'ext4', 'f2fs' or 'erofs'. Default 'ext4'.
151	Payload_fs_type *string
152
153	// For telling the APEX to ignore special handling for system libraries such as bionic.
154	// Default is false.
155	Ignore_system_library_special_case *bool
156
157	// Whenever apex_payload.img of the APEX should not be dm-verity signed. Should be only
158	// used in tests.
159	Test_only_unsigned_payload *bool
160
161	// Whenever apex should be compressed, regardless of product flag used. Should be only
162	// used in tests.
163	Test_only_force_compression *bool
164
165	// Put extra tags (signer=<value>) to apexkeys.txt, so that release tools can sign this apex
166	// with the tool to sign payload contents.
167	Custom_sign_tool *string
168
169	// Whether this is a dynamic common lib apex, if so the native shared libs will be placed
170	// in a special way that include the digest of the lib file under /lib(64)?
171	Dynamic_common_lib_apex *bool
172
173	// Canonical name of this APEX bundle. Used to determine the path to the
174	// activated APEX on device (i.e. /apex/<apexVariationName>), and used for the
175	// apex mutator variations. For override_apex modules, this is the name of the
176	// overridden base module.
177	ApexVariationName string `blueprint:"mutated"`
178
179	IsCoverageVariant bool `blueprint:"mutated"`
180
181	// List of sanitizer names that this APEX is enabled for
182	SanitizerNames []string `blueprint:"mutated"`
183
184	PreventInstall bool `blueprint:"mutated"`
185
186	HideFromMake bool `blueprint:"mutated"`
187
188	// Name that dependencies can specify in their apex_available properties to refer to this module.
189	// If not specified, this defaults to Soong module name. This must be the name of a Soong module.
190	Apex_available_name *string
191
192	// Variant version of the mainline module. Must be an integer between 0-9
193	Variant_version *string
194}
195
196type ApexNativeDependencies struct {
197	// List of native libraries that are embedded inside this APEX.
198	Native_shared_libs proptools.Configurable[[]string]
199
200	// List of JNI libraries that are embedded inside this APEX.
201	Jni_libs proptools.Configurable[[]string]
202
203	// List of rust dyn libraries that are embedded inside this APEX.
204	Rust_dyn_libs []string
205
206	// List of native executables that are embedded inside this APEX.
207	Binaries proptools.Configurable[[]string]
208
209	// List of native tests that are embedded inside this APEX.
210	Tests []string
211
212	// List of filesystem images that are embedded inside this APEX bundle.
213	Filesystems []string
214
215	// List of prebuilt_etcs that are embedded inside this APEX bundle.
216	Prebuilts proptools.Configurable[[]string]
217
218	// List of native libraries to exclude from this APEX.
219	Exclude_native_shared_libs []string
220
221	// List of JNI libraries to exclude from this APEX.
222	Exclude_jni_libs []string
223
224	// List of rust dyn libraries to exclude from this APEX.
225	Exclude_rust_dyn_libs []string
226
227	// List of native executables to exclude from this APEX.
228	Exclude_binaries []string
229
230	// List of native tests to exclude from this APEX.
231	Exclude_tests []string
232
233	// List of filesystem images to exclude from this APEX bundle.
234	Exclude_filesystems []string
235
236	// List of prebuilt_etcs to exclude from this APEX bundle.
237	Exclude_prebuilts []string
238}
239
240type ResolvedApexNativeDependencies struct {
241	// List of native libraries that are embedded inside this APEX.
242	Native_shared_libs []string
243
244	// List of JNI libraries that are embedded inside this APEX.
245	Jni_libs []string
246
247	// List of rust dyn libraries that are embedded inside this APEX.
248	Rust_dyn_libs []string
249
250	// List of native executables that are embedded inside this APEX.
251	Binaries []string
252
253	// List of native tests that are embedded inside this APEX.
254	Tests []string
255
256	// List of filesystem images that are embedded inside this APEX bundle.
257	Filesystems []string
258
259	// List of prebuilt_etcs that are embedded inside this APEX bundle.
260	Prebuilts []string
261
262	// List of native libraries to exclude from this APEX.
263	Exclude_native_shared_libs []string
264
265	// List of JNI libraries to exclude from this APEX.
266	Exclude_jni_libs []string
267
268	// List of rust dyn libraries to exclude from this APEX.
269	Exclude_rust_dyn_libs []string
270
271	// List of native executables to exclude from this APEX.
272	Exclude_binaries []string
273
274	// List of native tests to exclude from this APEX.
275	Exclude_tests []string
276
277	// List of filesystem images to exclude from this APEX bundle.
278	Exclude_filesystems []string
279
280	// List of prebuilt_etcs to exclude from this APEX bundle.
281	Exclude_prebuilts []string
282}
283
284// Merge combines another ApexNativeDependencies into this one
285func (a *ResolvedApexNativeDependencies) Merge(ctx android.BaseModuleContext, b ApexNativeDependencies) {
286	a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs.GetOrDefault(ctx, nil)...)
287	a.Jni_libs = append(a.Jni_libs, b.Jni_libs.GetOrDefault(ctx, nil)...)
288	a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
289	a.Binaries = append(a.Binaries, b.Binaries.GetOrDefault(ctx, nil)...)
290	a.Tests = append(a.Tests, b.Tests...)
291	a.Filesystems = append(a.Filesystems, b.Filesystems...)
292	a.Prebuilts = append(a.Prebuilts, b.Prebuilts.GetOrDefault(ctx, nil)...)
293
294	a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...)
295	a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...)
296	a.Exclude_rust_dyn_libs = append(a.Exclude_rust_dyn_libs, b.Exclude_rust_dyn_libs...)
297	a.Exclude_binaries = append(a.Exclude_binaries, b.Exclude_binaries...)
298	a.Exclude_tests = append(a.Exclude_tests, b.Exclude_tests...)
299	a.Exclude_filesystems = append(a.Exclude_filesystems, b.Exclude_filesystems...)
300	a.Exclude_prebuilts = append(a.Exclude_prebuilts, b.Exclude_prebuilts...)
301}
302
303type apexMultilibProperties struct {
304	// Native dependencies whose compile_multilib is "first"
305	First ApexNativeDependencies
306
307	// Native dependencies whose compile_multilib is "both"
308	Both ApexNativeDependencies
309
310	// Native dependencies whose compile_multilib is "prefer32"
311	Prefer32 ApexNativeDependencies
312
313	// Native dependencies whose compile_multilib is "32"
314	Lib32 ApexNativeDependencies
315
316	// Native dependencies whose compile_multilib is "64"
317	Lib64 ApexNativeDependencies
318}
319
320type apexTargetBundleProperties struct {
321	Target struct {
322		// Multilib properties only for android.
323		Android struct {
324			Multilib apexMultilibProperties
325		}
326
327		// Multilib properties only for host.
328		Host struct {
329			Multilib apexMultilibProperties
330		}
331
332		// Multilib properties only for host linux_bionic.
333		Linux_bionic struct {
334			Multilib apexMultilibProperties
335		}
336
337		// Multilib properties only for host linux_glibc.
338		Linux_glibc struct {
339			Multilib apexMultilibProperties
340		}
341	}
342}
343
344type apexArchBundleProperties struct {
345	Arch struct {
346		Arm struct {
347			ApexNativeDependencies
348		}
349		Arm64 struct {
350			ApexNativeDependencies
351		}
352		Riscv64 struct {
353			ApexNativeDependencies
354		}
355		X86 struct {
356			ApexNativeDependencies
357		}
358		X86_64 struct {
359			ApexNativeDependencies
360		}
361	}
362}
363
364// These properties can be used in override_apex to override the corresponding properties in the
365// base apex.
366type overridableProperties struct {
367	// List of APKs that are embedded inside this APEX.
368	Apps proptools.Configurable[[]string]
369
370	// List of prebuilt files that are embedded inside this APEX bundle.
371	Prebuilts proptools.Configurable[[]string]
372
373	// List of BPF programs inside this APEX bundle.
374	Bpfs []string
375
376	// Names of modules to be overridden. Listed modules can only be other binaries (in Make or
377	// Soong). This does not completely prevent installation of the overridden binaries, but if
378	// both binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will
379	// be removed from PRODUCT_PACKAGES.
380	Overrides []string
381
382	Multilib apexMultilibProperties
383
384	// Logging parent value.
385	Logging_parent string
386
387	// Apex Container package name. Override value for attribute package:name in
388	// AndroidManifest.xml
389	Package_name proptools.Configurable[string]
390
391	// A txt file containing list of files that are allowed to be included in this APEX.
392	Allowed_files *string `android:"path"`
393
394	// Name of the apex_key module that provides the private key to sign this APEX bundle.
395	Key *string
396
397	// Specifies the certificate and the private key to sign the zip container of this APEX. If
398	// this is "foo", foo.x509.pem and foo.pk8 under PRODUCT_DEFAULT_DEV_CERTIFICATE are used
399	// as the certificate and the private key, respectively. If this is ":module", then the
400	// certificate and the private key are provided from the android_app_certificate module
401	// named "module".
402	Certificate *string
403
404	// Whether this APEX can be compressed or not. Setting this property to false means this
405	// APEX will never be compressed. When set to true, APEX will be compressed if other
406	// conditions, e.g., target device needs to support APEX compression, are also fulfilled.
407	// Default: false.
408	Compressible *bool
409
410	// Trim against a specific Dynamic Common Lib APEX
411	Trim_against *string
412
413	// The minimum SDK version that this APEX must support at minimum. This is usually set to
414	// the SDK version that the APEX was first introduced.
415	Min_sdk_version *string
416}
417
418type apexBundle struct {
419	// Inherited structs
420	android.ModuleBase
421	android.DefaultableModuleBase
422	android.OverridableModuleBase
423
424	// Properties
425	properties            apexBundleProperties
426	targetProperties      apexTargetBundleProperties
427	archProperties        apexArchBundleProperties
428	overridableProperties overridableProperties
429	vndkProperties        apexVndkProperties // only for apex_vndk modules
430	testProperties        apexTestProperties // only for apex_test modules
431
432	///////////////////////////////////////////////////////////////////////////////////////////
433	// Inputs
434
435	// Keys for apex_payload.img
436	publicKeyFile  android.Path
437	privateKeyFile android.Path
438
439	// Cert/priv-key for the zip container
440	containerCertificateFile android.Path
441	containerPrivateKeyFile  android.Path
442
443	// Flags for special variants of APEX
444	testApex bool
445	vndkApex bool
446
447	// File system type of apex_payload.img
448	payloadFsType fsType
449
450	// Whether to create symlink to the system file instead of having a file inside the apex or
451	// not
452	linkToSystemLib bool
453
454	// List of files to be included in this APEX. This is filled in the first part of
455	// GenerateAndroidBuildActions.
456	filesInfo []apexFile
457
458	// List of files that were excluded by the unwanted_transitive_deps property.
459	unwantedTransitiveFilesInfo []apexFile
460
461	// List of files that were excluded due to conflicts with other variants of the same module.
462	duplicateTransitiveFilesInfo []apexFile
463
464	// List of other module names that should be installed when this APEX gets installed (LOCAL_REQUIRED_MODULES).
465	makeModulesToInstall []string
466
467	///////////////////////////////////////////////////////////////////////////////////////////
468	// Outputs (final and intermediates)
469
470	// Processed apex manifest in JSONson format (for Q)
471	manifestJsonOut android.WritablePath
472
473	// Processed apex manifest in PB format (for R+)
474	manifestPbOut android.WritablePath
475
476	// Processed file_contexts files
477	fileContexts android.WritablePath
478
479	// The built APEX file. This is the main product.
480	// Could be .apex or .capex
481	outputFile android.WritablePath
482
483	// The built uncompressed .apex file.
484	outputApexFile android.WritablePath
485
486	// The built APEX file in app bundle format. This file is not directly installed to the
487	// device. For an APEX, multiple app bundles are created each of which is for a specific ABI
488	// like arm, arm64, x86, etc. Then they are processed again (outside of the Android build
489	// system) to be merged into a single app bundle file that Play accepts. See
490	// vendor/google/build/build_unbundled_mainline_module.sh for more detail.
491	bundleModuleFile android.WritablePath
492
493	// Target directory to install this APEX. Usually out/target/product/<device>/<partition>/apex.
494	installDir android.InstallPath
495
496	// Path where this APEX was installed.
497	installedFile android.InstallPath
498
499	// fragment for this apex for apexkeys.txt
500	apexKeysPath android.WritablePath
501
502	// Installed locations of symlinks for backward compatibility.
503	compatSymlinks android.InstallPaths
504
505	// Text file having the list of individual files that are included in this APEX. Used for
506	// debugging purpose.
507	installedFilesFile android.Path
508
509	// List of module names that this APEX is including (to be shown via *-deps-info target).
510	// Used for debugging purpose.
511	android.ApexBundleDepsInfo
512
513	// Optional list of lint report zip files for apexes that contain java or app modules
514	lintReports android.Paths
515
516	isCompressed bool
517
518	// Path of API coverage generate file
519	nativeApisUsedByModuleFile   android.ModuleOutPath
520	nativeApisBackedByModuleFile android.ModuleOutPath
521	javaApisUsedByModuleFile     android.ModuleOutPath
522
523	aconfigFiles []android.Path
524
525	// Required modules, filled out during GenerateAndroidBuildActions and used in AndroidMk
526	required []string
527}
528
529// apexFileClass represents a type of file that can be included in APEX.
530type apexFileClass int
531
532const (
533	app apexFileClass = iota
534	appSet
535	etc
536	javaSharedLib
537	nativeExecutable
538	nativeSharedLib
539	nativeTest
540	shBinary
541)
542
543var (
544	classes = map[string]apexFileClass{
545		"app":              app,
546		"appSet":           appSet,
547		"etc":              etc,
548		"javaSharedLib":    javaSharedLib,
549		"nativeExecutable": nativeExecutable,
550		"nativeSharedLib":  nativeSharedLib,
551		"nativeTest":       nativeTest,
552		"shBinary":         shBinary,
553	}
554)
555
556// apexFile represents a file in an APEX bundle. This is created during the first half of
557// GenerateAndroidBuildActions by traversing the dependencies of the APEX. Then in the second half
558// of the function, this is used to create commands that copies the files into a staging directory,
559// where they are packaged into the APEX file.
560type apexFile struct {
561	// buildFile is put in the installDir inside the APEX.
562	builtFile  android.Path
563	installDir string
564	partition  string
565	customStem string
566	symlinks   []string // additional symlinks
567
568	checkbuildTarget android.Path
569
570	// Info for Android.mk Module name of `module` in AndroidMk. Note the generated AndroidMk
571	// module for apexFile is named something like <AndroidMk module name>.<apex name>[<apex
572	// suffix>]
573	androidMkModuleName       string             // becomes LOCAL_MODULE
574	class                     apexFileClass      // becomes LOCAL_MODULE_CLASS
575	moduleDir                 string             // becomes LOCAL_PATH
576	requiredModuleNames       []string           // becomes LOCAL_REQUIRED_MODULES
577	targetRequiredModuleNames []string           // becomes LOCAL_TARGET_REQUIRED_MODULES
578	hostRequiredModuleNames   []string           // becomes LOCAL_HOST_REQUIRED_MODULES
579	dataPaths                 []android.DataPath // becomes LOCAL_TEST_DATA
580
581	jacocoReportClassesFile android.Path     // only for javalibs and apps
582	lintInfo                *java.LintInfo   // only for javalibs and apps
583	certificate             java.Certificate // only for apps
584	overriddenPackageName   string           // only for apps
585
586	transitiveDep bool
587	isJniLib      bool
588
589	multilib string
590
591	// TODO(jiyong): remove this
592	module android.Module
593}
594
595// TODO(jiyong): shorten the arglist using an option struct
596func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string, installDir string, class apexFileClass, module android.Module) apexFile {
597	ret := apexFile{
598		builtFile:           builtFile,
599		installDir:          installDir,
600		androidMkModuleName: androidMkModuleName,
601		class:               class,
602		module:              module,
603	}
604	if module != nil {
605		if installFilesInfo, ok := android.OtherModuleProvider(ctx, module, android.InstallFilesProvider); ok {
606			ret.checkbuildTarget = installFilesInfo.CheckbuildTarget
607		}
608		ret.moduleDir = ctx.OtherModuleDir(module)
609		ret.partition = module.PartitionTag(ctx.DeviceConfig())
610		ret.multilib = module.Target().Arch.ArchType.Multilib
611	}
612	return ret
613}
614
615func (af *apexFile) ok() bool {
616	return af.builtFile != nil && af.builtFile.String() != ""
617}
618
619// apexRelativePath returns the relative path of the given path from the install directory of this
620// apexFile.
621// TODO(jiyong): rename this
622func (af *apexFile) apexRelativePath(path string) string {
623	return filepath.Join(af.installDir, path)
624}
625
626// path returns path of this apex file relative to the APEX root
627func (af *apexFile) path() string {
628	return af.apexRelativePath(af.stem())
629}
630
631// stem returns the base filename of this apex file
632func (af *apexFile) stem() string {
633	if af.customStem != "" {
634		return af.customStem
635	}
636	return af.builtFile.Base()
637}
638
639// symlinkPaths returns paths of the symlinks (if any) relative to the APEX root
640func (af *apexFile) symlinkPaths() []string {
641	var ret []string
642	for _, symlink := range af.symlinks {
643		ret = append(ret, af.apexRelativePath(symlink))
644	}
645	return ret
646}
647
648// availableToPlatform tests whether this apexFile is from a module that can be installed to the
649// platform.
650func (af *apexFile) availableToPlatform() bool {
651	if af.module == nil {
652		return false
653	}
654	if am, ok := af.module.(android.ApexModule); ok {
655		return am.AvailableFor(android.AvailableToPlatform)
656	}
657	return false
658}
659
660////////////////////////////////////////////////////////////////////////////////////////////////////
661// Mutators
662//
663// Brief description about mutators for APEX. The following three mutators are the most important
664// ones.
665//
666// 1) DepsMutator: from the properties like native_shared_libs, java_libs, etc., modules are added
667// to the (direct) dependencies of this APEX bundle.
668//
669// 2) apexInfoMutator: this is a post-deps mutator, so runs after DepsMutator. Its goal is to
670// collect modules that are direct and transitive dependencies of each APEX bundle. The collected
671// modules are marked as being included in the APEX via BuildForApex().
672//
673// 3) apexMutator: this is a post-deps mutator that runs after apexInfoMutator. For each module that
674// are marked by the apexInfoMutator, apex variations are created using CreateApexVariations().
675
676type dependencyTag struct {
677	blueprint.BaseDependencyTag
678	name string
679
680	// Determines if the dependent will be part of the APEX payload. Can be false for the
681	// dependencies to the signing key module, etc.
682	payload bool
683
684	// True if the dependent can only be a source module, false if a prebuilt module is a suitable
685	// replacement. This is needed because some prebuilt modules do not provide all the information
686	// needed by the apex.
687	sourceOnly bool
688
689	// If not-nil and an APEX is a member of an SDK then dependencies of that APEX with this tag will
690	// also be added as exported members of that SDK.
691	memberType android.SdkMemberType
692
693	installable bool
694}
695
696func (d *dependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType {
697	return d.memberType
698}
699
700func (d *dependencyTag) ExportMember() bool {
701	return true
702}
703
704func (d *dependencyTag) String() string {
705	return fmt.Sprintf("apex.dependencyTag{%q}", d.name)
706}
707
708func (d *dependencyTag) ReplaceSourceWithPrebuilt() bool {
709	return !d.sourceOnly
710}
711
712func (d *dependencyTag) InstallDepNeeded() bool {
713	return d.installable
714}
715
716var _ android.ReplaceSourceWithPrebuilt = &dependencyTag{}
717var _ android.SdkMemberDependencyTag = &dependencyTag{}
718
719var (
720	androidAppTag  = &dependencyTag{name: "androidApp", payload: true}
721	bpfTag         = &dependencyTag{name: "bpf", payload: true}
722	certificateTag = &dependencyTag{name: "certificate"}
723	executableTag  = &dependencyTag{name: "executable", payload: true}
724	fsTag          = &dependencyTag{name: "filesystem", payload: true}
725	bcpfTag        = &dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true, memberType: java.BootclasspathFragmentSdkMemberType}
726	// The dexpreopt artifacts of apex system server jars are installed onto system image.
727	sscpfTag        = &dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true, memberType: java.SystemServerClasspathFragmentSdkMemberType, installable: true}
728	compatConfigTag = &dependencyTag{name: "compatConfig", payload: true, sourceOnly: true, memberType: java.CompatConfigSdkMemberType}
729	javaLibTag      = &dependencyTag{name: "javaLib", payload: true}
730	jniLibTag       = &dependencyTag{name: "jniLib", payload: true}
731	keyTag          = &dependencyTag{name: "key"}
732	prebuiltTag     = &dependencyTag{name: "prebuilt", payload: true}
733	rroTag          = &dependencyTag{name: "rro", payload: true}
734	sharedLibTag    = &dependencyTag{name: "sharedLib", payload: true}
735	testTag         = &dependencyTag{name: "test", payload: true}
736	shBinaryTag     = &dependencyTag{name: "shBinary", payload: true}
737)
738
739// TODO(jiyong): shorten this function signature
740func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ResolvedApexNativeDependencies, target android.Target, imageVariation string) {
741	binVariations := target.Variations()
742	libVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
743	rustLibVariations := append(
744		target.Variations(), []blueprint.Variation{
745			{Mutator: "rust_libraries", Variation: "dylib"},
746		}...,
747	)
748
749	// Append "image" variation
750	binVariations = append(binVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation})
751	libVariations = append(libVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation})
752	rustLibVariations = append(rustLibVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation})
753
754	// Use *FarVariation* to be able to depend on modules having conflicting variations with
755	// this module. This is required since arch variant of an APEX bundle is 'common' but it is
756	// 'arm' or 'arm64' for native shared libs.
757	ctx.AddFarVariationDependencies(binVariations, executableTag,
758		android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...)
759	ctx.AddFarVariationDependencies(binVariations, testTag,
760		android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...)
761	ctx.AddFarVariationDependencies(libVariations, jniLibTag,
762		android.RemoveListFromList(nativeModules.Jni_libs, nativeModules.Exclude_jni_libs)...)
763	ctx.AddFarVariationDependencies(libVariations, sharedLibTag,
764		android.RemoveListFromList(nativeModules.Native_shared_libs, nativeModules.Exclude_native_shared_libs)...)
765	ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag,
766		android.RemoveListFromList(nativeModules.Rust_dyn_libs, nativeModules.Exclude_rust_dyn_libs)...)
767	ctx.AddFarVariationDependencies(target.Variations(), fsTag,
768		android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...)
769	ctx.AddFarVariationDependencies(target.Variations(), prebuiltTag,
770		android.RemoveListFromList(nativeModules.Prebuilts, nativeModules.Exclude_prebuilts)...)
771}
772
773func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
774	proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil)
775}
776
777// getImageVariationPair returns a pair for the image variation name as its
778// prefix and suffix. The prefix indicates whether it's core/vendor/product and the
779// suffix indicates the vndk version for vendor/product if vndk is enabled.
780// getImageVariation can simply join the result of this function to get the
781// image variation name.
782func (a *apexBundle) getImageVariationPair() (string, string) {
783	if a.vndkApex {
784		return cc.VendorVariationPrefix, a.vndkVersion()
785	}
786
787	prefix := android.CoreVariation
788	if a.SocSpecific() || a.DeviceSpecific() {
789		prefix = android.VendorVariation
790	} else if a.ProductSpecific() {
791		prefix = android.ProductVariation
792	}
793
794	return prefix, ""
795}
796
797// getImageVariation returns the image variant name for this apexBundle. In most cases, it's simply
798// android.CoreVariation, but gets complicated for the vendor APEXes and the VNDK APEX.
799func (a *apexBundle) getImageVariation() string {
800	prefix, vndkVersion := a.getImageVariationPair()
801	return prefix + vndkVersion
802}
803
804func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
805	// apexBundle is a multi-arch targets module. Arch variant of apexBundle is set to 'common'.
806	// arch-specific targets are enabled by the compile_multilib setting of the apex bundle. For
807	// each target os/architectures, appropriate dependencies are selected by their
808	// target.<os>.multilib.<type> groups and are added as (direct) dependencies.
809	targets := ctx.MultiTargets()
810	imageVariation := a.getImageVariation()
811
812	a.combineProperties(ctx)
813
814	has32BitTarget := false
815	for _, target := range targets {
816		if target.Arch.ArchType.Multilib == "lib32" {
817			has32BitTarget = true
818		}
819	}
820	for i, target := range targets {
821		var deps ResolvedApexNativeDependencies
822
823		// Add native modules targeting both ABIs. When multilib.* is omitted for
824		// native_shared_libs/jni_libs/tests, it implies multilib.both
825		deps.Merge(ctx, a.properties.Multilib.Both)
826		deps.Merge(ctx, ApexNativeDependencies{
827			Native_shared_libs: a.properties.Native_shared_libs,
828			Rust_dyn_libs:      a.properties.Rust_dyn_libs,
829			Tests:              a.properties.Tests,
830			Jni_libs:           a.properties.Jni_libs,
831		})
832
833		// Add native modules targeting the first ABI When multilib.* is omitted for
834		// binaries, it implies multilib.first
835		isPrimaryAbi := i == 0
836		if isPrimaryAbi {
837			deps.Merge(ctx, a.properties.Multilib.First)
838			deps.Merge(ctx, ApexNativeDependencies{
839				Native_shared_libs: proptools.NewConfigurable[[]string](nil, nil),
840				Tests:              nil,
841				Jni_libs:           proptools.NewConfigurable[[]string](nil, nil),
842				Binaries:           a.properties.Binaries,
843			})
844		}
845
846		// Add native modules targeting either 32-bit or 64-bit ABI
847		switch target.Arch.ArchType.Multilib {
848		case "lib32":
849			deps.Merge(ctx, a.properties.Multilib.Lib32)
850			deps.Merge(ctx, a.properties.Multilib.Prefer32)
851		case "lib64":
852			deps.Merge(ctx, a.properties.Multilib.Lib64)
853			if !has32BitTarget {
854				deps.Merge(ctx, a.properties.Multilib.Prefer32)
855			}
856		}
857
858		// Add native modules targeting a specific arch variant
859		switch target.Arch.ArchType {
860		case android.Arm:
861			deps.Merge(ctx, a.archProperties.Arch.Arm.ApexNativeDependencies)
862		case android.Arm64:
863			deps.Merge(ctx, a.archProperties.Arch.Arm64.ApexNativeDependencies)
864		case android.Riscv64:
865			deps.Merge(ctx, a.archProperties.Arch.Riscv64.ApexNativeDependencies)
866		case android.X86:
867			deps.Merge(ctx, a.archProperties.Arch.X86.ApexNativeDependencies)
868		case android.X86_64:
869			deps.Merge(ctx, a.archProperties.Arch.X86_64.ApexNativeDependencies)
870		default:
871			panic(fmt.Errorf("unsupported arch %v\n", ctx.Arch().ArchType))
872		}
873
874		addDependenciesForNativeModules(ctx, deps, target, imageVariation)
875		if isPrimaryAbi {
876			ctx.AddFarVariationDependencies([]blueprint.Variation{
877				{Mutator: "os", Variation: target.OsVariation()},
878				{Mutator: "arch", Variation: target.ArchVariation()},
879			}, shBinaryTag, a.properties.Sh_binaries...)
880		}
881	}
882
883	// Common-arch dependencies come next
884	commonVariation := ctx.Config().AndroidCommonTarget.Variations()
885	ctx.AddFarVariationDependencies(commonVariation, rroTag, a.properties.Rros...)
886	ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments.GetOrDefault(ctx, nil)...)
887	ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments.GetOrDefault(ctx, nil)...)
888	ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
889	ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
890	ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
891}
892
893// DepsMutator for the overridden properties.
894func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
895	if a.overridableProperties.Allowed_files != nil {
896		android.ExtractSourceDeps(ctx, a.overridableProperties.Allowed_files)
897	}
898
899	commonVariation := ctx.Config().AndroidCommonTarget.Variations()
900	ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps.GetOrDefault(ctx, nil)...)
901	ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...)
902	if prebuilts := a.overridableProperties.Prebuilts.GetOrDefault(ctx, nil); len(prebuilts) > 0 {
903		// For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device)
904		// regardless of the TARGET_PREFER_* setting. See b/144532908
905		arches := ctx.DeviceConfig().Arches()
906		if len(arches) != 0 {
907			archForPrebuiltEtc := arches[0]
908			for _, arch := range arches {
909				// Prefer 64-bit arch if there is any
910				if arch.ArchType.Multilib == "lib64" {
911					archForPrebuiltEtc = arch
912					break
913				}
914			}
915			ctx.AddFarVariationDependencies([]blueprint.Variation{
916				{Mutator: "os", Variation: ctx.Os().String()},
917				{Mutator: "arch", Variation: archForPrebuiltEtc.String()},
918			}, prebuiltTag, prebuilts...)
919		}
920	}
921
922	// Dependencies for signing
923	if String(a.overridableProperties.Key) == "" {
924		ctx.PropertyErrorf("key", "missing")
925		return
926	}
927	ctx.AddDependency(ctx.Module(), keyTag, String(a.overridableProperties.Key))
928
929	cert := android.SrcIsModule(a.getCertString(ctx))
930	if cert != "" {
931		ctx.AddDependency(ctx.Module(), certificateTag, cert)
932		// empty cert is not an error. Cert and private keys will be directly found under
933		// PRODUCT_DEFAULT_DEV_CERTIFICATE
934	}
935}
936
937var _ ApexInfoMutator = (*apexBundle)(nil)
938
939func (a *apexBundle) ApexVariationName() string {
940	return a.properties.ApexVariationName
941}
942
943// ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are
944// identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and
945// indirect) dependencies are collected. But a few types of modules that shouldn't be included in
946// the apexBundle (e.g. stub libraries) are not collected. Note that a single module can be depended
947// on by multiple apexBundles. In that case, the module is collected for all of the apexBundles.
948//
949// For each dependency between an apex and an ApexModule an ApexInfo object describing the apex
950// is passed to that module's BuildForApex(ApexInfo) method which collates them all in a list.
951// The apexMutator uses that list to create module variants for the apexes to which it belongs.
952// The relationship between module variants and apexes is not one-to-one as variants will be
953// shared between compatible apexes.
954func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
955
956	// The VNDK APEX is special. For the APEX, the membership is described in a very different
957	// way. There is no dependency from the VNDK APEX to the VNDK libraries. Instead, VNDK
958	// libraries are self-identified by their vndk.enabled properties. There is no need to run
959	// this mutator for the APEX as nothing will be collected. So, let's return fast.
960	if a.vndkApex {
961		return
962	}
963
964	continueApexDepsWalk := func(child, parent android.Module) bool {
965		am, ok := child.(android.ApexModule)
966		if !ok || !am.CanHaveApexVariants() {
967			return false
968		}
969		depTag := mctx.OtherModuleDependencyTag(child)
970
971		// Check to see if the tag always requires that the child module has an apex variant for every
972		// apex variant of the parent module. If it does not then it is still possible for something
973		// else, e.g. the DepIsInSameApex(...) method to decide that a variant is required.
974		if required, ok := depTag.(android.AlwaysRequireApexVariantTag); ok && required.AlwaysRequireApexVariant() {
975			return true
976		}
977		if !android.IsDepInSameApex(mctx, parent, child) {
978			return false
979		}
980
981		// By default, all the transitive dependencies are collected, unless filtered out
982		// above.
983		return true
984	}
985
986	android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
987
988	minSdkVersion := a.minSdkVersion(mctx)
989	// When min_sdk_version is not set, the apex is built against FutureApiLevel.
990	if minSdkVersion.IsNone() {
991		minSdkVersion = android.FutureApiLevel
992	}
993
994	// This is the main part of this mutator. Mark the collected dependencies that they need to
995	// be built for this apexBundle.
996
997	apexVariationName := mctx.ModuleName() // could be com.android.foo
998	if overridable, ok := mctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
999		// use the overridden name com.mycompany.android.foo
1000		apexVariationName = overridable.GetOverriddenBy()
1001	}
1002
1003	a.properties.ApexVariationName = apexVariationName
1004	testApexes := []string{}
1005	if a.testApex {
1006		testApexes = []string{apexVariationName}
1007	}
1008	apexInfo := android.ApexInfo{
1009		ApexVariationName: apexVariationName,
1010		MinSdkVersion:     minSdkVersion,
1011		Updatable:         a.Updatable(),
1012		UsePlatformApis:   a.UsePlatformApis(),
1013		InApexVariants:    []string{apexVariationName},
1014		TestApexes:        testApexes,
1015		BaseApexName:      mctx.ModuleName(),
1016		ApexAvailableName: proptools.String(a.properties.Apex_available_name),
1017	}
1018	mctx.WalkDeps(func(child, parent android.Module) bool {
1019		if !continueApexDepsWalk(child, parent) {
1020			return false
1021		}
1022		child.(android.ApexModule).BuildForApex(apexInfo) // leave a mark!
1023		return true
1024	})
1025}
1026
1027type ApexInfoMutator interface {
1028	// ApexVariationName returns the name of the APEX variation to use in the apex
1029	// mutator etc. It is the same name as ApexInfo.ApexVariationName.
1030	ApexVariationName() string
1031
1032	// ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are
1033	// depended upon by an apex and which require an apex specific variant.
1034	ApexInfoMutator(android.TopDownMutatorContext)
1035}
1036
1037// apexInfoMutator delegates the work of identifying which modules need an ApexInfo and apex
1038// specific variant to modules that support the ApexInfoMutator.
1039// It also propagates updatable=true to apps of updatable apexes
1040func apexInfoMutator(mctx android.TopDownMutatorContext) {
1041	if !mctx.Module().Enabled(mctx) {
1042		return
1043	}
1044
1045	if a, ok := mctx.Module().(ApexInfoMutator); ok {
1046		a.ApexInfoMutator(mctx)
1047	}
1048
1049	if am, ok := mctx.Module().(android.ApexModule); ok {
1050		android.ApexInfoMutator(mctx, am)
1051	}
1052}
1053
1054// TODO: b/215736885 Whittle the denylist
1055// Transitive deps of certain mainline modules baseline NewApi errors
1056// Skip these mainline modules for now
1057var (
1058	skipStrictUpdatabilityLintAllowlist = []string{
1059		// go/keep-sorted start
1060		"PackageManagerTestApex",
1061		"com.android.adservices",
1062		"com.android.appsearch",
1063		"com.android.art",
1064		"com.android.art.debug",
1065		"com.android.btservices",
1066		"com.android.cellbroadcast",
1067		"com.android.configinfrastructure",
1068		"com.android.conscrypt",
1069		"com.android.extservices",
1070		"com.android.extservices_tplus",
1071		"com.android.healthfitness",
1072		"com.android.ipsec",
1073		"com.android.media",
1074		"com.android.mediaprovider",
1075		"com.android.ondevicepersonalization",
1076		"com.android.os.statsd",
1077		"com.android.permission",
1078		"com.android.profiling",
1079		"com.android.rkpd",
1080		"com.android.scheduling",
1081		"com.android.tethering",
1082		"com.android.uwb",
1083		"com.android.wifi",
1084		"test_com.android.art",
1085		"test_com.android.cellbroadcast",
1086		"test_com.android.conscrypt",
1087		"test_com.android.extservices",
1088		"test_com.android.ipsec",
1089		"test_com.android.media",
1090		"test_com.android.mediaprovider",
1091		"test_com.android.os.statsd",
1092		"test_com.android.permission",
1093		"test_com.android.wifi",
1094		"test_imgdiag_com.android.art",
1095		"test_jitzygote_com.android.art",
1096		// go/keep-sorted end
1097	}
1098)
1099
1100func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.ModuleContext) bool {
1101	// The allowlist contains the base apex name, so use that instead of the ApexVariationName
1102	return a.Updatable() && !android.InList(mctx.ModuleName(), skipStrictUpdatabilityLintAllowlist)
1103}
1104
1105// apexUniqueVariationsMutator checks if any dependencies use unique apex variations. If so, use
1106// unique apex variations for this module. See android/apex.go for more about unique apex variant.
1107// TODO(jiyong): move this to android/apex.go?
1108func apexUniqueVariationsMutator(mctx android.BottomUpMutatorContext) {
1109	if !mctx.Module().Enabled(mctx) {
1110		return
1111	}
1112	if am, ok := mctx.Module().(android.ApexModule); ok {
1113		android.UpdateUniqueApexVariationsForDeps(mctx, am)
1114	}
1115}
1116
1117// markPlatformAvailability marks whether or not a module can be available to platform. A module
1118// cannot be available to platform if 1) it is explicitly marked as not available (i.e.
1119// "//apex_available:platform" is absent) or 2) it depends on another module that isn't (or can't
1120// be) available to platform
1121// TODO(jiyong): move this to android/apex.go?
1122func markPlatformAvailability(mctx android.BottomUpMutatorContext) {
1123	// Recovery is not considered as platform
1124	if mctx.Module().InstallInRecovery() {
1125		return
1126	}
1127
1128	am, ok := mctx.Module().(android.ApexModule)
1129	if !ok {
1130		return
1131	}
1132
1133	availableToPlatform := am.AvailableFor(android.AvailableToPlatform)
1134
1135	// If any of the dep is not available to platform, this module is also considered as being
1136	// not available to platform even if it has "//apex_available:platform"
1137	mctx.VisitDirectDeps(func(child android.Module) {
1138		if !android.IsDepInSameApex(mctx, am, child) {
1139			// if the dependency crosses apex boundary, don't consider it
1140			return
1141		}
1142		if dep, ok := child.(android.ApexModule); ok && dep.NotAvailableForPlatform() {
1143			availableToPlatform = false
1144			// TODO(b/154889534) trigger an error when 'am' has
1145			// "//apex_available:platform"
1146		}
1147	})
1148
1149	// Exception 1: check to see if the module always requires it.
1150	if am.AlwaysRequiresPlatformApexVariant() {
1151		availableToPlatform = true
1152	}
1153
1154	// Exception 2: bootstrap bionic libraries are also always available to platform
1155	if cc.InstallToBootstrap(mctx.ModuleName(), mctx.Config()) {
1156		availableToPlatform = true
1157	}
1158
1159	if !availableToPlatform {
1160		am.SetNotAvailableForPlatform()
1161	}
1162}
1163
1164type apexTransitionMutator struct{}
1165
1166func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
1167	// apexBundle itself is mutated so that it and its dependencies have the same apex variant.
1168	if ai, ok := ctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
1169		if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
1170			return []string{overridable.GetOverriddenBy()}
1171		}
1172		return []string{ai.ApexVariationName()}
1173	} else if _, ok := ctx.Module().(*OverrideApex); ok {
1174		return []string{ctx.ModuleName()}
1175	}
1176	return []string{""}
1177}
1178
1179func (a *apexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
1180	return sourceVariation
1181}
1182
1183func (a *apexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
1184	if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
1185		return android.IncomingApexTransition(ctx, incomingVariation)
1186	} else if ai, ok := ctx.Module().(ApexInfoMutator); ok {
1187		if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
1188			return overridable.GetOverriddenBy()
1189		}
1190		return ai.ApexVariationName()
1191	} else if _, ok := ctx.Module().(*OverrideApex); ok {
1192		return ctx.Module().Name()
1193	}
1194
1195	return ""
1196}
1197
1198func (a *apexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
1199	if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
1200		android.MutateApexTransition(ctx, variation)
1201	}
1202}
1203
1204// apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific
1205// variant.
1206func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool {
1207	if a, ok := module.(*apexBundle); ok {
1208		// TODO(jiyong): document the reason why the VNDK APEX is an exception here.
1209		return !a.vndkApex
1210	}
1211
1212	return true
1213}
1214
1215const (
1216	// File extensions of an APEX for different packaging methods
1217	imageApexSuffix  = ".apex"
1218	imageCapexSuffix = ".capex"
1219
1220	// variant names each of which is for a packaging method
1221	imageApexType = "image"
1222
1223	ext4FsType  = "ext4"
1224	f2fsFsType  = "f2fs"
1225	erofsFsType = "erofs"
1226)
1227
1228var _ android.DepIsInSameApex = (*apexBundle)(nil)
1229
1230// Implements android.DepInInSameApex
1231func (a *apexBundle) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
1232	// direct deps of an APEX bundle are all part of the APEX bundle
1233	// TODO(jiyong): shouldn't we look into the payload field of the dependencyTag?
1234	return true
1235}
1236
1237func (a *apexBundle) Exportable() bool {
1238	return true
1239}
1240
1241func (a *apexBundle) TaggedOutputs() map[string]android.Paths {
1242	ret := make(map[string]android.Paths)
1243	ret["apex"] = android.Paths{a.outputFile}
1244	return ret
1245}
1246
1247var _ cc.Coverage = (*apexBundle)(nil)
1248
1249// Implements cc.Coverage
1250func (a *apexBundle) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool {
1251	return ctx.DeviceConfig().NativeCoverageEnabled()
1252}
1253
1254// Implements cc.Coverage
1255func (a *apexBundle) SetPreventInstall() {
1256	a.properties.PreventInstall = true
1257}
1258
1259// Implements cc.Coverage
1260func (a *apexBundle) HideFromMake() {
1261	a.properties.HideFromMake = true
1262	// This HideFromMake is shadowing the ModuleBase one, call through to it for now.
1263	// TODO(ccross): untangle these
1264	a.ModuleBase.HideFromMake()
1265}
1266
1267// Implements cc.Coverage
1268func (a *apexBundle) MarkAsCoverageVariant(coverage bool) {
1269	a.properties.IsCoverageVariant = coverage
1270}
1271
1272// Implements cc.Coverage
1273func (a *apexBundle) EnableCoverageIfNeeded() {}
1274
1275var _ android.ApexBundleDepsInfoIntf = (*apexBundle)(nil)
1276
1277// Implements android.ApexBundleDepsInfoIntf
1278func (a *apexBundle) Updatable() bool {
1279	return proptools.BoolDefault(a.properties.Updatable, true)
1280}
1281
1282func (a *apexBundle) FutureUpdatable() bool {
1283	return proptools.BoolDefault(a.properties.Future_updatable, false)
1284}
1285
1286func (a *apexBundle) UsePlatformApis() bool {
1287	return proptools.BoolDefault(a.properties.Platform_apis, false)
1288}
1289
1290type apexValidationType int
1291
1292const (
1293	hostApexVerifier apexValidationType = iota
1294	apexSepolicyTests
1295)
1296
1297func (a *apexBundle) skipValidation(validationType apexValidationType) bool {
1298	switch validationType {
1299	case hostApexVerifier:
1300		return proptools.Bool(a.testProperties.Skip_validations.Host_apex_verifier)
1301	case apexSepolicyTests:
1302		return proptools.Bool(a.testProperties.Skip_validations.Apex_sepolicy_tests)
1303	}
1304	panic("Unknown validation type")
1305}
1306
1307// getCertString returns the name of the cert that should be used to sign this APEX. This is
1308// basically from the "certificate" property, but could be overridden by the device config.
1309func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
1310	moduleName := ctx.ModuleName()
1311	// VNDK APEXes share the same certificate. To avoid adding a new VNDK version to the
1312	// OVERRIDE_* list, we check with the pseudo module name to see if its certificate is
1313	// overridden.
1314	if a.vndkApex {
1315		moduleName = vndkApexName
1316	}
1317	certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(moduleName)
1318	if overridden {
1319		return ":" + certificate
1320	}
1321	return String(a.overridableProperties.Certificate)
1322}
1323
1324// See the installable property
1325func (a *apexBundle) installable() bool {
1326	return !a.properties.PreventInstall && (a.properties.Installable == nil || proptools.Bool(a.properties.Installable))
1327}
1328
1329// See the test_only_unsigned_payload property
1330func (a *apexBundle) testOnlyShouldSkipPayloadSign() bool {
1331	return proptools.Bool(a.properties.Test_only_unsigned_payload)
1332}
1333
1334// See the test_only_force_compression property
1335func (a *apexBundle) testOnlyShouldForceCompression() bool {
1336	return proptools.Bool(a.properties.Test_only_force_compression)
1337}
1338
1339// See the dynamic_common_lib_apex property
1340func (a *apexBundle) dynamic_common_lib_apex() bool {
1341	return proptools.BoolDefault(a.properties.Dynamic_common_lib_apex, false)
1342}
1343
1344// These functions are interfacing with cc/sanitizer.go. The entire APEX (along with all of its
1345// members) can be sanitized, either forcibly, or by the global configuration. For some of the
1346// sanitizers, extra dependencies can be forcibly added as well.
1347
1348func (a *apexBundle) EnableSanitizer(sanitizerName string) {
1349	if !android.InList(sanitizerName, a.properties.SanitizerNames) {
1350		a.properties.SanitizerNames = append(a.properties.SanitizerNames, sanitizerName)
1351	}
1352}
1353
1354func (a *apexBundle) IsSanitizerEnabled(config android.Config, sanitizerName string) bool {
1355	if android.InList(sanitizerName, a.properties.SanitizerNames) {
1356		return true
1357	}
1358
1359	// Then follow the global setting
1360	var globalSanitizerNames []string
1361	arches := config.SanitizeDeviceArch()
1362	if len(arches) == 0 || android.InList(a.Arch().ArchType.Name, arches) {
1363		globalSanitizerNames = config.SanitizeDevice()
1364	}
1365	return android.InList(sanitizerName, globalSanitizerNames)
1366}
1367
1368func (a *apexBundle) AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string) {
1369	// TODO(jiyong): move this info (the sanitizer name, the lib name, etc.) to cc/sanitize.go
1370	// Keep only the mechanism here.
1371	if sanitizerName == "hwaddress" && strings.HasPrefix(a.Name(), "com.android.runtime") {
1372		imageVariation := a.getImageVariation()
1373		for _, target := range ctx.MultiTargets() {
1374			if target.Arch.ArchType.Multilib == "lib64" {
1375				addDependenciesForNativeModules(ctx, ResolvedApexNativeDependencies{
1376					Native_shared_libs: []string{"libclang_rt.hwasan"},
1377					Tests:              nil,
1378					Jni_libs:           nil,
1379				}, target, imageVariation)
1380				break
1381			}
1382		}
1383	}
1384}
1385
1386// apexFileFor<Type> functions below create an apexFile struct for a given Soong module. The
1387// returned apexFile saves information about the Soong module that will be used for creating the
1388// build rules.
1389func apexFileForNativeLibrary(ctx android.BaseModuleContext, ccMod *cc.Module, handleSpecialLibs bool) apexFile {
1390	// Decide the APEX-local directory by the multilib of the library In the future, we may
1391	// query this to the module.
1392	// TODO(jiyong): use the new PackagingSpec
1393	var dirInApex string
1394	switch ccMod.Arch().ArchType.Multilib {
1395	case "lib32":
1396		dirInApex = "lib"
1397	case "lib64":
1398		dirInApex = "lib64"
1399	}
1400	if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
1401		dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath)
1402	}
1403	if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), ctx.Config()) {
1404		// Special case for Bionic libs and other libs installed with them. This is to
1405		// prevent those libs from being included in the search path
1406		// /apex/com.android.runtime/${LIB}. This exclusion is required because those libs
1407		// in the Runtime APEX are available via the legacy paths in /system/lib/. By the
1408		// init process, the libs in the APEX are bind-mounted to the legacy paths and thus
1409		// will be loaded into the default linker namespace (aka "platform" namespace). If
1410		// the libs are directly in /apex/com.android.runtime/${LIB} then the same libs will
1411		// be loaded again into the runtime linker namespace, which will result in double
1412		// loading of them, which isn't supported.
1413		dirInApex = filepath.Join(dirInApex, "bionic")
1414	}
1415	// This needs to go after the runtime APEX handling because otherwise we would get
1416	// weird paths like lib64/rel_install_path/bionic rather than
1417	// lib64/bionic/rel_install_path.
1418	dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath())
1419
1420	fileToCopy := android.OutputFileForModule(ctx, ccMod, "")
1421	androidMkModuleName := ccMod.BaseModuleName() + ccMod.Properties.SubName
1422	return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, ccMod)
1423}
1424
1425func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFile {
1426	dirInApex := "bin"
1427	if cc.Target().NativeBridge == android.NativeBridgeEnabled {
1428		dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
1429	}
1430	dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
1431	fileToCopy := android.OutputFileForModule(ctx, cc, "")
1432	androidMkModuleName := cc.BaseModuleName() + cc.Properties.SubName
1433	af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, cc)
1434	af.symlinks = cc.Symlinks()
1435	af.dataPaths = cc.DataPaths()
1436	return af
1437}
1438
1439func apexFileForRustExecutable(ctx android.BaseModuleContext, rustm *rust.Module) apexFile {
1440	dirInApex := "bin"
1441	if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
1442		dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
1443	}
1444	dirInApex = filepath.Join(dirInApex, rustm.RelativeInstallPath())
1445	fileToCopy := android.OutputFileForModule(ctx, rustm, "")
1446	androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
1447	af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, rustm)
1448	return af
1449}
1450
1451func apexFileForRustLibrary(ctx android.BaseModuleContext, rustm *rust.Module) apexFile {
1452	// Decide the APEX-local directory by the multilib of the library
1453	// In the future, we may query this to the module.
1454	var dirInApex string
1455	switch rustm.Arch().ArchType.Multilib {
1456	case "lib32":
1457		dirInApex = "lib"
1458	case "lib64":
1459		dirInApex = "lib64"
1460	}
1461	if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
1462		dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
1463	}
1464	dirInApex = filepath.Join(dirInApex, rustm.RelativeInstallPath())
1465	fileToCopy := android.OutputFileForModule(ctx, rustm, "")
1466	androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
1467	return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, rustm)
1468}
1469
1470func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFile {
1471	dirInApex := filepath.Join("bin", sh.SubDir())
1472	if sh.Target().NativeBridge == android.NativeBridgeEnabled {
1473		dirInApex = filepath.Join(dirInApex, sh.Target().NativeBridgeRelativePath)
1474	}
1475	fileToCopy := sh.OutputFile()
1476	af := newApexFile(ctx, fileToCopy, sh.BaseModuleName(), dirInApex, shBinary, sh)
1477	af.symlinks = sh.Symlinks()
1478	return af
1479}
1480
1481func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, outputFile android.Path) apexFile {
1482	dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir())
1483	makeModuleName := strings.ReplaceAll(filepath.Join(dirInApex, outputFile.Base()), "/", "_")
1484	return newApexFile(ctx, outputFile, makeModuleName, dirInApex, etc, prebuilt)
1485}
1486
1487func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
1488	dirInApex := filepath.Join("etc", config.SubDir())
1489	fileToCopy := config.CompatConfig()
1490	return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, config)
1491}
1492
1493// javaModule is an interface to handle all Java modules (java_library, dex_import, etc) in the same
1494// way.
1495type javaModule interface {
1496	android.Module
1497	BaseModuleName() string
1498	DexJarBuildPath(ctx android.ModuleErrorfContext) java.OptionalDexJarPath
1499	JacocoReportClassesFile() android.Path
1500	Stem() string
1501}
1502
1503var _ javaModule = (*java.Library)(nil)
1504var _ javaModule = (*java.Import)(nil)
1505var _ javaModule = (*java.SdkLibrary)(nil)
1506var _ javaModule = (*java.DexImport)(nil)
1507var _ javaModule = (*java.SdkLibraryImport)(nil)
1508
1509// apexFileForJavaModule creates an apexFile for a java module's dex implementation jar.
1510func apexFileForJavaModule(ctx android.ModuleContext, module javaModule) apexFile {
1511	return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath(ctx).PathOrNil())
1512}
1513
1514// apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file.
1515func apexFileForJavaModuleWithFile(ctx android.ModuleContext, module javaModule, dexImplementationJar android.Path) apexFile {
1516	dirInApex := "javalib"
1517	af := newApexFile(ctx, dexImplementationJar, module.BaseModuleName(), dirInApex, javaSharedLib, module)
1518	af.jacocoReportClassesFile = module.JacocoReportClassesFile()
1519	if lintInfo, ok := android.OtherModuleProvider(ctx, module, java.LintProvider); ok {
1520		af.lintInfo = lintInfo
1521	}
1522	af.customStem = module.Stem() + ".jar"
1523	// TODO: b/338641779 - Remove special casing of sdkLibrary once bcpf and sscpf depends
1524	// on the implementation library
1525	if sdkLib, ok := module.(*java.SdkLibrary); ok {
1526		for _, install := range sdkLib.BuiltInstalledForApex() {
1527			af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
1528		}
1529	} else if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
1530		for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() {
1531			af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
1532		}
1533	}
1534	return af
1535}
1536
1537func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile {
1538	if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
1539		if profilePathOnHost := dexpreopter.OutputProfilePathOnHost(); profilePathOnHost != nil {
1540			dirInApex := "javalib"
1541			af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil)
1542			af.customStem = module.Stem() + ".jar.prof"
1543			return &af
1544		}
1545	}
1546	return nil
1547}
1548
1549// androidApp is an interface to handle all app modules (android_app, android_app_import, etc.) in
1550// the same way.
1551type androidApp interface {
1552	android.Module
1553	Privileged() bool
1554	InstallApkName() string
1555	OutputFile() android.Path
1556	JacocoReportClassesFile() android.Path
1557	Certificate() java.Certificate
1558	BaseModuleName() string
1559	PrivAppAllowlist() android.OptionalPath
1560}
1561
1562var _ androidApp = (*java.AndroidApp)(nil)
1563var _ androidApp = (*java.AndroidAppImport)(nil)
1564
1565func sanitizedBuildIdForPath(ctx android.BaseModuleContext) string {
1566	buildId := ctx.Config().BuildId()
1567
1568	// The build ID is used as a suffix for a filename, so ensure that
1569	// the set of characters being used are sanitized.
1570	// - any word character: [a-zA-Z0-9_]
1571	// - dots: .
1572	// - dashes: -
1573	validRegex := regexp.MustCompile(`^[\w\.\-\_]+$`)
1574	if !validRegex.MatchString(buildId) {
1575		ctx.ModuleErrorf("Unable to use build id %s as filename suffix, valid characters are [a-z A-Z 0-9 _ . -].", buildId)
1576	}
1577	return buildId
1578}
1579
1580func apexFilesForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) []apexFile {
1581	appDir := "app"
1582	if aapp.Privileged() {
1583		appDir = "priv-app"
1584	}
1585
1586	// TODO(b/224589412, b/226559955): Ensure that the subdirname is suffixed
1587	// so that PackageManager correctly invalidates the existing installed apk
1588	// in favour of the new APK-in-APEX.  See bugs for more information.
1589	dirInApex := filepath.Join(appDir, aapp.InstallApkName()+"@"+sanitizedBuildIdForPath(ctx))
1590	fileToCopy := aapp.OutputFile()
1591
1592	af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp)
1593	af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
1594	if lintInfo, ok := android.OtherModuleProvider(ctx, aapp, java.LintProvider); ok {
1595		af.lintInfo = lintInfo
1596	}
1597	af.certificate = aapp.Certificate()
1598
1599	if app, ok := aapp.(interface {
1600		OverriddenManifestPackageName() string
1601	}); ok {
1602		af.overriddenPackageName = app.OverriddenManifestPackageName()
1603	}
1604
1605	apexFiles := []apexFile{}
1606
1607	if allowlist := aapp.PrivAppAllowlist(); allowlist.Valid() {
1608		dirInApex := filepath.Join("etc", "permissions")
1609		privAppAllowlist := newApexFile(ctx, allowlist.Path(), aapp.BaseModuleName()+"_privapp", dirInApex, etc, aapp)
1610		apexFiles = append(apexFiles, privAppAllowlist)
1611	}
1612
1613	apexFiles = append(apexFiles, af)
1614
1615	return apexFiles
1616}
1617
1618func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, rro java.RuntimeResourceOverlayModule) apexFile {
1619	rroDir := "overlay"
1620	dirInApex := filepath.Join(rroDir, rro.Theme())
1621	fileToCopy := rro.OutputFile()
1622	af := newApexFile(ctx, fileToCopy, rro.Name(), dirInApex, app, rro)
1623	af.certificate = rro.Certificate()
1624
1625	if a, ok := rro.(interface {
1626		OverriddenManifestPackageName() string
1627	}); ok {
1628		af.overriddenPackageName = a.OverriddenManifestPackageName()
1629	}
1630	return af
1631}
1632
1633func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram bpf.BpfModule) apexFile {
1634	dirInApex := filepath.Join("etc", "bpf", apex_sub_dir)
1635	return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
1636}
1637
1638func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, fs filesystem.Filesystem) apexFile {
1639	dirInApex := filepath.Join("etc", "fs")
1640	return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, fs)
1641}
1642
1643// WalkPayloadDeps visits dependencies that contributes to the payload of this APEX. For each of the
1644// visited module, the `do` callback is executed. Returning true in the callback continues the visit
1645// to the child modules. Returning false makes the visit to continue in the sibling or the parent
1646// modules. This is used in check* functions below.
1647func (a *apexBundle) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) {
1648	ctx.WalkDeps(func(child, parent android.Module) bool {
1649		am, ok := child.(android.ApexModule)
1650		if !ok || !am.CanHaveApexVariants() {
1651			return false
1652		}
1653
1654		// Filter-out unwanted depedendencies
1655		depTag := ctx.OtherModuleDependencyTag(child)
1656		if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
1657			return false
1658		}
1659		if dt, ok := depTag.(*dependencyTag); ok && !dt.payload {
1660			return false
1661		}
1662		if depTag == android.RequiredDepTag {
1663			return false
1664		}
1665
1666		ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
1667		externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
1668
1669		// Visit actually
1670		return do(ctx, parent, am, externalDep)
1671	})
1672}
1673
1674func (a *apexBundle) WalkPayloadDepsProxy(ctx android.BaseModuleContext,
1675	do func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool) {
1676	ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
1677		if !android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey).CanHaveApexVariants {
1678			return false
1679		}
1680		// Filter-out unwanted depedendencies
1681		depTag := ctx.OtherModuleDependencyTag(child)
1682		if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
1683			return false
1684		}
1685		if dt, ok := depTag.(*dependencyTag); ok && !dt.payload {
1686			return false
1687		}
1688		if depTag == android.RequiredDepTag {
1689			return false
1690		}
1691
1692		ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
1693		externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
1694
1695		// Visit actually
1696		return do(ctx, parent, child, externalDep)
1697	})
1698}
1699
1700// filesystem type of the apex_payload.img inside the APEX. Currently, ext4 and f2fs are supported.
1701type fsType int
1702
1703const (
1704	ext4 fsType = iota
1705	f2fs
1706	erofs
1707)
1708
1709func (f fsType) string() string {
1710	switch f {
1711	case ext4:
1712		return ext4FsType
1713	case f2fs:
1714		return f2fsFsType
1715	case erofs:
1716		return erofsFsType
1717	default:
1718		panic(fmt.Errorf("unknown APEX payload type %d", f))
1719	}
1720}
1721
1722func (a *apexBundle) setCompression(ctx android.ModuleContext) {
1723	if a.testOnlyShouldForceCompression() {
1724		a.isCompressed = true
1725	} else {
1726		a.isCompressed = ctx.Config().ApexCompressionEnabled() && a.isCompressable()
1727	}
1728}
1729
1730func (a *apexBundle) setSystemLibLink(ctx android.ModuleContext) {
1731	// Optimization. If we are building bundled APEX, for the files that are gathered due to the
1732	// transitive dependencies, don't place them inside the APEX, but place a symlink pointing
1733	// the same library in the system partition, thus effectively sharing the same libraries
1734	// across the APEX boundary. For unbundled APEX, all the gathered files are actually placed
1735	// in the APEX.
1736	a.linkToSystemLib = !ctx.Config().UnbundledBuild() && a.installable()
1737
1738	// APEXes targeting other than system/system_ext partitions use vendor/product variants.
1739	// So we can't link them to /system/lib libs which are core variants.
1740	if a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
1741		a.linkToSystemLib = false
1742	}
1743
1744	forced := ctx.Config().ForceApexSymlinkOptimization()
1745	updatable := a.Updatable() || a.FutureUpdatable()
1746
1747	// We don't need the optimization for updatable APEXes, as it might give false signal
1748	// to the system health when the APEXes are still bundled (b/149805758).
1749	if !forced && updatable {
1750		a.linkToSystemLib = false
1751	}
1752}
1753
1754func (a *apexBundle) setPayloadFsType(ctx android.ModuleContext) {
1755	defaultFsType := ctx.Config().DefaultApexPayloadType()
1756	switch proptools.StringDefault(a.properties.Payload_fs_type, defaultFsType) {
1757	case ext4FsType:
1758		a.payloadFsType = ext4
1759	case f2fsFsType:
1760		a.payloadFsType = f2fs
1761	case erofsFsType:
1762		a.payloadFsType = erofs
1763	default:
1764		ctx.PropertyErrorf("payload_fs_type", "%q is not a valid filesystem for apex [ext4, f2fs, erofs]", *a.properties.Payload_fs_type)
1765	}
1766}
1767
1768func (a *apexBundle) isCompressable() bool {
1769	if a.testApex {
1770		return false
1771	}
1772	if a.payloadFsType == erofs {
1773		return false
1774	}
1775	return proptools.Bool(a.overridableProperties.Compressible)
1776}
1777
1778func (a *apexBundle) commonBuildActions(ctx android.ModuleContext) bool {
1779	a.checkApexAvailability(ctx)
1780	a.checkUpdatable(ctx)
1781	a.CheckMinSdkVersion(ctx)
1782	a.checkStaticLinkingToStubLibraries(ctx)
1783	a.checkStaticExecutables(ctx)
1784	a.enforceAppUpdatability(ctx)
1785	if len(a.properties.Tests) > 0 && !a.testApex {
1786		ctx.PropertyErrorf("tests", "property allowed only in apex_test module type")
1787		return false
1788	}
1789	return true
1790}
1791
1792type visitorContext struct {
1793	// all the files that will be included in this APEX
1794	filesInfo []apexFile
1795
1796	// native lib dependencies
1797	provideNativeLibs []string
1798	requireNativeLibs []string
1799
1800	handleSpecialLibs bool
1801
1802	// if true, raise error on duplicate apexFile
1803	checkDuplicate bool
1804
1805	// visitor skips these from this list of module names
1806	unwantedTransitiveDeps []string
1807
1808	// unwantedTransitiveFilesInfo contains files that would have been in the apex
1809	// except that they were listed in unwantedTransitiveDeps.
1810	unwantedTransitiveFilesInfo []apexFile
1811
1812	// duplicateTransitiveFilesInfo contains files that would ahve been in the apex
1813	// except that another variant of the same module was already in the apex.
1814	duplicateTransitiveFilesInfo []apexFile
1815}
1816
1817func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) {
1818	encountered := make(map[string]apexFile)
1819	for _, f := range vctx.filesInfo {
1820		// Skips unwanted transitive deps. This happens, for example, with Rust binaries with prefer_rlib:true.
1821		// TODO(b/295593640)
1822		// Needs additional verification for the resulting APEX to ensure that skipped artifacts don't make problems.
1823		// For example, DT_NEEDED modules should be found within the APEX unless they are marked in `requiredNativeLibs`.
1824		if f.transitiveDep && f.module != nil && android.InList(mctx.OtherModuleName(f.module), vctx.unwantedTransitiveDeps) {
1825			vctx.unwantedTransitiveFilesInfo = append(vctx.unwantedTransitiveFilesInfo, f)
1826			continue
1827		}
1828		dest := filepath.Join(f.installDir, f.builtFile.Base())
1829		if e, ok := encountered[dest]; !ok {
1830			encountered[dest] = f
1831		} else {
1832			if vctx.checkDuplicate && f.builtFile.String() != e.builtFile.String() {
1833				mctx.ModuleErrorf("apex file %v is provided by two different files %v and %v",
1834					dest, e.builtFile, f.builtFile)
1835				return
1836			} else {
1837				vctx.duplicateTransitiveFilesInfo = append(vctx.duplicateTransitiveFilesInfo, f)
1838			}
1839			// If a module is directly included and also transitively depended on
1840			// consider it as directly included.
1841			e.transitiveDep = e.transitiveDep && f.transitiveDep
1842			// If a module is added as both a JNI library and a regular shared library, consider it as a
1843			// JNI library.
1844			e.isJniLib = e.isJniLib || f.isJniLib
1845			encountered[dest] = e
1846		}
1847	}
1848	vctx.filesInfo = vctx.filesInfo[:0]
1849	for _, v := range encountered {
1850		vctx.filesInfo = append(vctx.filesInfo, v)
1851	}
1852
1853	sort.Slice(vctx.filesInfo, func(i, j int) bool {
1854		// Sort by destination path so as to ensure consistent ordering even if the source of the files
1855		// changes.
1856		return vctx.filesInfo[i].path() < vctx.filesInfo[j].path()
1857	})
1858}
1859
1860// enforcePartitionTagOnApexSystemServerJar checks that the partition tags of an apex system server jar  matches
1861// the partition tags of the top-level apex.
1862// e.g. if the top-level apex sets system_ext_specific to true, the javalib must set this property to true as well.
1863// This check ensures that the dexpreopt artifacts of the apex system server jar is installed in the same partition
1864// as the apex.
1865func (a *apexBundle) enforcePartitionTagOnApexSystemServerJar(ctx android.ModuleContext) {
1866	global := dexpreopt.GetGlobalConfig(ctx)
1867	ctx.VisitDirectDepsProxyWithTag(sscpfTag, func(child android.ModuleProxy) {
1868		info, ok := android.OtherModuleProvider(ctx, child, java.LibraryNameToPartitionInfoProvider)
1869		if !ok {
1870			ctx.ModuleErrorf("Could not find partition info of apex system server jars.")
1871		}
1872		apexPartition := ctx.Module().PartitionTag(ctx.DeviceConfig())
1873		for javalib, javalibPartition := range info.LibraryNameToPartition {
1874			if !global.AllApexSystemServerJars(ctx).ContainsJar(javalib) {
1875				continue // not an apex system server jar
1876			}
1877			if apexPartition != javalibPartition {
1878				ctx.ModuleErrorf(`
1879%s is an apex systemserver jar, but its partition does not match the partition of its containing apex. Expected %s, Got %s`,
1880					javalib, apexPartition, javalibPartition)
1881			}
1882		}
1883	})
1884}
1885
1886func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent android.Module) bool {
1887	depTag := ctx.OtherModuleDependencyTag(child)
1888	if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
1889		return false
1890	}
1891	if !child.Enabled(ctx) {
1892		return false
1893	}
1894	depName := ctx.OtherModuleName(child)
1895	if _, isDirectDep := parent.(*apexBundle); isDirectDep {
1896		switch depTag {
1897		case sharedLibTag, jniLibTag:
1898			isJniLib := depTag == jniLibTag
1899			propertyName := "native_shared_libs"
1900			if isJniLib {
1901				propertyName = "jni_libs"
1902			}
1903			switch ch := child.(type) {
1904			case *cc.Module:
1905				if ch.IsStubs() {
1906					ctx.PropertyErrorf(propertyName, "%q is a stub. Remove it from the list.", depName)
1907				}
1908				fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
1909				fi.isJniLib = isJniLib
1910				vctx.filesInfo = append(vctx.filesInfo, fi)
1911				// Collect the list of stub-providing libs except:
1912				// - VNDK libs are only for vendors
1913				// - bootstrap bionic libs are treated as provided by system
1914				if ch.HasStubsVariants() && !a.vndkApex && !cc.InstallToBootstrap(ch.BaseModuleName(), ctx.Config()) {
1915					vctx.provideNativeLibs = append(vctx.provideNativeLibs, fi.stem())
1916				}
1917				return true // track transitive dependencies
1918			case *rust.Module:
1919				fi := apexFileForRustLibrary(ctx, ch)
1920				fi.isJniLib = isJniLib
1921				vctx.filesInfo = append(vctx.filesInfo, fi)
1922				return true // track transitive dependencies
1923			default:
1924				ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
1925			}
1926		case executableTag:
1927			switch ch := child.(type) {
1928			case *cc.Module:
1929				vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch))
1930				return true // track transitive dependencies
1931			case *rust.Module:
1932				vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch))
1933				return true // track transitive dependencies
1934			default:
1935				ctx.PropertyErrorf("binaries",
1936					"%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, nor (host) bootstrap_go_binary", depName)
1937			}
1938		case shBinaryTag:
1939			if csh, ok := child.(*sh.ShBinary); ok {
1940				vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, csh))
1941			} else {
1942				ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName)
1943			}
1944		case bcpfTag:
1945			_, ok := child.(*java.BootclasspathFragmentModule)
1946			if !ok {
1947				ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a bootclasspath_fragment module", depName)
1948				return false
1949			}
1950
1951			vctx.filesInfo = append(vctx.filesInfo, apexBootclasspathFragmentFiles(ctx, child)...)
1952			return true
1953		case sscpfTag:
1954			if _, ok := child.(*java.SystemServerClasspathModule); !ok {
1955				ctx.PropertyErrorf("systemserverclasspath_fragments",
1956					"%q is not a systemserverclasspath_fragment module", depName)
1957				return false
1958			}
1959			if af := apexClasspathFragmentProtoFile(ctx, child); af != nil {
1960				vctx.filesInfo = append(vctx.filesInfo, *af)
1961			}
1962			return true
1963		case javaLibTag:
1964			switch child.(type) {
1965			case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
1966				af := apexFileForJavaModule(ctx, child.(javaModule))
1967				if !af.ok() {
1968					ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
1969					return false
1970				}
1971				vctx.filesInfo = append(vctx.filesInfo, af)
1972				return true // track transitive dependencies
1973			default:
1974				ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
1975			}
1976		case androidAppTag:
1977			switch ap := child.(type) {
1978			case *java.AndroidApp:
1979				vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
1980				return true // track transitive dependencies
1981			case *java.AndroidAppImport:
1982				vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
1983			case *java.AndroidTestHelperApp:
1984				vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
1985			case *java.AndroidAppSet:
1986				appDir := "app"
1987				if ap.Privileged() {
1988					appDir = "priv-app"
1989				}
1990				// TODO(b/224589412, b/226559955): Ensure that the dirname is
1991				// suffixed so that PackageManager correctly invalidates the
1992				// existing installed apk in favour of the new APK-in-APEX.
1993				// See bugs for more information.
1994				appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+sanitizedBuildIdForPath(ctx))
1995				af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap)
1996				af.certificate = java.PresignedCertificate
1997				vctx.filesInfo = append(vctx.filesInfo, af)
1998			default:
1999				ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
2000			}
2001		case rroTag:
2002			if rro, ok := child.(java.RuntimeResourceOverlayModule); ok {
2003				vctx.filesInfo = append(vctx.filesInfo, apexFileForRuntimeResourceOverlay(ctx, rro))
2004			} else {
2005				ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName)
2006			}
2007		case bpfTag:
2008			if bpfProgram, ok := child.(bpf.BpfModule); ok {
2009				filesToCopy := android.OutputFilesForModule(ctx, bpfProgram, "")
2010				apex_sub_dir := bpfProgram.SubDir()
2011				for _, bpfFile := range filesToCopy {
2012					vctx.filesInfo = append(vctx.filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram))
2013				}
2014			} else {
2015				ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
2016			}
2017		case fsTag:
2018			if fs, ok := child.(filesystem.Filesystem); ok {
2019				vctx.filesInfo = append(vctx.filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs))
2020			} else {
2021				ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName)
2022			}
2023		case prebuiltTag:
2024			if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
2025				filesToCopy := android.OutputFilesForModule(ctx, prebuilt, "")
2026				for _, etcFile := range filesToCopy {
2027					vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
2028				}
2029			} else {
2030				ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
2031			}
2032		case compatConfigTag:
2033			if compatConfig, ok := child.(java.PlatformCompatConfigIntf); ok {
2034				vctx.filesInfo = append(vctx.filesInfo, apexFileForCompatConfig(ctx, compatConfig, depName))
2035			} else {
2036				ctx.PropertyErrorf("compat_configs", "%q is not a platform_compat_config module", depName)
2037			}
2038		case testTag:
2039			if ccTest, ok := child.(*cc.Module); ok {
2040				af := apexFileForExecutable(ctx, ccTest)
2041				af.class = nativeTest
2042				vctx.filesInfo = append(vctx.filesInfo, af)
2043				return true // track transitive dependencies
2044			} else {
2045				ctx.PropertyErrorf("tests", "%q is not a cc module", depName)
2046			}
2047		case keyTag:
2048			if key, ok := child.(*apexKey); ok {
2049				a.privateKeyFile = key.privateKeyFile
2050				a.publicKeyFile = key.publicKeyFile
2051			} else {
2052				ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
2053			}
2054		case certificateTag:
2055			if dep, ok := child.(*java.AndroidAppCertificate); ok {
2056				a.containerCertificateFile = dep.Certificate.Pem
2057				a.containerPrivateKeyFile = dep.Certificate.Key
2058			} else {
2059				ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
2060			}
2061		}
2062		return false
2063	}
2064
2065	if a.vndkApex {
2066		return false
2067	}
2068
2069	// indirect dependencies
2070	am, ok := child.(android.ApexModule)
2071	if !ok {
2072		return false
2073	}
2074	// We cannot use a switch statement on `depTag` here as the checked
2075	// tags used below are private (e.g. `cc.sharedDepTag`).
2076	if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
2077		if ch, ok := child.(*cc.Module); ok {
2078			af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
2079			af.transitiveDep = true
2080
2081			if ch.IsStubs() || ch.HasStubsVariants() {
2082				// If the dependency is a stubs lib, don't include it in this APEX,
2083				// but make sure that the lib is installed on the device.
2084				// In case no APEX is having the lib, the lib is installed to the system
2085				// partition.
2086				//
2087				// Always include if we are a host-apex however since those won't have any
2088				// system libraries.
2089				//
2090				// Skip the dependency in unbundled builds where the device image is not
2091				// being built.
2092				if ch.IsStubsImplementationRequired() && !am.NotInPlatform() && !ctx.Config().UnbundledBuild() {
2093					// we need a module name for Make
2094					name := ch.ImplementationModuleNameForMake(ctx) + ch.Properties.SubName
2095					if !android.InList(name, a.makeModulesToInstall) {
2096						a.makeModulesToInstall = append(a.makeModulesToInstall, name)
2097					}
2098				}
2099				vctx.requireNativeLibs = append(vctx.requireNativeLibs, af.stem())
2100				// Don't track further
2101				return false
2102			}
2103
2104			// If the dep is not considered to be in the same
2105			// apex, don't add it to filesInfo so that it is not
2106			// included in this APEX.
2107			// TODO(jiyong): move this to at the top of the
2108			// else-if clause for the indirect dependencies.
2109			// Currently, that's impossible because we would
2110			// like to record requiredNativeLibs even when
2111			// DepIsInSameAPex is false. We also shouldn't do
2112			// this for host.
2113			//
2114			// TODO(jiyong): explain why the same module is passed in twice.
2115			// Switching the first am to parent breaks lots of tests.
2116			if !android.IsDepInSameApex(ctx, am, am) {
2117				return false
2118			}
2119
2120			vctx.filesInfo = append(vctx.filesInfo, af)
2121			return true // track transitive dependencies
2122		} else if rm, ok := child.(*rust.Module); ok {
2123			if !android.IsDepInSameApex(ctx, am, am) {
2124				return false
2125			}
2126
2127			af := apexFileForRustLibrary(ctx, rm)
2128			af.transitiveDep = true
2129			vctx.filesInfo = append(vctx.filesInfo, af)
2130			return true // track transitive dependencies
2131		}
2132	} else if cc.IsHeaderDepTag(depTag) {
2133		// nothing
2134	} else if java.IsJniDepTag(depTag) {
2135		// Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
2136	} else if java.IsXmlPermissionsFileDepTag(depTag) {
2137		if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
2138			filesToCopy := android.OutputFilesForModule(ctx, prebuilt, "")
2139			for _, etcFile := range filesToCopy {
2140				vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
2141			}
2142		}
2143	} else if rust.IsDylibDepTag(depTag) {
2144		if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
2145			if !android.IsDepInSameApex(ctx, am, am) {
2146				return false
2147			}
2148
2149			af := apexFileForRustLibrary(ctx, rustm)
2150			af.transitiveDep = true
2151			vctx.filesInfo = append(vctx.filesInfo, af)
2152			return true // track transitive dependencies
2153		}
2154	} else if rust.IsRlibDepTag(depTag) {
2155		// Rlib is statically linked, but it might have shared lib
2156		// dependencies. Track them.
2157		return true
2158	} else if java.IsBootclasspathFragmentContentDepTag(depTag) {
2159		// Add the contents of the bootclasspath fragment to the apex.
2160		switch child.(type) {
2161		case *java.Library, *java.SdkLibrary:
2162			javaModule := child.(javaModule)
2163			af := apexFileForBootclasspathFragmentContentModule(ctx, parent, javaModule)
2164			if !af.ok() {
2165				ctx.PropertyErrorf("bootclasspath_fragments",
2166					"bootclasspath_fragment content %q is not configured to be compiled into dex", depName)
2167				return false
2168			}
2169			vctx.filesInfo = append(vctx.filesInfo, af)
2170			return true // track transitive dependencies
2171		default:
2172			ctx.PropertyErrorf("bootclasspath_fragments",
2173				"bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
2174		}
2175	} else if java.IsSystemServerClasspathFragmentContentDepTag(depTag) {
2176		// Add the contents of the systemserverclasspath fragment to the apex.
2177		switch child.(type) {
2178		case *java.Library, *java.SdkLibrary:
2179			af := apexFileForJavaModule(ctx, child.(javaModule))
2180			vctx.filesInfo = append(vctx.filesInfo, af)
2181			if profileAf := apexFileForJavaModuleProfile(ctx, child.(javaModule)); profileAf != nil {
2182				vctx.filesInfo = append(vctx.filesInfo, *profileAf)
2183			}
2184			return true // track transitive dependencies
2185		default:
2186			ctx.PropertyErrorf("systemserverclasspath_fragments",
2187				"systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
2188		}
2189	} else if depTag == android.DarwinUniversalVariantTag {
2190		// nothing
2191	} else if depTag == android.RequiredDepTag {
2192		// nothing
2193	} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
2194		ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
2195	}
2196	return false
2197}
2198
2199func (a *apexBundle) shouldCheckDuplicate(ctx android.ModuleContext) bool {
2200	// TODO(b/263308293) remove this
2201	if a.properties.IsCoverageVariant {
2202		return false
2203	}
2204	if ctx.DeviceConfig().DeviceArch() == "" {
2205		return false
2206	}
2207	return true
2208}
2209
2210// Creates build rules for an APEX. It consists of the following major steps:
2211//
2212// 1) do some validity checks such as apex_available, min_sdk_version, etc.
2213// 2) traverse the dependency tree to collect apexFile structs from them.
2214// 3) some fields in apexBundle struct are configured
2215// 4) generate the build rules to create the APEX. This is mostly done in builder.go.
2216func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
2217	////////////////////////////////////////////////////////////////////////////////////////////
2218	// 1) do some validity checks such as apex_available, min_sdk_version, etc.
2219	if !a.commonBuildActions(ctx) {
2220		return
2221	}
2222	////////////////////////////////////////////////////////////////////////////////////////////
2223	// 2) traverse the dependency tree to collect apexFile structs from them.
2224
2225	// TODO(jiyong): do this using WalkPayloadDeps
2226	// TODO(jiyong): make this clean!!!
2227	vctx := visitorContext{
2228		handleSpecialLibs:      !android.Bool(a.properties.Ignore_system_library_special_case),
2229		checkDuplicate:         a.shouldCheckDuplicate(ctx),
2230		unwantedTransitiveDeps: a.properties.Unwanted_transitive_deps,
2231	}
2232	ctx.WalkDeps(func(child, parent android.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
2233	vctx.normalizeFileInfo(ctx)
2234	if a.privateKeyFile == nil {
2235		if ctx.Config().AllowMissingDependencies() {
2236			// TODO(b/266099037): a better approach for slim manifests.
2237			ctx.AddMissingDependencies([]string{String(a.overridableProperties.Key)})
2238			// Create placeholder paths for later stages that expect to see those paths,
2239			// though they won't be used.
2240			var unusedPath = android.PathForModuleOut(ctx, "nonexistentprivatekey")
2241			ctx.Build(pctx, android.BuildParams{
2242				Rule:   android.ErrorRule,
2243				Output: unusedPath,
2244				Args: map[string]string{
2245					"error": "Private key not available",
2246				},
2247			})
2248			a.privateKeyFile = unusedPath
2249		} else {
2250			ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.overridableProperties.Key))
2251			return
2252		}
2253	}
2254
2255	if a.publicKeyFile == nil {
2256		if ctx.Config().AllowMissingDependencies() {
2257			// TODO(b/266099037): a better approach for slim manifests.
2258			ctx.AddMissingDependencies([]string{String(a.overridableProperties.Key)})
2259			// Create placeholder paths for later stages that expect to see those paths,
2260			// though they won't be used.
2261			var unusedPath = android.PathForModuleOut(ctx, "nonexistentpublickey")
2262			ctx.Build(pctx, android.BuildParams{
2263				Rule:   android.ErrorRule,
2264				Output: unusedPath,
2265				Args: map[string]string{
2266					"error": "Public key not available",
2267				},
2268			})
2269			a.publicKeyFile = unusedPath
2270		} else {
2271			ctx.PropertyErrorf("key", "public_key for %q could not be found", String(a.overridableProperties.Key))
2272			return
2273		}
2274	}
2275
2276	////////////////////////////////////////////////////////////////////////////////////////////
2277	// 3) some fields in apexBundle struct are configured
2278	a.installDir = android.PathForModuleInstall(ctx, "apex")
2279	a.filesInfo = vctx.filesInfo
2280	a.unwantedTransitiveFilesInfo = vctx.unwantedTransitiveFilesInfo
2281	a.duplicateTransitiveFilesInfo = vctx.duplicateTransitiveFilesInfo
2282
2283	a.setPayloadFsType(ctx)
2284	a.setSystemLibLink(ctx)
2285	a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
2286
2287	////////////////////////////////////////////////////////////////////////////////////////////
2288	// 3.a) some artifacts are generated from the collected files
2289	a.filesInfo = append(a.filesInfo, a.buildAconfigFiles(ctx)...)
2290
2291	////////////////////////////////////////////////////////////////////////////////////////////
2292	// 4) generate the build rules to create the APEX. This is done in builder.go.
2293	a.buildManifest(ctx, vctx.provideNativeLibs, vctx.requireNativeLibs)
2294	a.buildApex(ctx)
2295	a.buildApexDependencyInfo(ctx)
2296	a.buildLintReports(ctx)
2297
2298	// Set a provider for dexpreopt of bootjars
2299	a.provideApexExportsInfo(ctx)
2300
2301	a.providePrebuiltInfo(ctx)
2302
2303	a.required = a.RequiredModuleNames(ctx)
2304	a.required = append(a.required, a.VintfFragmentModuleNames(ctx)...)
2305
2306	a.setOutputFiles(ctx)
2307	a.enforcePartitionTagOnApexSystemServerJar(ctx)
2308
2309	a.verifyNativeImplementationLibs(ctx)
2310}
2311
2312// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
2313// with information about whether source or prebuilt of an apex was used during the build.
2314func (a *apexBundle) providePrebuiltInfo(ctx android.ModuleContext) {
2315	info := android.PrebuiltInfo{
2316		Name:        a.Name(),
2317		Is_prebuilt: false,
2318	}
2319	android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
2320}
2321
2322// Set a provider containing information about the jars and .prof provided by the apex
2323// Apexes built from source retrieve this information by visiting `bootclasspath_fragments`
2324// Used by dex_bootjars to generate the boot image
2325func (a *apexBundle) provideApexExportsInfo(ctx android.ModuleContext) {
2326	ctx.VisitDirectDepsProxyWithTag(bcpfTag, func(child android.ModuleProxy) {
2327		if info, ok := android.OtherModuleProvider(ctx, child, java.BootclasspathFragmentApexContentInfoProvider); ok {
2328			exports := android.ApexExportsInfo{
2329				ApexName:                      a.ApexVariationName(),
2330				ProfilePathOnHost:             info.ProfilePathOnHost(),
2331				LibraryNameToDexJarPathOnHost: info.DexBootJarPathMap(),
2332			}
2333			android.SetProvider(ctx, android.ApexExportsInfoProvider, exports)
2334		}
2335	})
2336}
2337
2338// Set output files to outputFiles property, which is later used to set the
2339// OutputFilesProvider
2340func (a *apexBundle) setOutputFiles(ctx android.ModuleContext) {
2341	// default dist path
2342	ctx.SetOutputFiles(android.Paths{a.outputFile}, "")
2343	ctx.SetOutputFiles(android.Paths{a.outputFile}, android.DefaultDistTag)
2344	// uncompressed one
2345	if a.outputApexFile != nil {
2346		ctx.SetOutputFiles(android.Paths{a.outputApexFile}, imageApexSuffix)
2347	}
2348}
2349
2350// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
2351func (a *apexBundle) enforceAppUpdatability(mctx android.ModuleContext) {
2352	if !a.Enabled(mctx) {
2353		return
2354	}
2355	if a.Updatable() {
2356		// checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults
2357		mctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
2358			if appInfo, ok := android.OtherModuleProvider(mctx, module, java.AppInfoProvider); ok {
2359				// ignore android_test_app
2360				if !appInfo.TestHelperApp && !appInfo.Updatable {
2361					mctx.ModuleErrorf("app dependency %s must have updatable: true", mctx.OtherModuleName(module))
2362				}
2363			}
2364		})
2365	}
2366}
2367
2368// apexBootclasspathFragmentFiles returns the list of apexFile structures defining the files that
2369// the bootclasspath_fragment contributes to the apex.
2370func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.Module) []apexFile {
2371	bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, module, java.BootclasspathFragmentApexContentInfoProvider)
2372	var filesToAdd []apexFile
2373
2374	// Add classpaths.proto config.
2375	if af := apexClasspathFragmentProtoFile(ctx, module); af != nil {
2376		filesToAdd = append(filesToAdd, *af)
2377	}
2378
2379	pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex()
2380	if pathInApex != "" {
2381		pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost()
2382		tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex)
2383
2384		if pathOnHost != nil {
2385			// We need to copy the profile to a temporary path with the right filename because the apexer
2386			// will take the filename as is.
2387			ctx.Build(pctx, android.BuildParams{
2388				Rule:   android.Cp,
2389				Input:  pathOnHost,
2390				Output: tempPath,
2391			})
2392		} else {
2393			// At this point, the boot image profile cannot be generated. It is probably because the boot
2394			// image profile source file does not exist on the branch, or it is not available for the
2395			// current build target.
2396			// However, we cannot enforce the boot image profile to be generated because some build
2397			// targets (such as module SDK) do not need it. It is only needed when the APEX is being
2398			// built. Therefore, we create an error rule so that an error will occur at the ninja phase
2399			// only if the APEX is being built.
2400			ctx.Build(pctx, android.BuildParams{
2401				Rule:   android.ErrorRule,
2402				Output: tempPath,
2403				Args: map[string]string{
2404					"error": "Boot image profile cannot be generated",
2405				},
2406			})
2407		}
2408
2409		androidMkModuleName := filepath.Base(pathInApex)
2410		af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, nil)
2411		filesToAdd = append(filesToAdd, af)
2412	}
2413
2414	return filesToAdd
2415}
2416
2417// apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that
2418// the module contributes to the apex; or nil if the proto config was not generated.
2419func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) *apexFile {
2420	info, _ := android.OtherModuleProvider(ctx, module, java.ClasspathFragmentProtoContentInfoProvider)
2421	if !info.ClasspathFragmentProtoGenerated {
2422		return nil
2423	}
2424	classpathProtoOutput := info.ClasspathFragmentProtoOutput
2425	af := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), info.ClasspathFragmentProtoInstallDir.Rel(), etc, nil)
2426	return &af
2427}
2428
2429// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment
2430// content module, i.e. a library that is part of the bootclasspath.
2431func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule blueprint.Module, javaModule javaModule) apexFile {
2432	bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragmentModule, java.BootclasspathFragmentApexContentInfoProvider)
2433
2434	// Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the
2435	// hidden API encpding.
2436	dexBootJar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule)
2437	if err != nil {
2438		ctx.ModuleErrorf("%s", err)
2439	}
2440
2441	// Create an apexFile as for a normal java module but with the dex boot jar provided by the
2442	// bootclasspath_fragment.
2443	af := apexFileForJavaModuleWithFile(ctx, javaModule, dexBootJar)
2444	return af
2445}
2446
2447///////////////////////////////////////////////////////////////////////////////////////////////////
2448// Factory functions
2449//
2450
2451func newApexBundle() *apexBundle {
2452	module := &apexBundle{}
2453
2454	module.AddProperties(&module.properties)
2455	module.AddProperties(&module.targetProperties)
2456	module.AddProperties(&module.archProperties)
2457	module.AddProperties(&module.overridableProperties)
2458
2459	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
2460	android.InitDefaultableModule(module)
2461	android.InitOverridableModule(module, &module.overridableProperties.Overrides)
2462	return module
2463}
2464
2465type apexTestProperties struct {
2466	// Boolean flags for validation checks. Test APEXes can turn on/off individual checks.
2467	Skip_validations struct {
2468		// Skips `Apex_sepolicy_tests` check if true
2469		Apex_sepolicy_tests *bool
2470		// Skips `Host_apex_verifier` check if true
2471		Host_apex_verifier *bool
2472	}
2473}
2474
2475// apex_test is an APEX for testing. The difference from the ordinary apex module type is that
2476// certain compatibility checks such as apex_available are not done for apex_test.
2477func TestApexBundleFactory() android.Module {
2478	bundle := newApexBundle()
2479	bundle.testApex = true
2480	bundle.AddProperties(&bundle.testProperties)
2481	return bundle
2482}
2483
2484// apex packages other modules into an APEX file which is a packaging format for system-level
2485// components like binaries, shared libraries, etc.
2486func BundleFactory() android.Module {
2487	return newApexBundle()
2488}
2489
2490type Defaults struct {
2491	android.ModuleBase
2492	android.DefaultsModuleBase
2493}
2494
2495// apex_defaults provides defaultable properties to other apex modules.
2496func DefaultsFactory() android.Module {
2497	module := &Defaults{}
2498
2499	module.AddProperties(
2500		&apexBundleProperties{},
2501		&apexTargetBundleProperties{},
2502		&apexArchBundleProperties{},
2503		&overridableProperties{},
2504	)
2505
2506	android.InitDefaultsModule(module)
2507	return module
2508}
2509
2510type OverrideApex struct {
2511	android.ModuleBase
2512	android.OverrideModuleBase
2513}
2514
2515func (o *OverrideApex) GenerateAndroidBuildActions(_ android.ModuleContext) {
2516	// All the overrides happen in the base module.
2517}
2518
2519// override_apex is used to create an apex module based on another apex module by overriding some of
2520// its properties.
2521func OverrideApexFactory() android.Module {
2522	m := &OverrideApex{}
2523
2524	m.AddProperties(&overridableProperties{})
2525
2526	android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
2527	android.InitOverrideModule(m)
2528	return m
2529}
2530
2531///////////////////////////////////////////////////////////////////////////////////////////////////
2532// Vality check routines
2533//
2534// These are called in at the very beginning of GenerateAndroidBuildActions to flag an error when
2535// certain conditions are not met.
2536//
2537// TODO(jiyong): move these checks to a separate go file.
2538
2539var _ android.ModuleWithMinSdkVersionCheck = (*apexBundle)(nil)
2540
2541// Ensures that min_sdk_version of the included modules are equal or less than the min_sdk_version
2542// of this apexBundle.
2543func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) {
2544	if a.testApex || a.vndkApex {
2545		return
2546	}
2547	// apexBundle::minSdkVersion reports its own errors.
2548	minSdkVersion := a.minSdkVersion(ctx)
2549	android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
2550}
2551
2552// Returns apex's min_sdk_version string value, honoring overrides
2553func (a *apexBundle) minSdkVersionValue(ctx android.EarlyModuleContext) string {
2554	// Only override the minSdkVersion value on Apexes which already specify
2555	// a min_sdk_version (it's optional for non-updatable apexes), and that its
2556	// min_sdk_version value is lower than the one to override with.
2557	minApiLevel := android.MinSdkVersionFromValue(ctx, proptools.String(a.overridableProperties.Min_sdk_version))
2558	if minApiLevel.IsNone() {
2559		return ""
2560	}
2561
2562	overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride()
2563	overrideApiLevel := android.MinSdkVersionFromValue(ctx, overrideMinSdkValue)
2564	if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(minApiLevel) > 0 {
2565		minApiLevel = overrideApiLevel
2566	}
2567
2568	return minApiLevel.String()
2569}
2570
2571// Returns apex's min_sdk_version SdkSpec, honoring overrides
2572func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
2573	return a.minSdkVersion(ctx)
2574}
2575
2576// Returns apex's min_sdk_version ApiLevel, honoring overrides
2577func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
2578	return android.MinSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
2579}
2580
2581// Ensures that a lib providing stub isn't statically linked
2582func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext) {
2583	// Practically, we only care about regular APEXes on the device.
2584	if a.testApex || a.vndkApex {
2585		return
2586	}
2587
2588	librariesDirectlyInApex := make(map[string]bool)
2589	ctx.VisitDirectDepsProxyWithTag(sharedLibTag, func(dep android.ModuleProxy) {
2590		librariesDirectlyInApex[ctx.OtherModuleName(dep)] = true
2591	})
2592
2593	a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
2594		if ccInfo, ok := android.OtherModuleProvider(ctx, to, cc.CcInfoProvider); ok {
2595			// If `to` is not actually in the same APEX as `from` then it does not need
2596			// apex_available and neither do any of its dependencies.
2597			if externalDep {
2598				// As soon as the dependency graph crosses the APEX boundary, don't go further.
2599				return false
2600			}
2601
2602			apexName := ctx.ModuleName()
2603			fromName := ctx.OtherModuleName(from)
2604			toName := ctx.OtherModuleName(to)
2605
2606			// The dynamic linker and crash_dump tool in the runtime APEX is the only
2607			// exception to this rule. It can't make the static dependencies dynamic
2608			// because it can't do the dynamic linking for itself.
2609			// Same rule should be applied to linkerconfig, because it should be executed
2610			// only with static linked libraries before linker is available with ld.config.txt
2611			if apexName == "com.android.runtime" && (fromName == "linker" || fromName == "crash_dump" || fromName == "linkerconfig") {
2612				return false
2613			}
2614
2615			isStubLibraryFromOtherApex := ccInfo.HasStubsVariants && !librariesDirectlyInApex[toName]
2616			if isStubLibraryFromOtherApex && !externalDep {
2617				ctx.ModuleErrorf("%q required by %q is a native library providing stub. "+
2618					"It shouldn't be included in this APEX via static linking. Dependency path: %s", to.String(), fromName, ctx.GetPathString(false))
2619			}
2620		}
2621		return true
2622	})
2623}
2624
2625// checkUpdatable enforces APEX and its transitive dep properties to have desired values for updatable APEXes.
2626func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
2627	if a.Updatable() {
2628		if a.minSdkVersionValue(ctx) == "" {
2629			ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
2630		}
2631		if a.minSdkVersion(ctx).IsCurrent() {
2632			ctx.PropertyErrorf("updatable", "updatable APEXes should not set min_sdk_version to current. Please use a finalized API level or a recognized in-development codename")
2633		}
2634		if a.UsePlatformApis() {
2635			ctx.PropertyErrorf("updatable", "updatable APEXes can't use platform APIs")
2636		}
2637		if a.FutureUpdatable() {
2638			ctx.PropertyErrorf("future_updatable", "Already updatable. Remove `future_updatable: true:`")
2639		}
2640		a.checkJavaStableSdkVersion(ctx)
2641		a.checkClasspathFragments(ctx)
2642	}
2643}
2644
2645// checkClasspathFragments enforces that all classpath fragments in deps generate classpaths.proto config.
2646func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) {
2647	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
2648		if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag {
2649			info, _ := android.OtherModuleProvider(ctx, module, java.ClasspathFragmentProtoContentInfoProvider)
2650			if !info.ClasspathFragmentProtoGenerated {
2651				ctx.OtherModuleErrorf(module, "is included in updatable apex %v, it must not set generate_classpaths_proto to false", ctx.ModuleName())
2652			}
2653		}
2654	})
2655}
2656
2657// checkJavaStableSdkVersion enforces that all Java deps are using stable SDKs to compile.
2658func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) {
2659	// Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs,
2660	// java's checkLinkType guarantees correct usage for transitive deps
2661	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
2662		tag := ctx.OtherModuleDependencyTag(module)
2663		switch tag {
2664		case javaLibTag, androidAppTag:
2665			if err := java.CheckStableSdkVersion(ctx, module); err != nil {
2666				ctx.ModuleErrorf("cannot depend on \"%v\": %v", ctx.OtherModuleName(module), err)
2667			}
2668		}
2669	})
2670}
2671
2672// checkApexAvailability ensures that the all the dependencies are marked as available for this APEX.
2673func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
2674	// Let's be practical. Availability for test, host, and the VNDK apex isn't important
2675	if a.testApex || a.vndkApex {
2676		return
2677	}
2678
2679	// Because APEXes targeting other than system/system_ext partitions can't set
2680	// apex_available, we skip checks for these APEXes
2681	if a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
2682		return
2683	}
2684
2685	// Temporarily bypass /product APEXes with a specific prefix.
2686	// TODO: b/352818241 - Remove this after APEX availability is enforced for /product APEXes.
2687	if a.ProductSpecific() && strings.HasPrefix(a.ApexVariationName(), "com.sdv.") {
2688		return
2689	}
2690
2691	// Coverage build adds additional dependencies for the coverage-only runtime libraries.
2692	// Requiring them and their transitive depencies with apex_available is not right
2693	// because they just add noise.
2694	if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") || a.IsNativeCoverageNeeded(ctx) {
2695		return
2696	}
2697
2698	a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
2699		// As soon as the dependency graph crosses the APEX boundary, don't go further.
2700		if externalDep {
2701			return false
2702		}
2703
2704		apexName := ctx.ModuleName()
2705		for _, props := range ctx.Module().GetProperties() {
2706			if apexProps, ok := props.(*apexBundleProperties); ok {
2707				if apexProps.Apex_available_name != nil {
2708					apexName = *apexProps.Apex_available_name
2709				}
2710			}
2711		}
2712		fromName := ctx.OtherModuleName(from)
2713		toName := ctx.OtherModuleName(to)
2714
2715		// If `to` is not actually in the same APEX as `from` then it does not need
2716		// apex_available and neither do any of its dependencies.
2717		//
2718		// It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps().
2719		if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
2720			// As soon as the dependency graph crosses the APEX boundary, don't go
2721			// further.
2722			return false
2723		}
2724
2725		if to.AvailableFor(apexName) {
2726			return true
2727		}
2728
2729		// Let's give some hint for apex_available
2730		hint := fmt.Sprintf("%q", apexName)
2731
2732		if strings.HasPrefix(apexName, "com.") && !strings.HasPrefix(apexName, "com.android.") && strings.Count(apexName, ".") >= 2 {
2733			// In case of a partner APEX, prefix format might be an option.
2734			components := strings.Split(apexName, ".")
2735			components[len(components)-1] = "*"
2736			hint += fmt.Sprintf(" or %q", strings.Join(components, "."))
2737		}
2738
2739		ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+
2740			"\n\nDependency path:%s\n\n"+
2741			"Consider adding %s to 'apex_available' property of %q",
2742			fromName, toName, ctx.GetPathString(true), hint, toName)
2743		// Visit this module's dependencies to check and report any issues with their availability.
2744		return true
2745	})
2746}
2747
2748// checkStaticExecutable ensures that executables in an APEX are not static.
2749func (a *apexBundle) checkStaticExecutables(ctx android.ModuleContext) {
2750	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
2751		if ctx.OtherModuleDependencyTag(module) != executableTag {
2752			return
2753		}
2754
2755		if android.OtherModuleProviderOrDefault(ctx, module, cc.LinkableInfoKey).StaticExecutable {
2756			apex := a.ApexVariationName()
2757			exec := ctx.OtherModuleName(module)
2758			if isStaticExecutableAllowed(apex, exec) {
2759				return
2760			}
2761			ctx.ModuleErrorf("executable %s is static", ctx.OtherModuleName(module))
2762		}
2763	})
2764}
2765
2766// A small list of exceptions where static executables are allowed in APEXes.
2767func isStaticExecutableAllowed(apex string, exec string) bool {
2768	m := map[string][]string{
2769		"com.android.runtime": {
2770			"linker",
2771			"linkerconfig",
2772		},
2773	}
2774	execNames, ok := m[apex]
2775	return ok && android.InList(exec, execNames)
2776}
2777
2778// Collect information for opening IDE project files in java/jdeps.go.
2779func (a *apexBundle) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
2780	dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...)
2781	dpInfo.Deps = append(dpInfo.Deps, a.properties.Bootclasspath_fragments.GetOrDefault(ctx, nil)...)
2782	dpInfo.Deps = append(dpInfo.Deps, a.properties.Systemserverclasspath_fragments.GetOrDefault(ctx, nil)...)
2783}
2784
2785func init() {
2786	android.AddNeverAllowRules(createBcpPermittedPackagesRules(qBcpPackages())...)
2787	android.AddNeverAllowRules(createBcpPermittedPackagesRules(rBcpPackages())...)
2788}
2789
2790func createBcpPermittedPackagesRules(bcpPermittedPackages map[string][]string) []android.Rule {
2791	rules := make([]android.Rule, 0, len(bcpPermittedPackages))
2792	for jar, permittedPackages := range bcpPermittedPackages {
2793		permittedPackagesRule := android.NeverAllow().
2794			With("name", jar).
2795			WithMatcher("permitted_packages", android.NotInList(permittedPackages)).
2796			Because(jar +
2797				" bootjar may only use these package prefixes: " + strings.Join(permittedPackages, ",") +
2798				". Please consider the following alternatives:\n" +
2799				"    1. If the offending code is from a statically linked library, consider " +
2800				"removing that dependency and using an alternative already in the " +
2801				"bootclasspath, or perhaps a shared library." +
2802				"    2. Move the offending code into an allowed package.\n" +
2803				"    3. Jarjar the offending code. Please be mindful of the potential system " +
2804				"health implications of bundling that code, particularly if the offending jar " +
2805				"is part of the bootclasspath.")
2806
2807		rules = append(rules, permittedPackagesRule)
2808	}
2809	return rules
2810}
2811
2812// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
2813// Adding code to the bootclasspath in new packages will cause issues on module update.
2814func qBcpPackages() map[string][]string {
2815	return map[string][]string{
2816		"conscrypt": {
2817			"android.net.ssl",
2818			"com.android.org.conscrypt",
2819		},
2820		"updatable-media": {
2821			"android.media",
2822		},
2823	}
2824}
2825
2826// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
2827// Adding code to the bootclasspath in new packages will cause issues on module update.
2828func rBcpPackages() map[string][]string {
2829	return map[string][]string{
2830		"framework-mediaprovider": {
2831			"android.provider",
2832		},
2833		"framework-permission": {
2834			"android.permission",
2835			"android.app.role",
2836			"com.android.permission",
2837			"com.android.role",
2838		},
2839		"framework-sdkextensions": {
2840			"android.os.ext",
2841		},
2842		"framework-statsd": {
2843			"android.app",
2844			"android.os",
2845			"android.util",
2846			"com.android.internal.statsd",
2847			"com.android.server.stats",
2848		},
2849		"framework-wifi": {
2850			"com.android.server.wifi",
2851			"com.android.wifi.x",
2852			"android.hardware.wifi",
2853			"android.net.wifi",
2854		},
2855		"framework-tethering": {
2856			"android.net",
2857		},
2858	}
2859}
2860
2861// verifyNativeImplementationLibs compares the list of transitive implementation libraries used to link native
2862// libraries in the apex against the list of implementation libraries in the apex, ensuring that none of the
2863// libraries in the apex have references to private APIs from outside the apex.
2864func (a *apexBundle) verifyNativeImplementationLibs(ctx android.ModuleContext) {
2865	var directImplementationLibs android.Paths
2866	var transitiveImplementationLibs []depset.DepSet[android.Path]
2867
2868	if a.properties.IsCoverageVariant {
2869		return
2870	}
2871
2872	if a.testApex {
2873		return
2874	}
2875
2876	if a.UsePlatformApis() {
2877		return
2878	}
2879
2880	checkApexTag := func(tag blueprint.DependencyTag) bool {
2881		switch tag {
2882		case sharedLibTag, jniLibTag, executableTag, androidAppTag:
2883			return true
2884		default:
2885			return false
2886		}
2887	}
2888
2889	checkTransitiveTag := func(tag blueprint.DependencyTag) bool {
2890		switch {
2891		case cc.IsSharedDepTag(tag), java.IsJniDepTag(tag), rust.IsRlibDepTag(tag), rust.IsDylibDepTag(tag), checkApexTag(tag):
2892			return true
2893		default:
2894			return false
2895		}
2896	}
2897
2898	var appEmbeddedJNILibs android.Paths
2899	ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
2900		tag := ctx.OtherModuleDependencyTag(dep)
2901		if !checkApexTag(tag) {
2902			return
2903		}
2904		if tag == sharedLibTag || tag == jniLibTag {
2905			outputFile := android.OutputFileForModule(ctx, dep, "")
2906			directImplementationLibs = append(directImplementationLibs, outputFile)
2907		}
2908		if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
2909			transitiveImplementationLibs = append(transitiveImplementationLibs, info.ImplementationDeps)
2910		}
2911		if info, ok := android.OtherModuleProvider(ctx, dep, java.AppInfoProvider); ok {
2912			appEmbeddedJNILibs = append(appEmbeddedJNILibs, info.EmbeddedJNILibs...)
2913		}
2914	})
2915
2916	depSet := depset.New(depset.PREORDER, directImplementationLibs, transitiveImplementationLibs)
2917	allImplementationLibs := depSet.ToList()
2918
2919	allFileInfos := slices.Concat(a.filesInfo, a.unwantedTransitiveFilesInfo, a.duplicateTransitiveFilesInfo)
2920
2921	for _, lib := range allImplementationLibs {
2922		inApex := slices.ContainsFunc(allFileInfos, func(fi apexFile) bool {
2923			return fi.builtFile == lib
2924		})
2925		inApkInApex := slices.Contains(appEmbeddedJNILibs, lib)
2926
2927		if !inApex && !inApkInApex {
2928			ctx.ModuleErrorf("library in apex transitively linked against implementation library %q not in apex", lib)
2929			var depPath []android.Module
2930			ctx.WalkDeps(func(child, parent android.Module) bool {
2931				if depPath != nil {
2932					return false
2933				}
2934
2935				tag := ctx.OtherModuleDependencyTag(child)
2936
2937				if parent == ctx.Module() {
2938					if !checkApexTag(tag) {
2939						return false
2940					}
2941				}
2942
2943				if checkTransitiveTag(tag) {
2944					if android.OutputFileForModule(ctx, child, "") == lib {
2945						depPath = ctx.GetWalkPath()
2946					}
2947					return true
2948				}
2949
2950				return false
2951			})
2952			if depPath != nil {
2953				ctx.ModuleErrorf("dependency path:")
2954				for _, m := range depPath {
2955					ctx.ModuleErrorf("   %s", ctx.OtherModuleName(m))
2956				}
2957				return
2958			}
2959		}
2960	}
2961}
2962