blob: b1b4e4716202853d181ceda9d06925c1ad28fe0c [file] [log] [blame]
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001// 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
Jiyong Parkc0ec6f92020-11-19 23:00:52 +090015// 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
Jiyong Park48ca7dc2018-10-10 14:01:00 +090017package apex
18
19import (
20 "fmt"
Jiyong Park48ca7dc2018-10-10 14:01:00 +090021 "path/filepath"
Oriol Prieto Gasco17e22902022-05-05 13:52:25 +000022 "regexp"
Jiyong Parkab3ceb32018-10-10 14:05:29 +090023 "sort"
Jiyong Park48ca7dc2018-10-10 14:01:00 +090024 "strings"
25
Yu Liu4c212ce2022-10-14 12:20:20 -070026 "android/soong/bazel/cquery"
27
Jiyong Park48ca7dc2018-10-10 14:01:00 +090028 "github.com/google/blueprint"
Alex Light778127a2019-02-27 14:19:50 -080029 "github.com/google/blueprint/bootstrap"
Jiyong Park48ca7dc2018-10-10 14:01:00 +090030 "github.com/google/blueprint/proptools"
Jaewoong Jung4b79e982020-06-01 10:45:49 -070031
32 "android/soong/android"
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -040033 "android/soong/bazel"
markchien2f59ec92020-09-02 16:23:38 +080034 "android/soong/bpf"
Jaewoong Jung4b79e982020-06-01 10:45:49 -070035 "android/soong/cc"
36 prebuilt_etc "android/soong/etc"
Jiyong Park12a719c2021-01-07 15:31:24 +090037 "android/soong/filesystem"
Jaewoong Jung4b79e982020-06-01 10:45:49 -070038 "android/soong/java"
Inseob Kim5eb7ee92022-04-27 10:30:34 +090039 "android/soong/multitree"
Jaewoong Jung4b79e982020-06-01 10:45:49 -070040 "android/soong/python"
Jiyong Park99644e92020-11-17 22:21:02 +090041 "android/soong/rust"
Jaewoong Jung4b79e982020-06-01 10:45:49 -070042 "android/soong/sh"
Jiyong Park48ca7dc2018-10-10 14:01:00 +090043)
44
Jiyong Park8e6d52f2020-11-19 14:37:47 +090045func init() {
Paul Duffin667893c2021-03-09 22:34:13 +000046 registerApexBuildComponents(android.InitRegistrationContext)
47}
Jiyong Park8e6d52f2020-11-19 14:37:47 +090048
Paul Duffin667893c2021-03-09 22:34:13 +000049func registerApexBuildComponents(ctx android.RegistrationContext) {
50 ctx.RegisterModuleType("apex", BundleFactory)
Yu Liu4c212ce2022-10-14 12:20:20 -070051 ctx.RegisterModuleType("apex_test", TestApexBundleFactory)
Paul Duffin667893c2021-03-09 22:34:13 +000052 ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
53 ctx.RegisterModuleType("apex_defaults", defaultsFactory)
54 ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
Wei Li1c66fc72022-05-09 23:59:14 -070055 ctx.RegisterModuleType("override_apex", OverrideApexFactory)
Paul Duffin667893c2021-03-09 22:34:13 +000056 ctx.RegisterModuleType("apex_set", apexSetFactory)
57
Paul Duffin5dda3e32021-05-05 14:13:27 +010058 ctx.PreArchMutators(registerPreArchMutators)
Paul Duffin667893c2021-03-09 22:34:13 +000059 ctx.PreDepsMutators(RegisterPreDepsMutators)
60 ctx.PostDepsMutators(RegisterPostDepsMutators)
Jiyong Park8e6d52f2020-11-19 14:37:47 +090061}
62
Paul Duffin5dda3e32021-05-05 14:13:27 +010063func registerPreArchMutators(ctx android.RegisterMutatorsContext) {
64 ctx.TopDown("prebuilt_apex_module_creator", prebuiltApexModuleCreatorMutator).Parallel()
65}
66
Jiyong Park8e6d52f2020-11-19 14:37:47 +090067func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
68 ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
69 ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
70}
71
72func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
Paul Duffin949abc02020-12-08 10:34:30 +000073 ctx.TopDown("apex_info", apexInfoMutator).Parallel()
Jiyong Park8e6d52f2020-11-19 14:37:47 +090074 ctx.BottomUp("apex_unique", apexUniqueVariationsMutator).Parallel()
75 ctx.BottomUp("apex_test_for_deps", apexTestForDepsMutator).Parallel()
76 ctx.BottomUp("apex_test_for", apexTestForMutator).Parallel()
Paul Duffin28bf7ee2021-05-12 16:41:35 +010077 // Run mark_platform_availability before the apexMutator as the apexMutator needs to know whether
78 // it should create a platform variant.
79 ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
Jiyong Park8e6d52f2020-11-19 14:37:47 +090080 ctx.BottomUp("apex", apexMutator).Parallel()
81 ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
82 ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
Spandan Das66773252022-01-15 00:23:18 +000083 // Register after apex_info mutator so that it can use ApexVariationName
84 ctx.TopDown("apex_strict_updatability_lint", apexStrictUpdatibilityLintMutator).Parallel()
Jiyong Park8e6d52f2020-11-19 14:37:47 +090085}
86
87type apexBundleProperties struct {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +090088 // Json manifest file describing meta info of this APEX bundle. Refer to
89 // system/apex/proto/apex_manifest.proto for the schema. Default: "apex_manifest.json"
Jiyong Park8e6d52f2020-11-19 14:37:47 +090090 Manifest *string `android:"path"`
91
Jiyong Parkc0ec6f92020-11-19 23:00:52 +090092 // AndroidManifest.xml file used for the zip container of this APEX bundle. If unspecified,
93 // a default one is automatically generated.
Jiyong Park8e6d52f2020-11-19 14:37:47 +090094 AndroidManifest *string `android:"path"`
95
Jiyong Parkc0ec6f92020-11-19 23:00:52 +090096 // Canonical name of this APEX bundle. Used to determine the path to the activated APEX on
97 // device (/apex/<apex_name>). If unspecified, follows the name property.
Jiyong Park8e6d52f2020-11-19 14:37:47 +090098 Apex_name *string
99
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900100 // Determines the file contexts file for setting the security contexts to files in this APEX
101 // bundle. For platform APEXes, this should points to a file under /system/sepolicy Default:
102 // /system/sepolicy/apex/<module_name>_file_contexts.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900103 File_contexts *string `android:"path"`
104
Jiyong Park038e8522021-12-13 23:56:35 +0900105 // Path to the canned fs config file for customizing file's uid/gid/mod/capabilities. The
106 // format is /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where path_or_glob is a
107 // path or glob pattern for a file or set of files, uid/gid are numerial values of user ID
108 // and group ID, mode is octal value for the file mode, and cap is hexadecimal value for the
109 // capability. If this property is not set, or a file is missing in the file, default config
110 // is used.
111 Canned_fs_config *string `android:"path"`
112
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900113 ApexNativeDependencies
114
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900115 Multilib apexMultilibProperties
116
Sundong Ahn80c04892021-11-23 00:57:19 +0000117 // List of sh binaries that are embedded inside this APEX bundle.
118 Sh_binaries []string
119
Paul Duffin3abc1742021-03-15 19:32:23 +0000120 // List of platform_compat_config files that are embedded inside this APEX bundle.
121 Compat_configs []string
122
Jiyong Park12a719c2021-01-07 15:31:24 +0900123 // List of filesystem images that are embedded inside this APEX bundle.
124 Filesystems []string
125
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900126 // The minimum SDK version that this APEX must support at minimum. This is usually set to
127 // the SDK version that the APEX was first introduced.
128 Min_sdk_version *string
129
130 // Whether this APEX is considered updatable or not. When set to true, this will enforce
131 // additional rules for making sure that the APEX is truly updatable. To be updatable,
132 // min_sdk_version should be set as well. This will also disable the size optimizations like
Mathew Inwoodf8dcf5e2021-02-16 11:40:16 +0000133 // symlinking to the system libs. Default is true.
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900134 Updatable *bool
135
Jiyong Parkf4020582021-11-29 12:37:10 +0900136 // Marks that this APEX is designed to be updatable in the future, although it's not
137 // updatable yet. This is used to mimic some of the build behaviors that are applied only to
138 // updatable APEXes. Currently, this disables the size optimization, so that the size of
139 // APEX will not increase when the APEX is actually marked as truly updatable. Default is
140 // false.
141 Future_updatable *bool
142
Jiyong Park1bc84122021-06-22 20:23:05 +0900143 // Whether this APEX can use platform APIs or not. Can be set to true only when `updatable:
144 // false`. Default is false.
145 Platform_apis *bool
146
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900147 // Whether this APEX is installable to one of the partitions like system, vendor, etc.
148 // Default: true.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900149 Installable *bool
150
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900151 // If set true, VNDK libs are considered as stable libs and are not included in this APEX.
152 // Should be only used in non-system apexes (e.g. vendor: true). Default is false.
153 Use_vndk_as_stable *bool
154
Daniel Norman6cfb37af2021-11-16 20:28:29 +0000155 // Whether this is multi-installed APEX should skip installing symbol files.
156 // Multi-installed APEXes share the same apex_name and are installed at the same time.
157 // Default is false.
158 //
159 // Should be set to true for all multi-installed APEXes except the singular
160 // default version within the multi-installed group.
161 // Only the default version can install symbol files in $(PRODUCT_OUT}/apex,
162 // or else conflicting build rules may be created.
163 Multi_install_skip_symbol_files *bool
164
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900165 // The type of APEX to build. Controls what the APEX payload is. Either 'image', 'zip' or
166 // 'both'. When set to image, contents are stored in a filesystem image inside a zip
167 // container. When set to zip, contents are stored in a zip container directly. This type is
168 // mostly for host-side debugging. When set to both, the two types are both built. Default
169 // is 'image'.
170 Payload_type *string
171
Huang Jianan13cac632021-08-02 15:02:17 +0800172 // The type of filesystem to use when the payload_type is 'image'. Either 'ext4', 'f2fs'
173 // or 'erofs'. Default 'ext4'.
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900174 Payload_fs_type *string
175
176 // For telling the APEX to ignore special handling for system libraries such as bionic.
177 // Default is false.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900178 Ignore_system_library_special_case *bool
179
Nikita Ioffeda6dc312021-06-09 19:43:46 +0100180 // Whenever apex_payload.img of the APEX should include dm-verity hashtree.
Nikita Ioffee261ae62021-06-16 18:15:03 +0100181 // Default value is true.
Nikita Ioffeda6dc312021-06-09 19:43:46 +0100182 Generate_hashtree *bool
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900183
184 // Whenever apex_payload.img of the APEX should not be dm-verity signed. Should be only
185 // used in tests.
186 Test_only_unsigned_payload *bool
187
Mohammad Samiul Islama8008f92020-12-22 10:47:50 +0000188 // Whenever apex should be compressed, regardless of product flag used. Should be only
189 // used in tests.
190 Test_only_force_compression *bool
191
Jooyung Han09c11ad2021-10-27 03:45:31 +0900192 // Put extra tags (signer=<value>) to apexkeys.txt, so that release tools can sign this apex
193 // with the tool to sign payload contents.
194 Custom_sign_tool *string
195
Dennis Shenaf41bc12022-08-03 16:46:43 +0000196 // Whether this is a dynamic common lib apex, if so the native shared libs will be placed
197 // in a special way that include the digest of the lib file under /lib(64)?
198 Dynamic_common_lib_apex *bool
199
Martin Stjernholmbfffae72021-06-24 14:37:13 +0100200 // Canonical name of this APEX bundle. Used to determine the path to the
201 // activated APEX on device (i.e. /apex/<apexVariationName>), and used for the
202 // apex mutator variations. For override_apex modules, this is the name of the
203 // overridden base module.
204 ApexVariationName string `blueprint:"mutated"`
205
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900206 IsCoverageVariant bool `blueprint:"mutated"`
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900207
208 // List of sanitizer names that this APEX is enabled for
209 SanitizerNames []string `blueprint:"mutated"`
210
211 PreventInstall bool `blueprint:"mutated"`
212
213 HideFromMake bool `blueprint:"mutated"`
214
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900215 // Internal package method for this APEX. When payload_type is image, this can be either
216 // imageApex or flattenedApex depending on Config.FlattenApex(). When payload_type is zip,
217 // this becomes zipApex.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900218 ApexType apexPackaging `blueprint:"mutated"`
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900219}
220
221type ApexNativeDependencies struct {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900222 // List of native libraries that are embedded inside this APEX.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900223 Native_shared_libs []string
224
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900225 // List of JNI libraries that are embedded inside this APEX.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900226 Jni_libs []string
227
Colin Cross70572ed2022-11-02 13:14:20 -0700228 // List of rust dyn libraries that are embedded inside this APEX.
Jiyong Park99644e92020-11-17 22:21:02 +0900229 Rust_dyn_libs []string
230
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900231 // List of native executables that are embedded inside this APEX.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900232 Binaries []string
233
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900234 // List of native tests that are embedded inside this APEX.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900235 Tests []string
Jiyong Park06711462021-02-15 17:54:43 +0900236
237 // List of filesystem images that are embedded inside this APEX bundle.
238 Filesystems []string
Colin Cross70572ed2022-11-02 13:14:20 -0700239
240 // List of native libraries to exclude from this APEX.
241 Exclude_native_shared_libs []string
242
243 // List of JNI libraries to exclude from this APEX.
244 Exclude_jni_libs []string
245
246 // List of rust dyn libraries to exclude from this APEX.
247 Exclude_rust_dyn_libs []string
248
249 // List of native executables to exclude from this APEX.
250 Exclude_binaries []string
251
252 // List of native tests to exclude from this APEX.
253 Exclude_tests []string
254
255 // List of filesystem images to exclude from this APEX bundle.
256 Exclude_filesystems []string
257}
258
259// Merge combines another ApexNativeDependencies into this one
260func (a *ApexNativeDependencies) Merge(b ApexNativeDependencies) {
261 a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...)
262 a.Jni_libs = append(a.Jni_libs, b.Jni_libs...)
263 a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
264 a.Binaries = append(a.Binaries, b.Binaries...)
265 a.Tests = append(a.Tests, b.Tests...)
266 a.Filesystems = append(a.Filesystems, b.Filesystems...)
267
268 a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...)
269 a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...)
270 a.Exclude_rust_dyn_libs = append(a.Exclude_rust_dyn_libs, b.Exclude_rust_dyn_libs...)
271 a.Exclude_binaries = append(a.Exclude_binaries, b.Exclude_binaries...)
272 a.Exclude_tests = append(a.Exclude_tests, b.Exclude_tests...)
273 a.Exclude_filesystems = append(a.Exclude_filesystems, b.Exclude_filesystems...)
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900274}
275
276type apexMultilibProperties struct {
277 // Native dependencies whose compile_multilib is "first"
278 First ApexNativeDependencies
279
280 // Native dependencies whose compile_multilib is "both"
281 Both ApexNativeDependencies
282
283 // Native dependencies whose compile_multilib is "prefer32"
284 Prefer32 ApexNativeDependencies
285
286 // Native dependencies whose compile_multilib is "32"
287 Lib32 ApexNativeDependencies
288
289 // Native dependencies whose compile_multilib is "64"
290 Lib64 ApexNativeDependencies
291}
292
293type apexTargetBundleProperties struct {
294 Target struct {
295 // Multilib properties only for android.
296 Android struct {
297 Multilib apexMultilibProperties
298 }
299
300 // Multilib properties only for host.
301 Host struct {
302 Multilib apexMultilibProperties
303 }
304
305 // Multilib properties only for host linux_bionic.
306 Linux_bionic struct {
307 Multilib apexMultilibProperties
308 }
309
310 // Multilib properties only for host linux_glibc.
311 Linux_glibc struct {
312 Multilib apexMultilibProperties
313 }
314 }
315}
316
Jiyong Park59140302020-12-14 18:44:04 +0900317type apexArchBundleProperties struct {
318 Arch struct {
319 Arm struct {
320 ApexNativeDependencies
321 }
322 Arm64 struct {
323 ApexNativeDependencies
324 }
Colin Crossa2aaa2f2022-10-03 12:41:50 -0700325 Riscv64 struct {
326 ApexNativeDependencies
327 }
Jiyong Park59140302020-12-14 18:44:04 +0900328 X86 struct {
329 ApexNativeDependencies
330 }
331 X86_64 struct {
332 ApexNativeDependencies
333 }
334 }
335}
336
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900337// These properties can be used in override_apex to override the corresponding properties in the
338// base apex.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900339type overridableProperties struct {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900340 // List of APKs that are embedded inside this APEX.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900341 Apps []string
342
Daniel Norman5a3ce132021-08-26 15:44:43 -0700343 // List of prebuilt files that are embedded inside this APEX bundle.
344 Prebuilts []string
345
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900346 // List of runtime resource overlays (RROs) that are embedded inside this APEX.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900347 Rros []string
348
markchien7c803b82021-08-26 22:10:06 +0800349 // List of BPF programs inside this APEX bundle.
350 Bpfs []string
351
Remi NGUYEN VANbe901722022-03-02 21:00:33 +0900352 // List of bootclasspath fragments that are embedded inside this APEX bundle.
353 Bootclasspath_fragments []string
354
355 // List of systemserverclasspath fragments that are embedded inside this APEX bundle.
356 Systemserverclasspath_fragments []string
357
358 // List of java libraries that are embedded inside this APEX bundle.
359 Java_libs []string
360
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900361 // Names of modules to be overridden. Listed modules can only be other binaries (in Make or
362 // Soong). This does not completely prevent installation of the overridden binaries, but if
363 // both binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will
364 // be removed from PRODUCT_PACKAGES.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900365 Overrides []string
366
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900367 // Logging parent value.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900368 Logging_parent string
369
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900370 // Apex Container package name. Override value for attribute package:name in
371 // AndroidManifest.xml
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900372 Package_name string
373
374 // A txt file containing list of files that are allowed to be included in this APEX.
375 Allowed_files *string `android:"path"`
Jaewoong Jung4cfdf7d2021-04-20 16:21:24 -0700376
377 // Name of the apex_key module that provides the private key to sign this APEX bundle.
378 Key *string
379
380 // Specifies the certificate and the private key to sign the zip container of this APEX. If
381 // this is "foo", foo.x509.pem and foo.pk8 under PRODUCT_DEFAULT_DEV_CERTIFICATE are used
382 // as the certificate and the private key, respectively. If this is ":module", then the
383 // certificate and the private key are provided from the android_app_certificate module
384 // named "module".
385 Certificate *string
Oriol Prieto Gascoa07099d2021-10-14 15:33:41 -0400386
387 // Whether this APEX can be compressed or not. Setting this property to false means this
388 // APEX will never be compressed. When set to true, APEX will be compressed if other
389 // conditions, e.g., target device needs to support APEX compression, are also fulfilled.
390 // Default: false.
391 Compressible *bool
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900392}
393
394type apexBundle struct {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900395 // Inherited structs
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900396 android.ModuleBase
397 android.DefaultableModuleBase
398 android.OverridableModuleBase
399 android.SdkBase
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -0400400 android.BazelModuleBase
Inseob Kim5eb7ee92022-04-27 10:30:34 +0900401 multitree.ExportableModuleBase
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900402
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900403 // Properties
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900404 properties apexBundleProperties
405 targetProperties apexTargetBundleProperties
Jiyong Park59140302020-12-14 18:44:04 +0900406 archProperties apexArchBundleProperties
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900407 overridableProperties overridableProperties
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900408 vndkProperties apexVndkProperties // only for apex_vndk modules
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900409
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900410 ///////////////////////////////////////////////////////////////////////////////////////////
411 // Inputs
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900412
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900413 // Keys for apex_paylaod.img
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800414 publicKeyFile android.Path
415 privateKeyFile android.Path
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900416
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900417 // Cert/priv-key for the zip container
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800418 containerCertificateFile android.Path
419 containerPrivateKeyFile android.Path
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900420
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900421 // Flags for special variants of APEX
422 testApex bool
423 vndkApex bool
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900424
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900425 // Tells whether this variant of the APEX bundle is the primary one or not. Only the primary
426 // one gets installed to the device.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900427 primaryApexType bool
428
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900429 // Suffix of module name in Android.mk ".flattened", ".apex", ".zipapex", or ""
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900430 suffix string
431
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900432 // File system type of apex_payload.img
433 payloadFsType fsType
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900434
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900435 // Whether to create symlink to the system file instead of having a file inside the apex or
436 // not
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900437 linkToSystemLib bool
438
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900439 // List of files to be included in this APEX. This is filled in the first part of
440 // GenerateAndroidBuildActions.
441 filesInfo []apexFile
442
443 // List of other module names that should be installed when this APEX gets installed.
444 requiredDeps []string
445
446 ///////////////////////////////////////////////////////////////////////////////////////////
447 // Outputs (final and intermediates)
448
449 // Processed apex manifest in JSONson format (for Q)
450 manifestJsonOut android.WritablePath
451
452 // Processed apex manifest in PB format (for R+)
453 manifestPbOut android.WritablePath
454
455 // Processed file_contexts files
456 fileContexts android.WritablePath
457
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900458 // The built APEX file. This is the main product.
Jooyung Hana6d36672022-02-24 13:58:07 +0900459 // Could be .apex or .capex
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900460 outputFile android.WritablePath
461
Jooyung Hana6d36672022-02-24 13:58:07 +0900462 // The built uncompressed .apex file.
463 outputApexFile android.WritablePath
464
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900465 // The built APEX file in app bundle format. This file is not directly installed to the
466 // device. For an APEX, multiple app bundles are created each of which is for a specific ABI
467 // like arm, arm64, x86, etc. Then they are processed again (outside of the Android build
468 // system) to be merged into a single app bundle file that Play accepts. See
469 // vendor/google/build/build_unbundled_mainline_module.sh for more detail.
470 bundleModuleFile android.WritablePath
471
Colin Cross6340ea52021-11-04 12:01:18 -0700472 // Target directory to install this APEX. Usually out/target/product/<device>/<partition>/apex.
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900473 installDir android.InstallPath
474
Colin Cross6340ea52021-11-04 12:01:18 -0700475 // Path where this APEX was installed.
476 installedFile android.InstallPath
477
478 // Installed locations of symlinks for backward compatibility.
479 compatSymlinks android.InstallPaths
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900480
481 // Text file having the list of individual files that are included in this APEX. Used for
482 // debugging purpose.
483 installedFilesFile android.WritablePath
484
485 // List of module names that this APEX is including (to be shown via *-deps-info target).
486 // Used for debugging purpose.
487 android.ApexBundleDepsInfo
488
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900489 // Optional list of lint report zip files for apexes that contain java or app modules
490 lintReports android.Paths
491
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900492 prebuiltFileToDelete string
sophiezc80a2b32020-11-12 16:39:19 +0000493
Mohammad Samiul Islam3cd005d2020-11-26 13:32:26 +0000494 isCompressed bool
495
sophiezc80a2b32020-11-12 16:39:19 +0000496 // Path of API coverage generate file
sophiez02347372021-11-02 17:58:02 -0700497 nativeApisUsedByModuleFile android.ModuleOutPath
498 nativeApisBackedByModuleFile android.ModuleOutPath
499 javaApisUsedByModuleFile android.ModuleOutPath
braleeb0c1f0c2021-06-07 22:49:13 +0800500
501 // Collect the module directory for IDE info in java/jdeps.go.
502 modulePaths []string
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900503}
504
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900505// apexFileClass represents a type of file that can be included in APEX.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900506type apexFileClass int
507
Jooyung Han72bd2f82019-10-23 16:46:38 +0900508const (
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900509 app apexFileClass = iota
510 appSet
511 etc
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900512 goBinary
513 javaSharedLib
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900514 nativeExecutable
515 nativeSharedLib
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900516 nativeTest
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900517 pyBinary
518 shBinary
Jooyung Han72bd2f82019-10-23 16:46:38 +0900519)
Jiyong Park48ca7dc2018-10-10 14:01:00 +0900520
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900521// apexFile represents a file in an APEX bundle. This is created during the first half of
522// GenerateAndroidBuildActions by traversing the dependencies of the APEX. Then in the second half
523// of the function, this is used to create commands that copies the files into a staging directory,
524// where they are packaged into the APEX file. This struct is also used for creating Make modules
525// for each of the files in case when the APEX is flattened.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900526type apexFile struct {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900527 // buildFile is put in the installDir inside the APEX.
Bob Badourde6a0872022-04-01 18:00:00 +0000528 builtFile android.Path
529 installDir string
530 customStem string
531 symlinks []string // additional symlinks
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900532
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900533 // Info for Android.mk Module name of `module` in AndroidMk. Note the generated AndroidMk
534 // module for apexFile is named something like <AndroidMk module name>.<apex name>[<apex
535 // suffix>]
536 androidMkModuleName string // becomes LOCAL_MODULE
537 class apexFileClass // becomes LOCAL_MODULE_CLASS
538 moduleDir string // becomes LOCAL_PATH
539 requiredModuleNames []string // becomes LOCAL_REQUIRED_MODULES
540 targetRequiredModuleNames []string // becomes LOCAL_TARGET_REQUIRED_MODULES
541 hostRequiredModuleNames []string // becomes LOCAL_HOST_REQUIRED_MODULES
542 dataPaths []android.DataPath // becomes LOCAL_TEST_DATA
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900543
544 jacocoReportClassesFile android.Path // only for javalibs and apps
545 lintDepSets java.LintDepSets // only for javalibs and apps
546 certificate java.Certificate // only for apps
547 overriddenPackageName string // only for apps
548
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900549 transitiveDep bool
550 isJniLib bool
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900551
Jiyong Park57621b22021-01-20 20:33:11 +0900552 multilib string
553
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900554 // TODO(jiyong): remove this
555 module android.Module
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900556}
557
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900558// TODO(jiyong): shorten the arglist using an option struct
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900559func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string, installDir string, class apexFileClass, module android.Module) apexFile {
560 ret := apexFile{
561 builtFile: builtFile,
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900562 installDir: installDir,
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900563 androidMkModuleName: androidMkModuleName,
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900564 class: class,
565 module: module,
566 }
567 if module != nil {
568 ret.moduleDir = ctx.OtherModuleDir(module)
569 ret.requiredModuleNames = module.RequiredModuleNames()
570 ret.targetRequiredModuleNames = module.TargetRequiredModuleNames()
571 ret.hostRequiredModuleNames = module.HostRequiredModuleNames()
Jiyong Park57621b22021-01-20 20:33:11 +0900572 ret.multilib = module.Target().Arch.ArchType.Multilib
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900573 }
574 return ret
575}
576
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900577func (af *apexFile) ok() bool {
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900578 return af.builtFile != nil && af.builtFile.String() != ""
579}
580
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900581// apexRelativePath returns the relative path of the given path from the install directory of this
582// apexFile.
583// TODO(jiyong): rename this
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900584func (af *apexFile) apexRelativePath(path string) string {
585 return filepath.Join(af.installDir, path)
586}
587
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900588// path returns path of this apex file relative to the APEX root
589func (af *apexFile) path() string {
590 return af.apexRelativePath(af.stem())
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900591}
592
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900593// stem returns the base filename of this apex file
594func (af *apexFile) stem() string {
595 if af.customStem != "" {
596 return af.customStem
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900597 }
598 return af.builtFile.Base()
599}
600
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900601// symlinkPaths returns paths of the symlinks (if any) relative to the APEX root
602func (af *apexFile) symlinkPaths() []string {
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900603 var ret []string
604 for _, symlink := range af.symlinks {
605 ret = append(ret, af.apexRelativePath(symlink))
606 }
607 return ret
608}
609
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900610// availableToPlatform tests whether this apexFile is from a module that can be installed to the
611// platform.
612func (af *apexFile) availableToPlatform() bool {
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900613 if af.module == nil {
614 return false
615 }
616 if am, ok := af.module.(android.ApexModule); ok {
617 return am.AvailableFor(android.AvailableToPlatform)
618 }
619 return false
620}
621
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900622////////////////////////////////////////////////////////////////////////////////////////////////////
623// Mutators
624//
625// Brief description about mutators for APEX. The following three mutators are the most important
626// ones.
627//
628// 1) DepsMutator: from the properties like native_shared_libs, java_libs, etc., modules are added
629// to the (direct) dependencies of this APEX bundle.
630//
Paul Duffin949abc02020-12-08 10:34:30 +0000631// 2) apexInfoMutator: this is a post-deps mutator, so runs after DepsMutator. Its goal is to
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900632// collect modules that are direct and transitive dependencies of each APEX bundle. The collected
633// modules are marked as being included in the APEX via BuildForApex().
634//
Paul Duffin949abc02020-12-08 10:34:30 +0000635// 3) apexMutator: this is a post-deps mutator that runs after apexInfoMutator. For each module that
636// are marked by the apexInfoMutator, apex variations are created using CreateApexVariations().
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900637
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900638type dependencyTag struct {
639 blueprint.BaseDependencyTag
640 name string
641
642 // Determines if the dependent will be part of the APEX payload. Can be false for the
643 // dependencies to the signing key module, etc.
644 payload bool
Paul Duffin8c535da2021-03-17 14:51:03 +0000645
646 // True if the dependent can only be a source module, false if a prebuilt module is a suitable
647 // replacement. This is needed because some prebuilt modules do not provide all the information
648 // needed by the apex.
649 sourceOnly bool
Paul Duffin4e7d1c42022-05-13 13:12:19 +0000650
651 // If not-nil and an APEX is a member of an SDK then dependencies of that APEX with this tag will
652 // also be added as exported members of that SDK.
653 memberType android.SdkMemberType
654}
655
656func (d *dependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType {
657 return d.memberType
658}
659
660func (d *dependencyTag) ExportMember() bool {
661 return true
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900662}
663
Paul Duffin520917a2022-05-13 13:01:59 +0000664func (d *dependencyTag) String() string {
665 return fmt.Sprintf("apex.dependencyTag{%q}", d.name)
666}
667
668func (d *dependencyTag) ReplaceSourceWithPrebuilt() bool {
Paul Duffin8c535da2021-03-17 14:51:03 +0000669 return !d.sourceOnly
670}
671
672var _ android.ReplaceSourceWithPrebuilt = &dependencyTag{}
Paul Duffin4e7d1c42022-05-13 13:12:19 +0000673var _ android.SdkMemberDependencyTag = &dependencyTag{}
Paul Duffin8c535da2021-03-17 14:51:03 +0000674
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900675var (
Paul Duffin520917a2022-05-13 13:01:59 +0000676 androidAppTag = &dependencyTag{name: "androidApp", payload: true}
677 bpfTag = &dependencyTag{name: "bpf", payload: true}
678 certificateTag = &dependencyTag{name: "certificate"}
679 executableTag = &dependencyTag{name: "executable", payload: true}
680 fsTag = &dependencyTag{name: "filesystem", payload: true}
Paul Duffin4e7d1c42022-05-13 13:12:19 +0000681 bcpfTag = &dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true, memberType: java.BootclasspathFragmentSdkMemberType}
682 sscpfTag = &dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true, memberType: java.SystemServerClasspathFragmentSdkMemberType}
Paul Duffinfcf79852022-07-20 14:18:24 +0000683 compatConfigTag = &dependencyTag{name: "compatConfig", payload: true, sourceOnly: true, memberType: java.CompatConfigSdkMemberType}
Paul Duffin520917a2022-05-13 13:01:59 +0000684 javaLibTag = &dependencyTag{name: "javaLib", payload: true}
685 jniLibTag = &dependencyTag{name: "jniLib", payload: true}
686 keyTag = &dependencyTag{name: "key"}
687 prebuiltTag = &dependencyTag{name: "prebuilt", payload: true}
688 rroTag = &dependencyTag{name: "rro", payload: true}
689 sharedLibTag = &dependencyTag{name: "sharedLib", payload: true}
690 testForTag = &dependencyTag{name: "test for"}
691 testTag = &dependencyTag{name: "test", payload: true}
692 shBinaryTag = &dependencyTag{name: "shBinary", payload: true}
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900693)
694
695// TODO(jiyong): shorten this function signature
696func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ApexNativeDependencies, target android.Target, imageVariation string) {
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900697 binVariations := target.Variations()
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900698 libVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
Jiyong Park99644e92020-11-17 22:21:02 +0900699 rustLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"})
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900700
701 if ctx.Device() {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900702 binVariations = append(binVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation})
Jiyong Parkf2cc1b72020-12-09 00:20:45 +0900703 libVariations = append(libVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation})
704 rustLibVariations = append(rustLibVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation})
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900705 }
706
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900707 // Use *FarVariation* to be able to depend on modules having conflicting variations with
708 // this module. This is required since arch variant of an APEX bundle is 'common' but it is
709 // 'arm' or 'arm64' for native shared libs.
Colin Cross70572ed2022-11-02 13:14:20 -0700710 ctx.AddFarVariationDependencies(binVariations, executableTag,
711 android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...)
712 ctx.AddFarVariationDependencies(binVariations, testTag,
713 android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...)
714 ctx.AddFarVariationDependencies(libVariations, jniLibTag,
715 android.RemoveListFromList(nativeModules.Jni_libs, nativeModules.Exclude_jni_libs)...)
716 ctx.AddFarVariationDependencies(libVariations, sharedLibTag,
717 android.RemoveListFromList(nativeModules.Native_shared_libs, nativeModules.Exclude_native_shared_libs)...)
718 ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag,
719 android.RemoveListFromList(nativeModules.Rust_dyn_libs, nativeModules.Exclude_rust_dyn_libs)...)
720 ctx.AddFarVariationDependencies(target.Variations(), fsTag,
721 android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...)
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900722}
723
724func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900725 if ctx.Device() {
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900726 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil)
727 } else {
728 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Host.Multilib, nil)
729 if ctx.Os().Bionic() {
730 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_bionic.Multilib, nil)
731 } else {
732 proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_glibc.Multilib, nil)
733 }
734 }
735}
736
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900737// getImageVariation returns the image variant name for this apexBundle. In most cases, it's simply
738// android.CoreVariation, but gets complicated for the vendor APEXes and the VNDK APEX.
739func (a *apexBundle) getImageVariation(ctx android.BottomUpMutatorContext) string {
740 deviceConfig := ctx.DeviceConfig()
741 if a.vndkApex {
742 return cc.VendorVariationPrefix + a.vndkVersion(deviceConfig)
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900743 }
744
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900745 var prefix string
746 var vndkVersion string
747 if deviceConfig.VndkVersion() != "" {
Steven Moreland2c4000c2021-04-27 02:08:49 +0000748 if a.SocSpecific() || a.DeviceSpecific() {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900749 prefix = cc.VendorVariationPrefix
750 vndkVersion = deviceConfig.VndkVersion()
751 } else if a.ProductSpecific() {
752 prefix = cc.ProductVariationPrefix
753 vndkVersion = deviceConfig.ProductVndkVersion()
754 }
755 }
756 if vndkVersion == "current" {
757 vndkVersion = deviceConfig.PlatformVndkVersion()
758 }
759 if vndkVersion != "" {
760 return prefix + vndkVersion
761 }
762
763 return android.CoreVariation // The usual case
764}
765
766func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900767 // apexBundle is a multi-arch targets module. Arch variant of apexBundle is set to 'common'.
768 // arch-specific targets are enabled by the compile_multilib setting of the apex bundle. For
769 // each target os/architectures, appropriate dependencies are selected by their
770 // target.<os>.multilib.<type> groups and are added as (direct) dependencies.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900771 targets := ctx.MultiTargets()
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900772 imageVariation := a.getImageVariation(ctx)
773
774 a.combineProperties(ctx)
775
776 has32BitTarget := false
777 for _, target := range targets {
778 if target.Arch.ArchType.Multilib == "lib32" {
779 has32BitTarget = true
Paul Duffin7d74e7b2020-03-06 12:30:13 +0000780 }
781 }
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900782 for i, target := range targets {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900783 // Don't include artifacts for the host cross targets because there is no way for us
784 // to run those artifacts natively on host
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900785 if target.HostCross {
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900786 continue
787 }
Paul Duffin7d74e7b2020-03-06 12:30:13 +0000788
Colin Cross70572ed2022-11-02 13:14:20 -0700789 var deps ApexNativeDependencies
Paul Duffin7d74e7b2020-03-06 12:30:13 +0000790
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900791 // Add native modules targeting both ABIs. When multilib.* is omitted for
792 // native_shared_libs/jni_libs/tests, it implies multilib.both
Colin Cross70572ed2022-11-02 13:14:20 -0700793 deps.Merge(a.properties.Multilib.Both)
794 deps.Merge(ApexNativeDependencies{
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900795 Native_shared_libs: a.properties.Native_shared_libs,
796 Tests: a.properties.Tests,
797 Jni_libs: a.properties.Jni_libs,
798 Binaries: nil,
799 })
Jooyung Hanacc7bbe2020-05-20 09:06:00 +0900800
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900801 // Add native modules targeting the first ABI When multilib.* is omitted for
802 // binaries, it implies multilib.first
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900803 isPrimaryAbi := i == 0
804 if isPrimaryAbi {
Colin Cross70572ed2022-11-02 13:14:20 -0700805 deps.Merge(a.properties.Multilib.First)
806 deps.Merge(ApexNativeDependencies{
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900807 Native_shared_libs: nil,
808 Tests: nil,
809 Jni_libs: nil,
810 Binaries: a.properties.Binaries,
811 })
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900812 }
813
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900814 // Add native modules targeting either 32-bit or 64-bit ABI
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900815 switch target.Arch.ArchType.Multilib {
816 case "lib32":
Colin Cross70572ed2022-11-02 13:14:20 -0700817 deps.Merge(a.properties.Multilib.Lib32)
818 deps.Merge(a.properties.Multilib.Prefer32)
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900819 case "lib64":
Colin Cross70572ed2022-11-02 13:14:20 -0700820 deps.Merge(a.properties.Multilib.Lib64)
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900821 if !has32BitTarget {
Colin Cross70572ed2022-11-02 13:14:20 -0700822 deps.Merge(a.properties.Multilib.Prefer32)
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900823 }
824 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900825
Jiyong Park59140302020-12-14 18:44:04 +0900826 // Add native modules targeting a specific arch variant
827 switch target.Arch.ArchType {
828 case android.Arm:
Colin Cross70572ed2022-11-02 13:14:20 -0700829 deps.Merge(a.archProperties.Arch.Arm.ApexNativeDependencies)
Jiyong Park59140302020-12-14 18:44:04 +0900830 case android.Arm64:
Colin Cross70572ed2022-11-02 13:14:20 -0700831 deps.Merge(a.archProperties.Arch.Arm64.ApexNativeDependencies)
Colin Crossa2aaa2f2022-10-03 12:41:50 -0700832 case android.Riscv64:
Colin Cross70572ed2022-11-02 13:14:20 -0700833 deps.Merge(a.archProperties.Arch.Riscv64.ApexNativeDependencies)
Jiyong Park59140302020-12-14 18:44:04 +0900834 case android.X86:
Colin Cross70572ed2022-11-02 13:14:20 -0700835 deps.Merge(a.archProperties.Arch.X86.ApexNativeDependencies)
Jiyong Park59140302020-12-14 18:44:04 +0900836 case android.X86_64:
Colin Cross70572ed2022-11-02 13:14:20 -0700837 deps.Merge(a.archProperties.Arch.X86_64.ApexNativeDependencies)
Jiyong Park59140302020-12-14 18:44:04 +0900838 default:
839 panic(fmt.Errorf("unsupported arch %v\n", ctx.Arch().ArchType))
840 }
841
Colin Cross70572ed2022-11-02 13:14:20 -0700842 addDependenciesForNativeModules(ctx, deps, target, imageVariation)
Sundong Ahn80c04892021-11-23 00:57:19 +0000843 ctx.AddFarVariationDependencies([]blueprint.Variation{
844 {Mutator: "os", Variation: target.OsVariation()},
845 {Mutator: "arch", Variation: target.ArchVariation()},
846 }, shBinaryTag, a.properties.Sh_binaries...)
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900847 }
848
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900849 // Common-arch dependencies come next
850 commonVariation := ctx.Config().AndroidCommonTarget.Variations()
Jiyong Park12a719c2021-01-07 15:31:24 +0900851 ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
Paul Duffin0b817782021-03-17 15:02:19 +0000852 ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
Andrei Onea115e7e72020-06-05 21:14:03 +0100853}
854
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900855// DepsMutator for the overridden properties.
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900856func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
857 if a.overridableProperties.Allowed_files != nil {
858 android.ExtractSourceDeps(ctx, a.overridableProperties.Allowed_files)
Andrei Onea115e7e72020-06-05 21:14:03 +0100859 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900860
861 commonVariation := ctx.Config().AndroidCommonTarget.Variations()
862 ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps...)
markchien7c803b82021-08-26 22:10:06 +0800863 ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900864 ctx.AddFarVariationDependencies(commonVariation, rroTag, a.overridableProperties.Rros...)
Remi NGUYEN VANbe901722022-03-02 21:00:33 +0900865 ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.overridableProperties.Bootclasspath_fragments...)
866 ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.overridableProperties.Systemserverclasspath_fragments...)
867 ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.overridableProperties.Java_libs...)
Daniel Norman5a3ce132021-08-26 15:44:43 -0700868 if prebuilts := a.overridableProperties.Prebuilts; len(prebuilts) > 0 {
869 // For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device)
870 // regardless of the TARGET_PREFER_* setting. See b/144532908
871 arches := ctx.DeviceConfig().Arches()
872 if len(arches) != 0 {
873 archForPrebuiltEtc := arches[0]
874 for _, arch := range arches {
875 // Prefer 64-bit arch if there is any
876 if arch.ArchType.Multilib == "lib64" {
877 archForPrebuiltEtc = arch
878 break
879 }
880 }
881 ctx.AddFarVariationDependencies([]blueprint.Variation{
882 {Mutator: "os", Variation: ctx.Os().String()},
883 {Mutator: "arch", Variation: archForPrebuiltEtc.String()},
884 }, prebuiltTag, prebuilts...)
885 }
886 }
Jaewoong Jung4cfdf7d2021-04-20 16:21:24 -0700887
888 // Dependencies for signing
889 if String(a.overridableProperties.Key) == "" {
890 ctx.PropertyErrorf("key", "missing")
891 return
892 }
893 ctx.AddDependency(ctx.Module(), keyTag, String(a.overridableProperties.Key))
894
895 cert := android.SrcIsModule(a.getCertString(ctx))
896 if cert != "" {
897 ctx.AddDependency(ctx.Module(), certificateTag, cert)
898 // empty cert is not an error. Cert and private keys will be directly found under
899 // PRODUCT_DEFAULT_DEV_CERTIFICATE
900 }
Andrei Onea115e7e72020-06-05 21:14:03 +0100901}
902
Jiyong Park8e6d52f2020-11-19 14:37:47 +0900903type ApexBundleInfo struct {
904 Contents *android.ApexContents
Andrei Onea115e7e72020-06-05 21:14:03 +0100905}
906
Paul Duffin949abc02020-12-08 10:34:30 +0000907var ApexBundleInfoProvider = blueprint.NewMutatorProvider(ApexBundleInfo{}, "apex_info")
Jiyong Park48ca7dc2018-10-10 14:01:00 +0900908
Paul Duffina7d6a892020-12-07 17:39:59 +0000909var _ ApexInfoMutator = (*apexBundle)(nil)
910
Martin Stjernholmbfffae72021-06-24 14:37:13 +0100911func (a *apexBundle) ApexVariationName() string {
912 return a.properties.ApexVariationName
913}
914
Paul Duffina7d6a892020-12-07 17:39:59 +0000915// ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900916// identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and
917// indirect) dependencies are collected. But a few types of modules that shouldn't be included in
918// the apexBundle (e.g. stub libraries) are not collected. Note that a single module can be depended
919// on by multiple apexBundles. In that case, the module is collected for all of the apexBundles.
Paul Duffin949abc02020-12-08 10:34:30 +0000920//
921// For each dependency between an apex and an ApexModule an ApexInfo object describing the apex
922// is passed to that module's BuildForApex(ApexInfo) method which collates them all in a list.
923// The apexMutator uses that list to create module variants for the apexes to which it belongs.
924// The relationship between module variants and apexes is not one-to-one as variants will be
925// shared between compatible apexes.
Paul Duffina7d6a892020-12-07 17:39:59 +0000926func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
Jooyung Handf78e212020-07-22 15:54:47 +0900927
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900928 // The VNDK APEX is special. For the APEX, the membership is described in a very different
929 // way. There is no dependency from the VNDK APEX to the VNDK libraries. Instead, VNDK
930 // libraries are self-identified by their vndk.enabled properties. There is no need to run
931 // this mutator for the APEX as nothing will be collected. So, let's return fast.
932 if a.vndkApex {
933 return
934 }
935
936 // Special casing for APEXes on non-system (e.g., vendor, odm, etc.) partitions. They are
937 // provided with a property named use_vndk_as_stable, which when set to true doesn't collect
938 // VNDK libraries as transitive dependencies. This option is useful for reducing the size of
939 // the non-system APEXes because the VNDK libraries won't be included (and duped) in the
940 // APEX, but shared across APEXes via the VNDK APEX.
Jooyung Handf78e212020-07-22 15:54:47 +0900941 useVndk := a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && mctx.Config().EnforceProductPartitionInterface())
942 excludeVndkLibs := useVndk && proptools.Bool(a.properties.Use_vndk_as_stable)
Jooyung Hanc5a96762022-02-04 11:54:50 +0900943 if proptools.Bool(a.properties.Use_vndk_as_stable) {
944 if !useVndk {
945 mctx.PropertyErrorf("use_vndk_as_stable", "not supported for system/system_ext APEXes")
946 }
947 mctx.VisitDirectDepsWithTag(sharedLibTag, func(dep android.Module) {
948 if c, ok := dep.(*cc.Module); ok && c.IsVndk() {
949 mctx.PropertyErrorf("use_vndk_as_stable", "Trying to include a VNDK library(%s) while use_vndk_as_stable is true.", dep.Name())
950 }
951 })
952 if mctx.Failed() {
953 return
954 }
Jooyung Handf78e212020-07-22 15:54:47 +0900955 }
956
Colin Cross56a83212020-09-15 18:30:11 -0700957 continueApexDepsWalk := func(child, parent android.Module) bool {
Jooyung Han698dd9f2020-07-22 15:17:19 +0900958 am, ok := child.(android.ApexModule)
959 if !ok || !am.CanHaveApexVariants() {
960 return false
Jiyong Parkf760cae2020-02-12 07:53:12 +0900961 }
Paul Duffin573989d2021-03-17 13:25:29 +0000962 depTag := mctx.OtherModuleDependencyTag(child)
963
964 // Check to see if the tag always requires that the child module has an apex variant for every
965 // apex variant of the parent module. If it does not then it is still possible for something
966 // else, e.g. the DepIsInSameApex(...) method to decide that a variant is required.
967 if required, ok := depTag.(android.AlwaysRequireApexVariantTag); ok && required.AlwaysRequireApexVariant() {
968 return true
969 }
Paul Duffin4c3e8e22021-03-18 15:41:29 +0000970 if !android.IsDepInSameApex(mctx, parent, child) {
Jooyung Han698dd9f2020-07-22 15:17:19 +0900971 return false
972 }
Jooyung Handf78e212020-07-22 15:54:47 +0900973 if excludeVndkLibs {
974 if c, ok := child.(*cc.Module); ok && c.IsVndk() {
975 return false
976 }
977 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900978 // By default, all the transitive dependencies are collected, unless filtered out
979 // above.
Colin Cross56a83212020-09-15 18:30:11 -0700980 return true
981 }
982
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900983 // Records whether a certain module is included in this apexBundle via direct dependency or
984 // inndirect dependency.
985 contents := make(map[string]android.ApexMembership)
Colin Cross56a83212020-09-15 18:30:11 -0700986 mctx.WalkDeps(func(child, parent android.Module) bool {
987 if !continueApexDepsWalk(child, parent) {
988 return false
989 }
Jooyung Han698dd9f2020-07-22 15:17:19 +0900990 // If the parent is apexBundle, this child is directly depended.
991 _, directDep := parent.(*apexBundle)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900992 depName := mctx.OtherModuleName(child)
Colin Cross56a83212020-09-15 18:30:11 -0700993 contents[depName] = contents[depName].Add(directDep)
994 return true
995 })
996
Jiyong Parkc0ec6f92020-11-19 23:00:52 +0900997 // The membership information is saved for later access
Jiyong Parke4758ed2020-11-18 01:34:22 +0900998 apexContents := android.NewApexContents(contents)
Colin Cross56a83212020-09-15 18:30:11 -0700999 mctx.SetProvider(ApexBundleInfoProvider, ApexBundleInfo{
1000 Contents: apexContents,
1001 })
1002
Jooyung Haned124c32021-01-26 11:43:46 +09001003 minSdkVersion := a.minSdkVersion(mctx)
1004 // When min_sdk_version is not set, the apex is built against FutureApiLevel.
1005 if minSdkVersion.IsNone() {
1006 minSdkVersion = android.FutureApiLevel
1007 }
1008
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001009 // This is the main part of this mutator. Mark the collected dependencies that they need to
1010 // be built for this apexBundle.
Jiyong Park78349b52021-05-12 17:13:56 +09001011
Martin Stjernholmbfffae72021-06-24 14:37:13 +01001012 apexVariationName := proptools.StringDefault(a.properties.Apex_name, mctx.ModuleName()) // could be com.android.foo
1013 a.properties.ApexVariationName = apexVariationName
Colin Cross56a83212020-09-15 18:30:11 -07001014 apexInfo := android.ApexInfo{
Martin Stjernholmbfffae72021-06-24 14:37:13 +01001015 ApexVariationName: apexVariationName,
Jiyong Park4eab21d2021-04-15 15:17:54 +09001016 MinSdkVersion: minSdkVersion,
Colin Cross56a83212020-09-15 18:30:11 -07001017 Updatable: a.Updatable(),
Jiyong Park1bc84122021-06-22 20:23:05 +09001018 UsePlatformApis: a.UsePlatformApis(),
Martin Stjernholmbfffae72021-06-24 14:37:13 +01001019 InApexVariants: []string{apexVariationName},
1020 InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo
Colin Cross56a83212020-09-15 18:30:11 -07001021 ApexContents: []*android.ApexContents{apexContents},
1022 }
Colin Cross56a83212020-09-15 18:30:11 -07001023 mctx.WalkDeps(func(child, parent android.Module) bool {
1024 if !continueApexDepsWalk(child, parent) {
1025 return false
1026 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001027 child.(android.ApexModule).BuildForApex(apexInfo) // leave a mark!
Jooyung Han698dd9f2020-07-22 15:17:19 +09001028 return true
Jiyong Parkf760cae2020-02-12 07:53:12 +09001029 })
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001030}
1031
Paul Duffina7d6a892020-12-07 17:39:59 +00001032type ApexInfoMutator interface {
Martin Stjernholmbfffae72021-06-24 14:37:13 +01001033 // ApexVariationName returns the name of the APEX variation to use in the apex
1034 // mutator etc. It is the same name as ApexInfo.ApexVariationName.
1035 ApexVariationName() string
1036
Paul Duffina7d6a892020-12-07 17:39:59 +00001037 // ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are
1038 // depended upon by an apex and which require an apex specific variant.
1039 ApexInfoMutator(android.TopDownMutatorContext)
1040}
1041
1042// apexInfoMutator delegates the work of identifying which modules need an ApexInfo and apex
1043// specific variant to modules that support the ApexInfoMutator.
Spandan Das42e89502022-05-06 22:12:55 +00001044// It also propagates updatable=true to apps of updatable apexes
Paul Duffina7d6a892020-12-07 17:39:59 +00001045func apexInfoMutator(mctx android.TopDownMutatorContext) {
1046 if !mctx.Module().Enabled() {
1047 return
1048 }
1049
1050 if a, ok := mctx.Module().(ApexInfoMutator); ok {
1051 a.ApexInfoMutator(mctx)
Paul Duffina7d6a892020-12-07 17:39:59 +00001052 }
Spandan Das42e89502022-05-06 22:12:55 +00001053 enforceAppUpdatability(mctx)
Paul Duffina7d6a892020-12-07 17:39:59 +00001054}
1055
Spandan Das66773252022-01-15 00:23:18 +00001056// apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module
1057// This check is enforced for updatable modules
1058func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) {
1059 if !mctx.Module().Enabled() {
1060 return
1061 }
Spandan Das08c911f2022-01-21 22:07:26 +00001062 if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting() {
Spandan Das66773252022-01-15 00:23:18 +00001063 mctx.WalkDeps(func(child, parent android.Module) bool {
Spandan Dasd9c23ab2022-02-10 02:34:13 +00001064 // b/208656169 Do not propagate strict updatability linting to libcore/
1065 // These libs are available on the classpath during compilation
1066 // These libs are transitive deps of the sdk. See java/sdk.go:decodeSdkDep
1067 // Only skip libraries defined in libcore root, not subdirectories
1068 if mctx.OtherModuleDir(child) == "libcore" {
1069 // Do not traverse transitive deps of libcore/ libs
1070 return false
1071 }
Spandan Das2cf278e2022-03-24 20:19:35 +00001072 if android.InList(child.Name(), skipLintJavalibAllowlist) {
1073 return false
1074 }
Spandan Das66773252022-01-15 00:23:18 +00001075 if lintable, ok := child.(java.LintDepSetsIntf); ok {
1076 lintable.SetStrictUpdatabilityLinting(true)
1077 }
1078 // visit transitive deps
1079 return true
1080 })
1081 }
1082}
1083
Spandan Das42e89502022-05-06 22:12:55 +00001084// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
1085func enforceAppUpdatability(mctx android.TopDownMutatorContext) {
1086 if !mctx.Module().Enabled() {
1087 return
1088 }
1089 if apex, ok := mctx.Module().(*apexBundle); ok && apex.Updatable() {
1090 // checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults
1091 mctx.VisitDirectDeps(func(module android.Module) {
1092 // ignore android_test_app
1093 if app, ok := module.(*java.AndroidApp); ok {
1094 app.SetUpdatable(true)
1095 }
1096 })
1097 }
1098}
1099
Spandan Das08c911f2022-01-21 22:07:26 +00001100// TODO: b/215736885 Whittle the denylist
1101// Transitive deps of certain mainline modules baseline NewApi errors
1102// Skip these mainline modules for now
1103var (
1104 skipStrictUpdatabilityLintAllowlist = []string{
1105 "com.android.art",
1106 "com.android.art.debug",
1107 "com.android.conscrypt",
1108 "com.android.media",
1109 // test apexes
1110 "test_com.android.art",
1111 "test_com.android.conscrypt",
1112 "test_com.android.media",
1113 "test_jitzygote_com.android.art",
1114 }
Spandan Das2cf278e2022-03-24 20:19:35 +00001115
1116 // TODO: b/215736885 Remove this list
1117 skipLintJavalibAllowlist = []string{
1118 "conscrypt.module.platform.api.stubs",
1119 "conscrypt.module.public.api.stubs",
1120 "conscrypt.module.public.api.stubs.system",
1121 "conscrypt.module.public.api.stubs.module_lib",
1122 "framework-media.stubs",
1123 "framework-media.stubs.system",
1124 "framework-media.stubs.module_lib",
1125 }
Spandan Das08c911f2022-01-21 22:07:26 +00001126)
1127
1128func (a *apexBundle) checkStrictUpdatabilityLinting() bool {
1129 return a.Updatable() && !android.InList(a.ApexVariationName(), skipStrictUpdatabilityLintAllowlist)
1130}
1131
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001132// apexUniqueVariationsMutator checks if any dependencies use unique apex variations. If so, use
1133// unique apex variations for this module. See android/apex.go for more about unique apex variant.
1134// TODO(jiyong): move this to android/apex.go?
Colin Crossaede88c2020-08-11 12:17:01 -07001135func apexUniqueVariationsMutator(mctx android.BottomUpMutatorContext) {
1136 if !mctx.Module().Enabled() {
1137 return
1138 }
1139 if am, ok := mctx.Module().(android.ApexModule); ok {
Colin Cross56a83212020-09-15 18:30:11 -07001140 android.UpdateUniqueApexVariationsForDeps(mctx, am)
1141 }
1142}
1143
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001144// apexTestForDepsMutator checks if this module is a test for an apex. If so, add a dependency on
1145// the apex in order to retrieve its contents later.
1146// TODO(jiyong): move this to android/apex.go?
Colin Cross56a83212020-09-15 18:30:11 -07001147func apexTestForDepsMutator(mctx android.BottomUpMutatorContext) {
1148 if !mctx.Module().Enabled() {
1149 return
1150 }
Colin Cross56a83212020-09-15 18:30:11 -07001151 if am, ok := mctx.Module().(android.ApexModule); ok {
1152 if testFor := am.TestFor(); len(testFor) > 0 {
1153 mctx.AddFarVariationDependencies([]blueprint.Variation{
1154 {Mutator: "os", Variation: am.Target().OsVariation()},
1155 {"arch", "common"},
1156 }, testForTag, testFor...)
1157 }
1158 }
1159}
1160
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001161// TODO(jiyong): move this to android/apex.go?
Colin Cross56a83212020-09-15 18:30:11 -07001162func apexTestForMutator(mctx android.BottomUpMutatorContext) {
1163 if !mctx.Module().Enabled() {
1164 return
1165 }
Colin Cross56a83212020-09-15 18:30:11 -07001166 if _, ok := mctx.Module().(android.ApexModule); ok {
1167 var contents []*android.ApexContents
1168 for _, testFor := range mctx.GetDirectDepsWithTag(testForTag) {
1169 abInfo := mctx.OtherModuleProvider(testFor, ApexBundleInfoProvider).(ApexBundleInfo)
1170 contents = append(contents, abInfo.Contents)
1171 }
1172 mctx.SetProvider(android.ApexTestForInfoProvider, android.ApexTestForInfo{
1173 ApexContents: contents,
1174 })
Colin Crossaede88c2020-08-11 12:17:01 -07001175 }
1176}
1177
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001178// markPlatformAvailability marks whether or not a module can be available to platform. A module
1179// cannot be available to platform if 1) it is explicitly marked as not available (i.e.
1180// "//apex_available:platform" is absent) or 2) it depends on another module that isn't (or can't
1181// be) available to platform
1182// TODO(jiyong): move this to android/apex.go?
Jiyong Park89e850a2020-04-07 16:37:39 +09001183func markPlatformAvailability(mctx android.BottomUpMutatorContext) {
1184 // Host and recovery are not considered as platform
1185 if mctx.Host() || mctx.Module().InstallInRecovery() {
1186 return
1187 }
1188
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001189 am, ok := mctx.Module().(android.ApexModule)
1190 if !ok {
1191 return
1192 }
Jiyong Park89e850a2020-04-07 16:37:39 +09001193
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001194 availableToPlatform := am.AvailableFor(android.AvailableToPlatform)
Jiyong Park89e850a2020-04-07 16:37:39 +09001195
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001196 // If any of the dep is not available to platform, this module is also considered as being
1197 // not available to platform even if it has "//apex_available:platform"
1198 mctx.VisitDirectDeps(func(child android.Module) {
Paul Duffin4c3e8e22021-03-18 15:41:29 +00001199 if !android.IsDepInSameApex(mctx, am, child) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001200 // if the dependency crosses apex boundary, don't consider it
1201 return
Jiyong Park89e850a2020-04-07 16:37:39 +09001202 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001203 if dep, ok := child.(android.ApexModule); ok && dep.NotAvailableForPlatform() {
1204 availableToPlatform = false
1205 // TODO(b/154889534) trigger an error when 'am' has
1206 // "//apex_available:platform"
Jiyong Park89e850a2020-04-07 16:37:39 +09001207 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001208 })
Jiyong Park89e850a2020-04-07 16:37:39 +09001209
Paul Duffinb5769c12021-05-12 16:16:51 +01001210 // Exception 1: check to see if the module always requires it.
1211 if am.AlwaysRequiresPlatformApexVariant() {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001212 availableToPlatform = true
1213 }
1214
1215 // Exception 2: bootstrap bionic libraries are also always available to platform
1216 if cc.InstallToBootstrap(mctx.ModuleName(), mctx.Config()) {
1217 availableToPlatform = true
1218 }
1219
1220 if !availableToPlatform {
1221 am.SetNotAvailableForPlatform()
Jiyong Park89e850a2020-04-07 16:37:39 +09001222 }
1223}
1224
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001225// apexMutator visits each module and creates apex variations if the module was marked in the
Paul Duffin949abc02020-12-08 10:34:30 +00001226// previous run of apexInfoMutator.
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001227func apexMutator(mctx android.BottomUpMutatorContext) {
Jooyung Han49f67012020-04-17 13:43:10 +09001228 if !mctx.Module().Enabled() {
1229 return
1230 }
Colin Cross56a83212020-09-15 18:30:11 -07001231
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001232 // This is the usual path.
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001233 if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
Colin Cross56a83212020-09-15 18:30:11 -07001234 android.CreateApexVariations(mctx, am)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001235 return
1236 }
1237
1238 // apexBundle itself is mutated so that it and its dependencies have the same apex variant.
Martin Stjernholmbfffae72021-06-24 14:37:13 +01001239 if ai, ok := mctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
1240 apexBundleName := ai.ApexVariationName()
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001241 mctx.CreateVariations(apexBundleName)
Martin Stjernholmec009002021-03-27 15:18:31 +00001242 if strings.HasPrefix(apexBundleName, "com.android.art") {
1243 // Create an alias from the platform variant. This is done to make
1244 // test_for dependencies work for modules that are split by the APEX
1245 // mutator, since test_for dependencies always go to the platform variant.
1246 // This doesn't happen for normal APEXes that are disjunct, so only do
1247 // this for the overlapping ART APEXes.
1248 // TODO(b/183882457): Remove this if the test_for functionality is
1249 // refactored to depend on the proper APEX variants instead of platform.
1250 mctx.CreateAliasVariation("", apexBundleName)
1251 }
Jiyong Park5d790c32019-11-15 18:40:32 +09001252 } else if o, ok := mctx.Module().(*OverrideApex); ok {
1253 apexBundleName := o.GetOverriddenModuleName()
1254 if apexBundleName == "" {
1255 mctx.ModuleErrorf("base property is not set")
1256 return
1257 }
1258 mctx.CreateVariations(apexBundleName)
Martin Stjernholmec009002021-03-27 15:18:31 +00001259 if strings.HasPrefix(apexBundleName, "com.android.art") {
1260 // TODO(b/183882457): See note for CreateAliasVariation above.
1261 mctx.CreateAliasVariation("", apexBundleName)
1262 }
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001263 }
1264}
Sundong Ahne9b55722019-09-06 17:37:42 +09001265
Paul Duffin6717d882021-06-15 19:09:41 +01001266// apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific
1267// variant.
Martin Stjernholmbfffae72021-06-24 14:37:13 +01001268func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool {
Paul Duffin6717d882021-06-15 19:09:41 +01001269 if a, ok := module.(*apexBundle); ok {
Martin Stjernholmbfffae72021-06-24 14:37:13 +01001270 // TODO(jiyong): document the reason why the VNDK APEX is an exception here.
Paul Duffin6717d882021-06-15 19:09:41 +01001271 return !a.vndkApex
1272 }
1273
Martin Stjernholmbfffae72021-06-24 14:37:13 +01001274 return true
Paul Duffin6717d882021-06-15 19:09:41 +01001275}
1276
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001277// See android.UpdateDirectlyInAnyApex
1278// TODO(jiyong): move this to android/apex.go?
Colin Cross56a83212020-09-15 18:30:11 -07001279func apexDirectlyInAnyMutator(mctx android.BottomUpMutatorContext) {
1280 if !mctx.Module().Enabled() {
1281 return
1282 }
1283 if am, ok := mctx.Module().(android.ApexModule); ok {
1284 android.UpdateDirectlyInAnyApex(mctx, am)
1285 }
1286}
1287
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001288// apexPackaging represents a specific packaging method for an APEX.
Jiyong Park8e6d52f2020-11-19 14:37:47 +09001289type apexPackaging int
1290
1291const (
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001292 // imageApex is a packaging method where contents are included in a filesystem image which
1293 // is then included in a zip container. This is the most typical way of packaging.
Jiyong Park8e6d52f2020-11-19 14:37:47 +09001294 imageApex apexPackaging = iota
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001295
1296 // zipApex is a packaging method where contents are directly included in the zip container.
1297 // This is used for host-side testing - because the contents are easily accessible by
1298 // unzipping the container.
Jiyong Park8e6d52f2020-11-19 14:37:47 +09001299 zipApex
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001300
1301 // flattendApex is a packaging method where contents are not included in the APEX file, but
1302 // installed to /apex/<apexname> directory on the device. This packaging method is used for
1303 // old devices where the filesystem-based APEX file can't be supported.
Jiyong Park8e6d52f2020-11-19 14:37:47 +09001304 flattenedApex
1305)
1306
1307const (
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001308 // File extensions of an APEX for different packaging methods
Samiul Islam7c02e262021-09-08 17:48:28 +01001309 imageApexSuffix = ".apex"
1310 imageCapexSuffix = ".capex"
1311 zipApexSuffix = ".zipapex"
1312 flattenedSuffix = ".flattened"
Jiyong Park8e6d52f2020-11-19 14:37:47 +09001313
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001314 // variant names each of which is for a packaging method
Jiyong Park8e6d52f2020-11-19 14:37:47 +09001315 imageApexType = "image"
1316 zipApexType = "zip"
1317 flattenedApexType = "flattened"
1318
Dan Willemsen47e1a752021-10-16 18:36:13 -07001319 ext4FsType = "ext4"
1320 f2fsFsType = "f2fs"
Huang Jianan13cac632021-08-02 15:02:17 +08001321 erofsFsType = "erofs"
Jiyong Park8e6d52f2020-11-19 14:37:47 +09001322)
1323
1324// The suffix for the output "file", not the module
1325func (a apexPackaging) suffix() string {
1326 switch a {
1327 case imageApex:
1328 return imageApexSuffix
1329 case zipApex:
1330 return zipApexSuffix
1331 default:
1332 panic(fmt.Errorf("unknown APEX type %d", a))
1333 }
1334}
1335
1336func (a apexPackaging) name() string {
1337 switch a {
1338 case imageApex:
1339 return imageApexType
1340 case zipApex:
1341 return zipApexType
1342 default:
1343 panic(fmt.Errorf("unknown APEX type %d", a))
1344 }
1345}
1346
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001347// apexFlattenedMutator creates one or more variations each of which is for a packaging method.
1348// TODO(jiyong): give a better name to this mutator
Sundong Ahne9b55722019-09-06 17:37:42 +09001349func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
Jooyung Han49f67012020-04-17 13:43:10 +09001350 if !mctx.Module().Enabled() {
1351 return
1352 }
Sundong Ahne8fb7242019-09-17 13:50:45 +09001353 if ab, ok := mctx.Module().(*apexBundle); ok {
Sundong Ahnabb64432019-10-22 13:58:29 +09001354 var variants []string
1355 switch proptools.StringDefault(ab.properties.Payload_type, "image") {
1356 case "image":
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001357 // This is the normal case. Note that both image and flattend APEXes are
1358 // created. The image type is installed to the system partition, while the
1359 // flattened APEX is (optionally) installed to the system_ext partition.
1360 // This is mostly for GSI which has to support wide range of devices. If GSI
1361 // is installed on a newer (APEX-capable) device, the image APEX in the
1362 // system will be used. However, if the same GSI is installed on an old
1363 // device which can't support image APEX, the flattened APEX in the
1364 // system_ext partion (which still is part of GSI) is used instead.
Sundong Ahnabb64432019-10-22 13:58:29 +09001365 variants = append(variants, imageApexType, flattenedApexType)
1366 case "zip":
1367 variants = append(variants, zipApexType)
1368 case "both":
1369 variants = append(variants, imageApexType, zipApexType, flattenedApexType)
1370 default:
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001371 mctx.PropertyErrorf("payload_type", "%q is not one of \"image\", \"zip\", or \"both\".", *ab.properties.Payload_type)
Sundong Ahnabb64432019-10-22 13:58:29 +09001372 return
1373 }
1374
1375 modules := mctx.CreateLocalVariations(variants...)
1376
1377 for i, v := range variants {
1378 switch v {
1379 case imageApexType:
1380 modules[i].(*apexBundle).properties.ApexType = imageApex
1381 case zipApexType:
1382 modules[i].(*apexBundle).properties.ApexType = zipApex
1383 case flattenedApexType:
1384 modules[i].(*apexBundle).properties.ApexType = flattenedApex
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001385 // See the comment above for why system_ext.
Jooyung Han91df2082019-11-20 01:49:42 +09001386 if !mctx.Config().FlattenApex() && ab.Platform() {
Sundong Ahnd95aa2d2019-10-08 19:34:03 +09001387 modules[i].(*apexBundle).MakeAsSystemExt()
1388 }
Sundong Ahnabb64432019-10-22 13:58:29 +09001389 }
Sundong Ahne9b55722019-09-06 17:37:42 +09001390 }
Jiyong Park5d790c32019-11-15 18:40:32 +09001391 } else if _, ok := mctx.Module().(*OverrideApex); ok {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001392 // payload_type is forcibly overridden to "image"
1393 // TODO(jiyong): is this the right decision?
Jiyong Park5d790c32019-11-15 18:40:32 +09001394 mctx.CreateVariations(imageApexType, flattenedApexType)
Sundong Ahne9b55722019-09-06 17:37:42 +09001395 }
1396}
1397
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001398var _ android.DepIsInSameApex = (*apexBundle)(nil)
Theotime Combes4ba38c12020-06-12 12:46:59 +00001399
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001400// Implements android.DepInInSameApex
Sasha Smundak6f9e91d2022-06-28 22:43:04 -07001401func (a *apexBundle) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
Jiyong Parka7bc8ad2019-10-15 15:20:07 +09001402 // direct deps of an APEX bundle are all part of the APEX bundle
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001403 // TODO(jiyong): shouldn't we look into the payload field of the dependencyTag?
Jiyong Parka7bc8ad2019-10-15 15:20:07 +09001404 return true
1405}
1406
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001407var _ android.OutputFileProducer = (*apexBundle)(nil)
1408
1409// Implements android.OutputFileProducer
1410func (a *apexBundle) OutputFiles(tag string) (android.Paths, error) {
1411 switch tag {
Paul Duffin74f05592020-11-25 16:37:46 +00001412 case "", android.DefaultDistTag:
1413 // This is the default dist path.
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001414 return android.Paths{a.outputFile}, nil
Jooyung Hana6d36672022-02-24 13:58:07 +09001415 case imageApexSuffix:
1416 // uncompressed one
1417 if a.outputApexFile != nil {
1418 return android.Paths{a.outputApexFile}, nil
1419 }
1420 fallthrough
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001421 default:
1422 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1423 }
1424}
1425
Inseob Kim5eb7ee92022-04-27 10:30:34 +09001426var _ multitree.Exportable = (*apexBundle)(nil)
1427
1428func (a *apexBundle) Exportable() bool {
1429 if a.properties.ApexType == flattenedApex {
1430 return false
1431 }
1432 return true
1433}
1434
1435func (a *apexBundle) TaggedOutputs() map[string]android.Paths {
1436 ret := make(map[string]android.Paths)
1437 ret["apex"] = android.Paths{a.outputFile}
1438 return ret
1439}
1440
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001441var _ cc.Coverage = (*apexBundle)(nil)
1442
1443// Implements cc.Coverage
1444func (a *apexBundle) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
1445 return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled()
1446}
1447
1448// Implements cc.Coverage
Ivan Lozanod7586b62021-04-01 09:49:36 -04001449func (a *apexBundle) SetPreventInstall() {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001450 a.properties.PreventInstall = true
1451}
1452
1453// Implements cc.Coverage
1454func (a *apexBundle) HideFromMake() {
1455 a.properties.HideFromMake = true
Colin Crosse6a83e62020-12-17 18:22:34 -08001456 // This HideFromMake is shadowing the ModuleBase one, call through to it for now.
1457 // TODO(ccross): untangle these
1458 a.ModuleBase.HideFromMake()
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001459}
1460
1461// Implements cc.Coverage
1462func (a *apexBundle) MarkAsCoverageVariant(coverage bool) {
1463 a.properties.IsCoverageVariant = coverage
1464}
1465
1466// Implements cc.Coverage
1467func (a *apexBundle) EnableCoverageIfNeeded() {}
1468
1469var _ android.ApexBundleDepsInfoIntf = (*apexBundle)(nil)
1470
Oriol Prieto Gascoa07099d2021-10-14 15:33:41 -04001471// Implements android.ApexBundleDepsInfoIntf
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001472func (a *apexBundle) Updatable() bool {
Mathew Inwoodf8dcf5e2021-02-16 11:40:16 +00001473 return proptools.BoolDefault(a.properties.Updatable, true)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001474}
1475
Jiyong Parkf4020582021-11-29 12:37:10 +09001476func (a *apexBundle) FutureUpdatable() bool {
1477 return proptools.BoolDefault(a.properties.Future_updatable, false)
1478}
1479
Jiyong Park1bc84122021-06-22 20:23:05 +09001480func (a *apexBundle) UsePlatformApis() bool {
1481 return proptools.BoolDefault(a.properties.Platform_apis, false)
1482}
1483
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001484// getCertString returns the name of the cert that should be used to sign this APEX. This is
1485// basically from the "certificate" property, but could be overridden by the device config.
Colin Cross0ea8ba82019-06-06 14:33:29 -07001486func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
Jooyung Han27151d92019-12-16 17:45:32 +09001487 moduleName := ctx.ModuleName()
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001488 // VNDK APEXes share the same certificate. To avoid adding a new VNDK version to the
1489 // OVERRIDE_* list, we check with the pseudo module name to see if its certificate is
1490 // overridden.
Jooyung Han27151d92019-12-16 17:45:32 +09001491 if a.vndkApex {
1492 moduleName = vndkApexName
1493 }
1494 certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(moduleName)
Jiyong Parkb2742fd2019-02-11 11:38:15 +09001495 if overridden {
Jaewoong Jungacb6db32019-02-28 16:22:30 +00001496 return ":" + certificate
Jiyong Parkb2742fd2019-02-11 11:38:15 +09001497 }
Jaewoong Jung4cfdf7d2021-04-20 16:21:24 -07001498 return String(a.overridableProperties.Certificate)
Jiyong Parkb2742fd2019-02-11 11:38:15 +09001499}
1500
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001501// See the installable property
Jiyong Park92c0f9c2018-12-13 23:14:57 +09001502func (a *apexBundle) installable() bool {
Jiyong Parkee9a98d2019-08-09 14:44:36 +09001503 return !a.properties.PreventInstall && (a.properties.Installable == nil || proptools.Bool(a.properties.Installable))
Jiyong Park92c0f9c2018-12-13 23:14:57 +09001504}
1505
Nikita Ioffeda6dc312021-06-09 19:43:46 +01001506// See the generate_hashtree property
1507func (a *apexBundle) shouldGenerateHashtree() bool {
Nikita Ioffee261ae62021-06-16 18:15:03 +01001508 return proptools.BoolDefault(a.properties.Generate_hashtree, true)
Nikita Ioffec72b5dd2019-12-07 17:30:22 +00001509}
1510
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001511// See the test_only_unsigned_payload property
Dario Frenica913392020-04-27 18:21:11 +01001512func (a *apexBundle) testOnlyShouldSkipPayloadSign() bool {
1513 return proptools.Bool(a.properties.Test_only_unsigned_payload)
1514}
1515
Mohammad Samiul Islama8008f92020-12-22 10:47:50 +00001516// See the test_only_force_compression property
1517func (a *apexBundle) testOnlyShouldForceCompression() bool {
1518 return proptools.Bool(a.properties.Test_only_force_compression)
1519}
1520
Dennis Shenaf41bc12022-08-03 16:46:43 +00001521// See the dynamic_common_lib_apex property
1522func (a *apexBundle) dynamic_common_lib_apex() bool {
1523 return proptools.BoolDefault(a.properties.Dynamic_common_lib_apex, false)
1524}
1525
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001526// These functions are interfacing with cc/sanitizer.go. The entire APEX (along with all of its
1527// members) can be sanitized, either forcibly, or by the global configuration. For some of the
1528// sanitizers, extra dependencies can be forcibly added as well.
Jiyong Parkda6eb592018-12-19 17:12:36 +09001529
Jiyong Parkf97782b2019-02-13 20:28:58 +09001530func (a *apexBundle) EnableSanitizer(sanitizerName string) {
1531 if !android.InList(sanitizerName, a.properties.SanitizerNames) {
1532 a.properties.SanitizerNames = append(a.properties.SanitizerNames, sanitizerName)
1533 }
1534}
1535
Lukacs T. Berki01a648a2022-06-17 08:59:37 +02001536func (a *apexBundle) IsSanitizerEnabled(config android.Config, sanitizerName string) bool {
Jiyong Parkf97782b2019-02-13 20:28:58 +09001537 if android.InList(sanitizerName, a.properties.SanitizerNames) {
1538 return true
Jiyong Park235e67c2019-02-09 11:50:56 +09001539 }
1540
1541 // Then follow the global setting
Sasha Smundak6f9e91d2022-06-28 22:43:04 -07001542 var globalSanitizerNames []string
Jiyong Park388ef3f2019-01-28 19:47:32 +09001543 if a.Host() {
Lukacs T. Berki01a648a2022-06-17 08:59:37 +02001544 globalSanitizerNames = config.SanitizeHost()
Jiyong Park388ef3f2019-01-28 19:47:32 +09001545 } else {
Lukacs T. Berki01a648a2022-06-17 08:59:37 +02001546 arches := config.SanitizeDeviceArch()
Jiyong Park388ef3f2019-01-28 19:47:32 +09001547 if len(arches) == 0 || android.InList(a.Arch().ArchType.Name, arches) {
Lukacs T. Berki01a648a2022-06-17 08:59:37 +02001548 globalSanitizerNames = config.SanitizeDevice()
Jiyong Park388ef3f2019-01-28 19:47:32 +09001549 }
1550 }
1551 return android.InList(sanitizerName, globalSanitizerNames)
Jiyong Park379de2f2018-12-19 02:47:14 +09001552}
1553
Jooyung Han8ce8db92020-05-15 19:05:05 +09001554func (a *apexBundle) AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001555 // TODO(jiyong): move this info (the sanitizer name, the lib name, etc.) to cc/sanitize.go
1556 // Keep only the mechanism here.
Jooyung Han8ce8db92020-05-15 19:05:05 +09001557 if ctx.Device() && sanitizerName == "hwaddress" && strings.HasPrefix(a.Name(), "com.android.runtime") {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001558 imageVariation := a.getImageVariation(ctx)
Jooyung Han8ce8db92020-05-15 19:05:05 +09001559 for _, target := range ctx.MultiTargets() {
1560 if target.Arch.ArchType.Multilib == "lib64" {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001561 addDependenciesForNativeModules(ctx, ApexNativeDependencies{
Colin Cross4c4c1be2022-02-10 11:41:18 -08001562 Native_shared_libs: []string{"libclang_rt.hwasan"},
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001563 Tests: nil,
1564 Jni_libs: nil,
1565 Binaries: nil,
1566 }, target, imageVariation)
Jooyung Han8ce8db92020-05-15 19:05:05 +09001567 break
1568 }
1569 }
1570 }
1571}
1572
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001573// apexFileFor<Type> functions below create an apexFile struct for a given Soong module. The
1574// returned apexFile saves information about the Soong module that will be used for creating the
1575// build rules.
Jiyong Park1833cef2019-12-13 13:28:36 +09001576func apexFileForNativeLibrary(ctx android.BaseModuleContext, ccMod *cc.Module, handleSpecialLibs bool) apexFile {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001577 // Decide the APEX-local directory by the multilib of the library In the future, we may
1578 // query this to the module.
1579 // TODO(jiyong): use the new PackagingSpec
Jiyong Parkf653b052019-11-18 15:39:01 +09001580 var dirInApex string
Martin Stjernholm279de572019-09-10 23:18:20 +01001581 switch ccMod.Arch().ArchType.Multilib {
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001582 case "lib32":
1583 dirInApex = "lib"
1584 case "lib64":
1585 dirInApex = "lib64"
1586 }
Colin Cross3b19f5d2019-09-17 14:45:31 -07001587 if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
Martin Stjernholm279de572019-09-10 23:18:20 +01001588 dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath)
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001589 }
Jooyung Han35155c42020-02-06 17:33:20 +09001590 dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath())
Jiyong Park1833cef2019-12-13 13:28:36 +09001591 if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), ctx.Config()) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001592 // Special case for Bionic libs and other libs installed with them. This is to
1593 // prevent those libs from being included in the search path
1594 // /apex/com.android.runtime/${LIB}. This exclusion is required because those libs
1595 // in the Runtime APEX are available via the legacy paths in /system/lib/. By the
1596 // init process, the libs in the APEX are bind-mounted to the legacy paths and thus
1597 // will be loaded into the default linker namespace (aka "platform" namespace). If
1598 // the libs are directly in /apex/com.android.runtime/${LIB} then the same libs will
1599 // be loaded again into the runtime linker namespace, which will result in double
1600 // loading of them, which isn't supported.
Martin Stjernholm279de572019-09-10 23:18:20 +01001601 dirInApex = filepath.Join(dirInApex, "bionic")
Jiyong Parkb0788572018-12-20 22:10:17 +09001602 }
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001603
Colin Cross1d487152022-10-03 19:14:46 -07001604 fileToCopy := android.OutputFileForModule(ctx, ccMod, "")
Yo Chiange8128052020-07-23 20:09:18 +08001605 androidMkModuleName := ccMod.BaseModuleName() + ccMod.Properties.SubName
1606 return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, ccMod)
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001607}
1608
Jiyong Park1833cef2019-12-13 13:28:36 +09001609func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFile {
Jooyung Han35155c42020-02-06 17:33:20 +09001610 dirInApex := "bin"
Colin Cross3b19f5d2019-09-17 14:45:31 -07001611 if cc.Target().NativeBridge == android.NativeBridgeEnabled {
dimitry8d6dde82019-07-11 10:23:53 +02001612 dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
Jiyong Parkacbf6c72019-07-09 16:19:16 +09001613 }
Jooyung Han35155c42020-02-06 17:33:20 +09001614 dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
Colin Cross1d487152022-10-03 19:14:46 -07001615 fileToCopy := android.OutputFileForModule(ctx, cc, "")
Yo Chiange8128052020-07-23 20:09:18 +08001616 androidMkModuleName := cc.BaseModuleName() + cc.Properties.SubName
1617 af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, cc)
Jiyong Parkf653b052019-11-18 15:39:01 +09001618 af.symlinks = cc.Symlinks()
Liz Kammer1c14a212020-05-12 15:26:55 -07001619 af.dataPaths = cc.DataPaths()
Jiyong Parkf653b052019-11-18 15:39:01 +09001620 return af
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001621}
1622
Jiyong Park99644e92020-11-17 22:21:02 +09001623func apexFileForRustExecutable(ctx android.BaseModuleContext, rustm *rust.Module) apexFile {
1624 dirInApex := "bin"
1625 if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
1626 dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
1627 }
Colin Cross1d487152022-10-03 19:14:46 -07001628 fileToCopy := android.OutputFileForModule(ctx, rustm, "")
Jiyong Park99644e92020-11-17 22:21:02 +09001629 androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
1630 af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, rustm)
1631 return af
1632}
1633
1634func apexFileForRustLibrary(ctx android.BaseModuleContext, rustm *rust.Module) apexFile {
1635 // Decide the APEX-local directory by the multilib of the library
1636 // In the future, we may query this to the module.
1637 var dirInApex string
1638 switch rustm.Arch().ArchType.Multilib {
1639 case "lib32":
1640 dirInApex = "lib"
1641 case "lib64":
1642 dirInApex = "lib64"
1643 }
1644 if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
1645 dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
1646 }
Colin Cross1d487152022-10-03 19:14:46 -07001647 fileToCopy := android.OutputFileForModule(ctx, rustm, "")
Jiyong Park99644e92020-11-17 22:21:02 +09001648 androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
1649 return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, rustm)
1650}
1651
Jiyong Park1833cef2019-12-13 13:28:36 +09001652func apexFileForPyBinary(ctx android.BaseModuleContext, py *python.Module) apexFile {
Jiyong Parkf653b052019-11-18 15:39:01 +09001653 dirInApex := "bin"
1654 fileToCopy := py.HostToolPath().Path()
Yo Chiange8128052020-07-23 20:09:18 +08001655 return newApexFile(ctx, fileToCopy, py.BaseModuleName(), dirInApex, pyBinary, py)
Alex Light778127a2019-02-27 14:19:50 -08001656}
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001657
Jiyong Park1833cef2019-12-13 13:28:36 +09001658func apexFileForGoBinary(ctx android.BaseModuleContext, depName string, gb bootstrap.GoBinaryTool) apexFile {
Jiyong Parkf653b052019-11-18 15:39:01 +09001659 dirInApex := "bin"
Colin Crossa44551f2021-10-25 15:36:21 -07001660 fileToCopy := android.PathForGoBinary(ctx, gb)
Jiyong Parkf653b052019-11-18 15:39:01 +09001661 // NB: Since go binaries are static we don't need the module for anything here, which is
1662 // good since the go tool is a blueprint.Module not an android.Module like we would
1663 // normally use.
Jiyong Park1833cef2019-12-13 13:28:36 +09001664 return newApexFile(ctx, fileToCopy, depName, dirInApex, goBinary, nil)
Alex Light778127a2019-02-27 14:19:50 -08001665}
1666
Jaewoong Jung4b79e982020-06-01 10:45:49 -07001667func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFile {
Jiyong Parkf653b052019-11-18 15:39:01 +09001668 dirInApex := filepath.Join("bin", sh.SubDir())
Sundong Ahn80c04892021-11-23 00:57:19 +00001669 if sh.Target().NativeBridge == android.NativeBridgeEnabled {
1670 dirInApex = filepath.Join(dirInApex, sh.Target().NativeBridgeRelativePath)
1671 }
Jiyong Parkf653b052019-11-18 15:39:01 +09001672 fileToCopy := sh.OutputFile()
Yo Chiange8128052020-07-23 20:09:18 +08001673 af := newApexFile(ctx, fileToCopy, sh.BaseModuleName(), dirInApex, shBinary, sh)
Jiyong Parkf653b052019-11-18 15:39:01 +09001674 af.symlinks = sh.Symlinks()
1675 return af
Jiyong Park04480cf2019-02-06 00:16:29 +09001676}
1677
Jaewoong Jung4b79e982020-06-01 10:45:49 -07001678func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, depName string) apexFile {
Jooyung Han0703fd82020-08-26 22:11:53 +09001679 dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir())
Jiyong Parkf653b052019-11-18 15:39:01 +09001680 fileToCopy := prebuilt.OutputFile()
Jiyong Park1833cef2019-12-13 13:28:36 +09001681 return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt)
Jiyong Park48ca7dc2018-10-10 14:01:00 +09001682}
1683
atrost6e126252020-01-27 17:01:16 +00001684func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
1685 dirInApex := filepath.Join("etc", config.SubDir())
1686 fileToCopy := config.CompatConfig()
1687 return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, config)
1688}
1689
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001690// javaModule is an interface to handle all Java modules (java_library, dex_import, etc) in the same
1691// way.
1692type javaModule interface {
1693 android.Module
1694 BaseModuleName() string
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001695 DexJarBuildPath() java.OptionalDexJarPath
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001696 JacocoReportClassesFile() android.Path
1697 LintDepSets() java.LintDepSets
1698 Stem() string
1699}
1700
1701var _ javaModule = (*java.Library)(nil)
Bill Peckhama41a6962021-01-11 10:58:54 -08001702var _ javaModule = (*java.Import)(nil)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001703var _ javaModule = (*java.SdkLibrary)(nil)
1704var _ javaModule = (*java.DexImport)(nil)
1705var _ javaModule = (*java.SdkLibraryImport)(nil)
1706
Paul Duffin190fdef2021-04-26 10:33:59 +01001707// apexFileForJavaModule creates an apexFile for a java module's dex implementation jar.
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001708func apexFileForJavaModule(ctx android.BaseModuleContext, module javaModule) apexFile {
Martin Stjernholm8be1e6d2021-09-15 03:34:04 +01001709 return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath().PathOrNil())
Paul Duffin190fdef2021-04-26 10:33:59 +01001710}
1711
1712// apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file.
1713func apexFileForJavaModuleWithFile(ctx android.BaseModuleContext, module javaModule, dexImplementationJar android.Path) apexFile {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001714 dirInApex := "javalib"
Paul Duffin190fdef2021-04-26 10:33:59 +01001715 af := newApexFile(ctx, dexImplementationJar, module.BaseModuleName(), dirInApex, javaSharedLib, module)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001716 af.jacocoReportClassesFile = module.JacocoReportClassesFile()
1717 af.lintDepSets = module.LintDepSets()
1718 af.customStem = module.Stem() + ".jar"
Jiakai Zhang519c5c82021-09-16 06:15:39 +00001719 if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
1720 for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() {
1721 af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
1722 }
1723 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001724 return af
1725}
1726
1727// androidApp is an interface to handle all app modules (android_app, android_app_import, etc.) in
1728// the same way.
1729type androidApp interface {
Jiyong Parkf653b052019-11-18 15:39:01 +09001730 android.Module
1731 Privileged() bool
Jooyung Han39ee1192020-03-23 20:21:11 +09001732 InstallApkName() string
Jiyong Parkf653b052019-11-18 15:39:01 +09001733 OutputFile() android.Path
Jiyong Park618922e2020-01-08 13:35:43 +09001734 JacocoReportClassesFile() android.Path
Colin Cross503c1d02020-01-28 14:00:53 -08001735 Certificate() java.Certificate
Yo Chiange8128052020-07-23 20:09:18 +08001736 BaseModuleName() string
Colin Cross8355c152021-08-10 19:24:07 -07001737 LintDepSets() java.LintDepSets
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001738}
1739
1740var _ androidApp = (*java.AndroidApp)(nil)
1741var _ androidApp = (*java.AndroidAppImport)(nil)
1742
Oriol Prieto Gasco17e22902022-05-05 13:52:25 +00001743func sanitizedBuildIdForPath(ctx android.BaseModuleContext) string {
1744 buildId := ctx.Config().BuildId()
1745
1746 // The build ID is used as a suffix for a filename, so ensure that
1747 // the set of characters being used are sanitized.
1748 // - any word character: [a-zA-Z0-9_]
1749 // - dots: .
1750 // - dashes: -
1751 validRegex := regexp.MustCompile(`^[\w\.\-\_]+$`)
1752 if !validRegex.MatchString(buildId) {
1753 ctx.ModuleErrorf("Unable to use build id %s as filename suffix, valid characters are [a-z A-Z 0-9 _ . -].", buildId)
1754 }
1755 return buildId
1756}
Jingwen Chen8ce1efc2022-04-19 13:57:01 +00001757
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001758func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) apexFile {
Jiyong Parkf7487312019-10-17 12:54:30 +09001759 appDir := "app"
Jiyong Parkf653b052019-11-18 15:39:01 +09001760 if aapp.Privileged() {
Jiyong Parkf7487312019-10-17 12:54:30 +09001761 appDir = "priv-app"
1762 }
Jingwen Chen8ce1efc2022-04-19 13:57:01 +00001763
1764 // TODO(b/224589412, b/226559955): Ensure that the subdirname is suffixed
1765 // so that PackageManager correctly invalidates the existing installed apk
1766 // in favour of the new APK-in-APEX. See bugs for more information.
Oriol Prieto Gasco17e22902022-05-05 13:52:25 +00001767 dirInApex := filepath.Join(appDir, aapp.InstallApkName()+"@"+sanitizedBuildIdForPath(ctx))
Jiyong Parkf653b052019-11-18 15:39:01 +09001768 fileToCopy := aapp.OutputFile()
Jingwen Chen8ce1efc2022-04-19 13:57:01 +00001769
Yo Chiange8128052020-07-23 20:09:18 +08001770 af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp)
Jiyong Park618922e2020-01-08 13:35:43 +09001771 af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
Colin Cross8355c152021-08-10 19:24:07 -07001772 af.lintDepSets = aapp.LintDepSets()
Colin Cross503c1d02020-01-28 14:00:53 -08001773 af.certificate = aapp.Certificate()
Jiyong Parkcfaa1642020-02-28 16:51:07 +09001774
1775 if app, ok := aapp.(interface {
1776 OverriddenManifestPackageName() string
1777 }); ok {
1778 af.overriddenPackageName = app.OverriddenManifestPackageName()
1779 }
Jiyong Park618922e2020-01-08 13:35:43 +09001780 return af
Dario Frenicde2a032019-10-27 00:29:22 +01001781}
1782
Jiyong Park69aeba92020-04-24 21:16:36 +09001783func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, rro java.RuntimeResourceOverlayModule) apexFile {
1784 rroDir := "overlay"
1785 dirInApex := filepath.Join(rroDir, rro.Theme())
1786 fileToCopy := rro.OutputFile()
1787 af := newApexFile(ctx, fileToCopy, rro.Name(), dirInApex, app, rro)
1788 af.certificate = rro.Certificate()
1789
1790 if a, ok := rro.(interface {
1791 OverriddenManifestPackageName() string
1792 }); ok {
1793 af.overriddenPackageName = a.OverriddenManifestPackageName()
1794 }
1795 return af
1796}
1797
Ken Chenfad7f9d2021-11-10 22:02:57 +08001798func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram bpf.BpfModule) apexFile {
1799 dirInApex := filepath.Join("etc", "bpf", apex_sub_dir)
markchien2f59ec92020-09-02 16:23:38 +08001800 return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
1801}
1802
Jiyong Park12a719c2021-01-07 15:31:24 +09001803func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, fs filesystem.Filesystem) apexFile {
1804 dirInApex := filepath.Join("etc", "fs")
1805 return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, fs)
1806}
1807
Paul Duffin064b70c2020-11-02 17:32:38 +00001808// WalkPayloadDeps visits dependencies that contributes to the payload of this APEX. For each of the
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001809// visited module, the `do` callback is executed. Returning true in the callback continues the visit
1810// to the child modules. Returning false makes the visit to continue in the sibling or the parent
1811// modules. This is used in check* functions below.
Jooyung Han749dc692020-04-15 11:03:39 +09001812func (a *apexBundle) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) {
Paul Duffindf915ff2020-03-30 17:58:21 +01001813 ctx.WalkDeps(func(child, parent android.Module) bool {
Jiyong Park0f80c182020-01-31 02:49:53 +09001814 am, ok := child.(android.ApexModule)
1815 if !ok || !am.CanHaveApexVariants() {
1816 return false
1817 }
1818
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001819 // Filter-out unwanted depedendencies
1820 depTag := ctx.OtherModuleDependencyTag(child)
1821 if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
1822 return false
1823 }
Paul Duffin520917a2022-05-13 13:01:59 +00001824 if dt, ok := depTag.(*dependencyTag); ok && !dt.payload {
Martin Stjernholm58c33f02020-07-06 22:56:01 +01001825 return false
1826 }
1827
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001828 ai := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo)
Jiyong Parkab50b072021-05-12 17:13:56 +09001829 externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
Jiyong Park0f80c182020-01-31 02:49:53 +09001830
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001831 // Visit actually
1832 return do(ctx, parent, am, externalDep)
Jiyong Park0f80c182020-01-31 02:49:53 +09001833 })
1834}
1835
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001836// filesystem type of the apex_payload.img inside the APEX. Currently, ext4 and f2fs are supported.
1837type fsType int
Jooyung Han03b51852020-02-26 22:45:42 +09001838
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001839const (
1840 ext4 fsType = iota
1841 f2fs
Huang Jianan13cac632021-08-02 15:02:17 +08001842 erofs
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001843)
Artur Satayev849f8442020-04-28 14:57:42 +01001844
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001845func (f fsType) string() string {
1846 switch f {
1847 case ext4:
1848 return ext4FsType
1849 case f2fs:
1850 return f2fsFsType
Huang Jianan13cac632021-08-02 15:02:17 +08001851 case erofs:
1852 return erofsFsType
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09001853 default:
1854 panic(fmt.Errorf("unknown APEX payload type %d", f))
Jooyung Han548640b2020-04-27 12:10:30 +09001855 }
1856}
1857
Sasha Smundakfe9a5b82022-07-27 14:51:45 -07001858var _ android.MixedBuildBuildable = (*apexBundle)(nil)
1859
1860func (a *apexBundle) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
1861 return ctx.ModuleType() == "apex" && a.properties.ApexType == imageApex
1862}
1863
1864func (a *apexBundle) QueueBazelCall(ctx android.BaseModuleContext) {
1865 bazelCtx := ctx.Config().BazelContext
1866 bazelCtx.QueueBazelRequest(a.GetBazelLabel(ctx, a), cquery.GetApexInfo, android.GetConfigKey(ctx))
1867}
1868
1869func (a *apexBundle) ProcessBazelQueryResponse(ctx android.ModuleContext) {
1870 if !a.commonBuildActions(ctx) {
1871 return
1872 }
1873
1874 a.setApexTypeAndSuffix(ctx)
1875 a.setPayloadFsType(ctx)
1876 a.setSystemLibLink(ctx)
1877
1878 if a.properties.ApexType != zipApex {
1879 a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, a.primaryApexType)
1880 }
1881
1882 bazelCtx := ctx.Config().BazelContext
1883 outputs, err := bazelCtx.GetApexInfo(a.GetBazelLabel(ctx, a), android.GetConfigKey(ctx))
1884 if err != nil {
1885 ctx.ModuleErrorf(err.Error())
1886 return
1887 }
1888 a.installDir = android.PathForModuleInstall(ctx, "apex")
1889 a.outputApexFile = android.PathForBazelOut(ctx, outputs.SignedOutput)
1890 a.outputFile = a.outputApexFile
1891 a.setCompression(ctx)
1892
Liz Kammer0e255ef2022-11-04 16:07:04 -04001893 // TODO(b/257829940): These are used by the apex_keys_text singleton; would probably be a clearer
1894 // interface if these were set in a provider rather than the module itself
Wei Li32dcdf92022-10-26 22:30:48 -07001895 a.publicKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[0])
1896 a.privateKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[1])
1897 a.containerCertificateFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[0])
1898 a.containerPrivateKeyFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[1])
Liz Kammer0e255ef2022-11-04 16:07:04 -04001899
Sasha Smundakfe9a5b82022-07-27 14:51:45 -07001900 apexType := a.properties.ApexType
1901 switch apexType {
1902 case imageApex:
Liz Kammer303978d2022-11-04 16:12:43 -04001903 a.bundleModuleFile = android.PathForBazelOut(ctx, outputs.BundleFile)
Jingwen Chen0c9a2762022-11-04 09:40:47 +00001904 a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.SymbolsUsedByApex))
Wei Licc73a052022-11-07 14:25:34 -08001905 a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.BackingLibs))
Jingwen Chen0c9a2762022-11-04 09:40:47 +00001906 // TODO(b/239084755): Generate the java api using.xml file from Bazel.
Jingwen Chen1ec77852022-11-07 14:36:12 +00001907 a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.JavaSymbolsUsedByApex))
Wei Li78c07de2022-11-08 16:01:05 -08001908 a.installedFilesFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.InstalledFiles))
Sasha Smundakfe9a5b82022-07-27 14:51:45 -07001909 installSuffix := imageApexSuffix
1910 if a.isCompressed {
1911 installSuffix = imageCapexSuffix
1912 }
1913 a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile,
1914 a.compatSymlinks.Paths()...)
1915 default:
1916 panic(fmt.Errorf("unexpected apex_type for the ProcessBazelQuery: %v", a.properties.ApexType))
1917 }
1918
1919 /*
1920 TODO(asmundak): compared to building an APEX with Soong, building it with Bazel does not
1921 return filesInfo and requiredDeps fields (in the Soong build the latter is updated).
1922 Fix this, as these fields are subsequently used in apex/androidmk.go and in apex/builder/go
1923 To find out what Soong build puts there, run:
1924 vctx := visitorContext{handleSpecialLibs: !android.Bool(a.properties.Ignore_system_library_special_case)}
1925 ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
1926 return a.depVisitor(&vctx, ctx, child, parent)
1927 })
1928 vctx.normalizeFileInfo()
1929 */
1930
1931}
1932
1933func (a *apexBundle) setCompression(ctx android.ModuleContext) {
1934 if a.properties.ApexType != imageApex {
1935 a.isCompressed = false
1936 } else if a.testOnlyShouldForceCompression() {
1937 a.isCompressed = true
1938 } else {
1939 a.isCompressed = ctx.Config().ApexCompressionEnabled() && a.isCompressable()
1940 }
1941}
1942
1943func (a *apexBundle) setSystemLibLink(ctx android.ModuleContext) {
1944 // Optimization. If we are building bundled APEX, for the files that are gathered due to the
1945 // transitive dependencies, don't place them inside the APEX, but place a symlink pointing
1946 // the same library in the system partition, thus effectively sharing the same libraries
1947 // across the APEX boundary. For unbundled APEX, all the gathered files are actually placed
1948 // in the APEX.
1949 a.linkToSystemLib = !ctx.Config().UnbundledBuild() && a.installable()
1950
1951 // APEXes targeting other than system/system_ext partitions use vendor/product variants.
1952 // So we can't link them to /system/lib libs which are core variants.
1953 if a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
1954 a.linkToSystemLib = false
1955 }
1956
1957 forced := ctx.Config().ForceApexSymlinkOptimization()
1958 updatable := a.Updatable() || a.FutureUpdatable()
1959
1960 // We don't need the optimization for updatable APEXes, as it might give false signal
1961 // to the system health when the APEXes are still bundled (b/149805758).
1962 if !forced && updatable && a.properties.ApexType == imageApex {
1963 a.linkToSystemLib = false
1964 }
1965
1966 // We also don't want the optimization for host APEXes, because it doesn't make sense.
1967 if ctx.Host() {
1968 a.linkToSystemLib = false
1969 }
1970}
1971
1972func (a *apexBundle) setPayloadFsType(ctx android.ModuleContext) {
1973 switch proptools.StringDefault(a.properties.Payload_fs_type, ext4FsType) {
1974 case ext4FsType:
1975 a.payloadFsType = ext4
1976 case f2fsFsType:
1977 a.payloadFsType = f2fs
1978 case erofsFsType:
1979 a.payloadFsType = erofs
1980 default:
1981 ctx.PropertyErrorf("payload_fs_type", "%q is not a valid filesystem for apex [ext4, f2fs, erofs]", *a.properties.Payload_fs_type)
1982 }
1983}
1984
1985func (a *apexBundle) setApexTypeAndSuffix(ctx android.ModuleContext) {
1986 // Set suffix and primaryApexType depending on the ApexType
1987 buildFlattenedAsDefault := ctx.Config().FlattenApex()
1988 switch a.properties.ApexType {
1989 case imageApex:
1990 if buildFlattenedAsDefault {
1991 a.suffix = imageApexSuffix
1992 } else {
1993 a.suffix = ""
1994 a.primaryApexType = true
1995
1996 if ctx.Config().InstallExtraFlattenedApexes() {
1997 a.requiredDeps = append(a.requiredDeps, a.Name()+flattenedSuffix)
1998 }
1999 }
2000 case zipApex:
2001 if proptools.String(a.properties.Payload_type) == "zip" {
2002 a.suffix = ""
2003 a.primaryApexType = true
2004 } else {
2005 a.suffix = zipApexSuffix
2006 }
2007 case flattenedApex:
2008 if buildFlattenedAsDefault {
2009 a.suffix = ""
2010 a.primaryApexType = true
2011 } else {
2012 a.suffix = flattenedSuffix
2013 }
2014 }
2015}
2016
2017func (a apexBundle) isCompressable() bool {
2018 return proptools.BoolDefault(a.overridableProperties.Compressible, false) && !a.testApex
2019}
2020
2021func (a *apexBundle) commonBuildActions(ctx android.ModuleContext) bool {
2022 a.checkApexAvailability(ctx)
2023 a.checkUpdatable(ctx)
2024 a.CheckMinSdkVersion(ctx)
2025 a.checkStaticLinkingToStubLibraries(ctx)
2026 a.checkStaticExecutables(ctx)
2027 if len(a.properties.Tests) > 0 && !a.testApex {
2028 ctx.PropertyErrorf("tests", "property allowed only in apex_test module type")
2029 return false
2030 }
2031 return true
2032}
2033
Sasha Smundak6f9e91d2022-06-28 22:43:04 -07002034type visitorContext struct {
2035 // all the files that will be included in this APEX
2036 filesInfo []apexFile
2037
2038 // native lib dependencies
2039 provideNativeLibs []string
2040 requireNativeLibs []string
2041
2042 handleSpecialLibs bool
2043}
2044
2045func (vctx *visitorContext) normalizeFileInfo() {
2046 encountered := make(map[string]apexFile)
2047 for _, f := range vctx.filesInfo {
2048 dest := filepath.Join(f.installDir, f.builtFile.Base())
2049 if e, ok := encountered[dest]; !ok {
2050 encountered[dest] = f
2051 } else {
2052 // If a module is directly included and also transitively depended on
2053 // consider it as directly included.
2054 e.transitiveDep = e.transitiveDep && f.transitiveDep
2055 encountered[dest] = e
2056 }
2057 }
2058 vctx.filesInfo = vctx.filesInfo[:0]
2059 for _, v := range encountered {
2060 vctx.filesInfo = append(vctx.filesInfo, v)
2061 }
2062 sort.Slice(vctx.filesInfo, func(i, j int) bool {
2063 // Sort by destination path so as to ensure consistent ordering even if the source of the files
2064 // changes.
2065 return vctx.filesInfo[i].path() < vctx.filesInfo[j].path()
2066 })
2067}
2068
2069func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent blueprint.Module) bool {
2070 depTag := ctx.OtherModuleDependencyTag(child)
2071 if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
2072 return false
2073 }
2074 if mod, ok := child.(android.Module); ok && !mod.Enabled() {
2075 return false
2076 }
2077 depName := ctx.OtherModuleName(child)
2078 if _, isDirectDep := parent.(*apexBundle); isDirectDep {
2079 switch depTag {
2080 case sharedLibTag, jniLibTag:
2081 isJniLib := depTag == jniLibTag
2082 switch ch := child.(type) {
2083 case *cc.Module:
2084 fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
2085 fi.isJniLib = isJniLib
2086 vctx.filesInfo = append(vctx.filesInfo, fi)
2087 // Collect the list of stub-providing libs except:
2088 // - VNDK libs are only for vendors
2089 // - bootstrap bionic libs are treated as provided by system
2090 if ch.HasStubsVariants() && !a.vndkApex && !cc.InstallToBootstrap(ch.BaseModuleName(), ctx.Config()) {
2091 vctx.provideNativeLibs = append(vctx.provideNativeLibs, fi.stem())
2092 }
2093 return true // track transitive dependencies
2094 case *rust.Module:
2095 fi := apexFileForRustLibrary(ctx, ch)
2096 fi.isJniLib = isJniLib
2097 vctx.filesInfo = append(vctx.filesInfo, fi)
2098 return true // track transitive dependencies
2099 default:
2100 propertyName := "native_shared_libs"
2101 if isJniLib {
2102 propertyName = "jni_libs"
2103 }
2104 ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
2105 }
2106 case executableTag:
2107 switch ch := child.(type) {
2108 case *cc.Module:
2109 vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch))
2110 return true // track transitive dependencies
2111 case *python.Module:
2112 if ch.HostToolPath().Valid() {
2113 vctx.filesInfo = append(vctx.filesInfo, apexFileForPyBinary(ctx, ch))
2114 }
2115 case bootstrap.GoBinaryTool:
2116 if a.Host() {
2117 vctx.filesInfo = append(vctx.filesInfo, apexFileForGoBinary(ctx, depName, ch))
2118 }
2119 case *rust.Module:
2120 vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch))
2121 return true // track transitive dependencies
2122 default:
2123 ctx.PropertyErrorf("binaries",
2124 "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, nor (host) bootstrap_go_binary", depName)
2125 }
2126 case shBinaryTag:
2127 if csh, ok := child.(*sh.ShBinary); ok {
2128 vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, csh))
2129 } else {
2130 ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName)
2131 }
2132 case bcpfTag:
2133 bcpfModule, ok := child.(*java.BootclasspathFragmentModule)
2134 if !ok {
2135 ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a bootclasspath_fragment module", depName)
2136 return false
2137 }
2138
2139 vctx.filesInfo = append(vctx.filesInfo, apexBootclasspathFragmentFiles(ctx, child)...)
2140 for _, makeModuleName := range bcpfModule.BootImageDeviceInstallMakeModules() {
2141 a.requiredDeps = append(a.requiredDeps, makeModuleName)
2142 }
2143 return true
2144 case sscpfTag:
2145 if _, ok := child.(*java.SystemServerClasspathModule); !ok {
2146 ctx.PropertyErrorf("systemserverclasspath_fragments",
2147 "%q is not a systemserverclasspath_fragment module", depName)
2148 return false
2149 }
2150 if af := apexClasspathFragmentProtoFile(ctx, child); af != nil {
2151 vctx.filesInfo = append(vctx.filesInfo, *af)
2152 }
2153 return true
2154 case javaLibTag:
2155 switch child.(type) {
2156 case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
2157 af := apexFileForJavaModule(ctx, child.(javaModule))
2158 if !af.ok() {
2159 ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
2160 return false
2161 }
2162 vctx.filesInfo = append(vctx.filesInfo, af)
2163 return true // track transitive dependencies
2164 default:
2165 ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
2166 }
2167 case androidAppTag:
2168 switch ap := child.(type) {
2169 case *java.AndroidApp:
2170 vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
2171 return true // track transitive dependencies
2172 case *java.AndroidAppImport:
2173 vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
2174 case *java.AndroidTestHelperApp:
2175 vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
2176 case *java.AndroidAppSet:
2177 appDir := "app"
2178 if ap.Privileged() {
2179 appDir = "priv-app"
2180 }
2181 // TODO(b/224589412, b/226559955): Ensure that the dirname is
2182 // suffixed so that PackageManager correctly invalidates the
2183 // existing installed apk in favour of the new APK-in-APEX.
2184 // See bugs for more information.
2185 appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+sanitizedBuildIdForPath(ctx))
2186 af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap)
2187 af.certificate = java.PresignedCertificate
2188 vctx.filesInfo = append(vctx.filesInfo, af)
2189 default:
2190 ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
2191 }
2192 case rroTag:
2193 if rro, ok := child.(java.RuntimeResourceOverlayModule); ok {
2194 vctx.filesInfo = append(vctx.filesInfo, apexFileForRuntimeResourceOverlay(ctx, rro))
2195 } else {
2196 ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName)
2197 }
2198 case bpfTag:
2199 if bpfProgram, ok := child.(bpf.BpfModule); ok {
2200 filesToCopy, _ := bpfProgram.OutputFiles("")
2201 apex_sub_dir := bpfProgram.SubDir()
2202 for _, bpfFile := range filesToCopy {
2203 vctx.filesInfo = append(vctx.filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram))
2204 }
2205 } else {
2206 ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
2207 }
2208 case fsTag:
2209 if fs, ok := child.(filesystem.Filesystem); ok {
2210 vctx.filesInfo = append(vctx.filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs))
2211 } else {
2212 ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName)
2213 }
2214 case prebuiltTag:
2215 if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
2216 vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
2217 } else {
2218 ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
2219 }
2220 case compatConfigTag:
2221 if compatConfig, ok := child.(java.PlatformCompatConfigIntf); ok {
2222 vctx.filesInfo = append(vctx.filesInfo, apexFileForCompatConfig(ctx, compatConfig, depName))
2223 } else {
2224 ctx.PropertyErrorf("compat_configs", "%q is not a platform_compat_config module", depName)
2225 }
2226 case testTag:
2227 if ccTest, ok := child.(*cc.Module); ok {
2228 if ccTest.IsTestPerSrcAllTestsVariation() {
2229 // Multiple-output test module (where `test_per_src: true`).
2230 //
2231 // `ccTest` is the "" ("all tests") variation of a `test_per_src` module.
2232 // We do not add this variation to `filesInfo`, as it has no output;
2233 // however, we do add the other variations of this module as indirect
2234 // dependencies (see below).
2235 } else {
2236 // Single-output test module (where `test_per_src: false`).
2237 af := apexFileForExecutable(ctx, ccTest)
2238 af.class = nativeTest
2239 vctx.filesInfo = append(vctx.filesInfo, af)
2240 }
2241 return true // track transitive dependencies
2242 } else {
2243 ctx.PropertyErrorf("tests", "%q is not a cc module", depName)
2244 }
2245 case keyTag:
2246 if key, ok := child.(*apexKey); ok {
2247 a.privateKeyFile = key.privateKeyFile
2248 a.publicKeyFile = key.publicKeyFile
2249 } else {
2250 ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
2251 }
2252 case certificateTag:
2253 if dep, ok := child.(*java.AndroidAppCertificate); ok {
2254 a.containerCertificateFile = dep.Certificate.Pem
2255 a.containerPrivateKeyFile = dep.Certificate.Key
2256 } else {
2257 ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
2258 }
2259 case android.PrebuiltDepTag:
2260 // If the prebuilt is force disabled, remember to delete the prebuilt file
2261 // that might have been installed in the previous builds
2262 if prebuilt, ok := child.(prebuilt); ok && prebuilt.isForceDisabled() {
2263 a.prebuiltFileToDelete = prebuilt.InstallFilename()
2264 }
2265 }
2266 return false
2267 }
2268
2269 if a.vndkApex {
2270 return false
2271 }
2272
2273 // indirect dependencies
2274 am, ok := child.(android.ApexModule)
2275 if !ok {
2276 return false
2277 }
2278 // We cannot use a switch statement on `depTag` here as the checked
2279 // tags used below are private (e.g. `cc.sharedDepTag`).
2280 if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
2281 if ch, ok := child.(*cc.Module); ok {
2282 if ch.UseVndk() && proptools.Bool(a.properties.Use_vndk_as_stable) && ch.IsVndk() {
2283 vctx.requireNativeLibs = append(vctx.requireNativeLibs, ":vndk")
2284 return false
2285 }
2286 af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
2287 af.transitiveDep = true
2288
2289 // Always track transitive dependencies for host.
2290 if a.Host() {
2291 vctx.filesInfo = append(vctx.filesInfo, af)
2292 return true
2293 }
2294
2295 abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo)
2296 if !abInfo.Contents.DirectlyInApex(depName) && (ch.IsStubs() || ch.HasStubsVariants()) {
2297 // If the dependency is a stubs lib, don't include it in this APEX,
2298 // but make sure that the lib is installed on the device.
2299 // In case no APEX is having the lib, the lib is installed to the system
2300 // partition.
2301 //
2302 // Always include if we are a host-apex however since those won't have any
2303 // system libraries.
Alan Stokes73feba32022-11-14 12:21:24 +00002304 if ch.IsStubsImplementationRequired() && !am.DirectlyInAnyApex() {
Sasha Smundak6f9e91d2022-06-28 22:43:04 -07002305 // we need a module name for Make
2306 name := ch.ImplementationModuleNameForMake(ctx) + ch.Properties.SubName
2307 if !android.InList(name, a.requiredDeps) {
2308 a.requiredDeps = append(a.requiredDeps, name)
2309 }
2310 }
2311 vctx.requireNativeLibs = append(vctx.requireNativeLibs, af.stem())
2312 // Don't track further
2313 return false
2314 }
2315
2316 // If the dep is not considered to be in the same
2317 // apex, don't add it to filesInfo so that it is not
2318 // included in this APEX.
2319 // TODO(jiyong): move this to at the top of the
2320 // else-if clause for the indirect dependencies.
2321 // Currently, that's impossible because we would
2322 // like to record requiredNativeLibs even when
2323 // DepIsInSameAPex is false. We also shouldn't do
2324 // this for host.
2325 //
2326 // TODO(jiyong): explain why the same module is passed in twice.
2327 // Switching the first am to parent breaks lots of tests.
2328 if !android.IsDepInSameApex(ctx, am, am) {
2329 return false
2330 }
2331
2332 vctx.filesInfo = append(vctx.filesInfo, af)
2333 return true // track transitive dependencies
2334 } else if rm, ok := child.(*rust.Module); ok {
2335 af := apexFileForRustLibrary(ctx, rm)
2336 af.transitiveDep = true
2337 vctx.filesInfo = append(vctx.filesInfo, af)
2338 return true // track transitive dependencies
2339 }
2340 } else if cc.IsTestPerSrcDepTag(depTag) {
2341 if ch, ok := child.(*cc.Module); ok {
2342 af := apexFileForExecutable(ctx, ch)
2343 // Handle modules created as `test_per_src` variations of a single test module:
2344 // use the name of the generated test binary (`fileToCopy`) instead of the name
2345 // of the original test module (`depName`, shared by all `test_per_src`
2346 // variations of that module).
2347 af.androidMkModuleName = filepath.Base(af.builtFile.String())
2348 // these are not considered transitive dep
2349 af.transitiveDep = false
2350 vctx.filesInfo = append(vctx.filesInfo, af)
2351 return true // track transitive dependencies
2352 }
2353 } else if cc.IsHeaderDepTag(depTag) {
2354 // nothing
2355 } else if java.IsJniDepTag(depTag) {
2356 // Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
2357 } else if java.IsXmlPermissionsFileDepTag(depTag) {
2358 if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
2359 vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
2360 }
2361 } else if rust.IsDylibDepTag(depTag) {
2362 if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
2363 af := apexFileForRustLibrary(ctx, rustm)
2364 af.transitiveDep = true
2365 vctx.filesInfo = append(vctx.filesInfo, af)
2366 return true // track transitive dependencies
2367 }
2368 } else if rust.IsRlibDepTag(depTag) {
2369 // Rlib is statically linked, but it might have shared lib
2370 // dependencies. Track them.
2371 return true
2372 } else if java.IsBootclasspathFragmentContentDepTag(depTag) {
2373 // Add the contents of the bootclasspath fragment to the apex.
2374 switch child.(type) {
2375 case *java.Library, *java.SdkLibrary:
2376 javaModule := child.(javaModule)
2377 af := apexFileForBootclasspathFragmentContentModule(ctx, parent, javaModule)
2378 if !af.ok() {
2379 ctx.PropertyErrorf("bootclasspath_fragments",
2380 "bootclasspath_fragment content %q is not configured to be compiled into dex", depName)
2381 return false
2382 }
2383 vctx.filesInfo = append(vctx.filesInfo, af)
2384 return true // track transitive dependencies
2385 default:
2386 ctx.PropertyErrorf("bootclasspath_fragments",
2387 "bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
2388 }
2389 } else if java.IsSystemServerClasspathFragmentContentDepTag(depTag) {
2390 // Add the contents of the systemserverclasspath fragment to the apex.
2391 switch child.(type) {
2392 case *java.Library, *java.SdkLibrary:
2393 af := apexFileForJavaModule(ctx, child.(javaModule))
2394 vctx.filesInfo = append(vctx.filesInfo, af)
2395 return true // track transitive dependencies
2396 default:
2397 ctx.PropertyErrorf("systemserverclasspath_fragments",
2398 "systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
2399 }
2400 } else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
2401 // nothing
2402 } else if depTag == android.DarwinUniversalVariantTag {
2403 // nothing
2404 } else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
2405 ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
2406 }
2407 return false
2408}
2409
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002410// Creates build rules for an APEX. It consists of the following major steps:
2411//
2412// 1) do some validity checks such as apex_available, min_sdk_version, etc.
2413// 2) traverse the dependency tree to collect apexFile structs from them.
2414// 3) some fields in apexBundle struct are configured
2415// 4) generate the build rules to create the APEX. This is mostly done in builder.go.
Jiyong Park48ca7dc2018-10-10 14:01:00 +09002416func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002417 ////////////////////////////////////////////////////////////////////////////////////////////
2418 // 1) do some validity checks such as apex_available, min_sdk_version, etc.
Sasha Smundakfe9a5b82022-07-27 14:51:45 -07002419 if !a.commonBuildActions(ctx) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002420 return
2421 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002422 ////////////////////////////////////////////////////////////////////////////////////////////
2423 // 2) traverse the dependency tree to collect apexFile structs from them.
2424
braleeb0c1f0c2021-06-07 22:49:13 +08002425 // Collect the module directory for IDE info in java/jdeps.go.
2426 a.modulePaths = append(a.modulePaths, ctx.ModuleDir())
2427
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002428 // TODO(jiyong): do this using WalkPayloadDeps
2429 // TODO(jiyong): make this clean!!!
Sasha Smundak6f9e91d2022-06-28 22:43:04 -07002430 vctx := visitorContext{handleSpecialLibs: !android.Bool(a.properties.Ignore_system_library_special_case)}
2431 ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
2432 vctx.normalizeFileInfo()
Jaewoong Jung18aefc12020-12-21 09:11:10 -08002433 if a.privateKeyFile == nil {
Jaewoong Jung4cfdf7d2021-04-20 16:21:24 -07002434 ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.overridableProperties.Key))
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002435 return
2436 }
Jiyong Park48ca7dc2018-10-10 14:01:00 +09002437
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002438 ////////////////////////////////////////////////////////////////////////////////////////////
2439 // 3) some fields in apexBundle struct are configured
Jiyong Park8fd61922018-11-08 02:50:25 +09002440 a.installDir = android.PathForModuleInstall(ctx, "apex")
Sasha Smundak6f9e91d2022-06-28 22:43:04 -07002441 a.filesInfo = vctx.filesInfo
Alex Light5098a612018-11-29 17:12:15 -08002442
Sasha Smundakfe9a5b82022-07-27 14:51:45 -07002443 a.setApexTypeAndSuffix(ctx)
2444 a.setPayloadFsType(ctx)
2445 a.setSystemLibLink(ctx)
Colin Cross6340ea52021-11-04 12:01:18 -07002446 if a.properties.ApexType != zipApex {
2447 a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, a.primaryApexType)
2448 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002449
2450 ////////////////////////////////////////////////////////////////////////////////////////////
2451 // 4) generate the build rules to create the APEX. This is done in builder.go.
Sasha Smundak6f9e91d2022-06-28 22:43:04 -07002452 a.buildManifest(ctx, vctx.provideNativeLibs, vctx.requireNativeLibs)
Jooyung Han01a3ee22019-11-02 02:52:25 +09002453 if a.properties.ApexType == flattenedApex {
2454 a.buildFlattenedApex(ctx)
2455 } else {
2456 a.buildUnflattenedApex(ctx)
2457 }
Jiyong Park956305c2020-01-09 12:32:06 +09002458 a.buildApexDependencyInfo(ctx)
Colin Cross08dca382020-07-21 20:31:17 -07002459 a.buildLintReports(ctx)
Jiyong Parkb81b9902020-11-24 19:51:18 +09002460
2461 // Append meta-files to the filesInfo list so that they are reflected in Android.mk as well.
2462 if a.installable() {
2463 // For flattened APEX, make sure that APEX manifest and apex_pubkey are also copied
2464 // along with other ordinary files. (Note that this is done by apexer for
2465 // non-flattened APEXes)
2466 a.filesInfo = append(a.filesInfo, newApexFile(ctx, a.manifestPbOut, "apex_manifest.pb", ".", etc, nil))
2467
2468 // Place the public key as apex_pubkey. This is also done by apexer for
2469 // non-flattened APEXes case.
2470 // TODO(jiyong): Why do we need this CP rule?
2471 copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
2472 ctx.Build(pctx, android.BuildParams{
2473 Rule: android.Cp,
Jaewoong Jung18aefc12020-12-21 09:11:10 -08002474 Input: a.publicKeyFile,
Jiyong Parkb81b9902020-11-24 19:51:18 +09002475 Output: copiedPubkey,
2476 })
2477 a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey", ".", etc, nil))
2478 }
Jooyung Han01a3ee22019-11-02 02:52:25 +09002479}
2480
Paul Duffincc33ec82021-04-25 23:14:55 +01002481// apexBootclasspathFragmentFiles returns the list of apexFile structures defining the files that
2482// the bootclasspath_fragment contributes to the apex.
2483func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.Module) []apexFile {
2484 bootclasspathFragmentInfo := ctx.OtherModuleProvider(module, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
2485 var filesToAdd []apexFile
2486
2487 // Add the boot image files, e.g. .art, .oat and .vdex files.
Jiakai Zhang6decef92022-01-12 17:56:19 +00002488 if bootclasspathFragmentInfo.ShouldInstallBootImageInApex() {
2489 for arch, files := range bootclasspathFragmentInfo.AndroidBootImageFilesByArchType() {
2490 dirInApex := filepath.Join("javalib", arch.String())
2491 for _, f := range files {
2492 androidMkModuleName := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
2493 // TODO(b/177892522) - consider passing in the bootclasspath fragment module here instead of nil
2494 af := newApexFile(ctx, f, androidMkModuleName, dirInApex, etc, nil)
2495 filesToAdd = append(filesToAdd, af)
2496 }
Paul Duffincc33ec82021-04-25 23:14:55 +01002497 }
2498 }
2499
satayev3db35472021-05-06 23:59:58 +01002500 // Add classpaths.proto config.
satayevb98371c2021-06-15 16:49:50 +01002501 if af := apexClasspathFragmentProtoFile(ctx, module); af != nil {
2502 filesToAdd = append(filesToAdd, *af)
2503 }
satayev3db35472021-05-06 23:59:58 +01002504
Ulya Trafimovichf5c548d2022-11-16 14:52:41 +00002505 pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex()
2506 if pathInApex != "" && !java.SkipDexpreoptBootJars(ctx) {
Jiakai Zhang49b1eb62021-11-26 18:09:27 +00002507 pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost()
2508 tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex)
2509
2510 if pathOnHost != nil {
2511 // We need to copy the profile to a temporary path with the right filename because the apexer
2512 // will take the filename as is.
2513 ctx.Build(pctx, android.BuildParams{
2514 Rule: android.Cp,
2515 Input: pathOnHost,
2516 Output: tempPath,
2517 })
2518 } else {
2519 // At this point, the boot image profile cannot be generated. It is probably because the boot
2520 // image profile source file does not exist on the branch, or it is not available for the
2521 // current build target.
2522 // However, we cannot enforce the boot image profile to be generated because some build
2523 // targets (such as module SDK) do not need it. It is only needed when the APEX is being
2524 // built. Therefore, we create an error rule so that an error will occur at the ninja phase
2525 // only if the APEX is being built.
2526 ctx.Build(pctx, android.BuildParams{
2527 Rule: android.ErrorRule,
2528 Output: tempPath,
2529 Args: map[string]string{
2530 "error": "Boot image profile cannot be generated",
2531 },
2532 })
2533 }
2534
2535 androidMkModuleName := filepath.Base(pathInApex)
2536 af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, nil)
2537 filesToAdd = append(filesToAdd, af)
2538 }
2539
Paul Duffincc33ec82021-04-25 23:14:55 +01002540 return filesToAdd
2541}
2542
satayevb98371c2021-06-15 16:49:50 +01002543// apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that
2544// the module contributes to the apex; or nil if the proto config was not generated.
2545func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) *apexFile {
2546 info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
2547 if !info.ClasspathFragmentProtoGenerated {
2548 return nil
2549 }
2550 classpathProtoOutput := info.ClasspathFragmentProtoOutput
2551 af := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), info.ClasspathFragmentProtoInstallDir.Rel(), etc, nil)
2552 return &af
satayev14e49132021-05-17 21:03:07 +01002553}
2554
Paul Duffincc33ec82021-04-25 23:14:55 +01002555// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment
2556// content module, i.e. a library that is part of the bootclasspath.
Paul Duffin190fdef2021-04-26 10:33:59 +01002557func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule blueprint.Module, javaModule javaModule) apexFile {
2558 bootclasspathFragmentInfo := ctx.OtherModuleProvider(fragmentModule, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
2559
2560 // Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the
2561 // hidden API encpding.
Paul Duffin1a8010a2021-05-15 12:39:23 +01002562 dexBootJar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule)
2563 if err != nil {
2564 ctx.ModuleErrorf("%s", err)
2565 }
Paul Duffin190fdef2021-04-26 10:33:59 +01002566
2567 // Create an apexFile as for a normal java module but with the dex boot jar provided by the
2568 // bootclasspath_fragment.
2569 af := apexFileForJavaModuleWithFile(ctx, javaModule, dexBootJar)
2570 return af
Paul Duffincc33ec82021-04-25 23:14:55 +01002571}
2572
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002573///////////////////////////////////////////////////////////////////////////////////////////////////
2574// Factory functions
2575//
2576
2577func newApexBundle() *apexBundle {
2578 module := &apexBundle{}
2579
2580 module.AddProperties(&module.properties)
2581 module.AddProperties(&module.targetProperties)
Jiyong Park59140302020-12-14 18:44:04 +09002582 module.AddProperties(&module.archProperties)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002583 module.AddProperties(&module.overridableProperties)
2584
2585 android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
2586 android.InitDefaultableModule(module)
2587 android.InitSdkAwareModule(module)
2588 android.InitOverridableModule(module, &module.overridableProperties.Overrides)
Jingwen Chenf59a8e12021-07-16 09:28:53 +00002589 android.InitBazelModule(module)
Inseob Kim5eb7ee92022-04-27 10:30:34 +09002590 multitree.InitExportableModule(module)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002591 return module
2592}
2593
Paul Duffineb8051d2021-10-18 17:49:39 +01002594func ApexBundleFactory(testApex bool) android.Module {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002595 bundle := newApexBundle()
2596 bundle.testApex = testApex
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002597 return bundle
2598}
2599
2600// apex_test is an APEX for testing. The difference from the ordinary apex module type is that
2601// certain compatibility checks such as apex_available are not done for apex_test.
Yu Liu4c212ce2022-10-14 12:20:20 -07002602func TestApexBundleFactory() android.Module {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002603 bundle := newApexBundle()
2604 bundle.testApex = true
2605 return bundle
2606}
2607
2608// apex packages other modules into an APEX file which is a packaging format for system-level
2609// components like binaries, shared libraries, etc.
2610func BundleFactory() android.Module {
2611 return newApexBundle()
2612}
2613
2614type Defaults struct {
2615 android.ModuleBase
2616 android.DefaultsModuleBase
2617}
2618
2619// apex_defaults provides defaultable properties to other apex modules.
2620func defaultsFactory() android.Module {
2621 return DefaultsFactory()
2622}
2623
2624func DefaultsFactory(props ...interface{}) android.Module {
2625 module := &Defaults{}
2626
2627 module.AddProperties(props...)
2628 module.AddProperties(
2629 &apexBundleProperties{},
2630 &apexTargetBundleProperties{},
Nikita Ioffee58f5272022-10-24 17:24:38 +01002631 &apexArchBundleProperties{},
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002632 &overridableProperties{},
2633 )
2634
2635 android.InitDefaultsModule(module)
2636 return module
2637}
2638
2639type OverrideApex struct {
2640 android.ModuleBase
2641 android.OverrideModuleBase
Wei Li1c66fc72022-05-09 23:59:14 -07002642 android.BazelModuleBase
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002643}
2644
Sasha Smundak6f9e91d2022-06-28 22:43:04 -07002645func (o *OverrideApex) GenerateAndroidBuildActions(_ android.ModuleContext) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002646 // All the overrides happen in the base module.
2647}
2648
2649// override_apex is used to create an apex module based on another apex module by overriding some of
2650// its properties.
Wei Li1c66fc72022-05-09 23:59:14 -07002651func OverrideApexFactory() android.Module {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002652 m := &OverrideApex{}
2653
2654 m.AddProperties(&overridableProperties{})
2655
2656 android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
2657 android.InitOverrideModule(m)
Wei Li1c66fc72022-05-09 23:59:14 -07002658 android.InitBazelModule(m)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002659 return m
2660}
2661
Wei Li1c66fc72022-05-09 23:59:14 -07002662func (o *OverrideApex) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
2663 if ctx.ModuleType() != "override_apex" {
2664 return
2665 }
2666
2667 baseApexModuleName := o.OverrideModuleBase.GetOverriddenModuleName()
2668 baseModule, baseApexExists := ctx.ModuleFromName(baseApexModuleName)
2669 if !baseApexExists {
2670 panic(fmt.Errorf("Base apex module doesn't exist: %s", baseApexModuleName))
2671 }
2672
2673 a, baseModuleIsApex := baseModule.(*apexBundle)
2674 if !baseModuleIsApex {
2675 panic(fmt.Errorf("Base module is not apex module: %s", baseApexModuleName))
2676 }
2677 attrs, props := convertWithBp2build(a, ctx)
2678
2679 for _, p := range o.GetProperties() {
2680 overridableProperties, ok := p.(*overridableProperties)
2681 if !ok {
2682 continue
2683 }
Wei Li40f98732022-05-20 22:08:11 -07002684
2685 // Manifest is either empty or a file in the directory of base APEX and is not overridable.
2686 // After it is converted in convertWithBp2build(baseApex, ctx),
2687 // the attrs.Manifest.Value.Label is the file path relative to the directory
2688 // of base apex. So the following code converts it to a label that looks like
2689 // <package of base apex>:<path of manifest file> if base apex and override
2690 // apex are not in the same package.
2691 baseApexPackage := ctx.OtherModuleDir(a)
2692 overrideApexPackage := ctx.ModuleDir()
2693 if baseApexPackage != overrideApexPackage {
2694 attrs.Manifest.Value.Label = "//" + baseApexPackage + ":" + attrs.Manifest.Value.Label
2695 }
2696
Wei Li1c66fc72022-05-09 23:59:14 -07002697 // Key
2698 if overridableProperties.Key != nil {
2699 attrs.Key = bazel.LabelAttribute{}
2700 attrs.Key.SetValue(android.BazelLabelForModuleDepSingle(ctx, *overridableProperties.Key))
2701 }
2702
2703 // Certificate
Jingwen Chenbea58092022-09-29 16:56:02 +00002704 if overridableProperties.Certificate == nil {
Jingwen Chen6817bbb2022-10-14 09:56:07 +00002705 // If overridableProperties.Certificate is nil, clear this out as
2706 // well with zeroed structs, so the override_apex does not use the
2707 // base apex's certificate.
2708 attrs.Certificate = bazel.LabelAttribute{}
2709 attrs.Certificate_name = bazel.StringAttribute{}
Jingwen Chenbea58092022-09-29 16:56:02 +00002710 } else {
Jingwen Chen6817bbb2022-10-14 09:56:07 +00002711 attrs.Certificate, attrs.Certificate_name = android.BazelStringOrLabelFromProp(ctx, overridableProperties.Certificate)
Wei Li1c66fc72022-05-09 23:59:14 -07002712 }
2713
2714 // Prebuilts
Jingwen Chendf165c92022-06-08 16:00:39 +00002715 if overridableProperties.Prebuilts != nil {
2716 prebuiltsLabelList := android.BazelLabelForModuleDeps(ctx, overridableProperties.Prebuilts)
2717 attrs.Prebuilts = bazel.MakeLabelListAttribute(prebuiltsLabelList)
2718 }
Wei Li1c66fc72022-05-09 23:59:14 -07002719
2720 // Compressible
2721 if overridableProperties.Compressible != nil {
2722 attrs.Compressible = bazel.BoolAttribute{Value: overridableProperties.Compressible}
2723 }
Jingwen Chen9b7ebca2022-06-03 09:11:20 +00002724
2725 // Package name
2726 //
2727 // e.g. com.android.adbd's package name is com.android.adbd, but
2728 // com.google.android.adbd overrides the package name to com.google.android.adbd
2729 //
2730 // TODO: this can be overridden from the product configuration, see
2731 // getOverrideManifestPackageName and
2732 // PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES.
2733 //
2734 // Instead of generating the BUILD files differently based on the product config
2735 // at the point of conversion, this should be handled by the BUILD file loading
2736 // from the soong_injection's product_vars, so product config is decoupled from bp2build.
2737 if overridableProperties.Package_name != "" {
2738 attrs.Package_name = &overridableProperties.Package_name
2739 }
Jingwen Chenb732d7c2022-06-10 08:14:19 +00002740
2741 // Logging parent
2742 if overridableProperties.Logging_parent != "" {
2743 attrs.Logging_parent = &overridableProperties.Logging_parent
2744 }
Wei Li1c66fc72022-05-09 23:59:14 -07002745 }
2746
2747 ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: o.Name()}, &attrs)
2748}
2749
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002750///////////////////////////////////////////////////////////////////////////////////////////////////
2751// Vality check routines
2752//
2753// These are called in at the very beginning of GenerateAndroidBuildActions to flag an error when
2754// certain conditions are not met.
2755//
2756// TODO(jiyong): move these checks to a separate go file.
2757
satayevad991492021-12-03 18:58:32 +00002758var _ android.ModuleWithMinSdkVersionCheck = (*apexBundle)(nil)
2759
Spandan Dasa5f39a12022-08-05 02:35:52 +00002760// Ensures that min_sdk_version of the included modules are equal or less than the min_sdk_version
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002761// of this apexBundle.
satayevb3fd4112021-12-02 13:59:35 +00002762func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002763 if a.testApex || a.vndkApex {
2764 return
2765 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002766 // apexBundle::minSdkVersion reports its own errors.
2767 minSdkVersion := a.minSdkVersion(ctx)
satayevb3fd4112021-12-02 13:59:35 +00002768 android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002769}
2770
Albert Martineefabcf2022-03-21 20:11:16 +00002771// Returns apex's min_sdk_version string value, honoring overrides
2772func (a *apexBundle) minSdkVersionValue(ctx android.EarlyModuleContext) string {
2773 // Only override the minSdkVersion value on Apexes which already specify
2774 // a min_sdk_version (it's optional for non-updatable apexes), and that its
2775 // min_sdk_version value is lower than the one to override with.
Colin Cross56534df2022-10-04 09:58:58 -07002776 minApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version))
2777 if minApiLevel.IsNone() {
2778 return ""
Albert Martineefabcf2022-03-21 20:11:16 +00002779 }
2780
Colin Cross56534df2022-10-04 09:58:58 -07002781 overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride()
2782 overrideApiLevel := minSdkVersionFromValue(ctx, overrideMinSdkValue)
2783 if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(minApiLevel) > 0 {
2784 minApiLevel = overrideApiLevel
2785 }
2786
2787 return minApiLevel.String()
Albert Martineefabcf2022-03-21 20:11:16 +00002788}
2789
2790// Returns apex's min_sdk_version SdkSpec, honoring overrides
satayevad991492021-12-03 18:58:32 +00002791func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
2792 return android.SdkSpec{
2793 Kind: android.SdkNone,
2794 ApiLevel: a.minSdkVersion(ctx),
Albert Martineefabcf2022-03-21 20:11:16 +00002795 Raw: a.minSdkVersionValue(ctx),
satayevad991492021-12-03 18:58:32 +00002796 }
2797}
2798
Albert Martineefabcf2022-03-21 20:11:16 +00002799// Returns apex's min_sdk_version ApiLevel, honoring overrides
satayevad991492021-12-03 18:58:32 +00002800func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
Albert Martineefabcf2022-03-21 20:11:16 +00002801 return minSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
2802}
2803
2804// Construct ApiLevel object from min_sdk_version string value
2805func minSdkVersionFromValue(ctx android.EarlyModuleContext, value string) android.ApiLevel {
2806 if value == "" {
Jooyung Haned124c32021-01-26 11:43:46 +09002807 return android.NoneApiLevel
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002808 }
Albert Martineefabcf2022-03-21 20:11:16 +00002809 apiLevel, err := android.ApiLevelFromUser(ctx, value)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002810 if err != nil {
2811 ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
2812 return android.NoneApiLevel
2813 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002814 return apiLevel
2815}
2816
2817// Ensures that a lib providing stub isn't statically linked
2818func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext) {
2819 // Practically, we only care about regular APEXes on the device.
2820 if ctx.Host() || a.testApex || a.vndkApex {
2821 return
2822 }
2823
2824 abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo)
2825
2826 a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
2827 if ccm, ok := to.(*cc.Module); ok {
2828 apexName := ctx.ModuleName()
2829 fromName := ctx.OtherModuleName(from)
2830 toName := ctx.OtherModuleName(to)
2831
2832 // If `to` is not actually in the same APEX as `from` then it does not need
2833 // apex_available and neither do any of its dependencies.
Paul Duffin4c3e8e22021-03-18 15:41:29 +00002834 //
2835 // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps().
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002836 if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
2837 // As soon as the dependency graph crosses the APEX boundary, don't go further.
2838 return false
2839 }
2840
2841 // The dynamic linker and crash_dump tool in the runtime APEX is the only
2842 // exception to this rule. It can't make the static dependencies dynamic
2843 // because it can't do the dynamic linking for itself.
Kiyoung Kim4098c7e2020-11-30 14:42:14 +09002844 // Same rule should be applied to linkerconfig, because it should be executed
2845 // only with static linked libraries before linker is available with ld.config.txt
2846 if apexName == "com.android.runtime" && (fromName == "linker" || fromName == "crash_dump" || fromName == "linkerconfig") {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002847 return false
2848 }
2849
2850 isStubLibraryFromOtherApex := ccm.HasStubsVariants() && !abInfo.Contents.DirectlyInApex(toName)
2851 if isStubLibraryFromOtherApex && !externalDep {
2852 ctx.ModuleErrorf("%q required by %q is a native library providing stub. "+
2853 "It shouldn't be included in this APEX via static linking. Dependency path: %s", to.String(), fromName, ctx.GetPathString(false))
2854 }
2855
2856 }
2857 return true
2858 })
2859}
2860
satayevb98371c2021-06-15 16:49:50 +01002861// checkUpdatable enforces APEX and its transitive dep properties to have desired values for updatable APEXes.
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002862func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
2863 if a.Updatable() {
Albert Martineefabcf2022-03-21 20:11:16 +00002864 if a.minSdkVersionValue(ctx) == "" {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002865 ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
2866 }
Jiyong Park1bc84122021-06-22 20:23:05 +09002867 if a.UsePlatformApis() {
2868 ctx.PropertyErrorf("updatable", "updatable APEXes can't use platform APIs")
2869 }
Daniel Norman69109112021-12-02 12:52:42 -08002870 if a.SocSpecific() || a.DeviceSpecific() {
2871 ctx.PropertyErrorf("updatable", "vendor APEXes are not updatable")
2872 }
Jiyong Parkf4020582021-11-29 12:37:10 +09002873 if a.FutureUpdatable() {
2874 ctx.PropertyErrorf("future_updatable", "Already updatable. Remove `future_updatable: true:`")
2875 }
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002876 a.checkJavaStableSdkVersion(ctx)
satayevb98371c2021-06-15 16:49:50 +01002877 a.checkClasspathFragments(ctx)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002878 }
2879}
2880
satayevb98371c2021-06-15 16:49:50 +01002881// checkClasspathFragments enforces that all classpath fragments in deps generate classpaths.proto config.
2882func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) {
2883 ctx.VisitDirectDeps(func(module android.Module) {
2884 if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag {
2885 info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
2886 if !info.ClasspathFragmentProtoGenerated {
2887 ctx.OtherModuleErrorf(module, "is included in updatable apex %v, it must not set generate_classpaths_proto to false", ctx.ModuleName())
2888 }
2889 }
2890 })
2891}
2892
2893// checkJavaStableSdkVersion enforces that all Java deps are using stable SDKs to compile.
Artur Satayev8cf899a2020-04-15 17:29:42 +01002894func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) {
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002895 // Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs,
2896 // java's checkLinkType guarantees correct usage for transitive deps
Artur Satayev8cf899a2020-04-15 17:29:42 +01002897 ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
2898 tag := ctx.OtherModuleDependencyTag(module)
2899 switch tag {
2900 case javaLibTag, androidAppTag:
Jiyong Parkdbd710c2021-04-02 08:45:46 +09002901 if m, ok := module.(interface {
2902 CheckStableSdkVersion(ctx android.BaseModuleContext) error
2903 }); ok {
2904 if err := m.CheckStableSdkVersion(ctx); err != nil {
Artur Satayev8cf899a2020-04-15 17:29:42 +01002905 ctx.ModuleErrorf("cannot depend on \"%v\": %v", ctx.OtherModuleName(module), err)
2906 }
2907 }
2908 }
2909 })
2910}
2911
satayevb98371c2021-06-15 16:49:50 +01002912// checkApexAvailability ensures that the all the dependencies are marked as available for this APEX.
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002913func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
2914 // Let's be practical. Availability for test, host, and the VNDK apex isn't important
2915 if ctx.Host() || a.testApex || a.vndkApex {
2916 return
2917 }
2918
2919 // Because APEXes targeting other than system/system_ext partitions can't set
2920 // apex_available, we skip checks for these APEXes
2921 if a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
2922 return
2923 }
2924
2925 // Coverage build adds additional dependencies for the coverage-only runtime libraries.
2926 // Requiring them and their transitive depencies with apex_available is not right
2927 // because they just add noise.
2928 if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") || a.IsNativeCoverageNeeded(ctx) {
2929 return
2930 }
2931
2932 a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
2933 // As soon as the dependency graph crosses the APEX boundary, don't go further.
2934 if externalDep {
2935 return false
2936 }
2937
2938 apexName := ctx.ModuleName()
2939 fromName := ctx.OtherModuleName(from)
2940 toName := ctx.OtherModuleName(to)
2941
2942 // If `to` is not actually in the same APEX as `from` then it does not need
2943 // apex_available and neither do any of its dependencies.
Paul Duffin4c3e8e22021-03-18 15:41:29 +00002944 //
2945 // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps().
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002946 if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
2947 // As soon as the dependency graph crosses the APEX boundary, don't go
2948 // further.
2949 return false
2950 }
2951
2952 if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
2953 return true
2954 }
Jiyong Park767dbd92021-03-04 13:03:10 +09002955 ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+
2956 "\n\nDependency path:%s\n\n"+
2957 "Consider adding %q to 'apex_available' property of %q",
2958 fromName, toName, ctx.GetPathString(true), apexName, toName)
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09002959 // Visit this module's dependencies to check and report any issues with their availability.
2960 return true
2961 })
2962}
2963
Jiyong Park192600a2021-08-03 07:52:17 +00002964// checkStaticExecutable ensures that executables in an APEX are not static.
2965func (a *apexBundle) checkStaticExecutables(ctx android.ModuleContext) {
Jiyong Parkd12979d2021-08-03 13:36:09 +09002966 // No need to run this for host APEXes
2967 if ctx.Host() {
2968 return
2969 }
2970
Jiyong Park192600a2021-08-03 07:52:17 +00002971 ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
2972 if ctx.OtherModuleDependencyTag(module) != executableTag {
2973 return
2974 }
Jiyong Parkd12979d2021-08-03 13:36:09 +09002975
2976 if l, ok := module.(cc.LinkableInterface); ok && l.StaticExecutable() {
Jiyong Park192600a2021-08-03 07:52:17 +00002977 apex := a.ApexVariationName()
2978 exec := ctx.OtherModuleName(module)
2979 if isStaticExecutableAllowed(apex, exec) {
2980 return
2981 }
2982 ctx.ModuleErrorf("executable %s is static", ctx.OtherModuleName(module))
2983 }
2984 })
2985}
2986
2987// A small list of exceptions where static executables are allowed in APEXes.
2988func isStaticExecutableAllowed(apex string, exec string) bool {
2989 m := map[string][]string{
Wei Li40f98732022-05-20 22:08:11 -07002990 "com.android.runtime": {
Jiyong Park192600a2021-08-03 07:52:17 +00002991 "linker",
2992 "linkerconfig",
2993 },
2994 }
2995 execNames, ok := m[apex]
2996 return ok && android.InList(exec, execNames)
2997}
2998
braleeb0c1f0c2021-06-07 22:49:13 +08002999// Collect information for opening IDE project files in java/jdeps.go.
3000func (a *apexBundle) IDEInfo(dpInfo *android.IdeInfo) {
Remi NGUYEN VANbe901722022-03-02 21:00:33 +09003001 dpInfo.Deps = append(dpInfo.Deps, a.overridableProperties.Java_libs...)
3002 dpInfo.Deps = append(dpInfo.Deps, a.overridableProperties.Bootclasspath_fragments...)
3003 dpInfo.Deps = append(dpInfo.Deps, a.overridableProperties.Systemserverclasspath_fragments...)
braleeb0c1f0c2021-06-07 22:49:13 +08003004 dpInfo.Paths = append(dpInfo.Paths, a.modulePaths...)
3005}
3006
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09003007var (
3008 apexAvailBaseline = makeApexAvailableBaseline()
3009 inverseApexAvailBaseline = invertApexBaseline(apexAvailBaseline)
3010)
3011
Colin Cross440e0d02020-06-11 11:32:11 -07003012func baselineApexAvailable(apex, moduleName string) bool {
Anton Hanssoneec79eb2020-01-10 15:12:39 +00003013 key := apex
Paul Duffin7d74e7b2020-03-06 12:30:13 +00003014 moduleName = normalizeModuleName(moduleName)
3015
Colin Cross440e0d02020-06-11 11:32:11 -07003016 if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) {
Paul Duffin7d74e7b2020-03-06 12:30:13 +00003017 return true
3018 }
3019
3020 key = android.AvailableToAnyApex
Colin Cross440e0d02020-06-11 11:32:11 -07003021 if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) {
Paul Duffin7d74e7b2020-03-06 12:30:13 +00003022 return true
3023 }
3024
3025 return false
3026}
3027
3028func normalizeModuleName(moduleName string) string {
Jiyong Park0f80c182020-01-31 02:49:53 +09003029 // Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build
3030 // system. Trim the prefix for the check since they are confusing
Paul Duffind23c7262020-12-11 18:13:08 +00003031 moduleName = android.RemoveOptionalPrebuiltPrefix(moduleName)
Jiyong Park0f80c182020-01-31 02:49:53 +09003032 if strings.HasPrefix(moduleName, "libclang_rt.") {
3033 // This module has many arch variants that depend on the product being built.
3034 // We don't want to list them all
3035 moduleName = "libclang_rt"
Anton Hanssoneec79eb2020-01-10 15:12:39 +00003036 }
Jooyung Hanacc7bbe2020-05-20 09:06:00 +09003037 if strings.HasPrefix(moduleName, "androidx.") {
3038 // TODO(b/156996905) Set apex_available/min_sdk_version for androidx support libraries
3039 moduleName = "androidx"
3040 }
Paul Duffin7d74e7b2020-03-06 12:30:13 +00003041 return moduleName
Anton Hanssoneec79eb2020-01-10 15:12:39 +00003042}
3043
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003044// Transform the map of apex -> modules to module -> apexes.
3045func invertApexBaseline(m map[string][]string) map[string][]string {
3046 r := make(map[string][]string)
3047 for apex, modules := range m {
3048 for _, module := range modules {
3049 r[module] = append(r[module], apex)
3050 }
3051 }
3052 return r
3053}
3054
3055// Retrieve the baseline of apexes to which the supplied module belongs.
3056func BaselineApexAvailable(moduleName string) []string {
3057 return inverseApexAvailBaseline[normalizeModuleName(moduleName)]
3058}
3059
Jiyong Parkc0ec6f92020-11-19 23:00:52 +09003060// This is a map from apex to modules, which overrides the apex_available setting for that
3061// particular module to make it available for the apex regardless of its setting.
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003062// TODO(b/147364041): remove this
3063func makeApexAvailableBaseline() map[string][]string {
3064 // The "Module separator"s below are employed to minimize merge conflicts.
3065 m := make(map[string][]string)
3066 //
3067 // Module separator
3068 //
3069 m["com.android.appsearch"] = []string{
3070 "icing-java-proto-lite",
3071 "libprotobuf-java-lite",
3072 }
3073 //
3074 // Module separator
3075 //
Oriol Prieto Gasco8132fbf2022-06-17 19:44:25 +00003076 m["com.android.btservices"] = []string{
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003077 "bluetooth-protos-lite",
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003078 "internal_include_headers",
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003079 "libaudio-a2dp-hw-utils",
3080 "libaudio-hearing-aid-hw-utils",
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003081 "libbluetooth",
3082 "libbluetooth-types",
3083 "libbluetooth-types-header",
3084 "libbluetooth_gd",
3085 "libbluetooth_headers",
3086 "libbluetooth_jni",
3087 "libbt-audio-hal-interface",
3088 "libbt-bta",
3089 "libbt-common",
3090 "libbt-hci",
3091 "libbt-platform-protos-lite",
3092 "libbt-protos-lite",
3093 "libbt-sbc-decoder",
3094 "libbt-sbc-encoder",
3095 "libbt-stack",
3096 "libbt-utils",
3097 "libbtcore",
3098 "libbtdevice",
3099 "libbte",
3100 "libbtif",
3101 "libchrome",
Oriol Prieto Gasco8132fbf2022-06-17 19:44:25 +00003102 }
3103 //
3104 // Module separator
3105 //
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003106 m["com.android.cellbroadcast"] = []string{"CellBroadcastApp", "CellBroadcastServiceModule"}
3107 //
3108 // Module separator
3109 //
3110 m["com.android.extservices"] = []string{
3111 "error_prone_annotations",
3112 "ExtServices-core",
3113 "ExtServices",
3114 "libtextclassifier-java",
3115 "libz_current",
3116 "textclassifier-statsd",
3117 "TextClassifierNotificationLibNoManifest",
3118 "TextClassifierServiceLibNoManifest",
3119 }
3120 //
3121 // Module separator
3122 //
3123 m["com.android.neuralnetworks"] = []string{
3124 "android.hardware.neuralnetworks@1.0",
3125 "android.hardware.neuralnetworks@1.1",
3126 "android.hardware.neuralnetworks@1.2",
3127 "android.hardware.neuralnetworks@1.3",
3128 "android.hidl.allocator@1.0",
3129 "android.hidl.memory.token@1.0",
3130 "android.hidl.memory@1.0",
3131 "android.hidl.safe_union@1.0",
3132 "libarect",
3133 "libbuildversion",
3134 "libmath",
3135 "libprocpartition",
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003136 }
3137 //
3138 // Module separator
3139 //
3140 m["com.android.media"] = []string{
Ray Essick5d240fb2022-02-07 11:01:32 -08003141 // empty
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003142 }
3143 //
3144 // Module separator
3145 //
3146 m["com.android.media.swcodec"] = []string{
Ray Essickde1e3002022-02-10 17:37:51 -08003147 // empty
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003148 }
3149 //
3150 // Module separator
3151 //
3152 m["com.android.mediaprovider"] = []string{
3153 "MediaProvider",
3154 "MediaProviderGoogle",
3155 "fmtlib_ndk",
3156 "libbase_ndk",
3157 "libfuse",
3158 "libfuse_jni",
3159 }
3160 //
3161 // Module separator
3162 //
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003163 m["com.android.runtime"] = []string{
3164 "bionic_libc_platform_headers",
3165 "libarm-optimized-routines-math",
3166 "libc_aeabi",
3167 "libc_bionic",
3168 "libc_bionic_ndk",
3169 "libc_bootstrap",
3170 "libc_common",
3171 "libc_common_shared",
3172 "libc_common_static",
3173 "libc_dns",
3174 "libc_dynamic_dispatch",
3175 "libc_fortify",
3176 "libc_freebsd",
3177 "libc_freebsd_large_stack",
3178 "libc_gdtoa",
3179 "libc_init_dynamic",
3180 "libc_init_static",
3181 "libc_jemalloc_wrapper",
3182 "libc_netbsd",
3183 "libc_nomalloc",
3184 "libc_nopthread",
3185 "libc_openbsd",
3186 "libc_openbsd_large_stack",
3187 "libc_openbsd_ndk",
3188 "libc_pthread",
3189 "libc_static_dispatch",
3190 "libc_syscalls",
3191 "libc_tzcode",
3192 "libc_unwind_static",
3193 "libdebuggerd",
3194 "libdebuggerd_common_headers",
3195 "libdebuggerd_handler_core",
3196 "libdebuggerd_handler_fallback",
3197 "libdl_static",
3198 "libjemalloc5",
3199 "liblinker_main",
3200 "liblinker_malloc",
3201 "liblz4",
3202 "liblzma",
3203 "libprocinfo",
3204 "libpropertyinfoparser",
3205 "libscudo",
3206 "libstdc++",
3207 "libsystemproperties",
3208 "libtombstoned_client_static",
3209 "libunwindstack",
3210 "libz",
3211 "libziparchive",
3212 }
3213 //
3214 // Module separator
3215 //
3216 m["com.android.tethering"] = []string{
3217 "android.hardware.tetheroffload.config-V1.0-java",
3218 "android.hardware.tetheroffload.control-V1.0-java",
3219 "android.hidl.base-V1.0-java",
3220 "libcgrouprc",
3221 "libcgrouprc_format",
3222 "libtetherutilsjni",
3223 "libvndksupport",
3224 "net-utils-framework-common",
3225 "netd_aidl_interface-V3-java",
3226 "netlink-client",
3227 "networkstack-aidl-interfaces-java",
3228 "tethering-aidl-interfaces-java",
3229 "TetheringApiCurrentLib",
3230 }
3231 //
3232 // Module separator
3233 //
3234 m["com.android.wifi"] = []string{
3235 "PlatformProperties",
3236 "android.hardware.wifi-V1.0-java",
3237 "android.hardware.wifi-V1.0-java-constants",
3238 "android.hardware.wifi-V1.1-java",
3239 "android.hardware.wifi-V1.2-java",
3240 "android.hardware.wifi-V1.3-java",
3241 "android.hardware.wifi-V1.4-java",
3242 "android.hardware.wifi.hostapd-V1.0-java",
3243 "android.hardware.wifi.hostapd-V1.1-java",
3244 "android.hardware.wifi.hostapd-V1.2-java",
3245 "android.hardware.wifi.supplicant-V1.0-java",
3246 "android.hardware.wifi.supplicant-V1.1-java",
3247 "android.hardware.wifi.supplicant-V1.2-java",
3248 "android.hardware.wifi.supplicant-V1.3-java",
3249 "android.hidl.base-V1.0-java",
3250 "android.hidl.manager-V1.0-java",
3251 "android.hidl.manager-V1.1-java",
3252 "android.hidl.manager-V1.2-java",
3253 "bouncycastle-unbundled",
3254 "dnsresolver_aidl_interface-V2-java",
3255 "error_prone_annotations",
3256 "framework-wifi-pre-jarjar",
3257 "framework-wifi-util-lib",
3258 "ipmemorystore-aidl-interfaces-V3-java",
3259 "ipmemorystore-aidl-interfaces-java",
3260 "ksoap2",
3261 "libnanohttpd",
3262 "libwifi-jni",
3263 "net-utils-services-common",
3264 "netd_aidl_interface-V2-java",
3265 "netd_aidl_interface-unstable-java",
3266 "netd_event_listener_interface-java",
3267 "netlink-client",
3268 "networkstack-client",
3269 "services.net",
3270 "wifi-lite-protos",
3271 "wifi-nano-protos",
3272 "wifi-service-pre-jarjar",
3273 "wifi-service-resources",
3274 }
3275 //
3276 // Module separator
3277 //
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003278 m["com.android.os.statsd"] = []string{
3279 "libstatssocket",
3280 }
3281 //
3282 // Module separator
3283 //
3284 m[android.AvailableToAnyApex] = []string{
3285 // TODO(b/156996905) Set apex_available/min_sdk_version for androidx/extras support libraries
3286 "androidx",
3287 "androidx-constraintlayout_constraintlayout",
3288 "androidx-constraintlayout_constraintlayout-nodeps",
3289 "androidx-constraintlayout_constraintlayout-solver",
3290 "androidx-constraintlayout_constraintlayout-solver-nodeps",
3291 "com.google.android.material_material",
3292 "com.google.android.material_material-nodeps",
3293
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003294 "libclang_rt",
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003295 "libprofile-clang-extras",
3296 "libprofile-clang-extras_ndk",
3297 "libprofile-extras",
3298 "libprofile-extras_ndk",
Ryan Prichardb35a85e2021-01-13 19:18:53 -08003299 "libunwind",
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003300 }
3301 return m
3302}
3303
3304func init() {
Spandan Dasf14e2542021-11-12 00:01:37 +00003305 android.AddNeverAllowRules(createBcpPermittedPackagesRules(qBcpPackages())...)
3306 android.AddNeverAllowRules(createBcpPermittedPackagesRules(rBcpPackages())...)
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003307}
3308
Spandan Dasf14e2542021-11-12 00:01:37 +00003309func createBcpPermittedPackagesRules(bcpPermittedPackages map[string][]string) []android.Rule {
3310 rules := make([]android.Rule, 0, len(bcpPermittedPackages))
3311 for jar, permittedPackages := range bcpPermittedPackages {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08003312 permittedPackagesRule := android.NeverAllow().
Spandan Dasf14e2542021-11-12 00:01:37 +00003313 With("name", jar).
3314 WithMatcher("permitted_packages", android.NotInList(permittedPackages)).
3315 Because(jar +
3316 " bootjar may only use these package prefixes: " + strings.Join(permittedPackages, ",") +
Anton Hanssone1b18362021-12-23 15:05:38 +00003317 ". Please consider the following alternatives:\n" +
Andrei Onead967aee2022-01-19 15:36:40 +00003318 " 1. If the offending code is from a statically linked library, consider " +
3319 "removing that dependency and using an alternative already in the " +
3320 "bootclasspath, or perhaps a shared library." +
3321 " 2. Move the offending code into an allowed package.\n" +
3322 " 3. Jarjar the offending code. Please be mindful of the potential system " +
3323 "health implications of bundling that code, particularly if the offending jar " +
3324 "is part of the bootclasspath.")
Spandan Dasf14e2542021-11-12 00:01:37 +00003325
Jaewoong Jung18aefc12020-12-21 09:11:10 -08003326 rules = append(rules, permittedPackagesRule)
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003327 }
3328 return rules
3329}
3330
Anton Hanssone1b18362021-12-23 15:05:38 +00003331// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003332// Adding code to the bootclasspath in new packages will cause issues on module update.
Spandan Dasf14e2542021-11-12 00:01:37 +00003333func qBcpPackages() map[string][]string {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003334 return map[string][]string{
Wei Li40f98732022-05-20 22:08:11 -07003335 "conscrypt": {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003336 "android.net.ssl",
3337 "com.android.org.conscrypt",
3338 },
Wei Li40f98732022-05-20 22:08:11 -07003339 "updatable-media": {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003340 "android.media",
3341 },
3342 }
3343}
3344
Anton Hanssone1b18362021-12-23 15:05:38 +00003345// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003346// Adding code to the bootclasspath in new packages will cause issues on module update.
Spandan Dasf14e2542021-11-12 00:01:37 +00003347func rBcpPackages() map[string][]string {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003348 return map[string][]string{
Wei Li40f98732022-05-20 22:08:11 -07003349 "framework-mediaprovider": {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003350 "android.provider",
3351 },
Wei Li40f98732022-05-20 22:08:11 -07003352 "framework-permission": {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003353 "android.permission",
3354 "android.app.role",
3355 "com.android.permission",
3356 "com.android.role",
3357 },
Wei Li40f98732022-05-20 22:08:11 -07003358 "framework-sdkextensions": {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003359 "android.os.ext",
3360 },
Wei Li40f98732022-05-20 22:08:11 -07003361 "framework-statsd": {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003362 "android.app",
3363 "android.os",
3364 "android.util",
3365 "com.android.internal.statsd",
3366 "com.android.server.stats",
3367 },
Wei Li40f98732022-05-20 22:08:11 -07003368 "framework-wifi": {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003369 "com.android.server.wifi",
3370 "com.android.wifi.x",
3371 "android.hardware.wifi",
3372 "android.net.wifi",
3373 },
Wei Li40f98732022-05-20 22:08:11 -07003374 "framework-tethering": {
Jiyong Park8e6d52f2020-11-19 14:37:47 +09003375 "android.net",
3376 },
3377 }
3378}
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -04003379
3380// For Bazel / bp2build
3381
3382type bazelApexBundleAttributes struct {
Yu Liu4ae55d12022-01-05 17:17:23 -08003383 Manifest bazel.LabelAttribute
3384 Android_manifest bazel.LabelAttribute
3385 File_contexts bazel.LabelAttribute
3386 Key bazel.LabelAttribute
Jingwen Chen6817bbb2022-10-14 09:56:07 +00003387 Certificate bazel.LabelAttribute // used when the certificate prop is a module
3388 Certificate_name bazel.StringAttribute // used when the certificate prop is a string
Yu Liu4ae55d12022-01-05 17:17:23 -08003389 Min_sdk_version *string
3390 Updatable bazel.BoolAttribute
3391 Installable bazel.BoolAttribute
3392 Binaries bazel.LabelListAttribute
3393 Prebuilts bazel.LabelListAttribute
3394 Native_shared_libs_32 bazel.LabelListAttribute
3395 Native_shared_libs_64 bazel.LabelListAttribute
Wei Lif034cb42022-01-19 15:54:31 -08003396 Compressible bazel.BoolAttribute
Jingwen Chen9b7ebca2022-06-03 09:11:20 +00003397 Package_name *string
Jingwen Chenb732d7c2022-06-10 08:14:19 +00003398 Logging_parent *string
Yu Liu4c212ce2022-10-14 12:20:20 -07003399 Tests bazel.LabelListAttribute
Yu Liu4ae55d12022-01-05 17:17:23 -08003400}
3401
3402type convertedNativeSharedLibs struct {
3403 Native_shared_libs_32 bazel.LabelListAttribute
3404 Native_shared_libs_64 bazel.LabelListAttribute
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -04003405}
3406
Liz Kammerbe46fcc2021-11-01 15:32:43 -04003407// ConvertWithBp2build performs bp2build conversion of an apex
3408func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
Yu Liu4c212ce2022-10-14 12:20:20 -07003409 // We only convert apex and apex_test modules at this time
3410 if ctx.ModuleType() != "apex" && ctx.ModuleType() != "apex_test" {
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -04003411 return
3412 }
3413
Wei Li1c66fc72022-05-09 23:59:14 -07003414 attrs, props := convertWithBp2build(a, ctx)
Yu Liu4c212ce2022-10-14 12:20:20 -07003415 commonAttrs := android.CommonAttributes{
3416 Name: a.Name(),
3417 }
3418 if a.testApex {
3419 commonAttrs.Testonly = proptools.BoolPtr(a.testApex)
3420 }
3421 ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
Wei Li1c66fc72022-05-09 23:59:14 -07003422}
3423
3424func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties) {
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -04003425 var manifestLabelAttribute bazel.LabelAttribute
Wei Li40f98732022-05-20 22:08:11 -07003426 manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")))
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003427
3428 var androidManifestLabelAttribute bazel.LabelAttribute
Liz Kammerbe46fcc2021-11-01 15:32:43 -04003429 if a.properties.AndroidManifest != nil {
3430 androidManifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.AndroidManifest))
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003431 }
3432
3433 var fileContextsLabelAttribute bazel.LabelAttribute
Wei Li1c66fc72022-05-09 23:59:14 -07003434 if a.properties.File_contexts == nil {
3435 // See buildFileContexts(), if file_contexts is not specified the default one is used, which is //system/sepolicy/apex:<module name>-file_contexts
3436 fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, a.Name()+"-file_contexts"))
3437 } else if strings.HasPrefix(*a.properties.File_contexts, ":") {
3438 // File_contexts is a module
Liz Kammerbe46fcc2021-11-01 15:32:43 -04003439 fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.properties.File_contexts))
Wei Li1c66fc72022-05-09 23:59:14 -07003440 } else {
3441 // File_contexts is a file
3442 fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.File_contexts))
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003443 }
3444
Albert Martineefabcf2022-03-21 20:11:16 +00003445 // TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but
3446 // given it's coming via config, we probably don't want to put it in here.
Liz Kammer46fb7ab2021-12-01 10:09:34 -05003447 var minSdkVersion *string
Liz Kammerbe46fcc2021-11-01 15:32:43 -04003448 if a.properties.Min_sdk_version != nil {
3449 minSdkVersion = a.properties.Min_sdk_version
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003450 }
3451
3452 var keyLabelAttribute bazel.LabelAttribute
Liz Kammerbe46fcc2021-11-01 15:32:43 -04003453 if a.overridableProperties.Key != nil {
3454 keyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.overridableProperties.Key))
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003455 }
3456
Jingwen Chen6817bbb2022-10-14 09:56:07 +00003457 // Certificate
3458 certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableProperties.Certificate)
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003459
Yu Liu4ae55d12022-01-05 17:17:23 -08003460 nativeSharedLibs := &convertedNativeSharedLibs{
3461 Native_shared_libs_32: bazel.LabelListAttribute{},
3462 Native_shared_libs_64: bazel.LabelListAttribute{},
3463 }
Vinh Tran8f5310f2022-10-07 18:16:47 -04003464
3465 // https://cs.android.com/android/platform/superproject/+/master:build/soong/android/arch.go;l=698;drc=f05b0d35d2fbe51be9961ce8ce8031f840295c68
3466 // https://cs.android.com/android/platform/superproject/+/master:build/soong/apex/apex.go;l=2549;drc=ec731a83e3e2d80a1254e32fd4ad7ef85e262669
3467 // In Soong, decodeMultilib, used to get multilib, return "first" if defaultMultilib is set to "common".
3468 // Since apex sets defaultMultilib to be "common", equivalent compileMultilib in bp2build for apex should be "first"
3469 compileMultilib := "first"
Yu Liu4ae55d12022-01-05 17:17:23 -08003470 if a.CompileMultilib() != nil {
3471 compileMultilib = *a.CompileMultilib()
3472 }
3473
3474 // properties.Native_shared_libs is treated as "both"
3475 convertBothLibs(ctx, compileMultilib, a.properties.Native_shared_libs, nativeSharedLibs)
3476 convertBothLibs(ctx, compileMultilib, a.properties.Multilib.Both.Native_shared_libs, nativeSharedLibs)
3477 convert32Libs(ctx, compileMultilib, a.properties.Multilib.Lib32.Native_shared_libs, nativeSharedLibs)
3478 convert64Libs(ctx, compileMultilib, a.properties.Multilib.Lib64.Native_shared_libs, nativeSharedLibs)
3479 convertFirstLibs(ctx, compileMultilib, a.properties.Multilib.First.Native_shared_libs, nativeSharedLibs)
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003480
Liz Kammerbe46fcc2021-11-01 15:32:43 -04003481 prebuilts := a.overridableProperties.Prebuilts
Rupert Shuttleworth9447e1e2021-07-28 05:53:42 -04003482 prebuiltsLabelList := android.BazelLabelForModuleDeps(ctx, prebuilts)
3483 prebuiltsLabelListAttribute := bazel.MakeLabelListAttribute(prebuiltsLabelList)
3484
Liz Kammerbe46fcc2021-11-01 15:32:43 -04003485 binaries := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Binaries)
Jingwen Chenb07c9012021-12-08 10:05:45 +00003486 binariesLabelListAttribute := bazel.MakeLabelListAttribute(binaries)
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003487
Yu Liu4c212ce2022-10-14 12:20:20 -07003488 var testsAttrs bazel.LabelListAttribute
3489 if a.testApex && len(a.properties.ApexNativeDependencies.Tests) > 0 {
3490 tests := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Tests)
3491 testsAttrs = bazel.MakeLabelListAttribute(tests)
3492 }
3493
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003494 var updatableAttribute bazel.BoolAttribute
Liz Kammerbe46fcc2021-11-01 15:32:43 -04003495 if a.properties.Updatable != nil {
3496 updatableAttribute.Value = a.properties.Updatable
Rupert Shuttleworth6e4950a2021-07-27 01:34:59 -04003497 }
3498
3499 var installableAttribute bazel.BoolAttribute
Liz Kammerbe46fcc2021-11-01 15:32:43 -04003500 if a.properties.Installable != nil {
3501 installableAttribute.Value = a.properties.Installable
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -04003502 }
3503
Wei Lif034cb42022-01-19 15:54:31 -08003504 var compressibleAttribute bazel.BoolAttribute
3505 if a.overridableProperties.Compressible != nil {
3506 compressibleAttribute.Value = a.overridableProperties.Compressible
3507 }
3508
Jingwen Chen9b7ebca2022-06-03 09:11:20 +00003509 var packageName *string
3510 if a.overridableProperties.Package_name != "" {
3511 packageName = &a.overridableProperties.Package_name
3512 }
3513
Jingwen Chenb732d7c2022-06-10 08:14:19 +00003514 var loggingParent *string
3515 if a.overridableProperties.Logging_parent != "" {
3516 loggingParent = &a.overridableProperties.Logging_parent
3517 }
3518
Wei Li1c66fc72022-05-09 23:59:14 -07003519 attrs := bazelApexBundleAttributes{
Yu Liu4ae55d12022-01-05 17:17:23 -08003520 Manifest: manifestLabelAttribute,
3521 Android_manifest: androidManifestLabelAttribute,
3522 File_contexts: fileContextsLabelAttribute,
3523 Min_sdk_version: minSdkVersion,
3524 Key: keyLabelAttribute,
Jingwen Chenbea58092022-09-29 16:56:02 +00003525 Certificate: certificate,
3526 Certificate_name: certificateName,
Yu Liu4ae55d12022-01-05 17:17:23 -08003527 Updatable: updatableAttribute,
3528 Installable: installableAttribute,
3529 Native_shared_libs_32: nativeSharedLibs.Native_shared_libs_32,
3530 Native_shared_libs_64: nativeSharedLibs.Native_shared_libs_64,
3531 Binaries: binariesLabelListAttribute,
3532 Prebuilts: prebuiltsLabelListAttribute,
Wei Lif034cb42022-01-19 15:54:31 -08003533 Compressible: compressibleAttribute,
Jingwen Chen9b7ebca2022-06-03 09:11:20 +00003534 Package_name: packageName,
Jingwen Chenb732d7c2022-06-10 08:14:19 +00003535 Logging_parent: loggingParent,
Yu Liu4c212ce2022-10-14 12:20:20 -07003536 Tests: testsAttrs,
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -04003537 }
3538
3539 props := bazel.BazelTargetModuleProperties{
3540 Rule_class: "apex",
Cole Faust5f90da32022-04-29 13:37:43 -07003541 Bzl_load_location: "//build/bazel/rules/apex:apex.bzl",
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -04003542 }
3543
Wei Li1c66fc72022-05-09 23:59:14 -07003544 return attrs, props
Rupert Shuttlewortha9d76dd2021-07-02 07:17:16 -04003545}
Yu Liu4ae55d12022-01-05 17:17:23 -08003546
3547// The following conversions are based on this table where the rows are the compile_multilib
3548// values and the columns are the properties.Multilib.*.Native_shared_libs. Each cell
3549// represents how the libs should be compiled for a 64-bit/32-bit device: 32 means it
3550// should be compiled as 32-bit, 64 means it should be compiled as 64-bit, none means it
3551// should not be compiled.
3552// multib/compile_multilib, 32, 64, both, first
3553// 32, 32/32, none/none, 32/32, none/32
3554// 64, none/none, 64/none, 64/none, 64/none
3555// both, 32/32, 64/none, 32&64/32, 64/32
3556// first, 32/32, 64/none, 64/32, 64/32
3557
3558func convert32Libs(ctx android.TopDownMutatorContext, compileMultilb string,
3559 libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
3560 libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
3561 switch compileMultilb {
3562 case "both", "32":
3563 makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3564 case "first":
3565 make32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3566 case "64":
3567 // Incompatible, ignore
3568 default:
3569 invalidCompileMultilib(ctx, compileMultilb)
3570 }
3571}
3572
3573func convert64Libs(ctx android.TopDownMutatorContext, compileMultilb string,
3574 libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
3575 libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
3576 switch compileMultilb {
3577 case "both", "64", "first":
3578 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3579 case "32":
3580 // Incompatible, ignore
3581 default:
3582 invalidCompileMultilib(ctx, compileMultilb)
3583 }
3584}
3585
3586func convertBothLibs(ctx android.TopDownMutatorContext, compileMultilb string,
3587 libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
3588 libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
3589 switch compileMultilb {
3590 case "both":
3591 makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3592 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3593 case "first":
3594 makeFirstSharedLibsAttributes(libsLabelList, nativeSharedLibs)
3595 case "32":
3596 makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3597 case "64":
3598 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3599 default:
3600 invalidCompileMultilib(ctx, compileMultilb)
3601 }
3602}
3603
3604func convertFirstLibs(ctx android.TopDownMutatorContext, compileMultilb string,
3605 libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
3606 libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
3607 switch compileMultilb {
3608 case "both", "first":
3609 makeFirstSharedLibsAttributes(libsLabelList, nativeSharedLibs)
3610 case "32":
3611 make32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3612 case "64":
3613 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3614 default:
3615 invalidCompileMultilib(ctx, compileMultilb)
3616 }
3617}
3618
3619func makeFirstSharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
3620 make32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3621 make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
3622}
3623
3624func makeNoConfig32SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
3625 list := bazel.LabelListAttribute{}
3626 list.SetSelectValue(bazel.NoConfigAxis, "", libsLabelList)
3627 nativeSharedLibs.Native_shared_libs_32.Append(list)
3628}
3629
3630func make32SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
3631 makeSharedLibsAttributes("x86", libsLabelList, &nativeSharedLibs.Native_shared_libs_32)
3632 makeSharedLibsAttributes("arm", libsLabelList, &nativeSharedLibs.Native_shared_libs_32)
3633}
3634
3635func make64SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
3636 makeSharedLibsAttributes("x86_64", libsLabelList, &nativeSharedLibs.Native_shared_libs_64)
3637 makeSharedLibsAttributes("arm64", libsLabelList, &nativeSharedLibs.Native_shared_libs_64)
3638}
3639
3640func makeSharedLibsAttributes(config string, libsLabelList bazel.LabelList,
3641 labelListAttr *bazel.LabelListAttribute) {
3642 list := bazel.LabelListAttribute{}
3643 list.SetSelectValue(bazel.ArchConfigurationAxis, config, libsLabelList)
3644 labelListAttr.Append(list)
3645}
3646
3647func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) {
3648 ctx.PropertyErrorf("compile_multilib", "Invalid value: %s", value)
3649}