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