Формат контейнера Android Pony EXpress (APEX) был представлен в Android 10 и используется в процессе установки для системных модулей более низкого уровня. Этот формат позволяет обновлять системные компоненты, которые не соответствуют стандартной модели приложений для Android. Примеры компонентов: встроенные сервисы и библиотеки, уровни абстракции оборудования (HAL), среда выполнения (ART) и библиотеки классов.
Термин "APEX" также может относиться к файлу APEX.
Фон
Хотя Android поддерживает обновление модулей, которые соответствуют стандартной модели приложений (например, сервисов, действий), с помощью установщиков пакетов (например, Google Play), использование аналогичной модели для компонентов ОС более низкого уровня имеет следующие недостатки:
- Модули на основе APK нельзя использовать на ранних этапах загрузки. Менеджер пакетов – это центральное хранилище информации о приложениях, которое можно запустить только из менеджера активностей, готового на более позднем этапе загрузки.
- Формат APK (в частности, манифест) разработан для приложений Android, и системные модули не всегда ему соответствуют.
Дизайн
В этом разделе описана общая структура формата файлов APEX и менеджер APEX – сервис, управляющий файлами APEX.
Подробнее о том, почему был выбран именно этот дизайн APEX, можно узнать в статье Альтернативные варианты при разработке APEX.
Формат APEX
Это формат файла APEX.

Рисунок 1. Формат файла APEX
На верхнем уровне файл APEX представляет собой ZIP-архив, в котором файлы хранятся без сжатия и расположены с шагом 4 КБ.
В APEX-файл входят следующие четыре файла:
apex_manifest.jsonAndroidManifest.xmlapex_payload.imgapex_pubkey
Файл apex_manifest.json содержит название пакета и версию, которые идентифицируют файл APEX. Это буфер протокола в формате JSON.
ApexManifest
Файл AndroidManifest.xml позволяет файлу APEX использовать инструменты и инфраструктуру, связанные с APK, например ADB, PackageManager и приложения для установки пакетов (такие как Google Play). Например, для проверки основных метаданных из файла APEX можно использовать существующий инструмент, такой как aapt. Файл содержит название пакета и информацию о версии. Эта информация также обычно доступна в элементе apex_manifest.json.
Для нового кода и систем, работающих с APEX, рекомендуется использовать apex_manifest.json вместо AndroidManifest.xml. AndroidManifest.xml может содержать дополнительную информацию о таргетинге, которую можно использовать в существующих инструментах для публикации приложений.
apex_payload.img – это образ файловой системы ext4, защищенный с помощью dm-verity. Образ монтируется во время выполнения через устройство обратной связи. В частности, дерево хешей и блок метаданных создаются с помощью библиотеки libavb. Полезная нагрузка файловой системы не анализируется (поскольку образ должен быть монтируемым). Обычные файлы включены в файл apex_payload.img.
apex_pubkey – открытый ключ, используемый для подписи образа файловой системы. Во время выполнения этот ключ гарантирует, что скачанный APEX подписан тем же лицом, что и APEX во встроенных разделах.
Правила в отношении названий APEX
Чтобы избежать конфликтов имен новых файлов APEX по мере развития платформы, следуйте приведенным ниже рекомендациям.
com.android.*- Зарезервировано для APEX-пакетов AOSP. Не уникален для какой-либо компании или устройства.
com.<companyname>.*- Зарезервировано для компании. Может использоваться несколькими устройствами компании.
com.<companyname>.<devicename>.*- Зарезервировано для APEX-файлов, уникальных для определенного устройства (или подмножества устройств).
Менеджер APEX
Менеджер APEX (или apexd) – это отдельный собственный процесс, отвечающий за проверку, установку и удаление файлов APEX. Этот процесс запускается и готов к работе на раннем этапе загрузки. APEX-файлы обычно предустановлены на устройстве в каталоге /system/apex. Менеджер APEX по умолчанию использует эти пакеты, если нет доступных обновлений.
Последовательность обновления APEX использует класс PackageManager и выглядит следующим образом:
- Файл APEX скачивается через приложение для установки пакетов, ADB или другой источник.
- Менеджер пакетов начнет установку. Когда менеджер пакетов распознает, что файл является APEX, он передает управление менеджеру APEX.
- Менеджер APEX проверяет файл APEX.
- Если файл APEX прошел проверку, внутренняя база данных менеджера APEX обновляется, чтобы отразить, что файл APEX будет активирован при следующей загрузке.
- После успешной проверки пакета отправитель запроса на установку получает широковещательное сообщение.
- Чтобы продолжить установку, необходимо перезагрузить систему.
При следующей загрузке запускается менеджер APEX, считывает внутреннюю базу данных и выполняет следующие действия для каждого файла APEX:
- Проверяет APEX-файл.
- Создает устройство обратной связи из файла APEX.
- Создает блочное устройство сопоставления устройств поверх устройства обратной связи.
- Монтирует блочное устройство сопоставителя устройств по уникальному пути (например,
/apex/name@ver).
Когда все файлы APEX, перечисленные во внутренней базе данных, будут смонтированы, менеджер APEX предоставит сервис Binder для других системных компонентов, чтобы они могли запрашивать информацию об установленных файлах APEX. Например, другие системные компоненты могут запрашивать список APEX-файлов, установленных на устройстве, или точный путь, по которому смонтирован определенный APEX-файл, чтобы получить доступ к файлам.
Файлы APEX – это файлы APK
APEX-файлы являются действительными APK-файлами, поскольку представляют собой подписанные ZIP-архивы (с использованием схемы подписи APK), содержащие файл AndroidManifest.xml. Это позволяет файлам APEX использовать инфраструктуру для APK-файлов, например приложение для установки пакетов, утилиту для подписи и менеджер пакетов.
Файл AndroidManifest.xml внутри файла APEX имеет минимальный размер и состоит из пакета name, versionCode и необязательных targetSdkVersion, minSdkVersion и maxSdkVersion для точного таргетинга. Эта информация позволяет доставлять файлы APEX через существующие каналы, такие как приложения для установки пакетов и ADB.
Поддерживаемые типы файлов
Формат APEX поддерживает следующие типы файлов:
- Нативные общие библиотеки
- Исполняемые файлы нативных приложений
- JAR-файлы
- Файлы данных
- Файлы конфигурации
Это не означает, что APEX может обновлять все эти типы файлов. Возможность обновления типа файла зависит от платформы и стабильности определений интерфейсов для типов файлов.
Варианты подписи
Файлы APEX подписываются двумя способами. Сначала файл apex_payload.img (а именно дескриптор vbmeta, добавленный к apex_payload.img) подписывается ключом.
Затем весь APEX подписывается с помощью схемы подписания APK версии 3. В этом процессе используются два разных ключа.
На устройстве устанавливается открытый ключ, соответствующий закрытому ключу, который используется для подписи дескриптора vbmeta. Менеджер APEX использует открытый ключ для проверки APEX-файлов, которые нужно установить. Каждый APEX должен быть подписан разными ключами. Это требование действует как во время сборки, так и во время выполнения.
APEX во встроенных разделах
Файлы APEX могут находиться во встроенных разделах, например /system. Раздел уже находится под управлением dm-verity, поэтому файлы APEX монтируются непосредственно через устройство обратной связи.
Если APEX-файл находится во встроенном разделе, его можно обновить, предоставив APEX-пакет с тем же названием пакета и кодом версии, равным или большим, чем у текущей версии. Новый APEX-файл хранится в /data. Как и в случае с APK-файлами, установленная версия заменяет версию, которая уже есть во встроенном разделе. Но в отличие от APK-файлов, установленная версия APEX активируется только после перезагрузки.
Требования к ядру
Чтобы поддерживать основные модули APEX на устройстве Android, необходимы следующие функции ядра Linux: драйвер loopback и dm-verity. Драйвер обратной связи монтирует образ файловой системы в модуле APEX, а dm-verity проверяет модуль APEX.
Производительность драйвера loopback и dm-verity важна для обеспечения хорошей работы системы при использовании модулей APEX.
Поддерживаемые версии ядра
Основные модули APEX поддерживаются на устройствах с ядром версии 4.4 или более поздней. Новые устройства с Android 10 или более поздней версии должны использовать ядро версии 4.9 или более поздней, чтобы поддерживать модули APEX.
Обязательные исправления ядра
Необходимые исправления ядра для поддержки модулей APEX включены в общее дерево Android. Чтобы получить исправления для поддержки APEX, используйте последнюю версию общего дерева Android.
Ядро версии 4.4
Эта версия поддерживается только на устройствах, на которых Android 9 был обновлен до Android 10 и которые должны поддерживать модули APEX. Чтобы получить необходимые исправления, настоятельно рекомендуется выполнить обратное слияние из ветки android-4.4. Ниже приведен список отдельных исправлений, необходимых для версии ядра 4.4.
- UPSTREAM: loop: add ioctl for changing logical block size (4.4)
- BACKPORT: block/loop: set hw_sectors (4.4)
- UPSTREAM: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl (4.4)
- ANDROID: mnt: Fix next_descendent (4.4)
- ANDROID: mnt: remount should propagate to slaves of slaves (4.4)
- ANDROID: mnt: Propagate remount correctly (4.4)
- Revert "ANDROID: dm verity: add minimum prefetch size" (4.4)
- UPSTREAM: loop: drop caches if offset or block_size are changed (4.4)
Версии ядра 4.9/4.14/4.19
Чтобы получить необходимые исправления для версий ядра 4.9, 4.14 и 4.19, выполните слияние с веткой android-common.
Обязательные параметры конфигурации ядра
Ниже приведены основные требования к конфигурации для поддержки модулей APEX, которые были представлены в Android 10. Звездочкой (*) отмечены требования, которые уже действовали в Android 9 и более ранних версиях.
(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support
Требования к параметрам командной строки ядра
Чтобы поддерживать APEX, убедитесь, что параметры командной строки ядра соответствуют следующим требованиям:
loop.max_loopне должен быть задан.- Значение поля
loop.max_partдолжно быть не больше 8.
Как создать APEX
В этом разделе рассказывается, как создать APEX-файл с помощью системы сборки Android.
Ниже приведен пример Android.bp для APEX с именем apex.test.
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
// libc.so and libcutils.so are included in the apex
native_shared_libs: ["libc", "libcutils"],
binaries: ["vold"],
java_libs: ["core-all"],
prebuilts: ["my_prebuilt"],
compile_multilib: "both",
key: "apex.test.key",
certificate: "platform",
}
Пример использования разметки типа apex_manifest.json
{
"name": "com.android.example.apex",
"version": 1
}
Пример использования разметки типа file_contexts
(/.*)? u:object_r:system_file:s0
/sub(/.*)? u:object_r:sub_file:s0
/sub/file3 u:object_r:file3_file:s0
Типы файлов и их расположение в APEX
| Тип файла | Местоположение в APEX |
|---|---|
| Общие библиотеки | /lib и /lib64 (/lib/arm для переведенной архитектуры ARM в x86) |
| Исполняемые файлы | /bin |
| Библиотеки Java | /javalib |
| Готовые решения | /etc |
Транзитивные зависимости
Файлы APEX автоматически включают транзитивные зависимости от нативных общих библиотек или исполняемых файлов. Например, если libFoo зависит от libBar, то обе библиотеки будут включены, даже если в свойстве native_shared_libs указана только libFoo.
Поддержка нескольких ABI
Установите свойство native_shared_libs для основного и дополнительного двоичных интерфейсов приложения (ABI) устройства. Если APEX предназначен для целевых устройств с одним ABI (то есть только 32-разрядным или только 64-разрядным), устанавливаются только библиотеки с соответствующим ABI.
Установите свойство binaries только для основного ABI устройства, как описано ниже.
- Если устройство поддерживает только 32-битные приложения, будет установлен только 32-битный вариант.
- Если устройство поддерживает только 64-разрядные версии, то будет установлен только 64-разрядный вариант двоичного файла.
Чтобы точнее управлять ABI нативных библиотек и двоичных файлов, используйте свойства multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries].
first– соответствует основному ABI устройства. Это значение по умолчанию для двоичных файлов.lib32– соответствует 32-разрядному ABI устройства, если он поддерживается.lib64– соответствует 64-разрядному ABI устройства, которое поддерживается.prefer32– соответствует 32-битному ABI устройства, если поддерживается. Если 32-разрядный ABI не поддерживается, он соответствует 64-разрядному ABI.both: соответствует обоим ABI. Это значение используется по умолчанию дляnative_shared_libraries.
Свойства java, libraries и prebuilts не зависят от ABI.
Пример для устройства, которое поддерживает 32- и 64-разрядные версии и не предпочитает 32-разрядную:
apex {
// other properties are omitted
native_shared_libs: ["libFoo"], // installed for 32 and 64
binaries: ["exec1"], // installed for 64, but not for 32
multilib: {
first: {
native_shared_libs: ["libBar"], // installed for 64, but not for 32
binaries: ["exec2"], // same as binaries without multilib.first
},
both: {
native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
binaries: ["exec3"], // installed for 32 and 64
},
prefer32: {
native_shared_libs: ["libX"], // installed for 32, but not for 64
},
lib64: {
native_shared_libs: ["libY"], // installed for 64, but not for 32
},
},
}
подпись vbmeta
Подпишите каждый APEX-файл разными ключами. Когда потребуется новый ключ, создайте пару из открытого и закрытого ключей и сделайте модуль apex_key. Используйте свойство key, чтобы подписать APEX с помощью ключа. Открытый ключ автоматически включается в APEX с названием avb_pubkey.
# create an rsa key pairopenssl genrsa -out foo.pem 4096# extract the public key from the key pairavbtool extract_public_key --key foo.pem --output foo.avbpubkey# in Android.bpapex_key { name: "apex.test.key", public_key: "foo.avbpubkey", private_key: "foo.pem", }
В примере выше название открытого ключа (foo) становится его идентификатором. Идентификатор ключа, использованного для подписи APEX, записывается в APEX. Во время выполнения apexd проверяет APEX с помощью открытого ключа с тем же идентификатором на устройстве.
Подпись APEX-файлов
Подписывайте APEX-файлы так же, как и APK-файлы. Подпишите APEX-файлы дважды: один раз для мини-файловой системы (файл apex_payload.img) и один раз для всего файла.
Чтобы подписать файл APEX, задайте свойство certificate одним из трех способов:
- Не задано. Если значение не задано, APEX подписывается сертификатом, расположенным по адресу
PRODUCT_DEFAULT_DEV_CERTIFICATE. Если параметр не задан, по умолчанию используется путьbuild/target/product/security/testkey. <name>: APEX подписан сертификатом<name>в том же каталоге, что иPRODUCT_DEFAULT_DEV_CERTIFICATE.:<name>: APEX подписан сертификатом, который определен модулем Soong с названием<name>. Модуль сертификата можно определить следующим образом:
android_app_certificate {
name: "my_key_name",
certificate: "dir/cert",
// this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}
Управление ключами
Тестовые ключи используются для сборок, находящихся в разработке, а ключи выпуска – для подписи общедоступных сборок. Как описано в разделе Замена ключа подписи APEX, перед публичным выпуском все тестовые ключи необходимо заменить соответствующими ключами выпуска. Серверы сборки OEM могут интегрировать инструмент хоста sign_target_files_apks, который повторно подписывает как образ файловой системы, так и весь файл APEX для всех файлов APEX, найденных в ZIP-архиве целевых файлов.
В целях безопасности важно придерживаться следующих рекомендаций по управлению ключами и подписанию выпусков:
Храните ключи выпуска в безопасной среде, чтобы ограничить доступ к ним.
Инициирование операций подписания релизов должно контролироваться с помощью списка контроля доступа.
Подписывайте артефакты ключом выпуска только после того, как они протестированы и сертифицированы для выпуска.
Действия по подписанию релиза должен выполнять человек, а не автоматизированный процесс.
Артефакты, подписанные ключом выпуска, должны храниться в безопасной среде.
Доступ к артефактам, подписанным ключом выпуска, должен быть ограничен и предоставляться только при наличии обоснованной деловой необходимости.
Сервер сборки OEM должен хранить записи о каждом запросе на подпись в базе данных подписей.
Как установить APEX
Чтобы установить APEX, используйте ADB.
adb install apex_file_nameadb reboot
Если для параметра supportsRebootlessUpdate задано значение true в apex_manifest.json и установленный в данный момент APEX не используется (например, все содержащиеся в нем сервисы остановлены), то новый APEX можно установить без перезагрузки с флагом --force-non-staged.
adb install --force-non-staged apex_file_nameКак использовать APEX
После перезагрузки APEX будет смонтирован в каталоге /apex/<apex_name>@<version>. Одновременно можно смонтировать несколько версий одного и того же APEX-пакета.
Среди путей монтирования тот, который соответствует последней версии, привязан к /apex/<apex_name>.
Клиенты могут использовать путь, смонтированный с помощью bind, чтобы читать или выполнять файлы из APEX.
APEX-файлы обычно используются следующим образом:
- Производитель устройства или поставщик услуг по его разработке и производству предварительно загружает APEX в каталог
/system/apexпри отправке устройства. - Доступ к файлам в APEX осуществляется по пути
/apex/<apex_name>/. - Когда в
/data/apexустанавливается обновленная версия APEX, путь указывает на новый APEX после перезагрузки.
Как обновить сервис с помощью APEX
Чтобы обновить сервис с помощью APEX-файла:
Отметьте сервис в системном разделе как обновляемый. Добавьте в определение сервиса параметр
updatable./system/etc/init/myservice.rc: service myservice /system/bin/myservice class core user system ... updatableСоздайте новый файл
.rcдля обновленного сервиса. Чтобы переопределить существующий сервис, используйте параметрoverride./apex/my.apex/etc/init.rc: service myservice /apex/my.apex/bin/myservice class core user system ... override
Определения сервисов можно задавать только в файле .rc APEX. Триггеры действий не поддерживаются в файлах APEX.
Если сервис, помеченный как обновляемый, запускается до активации APEX-пакетов, запуск откладывается до завершения активации.
Настройте систему для поддержки обновлений APEX
Чтобы поддерживать обновления файлов APEX, задайте для следующего системного свойства значение true:
<device.mk>:
PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
BoardConfig.mk:
TARGET_FLATTEN_APEX := false
или просто
<device.mk>:
$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
Распакованные APEX-файлы
Иногда невозможно или нецелесообразно обновить старое ядро на устаревших устройствах, чтобы оно полностью поддерживало APEX. Например, ядро могло быть создано без CONFIG_BLK_DEV_LOOP=Y, который необходим для монтирования образа файловой системы внутри APEX.
Сглаженный APEX – это специально созданный APEX, который можно активировать на устройствах с устаревшим ядром. Файлы из развернутого файла APEX устанавливаются непосредственно в каталог на встроенном разделе. Например, lib/libFoo.so в развернутом файле APEX my.apex устанавливается в /system/apex/my.apex/lib/libFoo.so.
При активации плоского файла APEX устройство петли не используется. Весь каталог /system/apex/my.apex напрямую примонтирован к /apex/name@ver.
Плоские APEX-файлы нельзя обновить, скачав их новые версии из сети, поскольку скачанные APEX-файлы нельзя сделать плоскими. Обновлять сглаженные файлы APEX можно только с помощью обычного OTA-обновления.
По умолчанию используется плоский APEX. Это означает, что по умолчанию все APEX-файлы будут сжаты, если вы не настроите устройство на создание несжатых APEX-файлов для поддержки обновлений APEX (как описано выше).
Использование в одном устройстве сжатых и несжатых файлов APEX НЕ ПОДДЕРЖИВАЕТСЯ. Все APEX-файлы на устройстве должны быть либо нераспакованными, либо распакованными.
Это особенно важно при отправке предварительно созданных APEX с подписью для таких проектов, как Mainline. APEX-файлы, которые не были подписаны заранее (то есть созданы из исходного кода), также должны быть неразвернутыми и подписанными с помощью правильных ключей. Устройство должно наследовать updatable_apex.mk, как описано в разделе Обновление сервиса с помощью APEX.
Сжатые APEX-файлы
В Android 12 и более поздних версиях используется сжатие APEX, чтобы уменьшить объем памяти, занимаемый обновляемыми пакетами APEX. После установки обновления APEX-файла его предустановленная версия больше не используется, но занимает столько же места. Занятое пространство останется недоступным.
Сжатие APEX позволяет минимизировать влияние на хранилище за счет использования набора сильно сжатых файлов APEX на разделах, доступных только для чтения (например, на разделе /system). В Android 12 и более поздних версий используется алгоритм сжатия Deflate.
Сжатие не оптимизирует следующие элементы:
Загрузочные APEX-пакеты, которые должны быть смонтированы на ранних этапах загрузки.
Необновляемые APEX-файлы. Сжатие полезно, только если обновленная версия APEX установлена в разделе
/data. Полный список обновляемых APEX-файлов можно найти на странице Модульные системные компоненты.APEX-файлы динамических общих библиотек. Поскольку
apexdвсегда активирует обе версии таких APEX-пакетов (предустановленную и обновленную), сжатие не имеет смысла.
Сжатый формат файла APEX
Это формат сжатого файла APEX.
Рисунок 2. Сжатый формат файла APEX
На верхнем уровне сжатый файл APEX представляет собой ZIP-архив, содержащий исходный файл APEX в сжатом виде с уровнем сжатия 9 и другие файлы, хранящиеся в несжатом виде.
Файл APEX состоит из четырех файлов:
original_apex: deflated with compression level of 9 (сжатие с уровнем 9) Это исходный APEX-файл без сжатия.apex_manifest.pb: только хранениеAndroidManifest.xml: только хранениеapex_pubkey: только хранение
Файлы apex_manifest.pb, AndroidManifest.xml и apex_pubkey являются копиями соответствующих файлов в original_apex.
Создание сжатого APEX
Сжатый APEX можно создать с помощью инструмента apex_compression_tool.py, расположенного по адресу system/apex/tools.
В системе сборки доступно несколько параметров, связанных со сжатием APEX.
В Android.bp возможность сжатия файла APEX определяется свойством compressible:
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
compressible: true,
}
Флаг продукта PRODUCT_COMPRESSED_APEX определяет, должны ли образы системы, созданные из исходного кода, содержать сжатые APEX-файлы.
Для локального эксперимента можно принудительно сжать APEX-файлы, задав для параметра OVERRIDE_PRODUCT_COMPRESSED_APEX= значение true.
Сжатые файлы APEX, созданные системой сборки, имеют расширение .capex.
Расширение позволяет легко отличить сжатую версию файла APEX от несжатой.
Поддерживаемые алгоритмы сжатия
Android 12 поддерживает только сжатие Deflate.
Активация сжатого файла APEX во время загрузки
Прежде чем активировать сжатый файл APEX, необходимо распаковать содержащийся в нем файл original_apex в каталог /data/apex/decompressed. Распакованный APEX-файл жестко связан с каталогом /data/apex/active.
Ниже приведен пример, иллюстрирующий описанный выше процесс.
Предположим, что /system/apex/com.android.foo.capex – это сжатый APEX-файл, который активируется с versionCode 37.
- Файл
original_apexиз папки/system/apex/com.android.foo.capexбудет распакован в папку/data/apex/decompressed/com.android.foo@37.apex. restorecon /data/apex/decompressed/com.android.foo@37.apex, чтобы проверить, есть ли у него правильная метка SELinux.- Чтобы убедиться в действительности
/data/apex/decompressed/com.android.foo@37.apex, выполняются проверки.apexdпроверяет открытый ключ, связанный с/data/apex/decompressed/com.android.foo@37.apex, чтобы убедиться, что он совпадает с ключом, связанным с/system/apex/com.android.foo.capex. - Файл
/data/apex/decompressed/com.android.foo@37.apexжестко связан с каталогом/data/apex/active/com.android.foo@37.apex. - Обычная логика активации несжатых файлов APEX выполняется на устройстве
/data/apex/active/com.android.foo@37.apex.
Взаимодействие с турагентством
Сжатые файлы APEX влияют на доставку и применение OTA-обновлений. Поскольку беспроводное обновление может содержать сжатый APEX-файл с более высоким уровнем версии, чем активный на устройстве, перед перезагрузкой устройства для применения беспроводного обновления необходимо зарезервировать определенный объем свободного места.
Для поддержки системы OTA apexd предоставляет два API связывателя:
calculateSizeForCompressedApex– вычисляет размер, необходимый для распаковки файлов APEX в пакете OTA. Это можно использовать, чтобы проверить, достаточно ли на устройстве места, прежде чем скачивать OTA-обновление.reserveSpaceForCompressedApex– резервирует место на диске для дальнейшего использованияapexdдля распаковки сжатых файлов APEX в пакете OTA.
При беспроводном обновлении A/B apexd пытается выполнить декомпрессию в фоновом режиме в рамках процедуры после установки. Если распаковка не удалась, apexd выполняет ее во время загрузки, которая применяет обновление OTA.
Альтернативные варианты, которые рассматривались при разработке APEX
Ниже перечислены варианты, которые рассматривались при разработке формата файлов APEX, а также причины, по которым они были включены или исключены.
Стандартные системы управления пакетами
В дистрибутивах Linux есть системы управления пакетами, например dpkg и rpm, которые отличаются надежностью и широкими возможностями. Однако они не были приняты для APEX, поскольку не могут защитить пакеты после установки. Проверка выполняется только при установке пакетов.
Злоумышленники могут незаметно нарушить целостность установленных пакетов. Это регрессия для Android, где все системные компоненты хранятся в файловых системах, доступных только для чтения, целостность которых защищена dm-verity для каждой операции ввода-вывода. Любое вмешательство в системные компоненты должно быть либо запрещено, либо обнаруживаться, чтобы устройство не загружалось в случае компрометации.
dm-crypt для целостности;
Файлы в контейнере APEX находятся во встроенных разделах (например, в разделе /system), которые защищены с помощью dm-verity. Любое изменение файлов запрещено даже после монтирования разделов. Чтобы обеспечить такой же уровень безопасности, все файлы в APEX хранятся в образе файловой системы, который связан с деревом хешей и дескриптором vbmeta. Без dm-verity APEX в разделе /data уязвим для непреднамеренных изменений, внесенных после его проверки и установки.
На самом деле раздел /data также защищен уровнями шифрования, например dm-crypt. Хотя это обеспечивает определенный уровень защиты от несанкционированного доступа, основная цель этого метода – конфиденциальность, а не целостность. Если злоумышленник получит доступ к разделу /data, дальнейшая защита будет невозможна. Это также является регрессом по сравнению с ситуацией, когда все компоненты системы находятся в разделе /system.
Дерево хешей в файле APEX вместе с dm-verity обеспечивает такой же уровень защиты контента.
Перенаправление путей из /system в /apex
Файлы системных компонентов, упакованные в APEX, доступны по новым путям, например /apex/<name>/lib/libfoo.so. Когда файлы были частью раздела /system, они были доступны по путям, таким как /system/lib/libfoo.so. Клиент файла APEX (другие файлы APEX или платформа) должен использовать новые пути. В результате изменения пути может потребоваться обновить существующий код.
Один из способов избежать изменения пути – наложить содержимое файла APEX на раздел /system. Однако команда Android решила не делать этого, поскольку наложение файлов на раздел /system может повлиять на производительность по мере увеличения количества накладываемых файлов (возможно, даже расположенных друг за другом).
Другой вариант – перехватить функции доступа к файлам, такие как open, stat и readlink, чтобы пути, начинающиеся с /system, перенаправлялись на соответствующие пути в /apex. Команда Android отказалась от этого варианта, поскольку изменить все функции, принимающие пути, невозможно.
Например, некоторые приложения статически связывают Bionic, который реализует функции.
В таких случаях перенаправление не выполняется.