АПЕКС поставщика

Формат файлов APEX позволяет упаковывать и устанавливать модули операционной системы Android нижнего уровня. Он обеспечивает независимую сборку и установку таких компонентов, как нативные сервисы и библиотеки, реализации HAL, микропрограммы, файлы конфигурации и т. д.

APEX-файлы от поставщика устанавливаются системой сборки автоматически в раздел /vendor и активируются во время выполнения программой apexd так же, как и APEX-файлы в других разделах.

Варианты использования

Модульная организация образов поставщиков

APEX-ы обеспечивают естественное объединение и модульную структуру реализаций функций в образах от поставщиков.

Когда образы от поставщиков создаются как комбинация независимо разработанных APEX-файлов от разных поставщиков, производители устройств могут легко выбирать конкретные реализации от поставщиков, необходимые для их устройства. Производители могут даже создать новый APEX-файл от поставщика, если ни один из предоставленных APEX-файлов не соответствует их потребностям или если у них есть совершенно новое специализированное оборудование.

Например, производитель оборудования может выбрать для своего устройства реализацию Wi-Fi на основе AOSP (APEX), реализацию Bluetooth на основе SoC (APEX) и собственную реализацию телефонии от производителя (APEX).

Без использования APEX-файлов от сторонних поставщиков реализация с таким количеством зависимостей между компонентами от разных поставщиков требует тщательной координации и отслеживания. Обернув все компоненты (включая файлы конфигурации и дополнительные библиотеки) в APEX-файлы с четко определенными интерфейсами в любой точке взаимодействия между функциями, различные компоненты становятся взаимозаменяемыми.

Итерация разработчиков

Встроенные APEX-файлы от поставщиков помогают разработчикам быстрее вносить изменения в модули от сторонних производителей, объединяя всю реализацию функций, например, HAL для Wi-Fi, в один 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 от поставщиков относятся 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

Фрагменты 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-файле. Например, APEX-файл com.android.foo может определять службу с именем foo-service .

on foo-service /apex/com.android.foo/bin/foo
  ...

Будьте осторожны при использовании директив ` on . Поскольку скрипты инициализации в APEX-приложениях анализируются и выполняются после активации APEX-приложений, некоторые события или свойства использовать нельзя. Используйте apex.all.ready=true , чтобы запускать действия как можно раньше. 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

Модули ядра необходимо устанавливать явно. Следующий пример скрипта инициализации в разделе vendor демонстрирует установку с помощью 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 от поставщика, и их количество постоянно увеличивается.

Примеры:

Bootstrap Vendor APEXes

Некоторые службы HAL, такие как keymint должны быть доступны до активации APEX. Для таких HAL обычно устанавливается early_hal в определении службы в скрипте инициализации. Другой пример — класс animation , который обычно запускается раньше, чем событие post-fs-data . Если такая служба HAL, работающая на ранней стадии, включена в APEX поставщика, установите параметр 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-файлы от поставщика могут быть активированы во время загрузки. Если вы укажете имя файла с помощью системного свойства ro.vendor.apex.<apex name> , будет активирован только тот APEX-файл, который соответствует этому имени, для конкретного <apex name> . APEX-файл с <apex name> будет проигнорирован (не активирован), если это системное свойство установлено в none . Вы можете использовать эту функцию для установки нескольких копий APEX-файла с одинаковым именем. Если существует несколько версий одного и того же APEX-файла, они должны использовать один и тот же ключ.

Примеры вариантов использования:

  • Установите 3 версии APEX от поставщика WiFi HAL: команды контроля качества могут запускать ручное или автоматизированное тестирование, используя одну версию, затем перезагрузиться в другую версию и повторно запустить тесты, после чего сравнить окончательные результаты.
  • Установите две версии HAL-компонента камеры APEX: текущую и экспериментальную : пользователи Dogfood могут использовать экспериментальную версию без загрузки и установки дополнительных файлов, поэтому они легко смогут вернуться к предыдущей.

Во время загрузки apexd ищет параметры sysprops в определенном формате, чтобы активировать правильную версию APEX.

Ожидаемые форматы для ключа свойства:

  • Bootconfig
    • Используется для установки значения по умолчанию в BoardConfig.mk .
    • androidboot.vendor.apex.<apex name>
  • Постоянный sysprop
    • Используется для изменения значения по умолчанию, установленного на уже загруженном устройстве.
    • Переопределяет значение параметра bootconfig, если оно присутствует.
    • persist.vendor.apex.<apex name>

Значение свойства должно быть равно имени файла APEX, который необходимо активировать, или none чтобы отключить 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

После загрузки устройства измените активированную версию, установив параметр persistent sysprop:

$ 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";