1# How To APEX 2 3[go/android-apex-howto](http://go/android-apex-howto) (internal link) 4 5This doc reflects the current implementation status, and thus is expected to 6change regularly. 7 8## Reference 9 10To understand the design rationale, visit this 11[public doc](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/docs/README.md#alternatives-considered-when-developing-apex) 12and [go/android-apex](http://go/android-apex) (internal). 13 14## Building an APEX 15 16A cheat sheet: 17 18``` 19apex { 20 name: "com.android.my.apex", 21 22 manifest: "apex_manifest.json", 23 24 // optional. if unspecified, a default one is auto-generated 25 androidManifest: "AndroidManifest.xml", 26 27 // libc.so and libcutils.so are included in the apex 28 native_shared_libs: ["libc", "libcutils"], 29 binaries: ["vold"], 30 java_libs: ["core-all"], 31 apps: ["myapk"], 32 prebuilts: ["my_prebuilt"], 33 34 compile_multilib: "both", 35 36 key: "com.android.my.apex.key", 37 certificate: ":com.android.my.apex.certificate", 38} 39``` 40 41`apex_manifest.json` should look like: 42 43``` 44{ 45 "name": "com.android.my.apex", 46 "version": 1 47} 48``` 49 50The file contexts files should be created at 51`/system/sepolicy/apex/com.android.my.apex-file_contexts`: 52 53``` 54(/.*)? u:object_r:system_file:s0 55/sub(/.*)? u:object_r:sub_file:s0 56/sub/file3 u:object_r:file3_file:s0 57``` 58 59The file should describe the contents of your apex. Note that the file is 60amended by the build system so that the `apexd` can access the root directory of 61your apex and the `apex_manifest.pb` file. (Technically, they are labeled as 62`system_file`.) So if you're 63[building the apex without Soong](#building-apex-without-soong), please be sure 64that `apexd` can access the root directory and the `apex_manifest.pb` file. (In 65the example above, the first line does that.) 66 67#### A script to create a skeleton of APEX 68 69For convenience, you might want to use a 70[script](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/tools/create_apex_skeleton.sh) 71that creates a skeleton (`Android.bp`, keys, etc.) of an APEX for you. You only 72need to adjust the `APEX_NAME` variable to be your actual APEX name. 73 74#### File types and places where they are installed in apex 75 76file type | place in apex 77-------------- | ---------------------------------------------------------- 78shared libs | `/lib` and `/lib64` (`/lib/arm` for translated arm in x86) 79executables | `/bin` 80java libraries | `/javalib` 81android apps | `/app` or `/priv-app` 82prebuilts | `/etc` 83 84### Transitive dependencies 85 86Transitive dependencies of a native shared lib or an executable are 87automatically included in the APEX. For example, if `libFoo` depends on 88`libBar`, then the two libs are included even when only `libFoo` is listed in 89`native_shared_libs` property. 90 91However, if a transitive dependency has a stable ABI, it is not included 92transitively. It can be included in an APEX only by directly being referenced. 93Currently (2019/08/05), the only module type that can provide stable ABI is 94`cc_library`. To do so, add `stubs.*` property as shown below: 95 96``` 97cc_library { 98 name: "foo", 99 srcs: [...], 100 stubs: { 101 symbol_file: "foo.map.txt", 102 versions: ["29", "30"], 103 }, 104} 105``` 106 107Use this when a lib has to be accessed across the APEX boundary, e.g. between 108APEXes or between an APEX and the platform. 109 110### apex_available 111 112Any module that is “included” (not just referenced) in an APEX either via the 113direct dependency or the transitive dependency has to correctly set the 114`apex_available` property in its `Android.bp` file. The property can have one or 115more of the following values: 116 117* `<name_of_an_apex>`: Like `com.android.adbd`. By specifying the APEX names 118 explicitly, the module is guaranteed to be included in those APEXes. This is 119 useful when a module has to be kept as an implementation detail of an APEX 120 and therefore shouldn’t be used from outside. 121* `//apex_available:anyapex`: This means that the module can be included in 122 any APEX. This is useful for general-purpose utility libraries like 123 `libbase`, `libcutils`, etc. 124* `//apex_available:platform`: The module can be installed to the platform, 125 outside of APEXes. This is the default value. However, `if apex_available` 126 is set to either of `<name_of_an_apex` or `//apex_available:anyapex`, the 127 default is removed. If a module has to be included in both APEX and the 128 platform, `//apex_available:platform` and`//apex_available:anyapex` should 129 be specified together. 130 131The act of adding an APEX name to the `apex_available` property of a module has 132to be done or be reviewed by the author(s) of the module. Being included in an 133APEX means that the module will be portable, i.e., running on multiple versions 134of the current and previous platforms, whereas it usually was expected to run on 135the current (the up-to-date) platform. Therefore, the module might have to be 136prepared to not have version-specific dependencies to the platform, like the 137existence of a dev node, a system call, etc. 138 139### Handling multiple ABIs 140 141`compile_multilib`: specifies the ABI(s) that this APEX will compile native 142modules for. Can be either of `both`, `first`, `32`, `64`, `prefer32`. For most 143of the cases, this should be `both`. 144 145`native_shared_libs`: installed for **_both_** primary and secondary ABIs of the 146device. Of course, if the APEX is built for a target having single ABI (i.e. 14732-bit only or 64-bit only), only libraries with the corresponding ABI are 148installed. 149 150`binaries`: installed only for the **_primary_** ABI of the device. In other 151words, 152 153* If the device is 32-bit only, only the 32-bit variant of the binary is 154 installed. 155* If the device supports both 32/64 ABIs, but with 156 `TARGET_PREFER_32_BIT_EXECUTABLES=true`, then only the 32-bit variant of the 157 binary is installed. 158* If the device is 64-bit only, then only the 64-bit variant of the binary is 159 installed. 160* If the device supports both 32/64 ABIs, but without 161 `TARGET_PREFER_32_BIT_EXECUTABLES=true`, then only the 64-bit variant of the 162 binary is installed. 163 164In order to fine control the ABIs of the native libraries and binaries to be 165installed, use 166`multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]` 167properties. 168 169* `first`: matches with the primary ABI of the device. This is the default for 170 `binaries`. 171* `lib32`: matches with the 32-bit ABI of the device, if supported 172* `lib64`: matches with the 64-bit ABI of the device, it supported 173* `prefer32`: matches with the 32-bit ABI of the device, if support. If 32-bit 174 ABI is not supported, it is matched with the 64-bit ABI. 175* `both`: matches with the both ABIs. This is the default for 176 `native_shared_libraries`. 177* `java libraries` and `prebuilts`: ABI-agnostic 178 179Example: (let’s assume that the device supports 32/64 and does not prefer32) 180 181``` 182apex { 183 // other properties are omitted 184 compile_multilib: "both", 185 native_shared_libs: ["libFoo"], // installed for 32 and 64 186 binaries: ["exec1"], // installed for 64, but not for 32 187 multilib: { 188 first: { 189 native_shared_libs: ["libBar"], // installed for 64, but not for 32 190 binaries: ["exec2"], // same as binaries without multilib.first 191 }, 192 both: { 193 native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib 194 binaries: ["exec3"], // installed for 32 and 64 195 }, 196 prefer32: { 197 native_shared_libs: ["libX"], // installed for 32, but not for 64 198 }, 199 lib64: { 200 native_shared_libs: ["libY"], // installed for 64, but not for 32 201 }, 202 }, 203} 204``` 205 206### APEX image signing 207 208**Note**: the APEX skeleton creation 209[script](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/tools/create_apex_skeleton.sh) 210automates this step. 211 212Each APEX must be signed with different keys. There is no concept of the 213platform key. `apexd` in the future might reject if multiple APEXes are signed 214with the same key. When a new key is needed, create a public-private key pair 215and make an `apex_key` module. Use `key` property to sign an APEX using the key. 216The public key is included in the zip container of the APEX as a file entry 217`apex_pubkey`. 218 219How to generate the key pair: 220 221``` 222# create an rsa key pair 223$ openssl genrsa -out com.android.my.apex.pem 4096 224 225# extract the public key from the key pair 226$ avbtool extract_public_key --key com.android.my.apex.pem \ 227--output com.android.my.apex.avbpubkey 228 229# in Android.bp 230apex_key { 231 name: "com.android.my.apex.key", 232 public_key: "com.android.my.apex.avbpubkey", 233 private_key: "com.android.my.apex.pem", 234} 235``` 236 237Important: In the above example, the name of the public key (that is 238`com.android.my.apex`) becomes the ID of the key. The ID of the key used to sign 239an APEX is recorded in the APEX. At runtime, a public key with the same ID in 240the device is used to verify the APEX. 241 242### APK (APEX container) signing 243 244**Note**: the APEX skeleton creation 245[script](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/tools/create_apex_skeleton.sh) 246automates this step. 247 248An APEX should also be signed just like APKs. So, an APEX is signed twice; once 249for the mini file system (`apex_payload.img` file) and once for the entire file. 250 251Just like APK, the file-level signing is done via the `certificate` property. It 252can be set in three ways. 253 254* not set: if unset, the APEX is signed with the certificate located at 255 `PRODUCT_DEFAULT_DEV_CERTIFICATE`. If the flag is also unset, it defaults to 256 `build/target/product/security/testkey` 257* `<name>`: the APEX is signed with the certificate named `<name>` in the same 258 directory as `PRODUCT_DEFAULT_DEV_CERTIFICATE` 259* `<name>`: the APEX signed with the certificate which is defined by a 260 Soong module named `<name>`. The certificate module can be defined as 261 follows. 262 263``` 264android_app_certificate { 265 name: "com.android.my.apex.certificate", 266 // This will use com.android.my.apex.x509.pem (the cert) and 267 // com.android.my.apex.pk8 (the private key) 268 certificate: "com.android.my.apex", 269} 270``` 271 272How to generate the certificate/private key pair: 273 274``` 275# Create certificate and private in PEM form 276$ openssl req -x509 -newkey rsa:4096 -nodes -days 999999 -keyout key.pem -out com.android.my.apex.x509.pem 277 278# Enter following info via the interactive prompts 279# Country Name: US 280# State: California 281# Locality Name: Mountain View 282# Organization Name: Android 283# Organization Unit Name: Android 284# Common Name: <your-apk-name> 285# Email address: android@android.com 286 287# Convert the private to pkcs8 format 288$ openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -out com.android.my.apex.pk8 -nocrypt 289``` 290 291### Signing APEXs with release keys 292 293The procedures described in the [APEX image signing](#apex-image-signing) and 294[APK (APEX container) signing](#apk-apex-container_signing) sections require the 295private keys to be present in the tree. This is not suitable for public release. 296Please refer to the 297[APEX signing key replacement](https://source.android.com/devices/tech/ota/sign_builds#apex-signing-key-replacement) 298documentation to prepare the APEX packages for release. 299 300For the Google-specific procedure for release keys, the documentation is 301available at 302[go/android-apex-howto-internal](http://go/android-apex-howto-internal) 303(internal only). 304 305### Linker namespaces for native libraries and binaries 306 307The linker needs to be set up with separate namespaces for each APEX, for 308isolation. It is done through `ld.config.txt` files, which are autogenerated by 309`linkerconfig`. Normally you only need to ensure that the APEX manifest 310correctly lists the native libraries it requires (from platform or other APEXes) 311and provides, which by default is taken from the build system. 312 313Refer to the [design doc](go/linker-config-apex) for more information about 314linkerconfig and apex. 315 316## Installing an APEX 317 318Use 319 320``` 321adb install --staged <path_to_apex> && adb reboot 322``` 323 324The `adb install --staged` command triggers a verification for the staged APEX 325which might fail when the APEX is signed incorrectly. 326 327Note that on Q devices when the `adb install --staged` command completes you 328still will have to wait until the verification for the staged APEX is finished 329before issuing `adb reboot`. 330 331On R devices we added the `--wait` option to `adb install` to wait until the 332verification is completed before returning. On S devices the `--wait` option is 333implicit. 334 335## Hot swapping an APEX (development only) 336 337Use 338 339``` 340adb sync && adb shell cmd -w apexservice remountPackages 341``` 342 343Note that for this command to remount your APEX, you must ensure that all 344processes that have reference to your APEX are killed. E.g. if you are 345developing an APEX that contributes to system\_server, you can use the 346following: 347 348``` 349adb root 350adb remount 351adb shell stop 352adb sync 353adb shell cmd -w apexservice remountPackages 354adb shell start 355``` 356 357## Using an APEX 358 359After the reboot, the apex will be mounted at `/apex/<apex_name>@<version>` 360directory. Multiple versions of the same APEX can be mounted at the same time. A 361mount point that always points to the latest version of an APEX is provided: 362`/apex/<apex_name>`. 363 364Clients can use the latter path to read or execute something from APEX. 365 366So, typical usage of APEX is as follows. 367 3681. an APEX is pre-loaded under `/system/apex`when the device is shipped. 3692. Files in it are accessed via the `/apex/<apex_name>/`path. 3703. When an updated version of the APEX is installed in `/data/apex/active`, the 371 path will point to the new APEX after the reboot. 372 373## Updating service with APEX 374 375Using APEX, you can update a service. To do so, you need … 376 3771) Mark the service in system partition as updatable. Add the new option 378‘updatable’ to the service definition. 379 380``` 381/system/etc/init/myservice.rc: 382 383service myservice /system/bin/myservice 384 class core 385 user system 386 … 387 updatable 388``` 389 3902) Create a new `.rc` file for the updated service. Use ‘`override`’ option to 391redefine the existing service. 392 393``` 394/apex/my.apex/etc/init.rc: 395 396service myservice /apex/my.apex/bin/myservice 397 class core 398 user system 399 … 400 override 401``` 402 403Note that you can only have service definitions in the rc file in APEX. You 404cannot have action triggers in APEXes. 405 406Also note that if a service marked as updatable is started before APEXes are 407activated, the start is delayed until the activation of APEXes is finished. 408 409## Configuring system to support APEX updates 410 411Set the following system property to true to support APEX file updates. 412 413``` 414<device.mk>: 415 416PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true 417 418BoardConfig.mk: 419TARGET_FLATTEN_APEX := false 420 421or just 422<device.mk>: 423 424$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk) 425``` 426 427## Flattened APEX 428 429For legacy devices, it is sometimes impossible or infeasible to update the old 430kernel to fully support APEX. For example, the kernel might have been built 431without `CONFIG_BLK_DEV_LOOP=Y`, which is crucial for mounting the file system 432image inside an APEX. 433 434Flattened APEX is a specially built APEX that can be activated on devices with a 435legacy kernel. Files in a flattened APEX are directly installed to a directory 436under the built-in partition. For example, `lib/libFoo.so` in a flattened APEX 437my.apex is installed to `/system/apex/my.apex/lib/libFoo.so`. 438 439Activating a flattened APEX doesn't involve the loop device. The entire 440directory `/system/apex/my.apex` is directly bind-mounted to `/apex/name@ver`. 441 442Flattened APEXs can‘t be updated by downloading updated versions of the APEXs 443from network because the downloaded APEXs can’t be flattened. Flattened APEXs 444can be updated only via a regular OTA. 445 446Note that flattened APEX is the default configuration for now (2019/Aug). This 447means all APEXes are by default flattened unless you explicitly configure your 448device to support updatable APEX (explained above). 449 450Also note that, mixing flattened and non-flattened APEXes in a device is NOT 451supported. It should be either all non-flattened or all flattened. This is 452especially important when shipping pre-signed APEX prebuilts for the projects 453like Mainline. APEXes that are not pre-signed (i.e. built from the source) 454should also be non-flattened and signed with proper keys in that case. The 455device should inherit from `updatable_apex.mk` as explained above. 456 457## Building APEX without Soong 458 459An APEX can be built without relying on the build commands generated by Soong. 460 4611) Prepare following files: 462 463- APEX manifest file (in JSON) 464 465- AndroidManifest file (in XML, optional) 466 467- AVB private key 468 469- APK certificate (`*.x509.pem`) 470 471- APK private key (`*.pk8`) 472 473- `file_contexts` file 474 475- files to be packaged into the APEX 476 4772) Create `canned_fs_config` file 478 479It is a file that specifies access bits and uid/gid of each file in the APEX. 480 481``` 482/ 1000 1000 0755 483/apex_manifest.json 1000 1000 0644 484/apex_manifest.pb 1000 1000 0644 485/file1 1000 1000 0644 486/file2 1000 1000 0644 487/dir 0 2000 0755 488/dir/file3 1000 1000 0644 489... 490``` 491 492Note that ALL files AND directories must be specified. And don’t forget to have 493a line for `/`and `/apex_manifest.pb`. (`/apex_manifest.json` line is for 494Q-targeting modules) 495 4963) Invoke `apexer` 497 498``` 499$ apexer \ 500 --manifest <apex_manifest_file> \ 501 --file_contexts <file_contexts_file> \ 502 --canned_fs_config <canned_fs_config_file> \ 503 --key <avb_private_key_file> \ 504 --payload_type image \ 505 --android_manifest <android_manifest_file> \ 506 --override_apk_package_name com.google.foo \ 507 <input_directory> \ 508 <output_apex_file> 509``` 510 511`--android_manifest` and -`-override_apk_package` are optional arguments and 512thus can be omitted if not needed. 513 514Note: The `<apex_manifest_file>` shouldn’t be under `<input_directory>`. 515 5164) Sign it 517 518`apexer` signs the `apex_payload.img` file only. The entire apex (which is a zip 519file) has to be signed with `Signapk`. 520 521``` 522$ java \ 523 -Djava.library.path=$(dirname out/soong/host/linux-x86/lib64/libconscrypt_openjdk_jni.so)\ 524 -jar out/soong/host/linux-x86/framework/signapk.jar \ 525 -a 4096 \ 526 <apk_certificate_file> \ 527 <apk_private_key_file> \ 528 <unsigned_input_file> \ 529 <signed_output_file> 530``` 531 532This will sign the input file with the cert/privkey pairs to produce the output 533file. 534 535## Re-packaging an existing APEX 536 537If an APEX has been build by passing `--include_build_info` to `apexer` (this is 538the default when building via Soong), it will then include a file named 539`apex_build_info.pb` which will store as much information as possible about how 540the apex was built (see the `ApexBuildInfo` proto 541[definition](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/proto/apex_build_info.proto) 542for more info) with the exception of the signing keys. 543 544We also provide a tool named `deapexer` to extract the payload content of an 545APEX in a local directory. 546 547By using these tools, you can then adapt the procedure described in the 548[building the apex without Soong](#building-apex-without-soong) section and pass 549the `--build_info apex_build_info.pb` file where `apex_build_info.pb` contains 550all the build parameters that you would otherwise pass via flag to `apexer`. 551 552We do this programmatically in some unit test code to generate "unusual" APEX 553files, see for example 554[here](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/apexer/apexer_test.py) 555and 556[here](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/tests/testdata/sharedlibs/build/shared_libs_repack.py). 557