README.md
1# APEX File Format
2
3Android Pony EXpress (APEX) is a container format introduced in Android Q that
4is used in the install flow for lower-level system modules. This format
5facilitates the updates of system components that don't fit into the standard
6Android application model. Some example components are native services and
7libraries, hardware abstraction layers
8([HALs](/https://source.android.com/devices/architecture/hal-types)), runtime
9([ART](/https://source.android.com/devices/tech/dalvik)), and class libraries.
10
11The term "APEX" can also refer to an APEX file.
12
13This document describes technical details of the APEX file format. If you are
14looking at how to build an APEX package, kindly refer to [this how-to](howto.md)
15document.
16
17## Background
18
19Although Android supports updates of modules that fit within the standard app
20model (for example, services, activities) via package installer apps (such as
21the Google Play Store app), using a similar model for lower-level OS components
22has the following drawbacks:
23
24- APK-based modules can't be used early in the boot sequence. The package
25 manager is the central repository of information about apps and can only be
26 started from the activity manager, which becomes ready in a later stage of
27 the boot procedure.
28- The APK format (particularly the manifest) is designed for Android apps and
29 system modules aren't always a good fit.
30
31## Design
32
33This section describes the high-level design of the APEX file format and the
34APEX manager, which is a service that manages APEX files.
35
36### APEX format {#apex-format}
37
38This is the format of an APEX file.
39
40![APEX file format](apex-format.png)
41
42**Figure 1.** APEX file format
43
44At the top level, an APEX file is a zip file in which files are stored
45uncompressed and located at 4 KB boundaries.
46
47The four files in an APEX file are:
48
49- `apex_manifest.json`
50- `AndroidManifest.xml`
51- `apex_payload.img`
52- `apex_pubkey`
53
54The `apex_manifest.json` file contains the package name and version, which
55identify an APEX file.
56
57The `AndroidManifest.xml` file allows the APEX file to use APK-related tools and
58infrastructure such as ADB, PackageManager, and package installer apps (such as
59Play Store). For example, the APEX file can use an existing tool such as `aapt`
60to inspect basic metadata from the file. The file contains package name and
61version information. This information is generally also available in
62`apex_manifest.json`. `AndroidManifest.xml` might contain additional targeting
63information that can be used by the existing app publishing tools.
64
65`apex_manifest.json` is recommended over `AndroidManifest.xml` for new code and
66systems that deal with APEX.
67
68`apex_payload.img` is an ext4 file system image backed by dm-verity. The image
69is mounted at runtime via a loop device. Specifically, the hash tree and
70metadata block are created using libavb. The file system payload isn't parsed
71(because the image should be mountable in place). Regular files are included
72inside the `apex_payload.img` file.
73
74`apex_pubkey` is the public key used to sign the file system image. At runtime,
75this key ensures that the downloaded APEX is signed with the same entity that
76signs the same APEX in the built-in partitions.
77
78### APEX manager
79
80The APEX manager (or `apexd`) is a native daemon responsible for verifying,
81installing, and uninstalling APEX files. This process is launched and is ready
82early in the boot sequence. APEX files are normally pre-installed on the device
83under `/system/apex`. The APEX manager defaults to using these packages if no
84updates are available.
85
86The update sequence of an APEX uses the
87[PackageManager class](https://developer.android.com/reference/android/content/pm/PackageManager)
88and is as follows.
89
901. An APEX file is downloaded via a package installer app, ADB, or other
91 source.
921. The package manager starts the installation procedure. Upon recognizing that
93 the file is an APEX, the package manager transfers control to the APEX
94 manager.
951. The APEX manager verifies the APEX file.
961. If the APEX file is verified, the internal database of the APEX manager is
97 updated to reflect that the APEX file will be activated at next boot.
981. The requestor of the install receives a broadcast upon successful
99 verification of the package.
1001. To continue the installation, the system automatically reboots the device.
1011. At reboot, the APEX manager starts, reads the internal database, and does
102 the following for each APEX file listed:
103
104 1. Verifies the APEX file.
105 1. Creates a loop device from the APEX file.
106 1. Creates a device mapper block device on top of the loop device.
107 1. Mounts the device mapper block device onto a unique path (for example,
108 <code>/apex/<var>name</var>@<var>ver</var></code>).
109
110When all APEX files listed in the internal database are mounted, the APEX
111manager provides a binder service for other system components to query
112information about the installed APEX files. For example, the other system
113components can query the list of APEX files installed in the device or query the
114exact path where a specific APEX is mounted, so the files can be accessed.
115
116### APEX files are APK files
117
118APEX files are valid APK files because they are signed zip archives (using the
119APK signature scheme) containing an `AndroidManifest.xml` file. This allows APEX
120files to use the infrastructure for APK files, such as a package installer app,
121the signing utility, and the package manager.
122
123The `AndroidManifest.xml` file inside an APEX file is minimal, consisting of the
124package `name`, `versionCode`, and optional `targetSdkVersion`, `minSdkVersion`,
125and `maxSdkVersion` for fine-grained targeting. This information allows APEX
126files to be delivered via existing channels such as package installer apps and
127ADB.
128
129### File types supported
130
131The APEX format supports these file types:
132
133- Native shared libs
134- Native executables
135- JAR files
136- Data files
137- Config files
138
139The APEX format can only update some of these file types. Whether a file type
140can be updated depends on the platform and how stable the interfaces for the
141files types are defined.
142
143### Signing
144
145APEX files are signed in two ways. First, the `apex_payload.img` (specifically,
146the vbmeta descriptor appended to `apex_payload.img`) file is signed with a key.
147Then, the entire APEX is signed using the
148[APK signature scheme v3](/https://source.android.com/security/apksigning/v3).
149Two different keys are used in this process.
150
151On the device side, a public key corresponding to the private key used to sign
152the vbmeta descriptor is installed. The APEX manager uses the public key to
153verify APEXs that are requested to be installed. Each APEX must be signed with
154different keys and is enforced both at build time and runtime.
155
156### APEX in built-in partitions
157
158APEX files can be located in built-in partitions such as `/system`. The
159partition is already over dm-verity, so the APEX files are mounted directly over
160the loop device.
161
162If an APEX is present in a built-in partition, the APEX can be updated by
163providing an APEX package with the same package name and a higher version code.
164The new APEX is stored in `/data` and, similar to APKs, the newer version
165shadows the version already present in the built-in partition. But unlike APKs,
166the newer version of the APEX is only activated after reboot.
167
168## Kernel requirements
169
170To support APEX mainline modules on an Android device, the following Linux
171kernel features are required: the loop driver and dm-verity. The loop driver
172mounts the file system image in an APEX module and dm-verity verifies the APEX
173module.
174
175The performance of the loop driver and dm-verity is important in achieving good
176system performance when using APEX modules.
177
178### Supported kernel versions
179
180APEX mainline modules are supported on devices using kernel versions 4.4 or
181higher. New devices launching with Android Q or higher must use kernel version
1824.9 or higher to support APEX modules.
183
184### Required kernel patches
185
186The required kernel patches for supporting APEX modules are included in the
187Android common tree. To get the patches to support APEX, use the latest version
188of the Android common tree.
189
190#### Kernel version 4.4
191
192This version is only supported for devices that are upgraded from Android 9 to
193Android Q and want to support APEX modules. To get the required patches, a
194down-merge from the `android-4.4` branch is strongly recommended. The following
195is a list of the required individual patches for kernel version 4.4.
196
197- UPSTREAM: loop: add ioctl for changing logical block size
198 ([4.4](https://android-review.googlesource.com/c/kernel/common/+/777013){: .external})
199- BACKPORT: block/loop: set hw_sectors
200 ([4.4](https://android-review.googlesource.com/c/kernel/common/+/777014/7){: .external})
201- UPSTREAM: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl
202 ([4.4](https://android-review.googlesource.com/c/kernel/common/+/777015/7){: .external})
203- ANDROID: mnt: Fix next_descendent
204 ([4.4](https://android-review.googlesource.com/c/kernel/common/+/405314){: .external})
205- ANDROID: mnt: remount should propagate to slaves of slaves
206 ([4.4](https://android-review.googlesource.com/c/kernel/common/+/320406){: .external})
207- ANDROID: mnt: Propagate remount correctly
208 ([4.4](https://android-review.googlesource.com/c/kernel/common/+/928253){: .external})
209- Revert "ANDROID: dm verity: add minimum prefetch size"
210 ([4.4](https://android-review.googlesource.com/c/kernel/common/+/867875){: .external})
211- UPSTREAM: loop: drop caches if offset or block_size are changed
212 ([4.4](https://android-review.googlesource.com/c/kernel/common/+/854265){: .external})
213
214#### Kernel versions 4.9/4.14/4.19
215
216To get the required patches for kernel versions 4.9/4.14/4.19, down-merge from
217the `android-common` branch.
218
219### Required kernel configuration options
220
221The following list shows the base configuration requirements for supporting APEX
222modules that were introduced in Android Q. The items with an asterisk (\*) are
223existing requirements from Android 9 and lower.
224
225```
226(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
227CONFIG_BLK_DEV_LOOP=Y # for loop device support
228CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
229(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
230(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
231CONFIG_DM_VERITY=Y # DM-verity support
232```
233
234### Kernel command line parameter requirements
235
236To support APEX, make sure the kernel command line parameters meet the following
237requirements.
238
239- `loop.max_loop` must NOT be set
240- `loop.max_part` must be <= 8
241
242## Building an APEX
243
244Note: Because the implementation details for APEX are still under development,
245the content in this section is subject to change.
246
247This section describes how to build an APEX using the Android build system. The
248following is an example of `Android.bp` for an APEX named `apex.test`.
249
250```
251apex {
252 name: "apex.test",
253 manifest: "apex_manifest.json",
254 file_contexts: "file_contexts",
255 // libc.so and libcutils.so are included in the apex
256 native_shared_libs: ["libc", "libcutils"],
257 binaries: ["vold"],
258 java_libs: ["core-all"],
259 prebuilts: ["my_prebuilt"],
260 compile_multilib: "both",
261 key: "apex.test.key",
262 certificate: "platform",
263}
264```
265
266`apex_manifest.json` example:
267
268```
269{
270 "name": "com.android.example.apex",
271 "version": 1
272}
273```
274
275`file_contexts` example:
276
277```
278(/.*)? u:object_r:system_file:s0
279/sub(/.*)? u:object_r:sub_file:s0
280/sub/file3 u:object_r:file3_file:s0
281```
282
283#### File types and locations in APEX
284
285File type | Location in APEX
286---------------- | ----------------------------------------------------------
287Shared libraries | `/lib` and `/lib64` (`/lib/arm` for translated arm in x86)
288Executables | `/bin`
289Java libraries | `/javalib`
290Prebuilts | `/etc`
291
292### Transitive dependencies
293
294APEX files automatically include transitive dependencies of native shared libs
295or executables. For example, if `libFoo` depends on `libBar`, the two libs are
296included when only `libFoo` is listed in the `native_shared_libs` property.
297
298### Handling multiple ABIs
299
300Install the `native_shared_libs` property for both primary and secondary
301application binary interfaces (ABIs) of the device. If an APEX targets devices
302with a single ABI (that is, 32 bit only or 64 bit only), only libraries with the
303corresponding ABI are installed.
304
305Install the `binaries` property only for the primary ABI of the device as
306described below:
307
308- If the device is 32 bit only, only the 32-bit variant of the binary is
309 installed.
310- If the device supports both 32/64 ABIs, but with
311 `TARGET_PREFER_32_BIT_EXECUTABLES=true`, then only the 32-bit variant of the
312 binary is installed.
313- If the device is 64 bit only, then only the 64-bit variant of the binary is
314 installed.
315- If the device supports both 32/64 ABIs, but without
316 TARGET_PREFER_32_BIT_EXECUTABLES`=true`, then only the 64-bit variant of the
317 binary is installed.
318
319To add fine-grained control over the ABIs of the native libraries and binaries,
320use the
321`multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]`
322properties.
323
324- `first`: Matches the primary ABI of the device. This is the default for
325 binaries.
326- `lib32`: Matches the 32-bit ABI of the device, if supported.
327- `lib64`: Matches the 64-bit ABI of the device, it supported.
328- `prefer32`: Matches the 32-bit ABI of the device, if supported. If the
329 32-bit ABI isn't supported, matches the 64-bit ABI.
330- `both`: Matches both ABIs. This is the default for
331 `native_shared_libraries`.
332
333The `java`, `libraries`, and `prebuilts` properties are ABI-agnostic.
334
335This example is for a device that supports 32/64 and doesn't prefer 32:
336
337```
338apex {
339 // other properties are omitted
340 native_shared_libs: ["libFoo"], // installed for 32 and 64
341 binaries: ["exec1"], // installed for 64, but not for 32
342 multilib: {
343 first: {
344 native_shared_libs: ["libBar"], // installed for 64, but not for 32
345 binaries: ["exec2"], // same as binaries without multilib.first
346 },
347 both: {
348 native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
349 binaries: ["exec3"], // installed for 32 and 64
350 },
351 prefer32: {
352 native_shared_libs: ["libX"], // installed for 32, but not for 64
353 },
354 lib64: {
355 native_shared_libs: ["libY"], // installed for 64, but not for 32
356 },
357 },
358}
359```
360
361### vbmeta signing
362
363Sign each APEX with different keys. When a new key is required, create a
364public-private key pair and make an `apex_key` module. Use the `key` property to
365sign the APEX using the key. The public key is automatically included in the
366APEX with the name `avb_pubkey`.
367
368Create an rsa key pair.
369
370```
371$ openssl genrsa -out foo.pem 4096
372```
373
374Extract the public key from the key pair.
375
376```
377$ avbtool extract_public_key --key foo.pem --output foo.avbpubkey
378```
379
380In Android.bp:
381
382```
383apex_key {
384 name: "apex.test.key",
385 public_key: "foo.avbpubkey",
386 private_key: "foo.pem",
387}
388```
389
390In the above example, the name of the public key (`foo`) becomes the ID of the
391key. The ID of the key used to sign an APEX is written in the APEX. At runtime,
392`apexd` verifies the APEX using a public key with the same ID in the device.
393
394### ZIP signing
395
396Sign APEXs in the same way as APKs. Sign APEXs twice, once for the mini file
397system (`apex_payload.img` file) and once for the entire file.
398
399To sign an APEX at the file-level, set the `certificate` property in one of
400these three ways:
401
402- Not set: If no value is set, the APEX is signed with the certificate located
403 at `PRODUCT_DEFAULT_DEV_CERTIFICATE`. If no flag is set, the path defaults
404 to `build/target/product/security/testkey`.
405- `<name>`: The APEX is signed with the `<name>` certificate in the same
406 directory as `PRODUCT_DEFAULT_DEV_CERTIFICATE`.
407- `:<name>`: The APEX is signed with the certificate that is defined by the
408 Soong module named `<name>`. The certificate module can be defined as
409 follows.
410
411```
412android_app_certificate {
413 name: "my_key_name",
414 certificate: "dir/cert",
415 // this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
416}
417```
418
419Note: The `key` and `certificate` values do NOT need to be derived from the same
420public/private key pairs. APK signing (specified by `certificate`) is required
421because an APEX is an APK.
422
423## Installing an APEX
424
425To install an APEX, use ADB.
426
427```
428$ adb install apex_file_name
429$ adb reboot
430```
431
432## Using an APEX
433
434After reboot, the APEX is mounted at the `/apex/<apex_name>@<version>`
435directory. Multiple versions of the same APEX can be mounted at the same time.
436Among the mount paths, the one that corresponds to the latest version is
437bind-mounted at `/apex/<apex_name>`.
438
439Clients can use the bind-mounted path to read or execute files from APEX.
440
441APEXs are typically used as follows:
442
4431. An OEM or ODM preloads an APEX under `/system/apex` when the device is
444 shipped.
4451. Files in the APEX are accessed via the `/apex/<apex_name>/` path.
4461. When an updated version of the APEX is installed in `/data/apex`, the path
447 points to the new APEX after reboot.
448
449### Updating a service with an APEX
450
451To update a service using an APEX:
452
4531. Mark the service in the system partition as updatable. Add the option
454 `updatable` to the service definition.
455
456 ```
457 /system/etc/init/myservice.rc:
458
459 service myservice /system/bin/myservice
460 class core
461 user system
462 ...
463 updatable
464 ```
465
4661. Create a new `.rc` file for the updated service. Use the `override` option
467 to redefine the existing service.
468
469 ```
470 /apex/my.apex@1/etc/init.rc:
471
472 service myservice /apex/my.apex@1/bin/myservice
473 class core
474 user system
475 ...
476 override
477 ```
478
479Service definitions can only be defined in the `.rc` file of an APEX. Action
480triggers aren't supported in APEXs.
481
482If a service marked as updatable starts before the APEXs are activated, the
483start is delayed until the activation of the APEXs is complete.
484
485## Configuring system to support APEX updates
486
487Set the following system property to `true` to support APEX file updates.
488
489```
490<device.mk>:
491
492PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
493
494BoardConfig.mk:
495TARGET_FLATTEN_APEX := false
496```
497
498or just
499
500```
501<device.mk>:
502
503$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
504```
505
506## Flattened APEX
507
508For legacy devices, it is sometimes impossible or infeasible to update the old
509kernel to fully support APEX. For example, the kernel might have been built
510without `CONFIG_BLK_DEV_LOOP=Y`, which is crucial for mounting the file system
511image inside an APEX.
512
513Flattened APEX is a specially built APEX that can be activated on devices with a
514legacy kernel. Files in a flattened APEX are directly installed to a directory
515under the built-in partition. For example, `lib/libFoo.so` in a flattend APEX
516`my.apex` is installed to `/system/apex/my.apex/lib/libFoo.so`.
517
518Activating a flattened APEX doesn't involve the loop device. The entire
519directory `/system/apex/my.apex` is directly bind-mounted to `/apex/name@ver`.
520
521Flattened APEXs can't be updated by downloading updated versions of the APEXs
522from network because the downloaded APEXs can't be flattened. Flattened APEXs
523can be updated only via a regular OTA.
524
525Note that flattened APEX is the default configuration for now. This means all
526APEXes are by default flattened unless you explicitly configure your device to
527support updatable APEX (explained above).
528
529Also note that, mixing flattened and non-flattened APEXes in a device is NOT
530supported. It should be either all non-flattened or all flattened. This is
531especially important when shipping pre-signed APEX prebuilts for the projects
532like Mainline. APEXes that are not pre-signed (i.e. built from the source)
533should also be non-flattened and signed with proper keys in that case. The
534device should inherit from `updatable_apex.mk` as explained above.
535
536## Compressed apexes {#compressed-apex}
537
538APEX compression is a new feature introduced in Android S. Its main purpose is
539to reduce the storage impact of updatable APEX packages: after an update to an
540APEX is installed, its pre-installed version is not used anymore, and space that
541is taken by it effectively becomes a dead weight.
542
543APEX compression minimizes the storage impact by using a highly-compressed
544set of APEX files on read-only partitions (e.g. `/system`). In Android S a
545DEFLATE zip compression is used.
546
547Note: compression doesn't provide any optimization in the following scenarios:
548
549* Bootstrap apexes that are required to be mounted very early in the boot
550 sequence. List of bootstrap apexes is configured in `kBootstrapApexes`
551 constant in `system/apex/apexd/apexd.cpp`.
552* Non-updatable apexes. Compression is only beneficial in case an updated
553 version of an apex is installed on `/data partition`.
554 Full list of updatable apexes is available at
555 https://source.android.com/devices/architecture/modular-system.
556* Dynamic shared libs apexes. Since `apexd` will always activate both versions
557 of such apexes (pre-installed and upgraded), compressing them doesn't provide
558 any value.
559
560### Compressed APEX file format
561
562This is the format of a compressed APEX file.
563
564![Compressed APEX file format](compressed-apex-format.png)
565
566**Figure 2.** Compressed APEX file format
567
568At the top level, a compressed APEX file is a zip file containing the original apex in deflated
569form with compression level of 9 and other files stored uncompressed.
570
571The four files in an APEX file are:
572
573* `original_apex`: deflated with compression level of 9
574* `apex_manifest.pb`: stored only
575* `AndroidManifest.xml`: stored only
576* `apex_pubkey`: stored only
577
578
579`original_apex` is the original uncompressed [APEX file](#apex-format).
580
581`apex_manifest.pb` `AndroidManifest.xml` `apex_pubkey` are copies of the
582corresponding files from `original_apex`.
583
584
585### Building compressed apex
586
587Compressed apex can be built using `apex_compression_tool.py` located at
588`system/apex/tools`.
589
590Note: the outer apk container of the produced compressed apex file won't be
591automatically signed. You will need to manually sign it with using the correct
592certificate. See [Signing Builds for Release](
593https://source.android.com/devices/tech/ota/sign_builds#apex-signing-key-replacement).
594
595There are a few different parameters related to APEX compression available in
596the build system.
597
598In `Android.bp` whether an apex is compressible is controlled by `compressible`
599property:
600
601```
602apex {
603 name: "apex.test",
604 manifest: "apex_manifest.json",
605 file_contexts: "file_contexts",
606 compressible: true,
607}
608```
609
610Note: this only serves as a hint to build system that this apex can be
611compressed. Such property is required due to the fact that not all apexes are
612compressible as mentioned in the [section above](#compressed-apex).
613
614TODO(b/183208430): add docs on how this works for prebuilts.
615
616A `PRODUCT_COMPRESSED_APEX` product flag is used to control whether a system
617image built from source should contain compressed apexes or not.
618
619For local experimentation you can force a build to compress apexes by setting
620`OVERRIDE_PRODUCT_COMPRESSED_APEX=true`.
621
622Compressed APEX files generated by the build system will have `.capex`
623extension. It makes it easier to distinguish between compressed and uncompressed
624versions of an APEX.
625
626### Supported compression algorithms
627
628Android S only supports deflate zip compression.
629
630### Activating compressed apex during boot
631
632Before activating a compressed APEX, `original_apex` inside it will be
633decompressed into `/data/apex/decompressed` directory. The resulting
634decompressed APEX will be hard linked to the `/data/apex/active` directory.
635
636Note: because of the hard link step above, it's important that files under
637`/data/apex/decompressed` have the same SELinux label as files under
638`/data/apex/active`.
639
640Consider following example as an illustration of the process described above.
641
642Let's assume that `/system/apex/com.android.foo.capex` is a compressed APEX
643being activated, and it's `versionCode` is `37`.
644
6451. First `original_apex` inside `/system/apex/com.android.foo.capex` is
646 decompressed into `/data/apex/decompressed/com.android.foo@37.apex`.
6472. After that `restorecon /data/apex/decompressed/com.android.foo@37.apex` is
648 performed to make sure that it has a correct SELinux label.
6493. Verification checks are performed on
650 `/data/apex/decompressed/com.android.foo@37.apex` to ensure it's validity:
651 * `apexd` checks that public key bundled in
652 `/data/apex/decompressed/com.android.foo@37.apex` is equal to the one
653 bundled in `/system/apex/com.android.foo.capex`
6544. Next `/data/apex/decompressed/com.android.foo@37.apex` is hard linked to
655 `/data/apex/active/com.android.foo@37.apex`.
6565. Finally, regular activation logic for uncompressed APEX files is performed
657 for `/data/apex/active/com.android.foo@37.apex`.
658
659For more information see implementation of `OnStart` function in
660`system/apex/apexd/apexd.cpp`.
661
662### Interaction with OTA
663
664Compressed APEX files have some implications on the OTA delivery and
665application. Since an OTA might contain a compressed APEX file with higher
666version compared to what is currently active on the device, some free space must
667be reserved before rebooting a device to apply an OTA.
668
669To help OTA system, two new binder APIs are exposed by apexd:
670
671* `calculateSizeForCompressedApex` - calculates size required for decompressing
672 APEX files in OTA package. It can be used to check if device has enough space
673 before downloading an OTA.
674* `reserveSpaceForCompressedApex` - reserves space on the disk that in the
675 future will be used by apexd for decompression of compressed APEX files inside
676 the OTA package.
677
678
679In case of A/B OTA, `apexd` will attempt decompression in the background as part
680of the postinstall OTA routine. If decompression fails, `apexd` will fallback to
681decompressing during the boot that applies the OTA.
682
683## Alternatives considered when developing APEX
684
685Here are some options that we considered when designing the APEX file format,
686and why we included or excluded them.
687
688### Regular package management systems
689
690Linux distributions have package management systems like `dpkg` and `rpm`, which
691are powerful, mature and robust. However, they weren't adopted for APEX because
692they can't protect the packages after installation. Verification is done only
693when packages are being installed. Attackers can break the integrity of the
694installed packages unnoticed. This is a regression for Android where all system
695components were stored in read-only file systems whose integrity is protected by
696dm-verity for every I/O. Any tampering to system components must be prohibited,
697or be detectable so that the device can refuse to boot if compromised.
698
699### dm-crypt for integrity
700
701The files in an APEX container are from built-in partitions (for example, the
702`/system` partition) that are protected by dm-verity, where any modification to
703the files are prohibited even after the partitions are mounted. To provide the
704same level of security to the files, all files in an APEX are stored in a file
705system image that is paired with a hash tree and a vbmeta descriptor. Without
706dm-verity, an APEX in the `/data` partition is vulnerable to unintended
707modifications made after it's verified and installed.
708
709In fact, the `/data` partition is also protected by encryption layers such as
710dm-crypt. Although this provides some level of protection against tampering, its
711primary purpose is privacy, not integrity. When an attacker gains access to the
712`/data` partition, there can be no further protection, and this again is a
713regression compared to every system component being in the `/system` partition.
714The hash tree inside an APEX file together with dm-verity provides the same
715level of content protection.
716
717### Redirecting paths from `/system` to `/apex`
718
719System component files packaged in an APEX are accessible via new paths like
720`/apex/<name>/lib/libfoo.so`. When the files were part of the `/system`
721partition, they were accessible via paths such as `/system/lib/libfoo.so`. A
722client of an APEX file (other APEX files or the platform) should use the new
723paths. This change in paths might require updates to the existing code.
724
725One way to avoid the path change is to overlay the file contents in an APEX file
726over the `/system` partition. However, we decided not to overlay files over the
727`/system` partition because we believed this would negatively affect performance
728as the number of files being overlayed (possibly even stacked one after another)
729increases.
730
731Another option was to hijack file access functions such as `open`, `stat`, and
732`readlink`, so that paths that start with `/system` are redirected to their
733corresponding paths under `/apex`. We discarded this option because it's
734practically infeasible to change all functions that accept paths. For example,
735some apps statically link Bionic, which implements the functions. In that case,
736the redirection won't happen for the app.
737