Вы можете использовать формат файла APEX для упаковки и установки модулей ОС Android нижнего уровня. Он позволяет независимо создавать и устанавливать такие компоненты, как собственные службы и библиотеки, реализации HAL, встроенное ПО, файлы конфигурации и т. д.
Вендорные APEX автоматически устанавливаются системой сборки в раздел /vendor
и активируются apexd
во время выполнения, как и APEX в других разделах.
Варианты использования
Модуляризация образов поставщиков
APEX облегчают естественное объединение и модульность реализаций функций в образах поставщиков.
Когда образы поставщиков создаются как комбинация APEX независимых поставщиков, производители устройств могут легко выбирать реализации конкретного поставщика, необходимые для их устройства. Производители могут даже создать APEX нового поставщика, если ни один из предоставленных APEX не соответствует их потребностям или у них есть совершенно новое специальное оборудование.
Например, OEM-производитель может выбрать в своем устройстве реализацию Wi-Fi AOSP APEX, реализацию Bluetooth SoC APEX и специальную реализацию OEM-телефонии APEX.
Без вендорных APEX реализация с таким большим количеством зависимостей между вендорными компонентами требует тщательной координации и отслеживания. Заключая все компоненты (включая файлы конфигурации и дополнительные библиотеки) в APEX с четко определенными интерфейсами в любой точке межфункционального взаимодействия, различные компоненты становятся взаимозаменяемыми.
Итерация разработчика
Вендорные APEX помогают разработчикам быстрее выполнять итерации при разработке вендорных модулей, объединяя всю реализацию функций, например Wi-Fi HAL, внутри вендорного APEX. Затем разработчики могут создавать и индивидуально использовать APEX поставщика для тестирования изменений вместо того, чтобы перестраивать весь образ поставщика.
Это упрощает и ускоряет цикл итераций для разработчиков, которые в основном работают над одной функциональной областью и хотят выполнять итерации только над этой функциональной областью.
Естественное объединение функциональной области в APEX также упрощает процесс создания, отправки и тестирования изменений для этой функциональной области. Например, при переустановке APEX автоматически обновляются все встроенные библиотеки или файлы конфигурации, входящие в состав APEX.
Объединение функциональной области в APEX также упрощает отладку или возврат в случае обнаружения плохого поведения устройства. Например, если в новой сборке телефония работает плохо, разработчики могут попробовать установить на устройство более старую реализацию телефонии APEX (без необходимости перепрошивки полной сборки) и посмотреть, восстановится ли хорошее поведение.
Пример рабочего процесса:
# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w
# Test the device.
... testing ...
# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...
# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...
Примеры
Основы
См. главную страницу формата файла APEX для получения общей информации APEX, включая требования к устройству, сведения о формате файла и этапы установки.
В Android.bp
установка vendor: true
делает модуль APEX APEX поставщика.
apex {
..
vendor: true,
..
}
Двоичные файлы и общие библиотеки
APEX включает в себя транзитивные зависимости внутри полезных данных APEX, если только они не имеют стабильных интерфейсов.
Стабильные собственные интерфейсы для зависимостей APEX от поставщиков включают cc_library
с stubs
и библиотеки LLNDK. Эти зависимости исключаются из упаковки и записываются в манифест APEX. Манифест обрабатывается linkerconfig
, поэтому внешние собственные зависимости доступны во время выполнения.
В следующем фрагменте APEX содержит как двоичный файл ( my_service
), так и его нестабильные зависимости (файлы *.so
).
apex {
..
vendor: true,
binaries: ["my_service"],
..
}
В следующем фрагменте APEX содержит общую библиотеку my_standalone_lib
и все ее нестабильные зависимости (как описано выше).
apex {
..
vendor: true,
native_shared_libs: ["my_standalone_lib"],
..
}
Уменьшите APEX
APEX может стать больше, потому что он объединяет нестабильные зависимости. Мы рекомендуем использовать статическое связывание. Общие библиотеки, такие как libc++.so
и libbase.so
могут быть статически связаны с двоичными файлами HAL. Еще одним вариантом может быть создание зависимости для обеспечения стабильного интерфейса. Зависимость не будет включена в APEX.
HAL-реализации
Чтобы определить реализацию HAL, предоставьте соответствующие двоичные файлы и библиотеки внутри APEX поставщика, как показано в следующих примерах:
Чтобы полностью инкапсулировать реализацию HAL, APEX должен также указать все соответствующие фрагменты VINTF и сценарии инициализации.
Фрагменты ВИНТФ
Фрагменты VINTF могут быть предоставлены поставщиком APEX, если фрагменты расположены в каталоге etc/vintf
APEX.
Используйте свойство prebuilts
для встраивания фрагментов VINTF в APEX.
apex {
..
vendor: true,
prebuilts: ["fragment.xml"],
..
}
prebuilt_etc {
name: "fragment.xml",
src: "fragment.xml",
sub_dir: "vintf",
}
API запросов
Когда фрагменты VINTF добавляются в APEX, используйте API-интерфейсы libbinder_ndk
, чтобы получить сопоставления интерфейсов HAL и имен APEX.
-
AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default")
:true
если экземпляр HAL определен в APEX. -
AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...)
: получает имя APEX, которое определяет экземпляр HAL. -
AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...)
: используйте это, чтобы открыть сквозной HAL.
Скрипты инициализации
APEX может включать сценарии инициализации двумя способами: (A) предварительно созданный текстовый файл в полезной нагрузке APEX или (B) обычный сценарий инициализации в /vendor/etc
. Вы можете установить оба для одного и того же APEX.
Скрипт инициализации в APEX:
prebuilt_etc {
name: "myinit.rc",
src: "myinit.rc"
}
apex {
..
vendor: true,
prebuilts: ["myinit.rc"],
..
}
Сценарии инициализации в APEX поставщика могут содержать определения service
и директивы on <property or event>
.
Убедитесь, что определение service
указывает на двоичный файл в том же APEX. Например, com.android.foo
APEX может определять службу с именем foo-service
.
on foo-service /apex/com.android.foo/bin/foo
...
Будьте осторожны при использовании директив on
. Поскольку сценарии инициализации в APEX анализируются и выполняются после активации APEX, некоторые события или свойства использовать нельзя. Используйте apex.all.ready=true
, чтобы запускать действия как можно раньше. Bootstrap APEX можно использовать on init
, но не on early-init
.
Прошивка
Пример:
Встройте прошивку в APEX поставщика с типом модуля prebuilt_firmware
следующим образом.
prebuilt_firmware {
name: "my.bin",
src: "path_to_prebuilt_firmware",
vendor: true,
}
apex {
..
vendor: true,
prebuilts: ["my.bin"], // installed inside APEX as /etc/firmware/my.bin
..
}
Модули prebuilt_firmware
устанавливаются в каталог <apex name>/etc/firmware
APEX. ueventd
сканирует каталоги /apex/*/etc/firmware
чтобы найти модули прошивки.
file_contexts
APEX должен правильно помечать все записи полезной нагрузки встроенного ПО, чтобы гарантировать доступность этих файлов для ueventd
во время выполнения; обычно достаточно vendor_file
. Например:
(/.*)? u:object_r:vendor_file:s0
Модули ядра
Встраивайте модули ядра в APEX поставщика как готовые модули следующим образом.
prebuilt_etc {
name: "my.ko",
src: "my.ko",
vendor: true,
sub_dir: "modules"
}
apex {
..
vendor: true,
prebuilts: ["my.ko"], // installed inside APEX as /etc/modules/my.ko
..
}
file_contexts
APEX должен правильно помечать любые записи полезной нагрузки модуля ядра. Например:
/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0
Модули ядра должны быть установлены явно. Следующий пример сценария инициализации в разделе поставщика показывает установку через insmod
:
my_init.rc
:
on early-boot
insmod /apex/myapex/etc/modules/my.ko
..
Наложения ресурсов среды выполнения
Пример:
Встраивайте наложения ресурсов среды выполнения в APEX поставщика с помощью свойства rros
.
runtime_resource_overlay {
name: "my_rro",
soc_specific: true,
}
apex {
..
vendor: true,
rros: ["my_rro"], // installed inside APEX as /overlay/my_rro.apk
..
}
Другие файлы конфигурации
APEX поставщика поддерживают различные другие файлы конфигурации, которые обычно находятся в разделе поставщика в качестве предварительно созданных внутри APEX поставщика, и добавляются новые.
Примеры:
- XML-файлы объявлений функций
- Датчики содержат XML-файлы как предварительно встроенные в датчик HAL поставщика APEX.
- Входные файлы конфигурации
- Конфигурации сенсорного экрана как предварительно созданные в поставщике APEX, предназначенном только для конфигураций.
APEX поставщиков начальной загрузки
Некоторые службы HAL, такие как keymint
должны быть доступны до активации APEX. Эти HAL обычно устанавливают early_hal
в определении службы в сценарии инициализации. Другим примером является класс animation
, который обычно запускается раньше, чем событие post-fs-data
. Когда такая ранняя служба HAL упаковывается в APEX поставщика, сделайте апекс "vendorBootstrap": true
в его манифесте APEX, чтобы его можно было активировать раньше. Обратите внимание, что загрузочные APEX можно активировать только из заранее созданного местоположения, например /vendor/apex
, а не из /data/apex
.
Свойства системы
Это системные свойства, которые считывает платформа для поддержки APEX поставщиков:
-
input_device.config_file.apex=<apex name>
— если этот параметр установлен, входные файлы конфигурации (*.idc
,*.kl
и*.kcm
) ищутся в каталоге/etc/usr
APEX. -
ro.vulkan.apex=<apex name>
— если установлено, драйвер Vulkan загружается из APEX. Поскольку драйвер Vulkan используется ранними HAL, сделайте APEX Bootstrap APEX и настройте это пространство имен компоновщика видимым.
Установите свойства системы в сценариях инициализации с помощью команды setprop
.
Дополнительные возможности разработки
Выбор APEX при загрузке
Пример:
Разработчики также могут установить несколько версий APEX разных производителей с одинаковым именем и ключом APEX, а затем выбирать, какая версия активируется во время каждой загрузки, используя постоянные системные свойства. В некоторых случаях использования разработчиками это может быть проще, чем установка новой копии APEX с помощью adb install
.
Примеры использования:
- Установите 3 версии поставщика Wi-Fi HAL APEX: команды контроля качества могут запускать ручное или автоматическое тестирование, используя одну версию, затем перезагрузиться в другую версию и повторно запустить тесты, а затем сравнить окончательные результаты.
- Установите 2 версии камеры HAL поставщика APEX, текущую и экспериментальную . Разработчики Dogfoods могут использовать экспериментальную версию без загрузки и установки дополнительного файла, поэтому они могут легко заменить ее обратно.
Во время загрузки apexd
ищет системные реквизиты определенного формата, чтобы активировать нужную версию APEX.
Ожидаемые форматы ключа свойства:
- Загрузочная конфигурация
- Используется для установки значения по умолчанию в
BoardConfig.mk
. -
androidboot.vendor.apex.<apex name>
- Используется для установки значения по умолчанию в
- Постоянный системный файл
- Используется для изменения значения по умолчанию, установленного на уже загруженном устройстве.
- Переопределяет значение bootconfig, если оно присутствует.
-
persist.vendor.apex.<apex name>
Значением свойства должно быть имя файла APEX, который необходимо активировать.
// Default version.
apex {
name: "com.oem.camera.hal.my_apex_default",
vendor: true,
..
}
// Non-default version.
apex {
name: "com.oem.camera.hal.my_apex_experimental",
vendor: true,
..
}
Версия по умолчанию также должна быть настроена с помощью bootconfig в BoardConfig.mk
:
# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default
После загрузки устройства измените активированную версию, установив постоянный системный параметр:
$ adb root;
$ adb shell setprop \
persist.vendor.apex.com.oem.camera.hal \
com.oem.camera.hal.my_apex_experimental;
$ adb reboot;
Если устройство поддерживает обновление bootconfig после прошивки (например, с помощью команд fastboot oem
), то изменение свойства bootconfig для многократно установленного APEX также меняет версию, активируемую при загрузке.
Для виртуальных эталонных устройств на базе Cuttlefish вы можете использовать команду --extra_bootconfig_args
, чтобы установить свойство bootconfig непосредственно во время запуска. Например:
launch_cvd --noresume \
--extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";