Proveedor APEX

Puede usar el formato de archivo APEX para empaquetar e instalar módulos del sistema operativo Android de nivel inferior. Permite la construcción e instalación independientes de componentes como bibliotecas y servicios nativos, implementaciones HAL, firmware, archivos de configuración, etc.

Los APEX de proveedores son instalados por el sistema de compilación automáticamente en la partición /vendor y apexd los activa en tiempo de ejecución al igual que los APEX en otras particiones.

casos de uso

Modularización de imágenes de proveedores

Los APEX facilitan la agrupación y la modularización naturales de implementaciones de funciones en imágenes de proveedores.

Cuando las imágenes de los proveedores se crean como una combinación de APEX de proveedores independientes, los fabricantes de dispositivos pueden seleccionar y elegir fácilmente las implementaciones específicas del proveedor que desean en su dispositivo. Los fabricantes pueden incluso crear un nuevo APEX de proveedor si ninguno de los APEX proporcionados se ajusta a sus necesidades, o si tienen un nuevo hardware personalizado.

Por ejemplo, un OEM puede elegir componer su dispositivo con el APEX de implementación wifi de AOSP, el APEX de implementación de SoC bluetooth y un APEX de implementación de telefonía OEM personalizado.

Sin APEX de proveedores, una implementación con tantas dependencias entre componentes de proveedores requiere una coordinación y un seguimiento cuidadosos. Al envolver todos los componentes (incluidos los archivos de configuración y las bibliotecas adicionales) en APEX con interfaces claramente definidas en cualquier punto de comunicación entre funciones, los diferentes componentes se vuelven intercambiables.

iteración del desarrollador

Los APEX de proveedores ayudan a los desarrolladores a iterar más rápido mientras desarrollan módulos de proveedores al agrupar una implementación de funciones completa, como wifi HAL, dentro de un APEX de proveedor. Luego, los desarrolladores pueden crear e impulsar individualmente el APEX del proveedor para probar los cambios, en lugar de reconstruir toda la imagen del proveedor.

Esto simplifica y acelera el ciclo de iteración del desarrollador para los desarrolladores que trabajan principalmente en un área de funciones y desean iterar solo en esa área de funciones.

La agrupación natural de un área de características en un APEX también simplifica el proceso de creación, envío y prueba de cambios para esa área de características. Por ejemplo, la reinstalación de un APEX actualiza automáticamente cualquier biblioteca incluida o archivos de configuración que incluya el APEX.

La agrupación de un área de características en un APEX también simplifica la depuración o la reversión cuando se observa un mal comportamiento del dispositivo. Por ejemplo, si la telefonía funciona mal en una nueva compilación, los desarrolladores podrían intentar instalar una implementación de telefonía APEX anterior en un dispositivo (sin necesidad de actualizar una compilación completa) y ver si se restaura el buen comportamiento.

Ejemplo de flujo de trabajo:

# 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 ...

Ejemplos

Lo esencial

Consulte la página principal de formato de archivo APEX para obtener información genérica de APEX, incluidos los requisitos del dispositivo, los detalles del formato de archivo y los pasos de instalación.

En Android.bp , establecer la propiedad vendor: true hace que un módulo APEX sea un proveedor APEX.

apex {
  ..
  vendor: true,
  ..
}

Binarios y bibliotecas compartidas

Un APEX incluye dependencias transitivas dentro de la carga útil de APEX a menos que tengan interfaces estables.

Las interfaces nativas estables para las dependencias APEX del proveedor incluyen cc_library con stubs , ndk_library o llndk_library . Estas dependencias se excluyen del empaquetado y se registran en el manifiesto de APEX. El manifiesto es procesado por linkerconfig para que las dependencias nativas externas estén disponibles en tiempo de ejecución.

A diferencia de los APEX en la partición /system , los APEX de proveedor generalmente están vinculados a una versión específica de VNDK. Las bibliotecas de VNDK garantizan la estabilidad de ABI dentro del lanzamiento, por lo que podemos tratar las bibliotecas de VNDK como estables y reducir el tamaño de los APEX de proveedores al excluirlos de los APEX mediante la propiedad use_vndk_as_stable .

En el fragmento a continuación, APEX contendrá tanto el binario ( my_service ) como sus dependencias no estables (archivos *.so ). No contendrá bibliotecas VNDK, incluso cuando my_service esté construido con bibliotecas VNDK como libbase . En su lugar, en tiempo de ejecución, my_service utilizará libbase de las bibliotecas VNDK proporcionadas por el sistema.

apex {
  ..
  vendor: true,
  use_vndk_as_stable: true,
  binaries: ["my_service"],
  ..
}

En el fragmento a continuación, APEX contendrá la biblioteca compartida my_standalone_lib y cualquiera de sus dependencias no estables (como se describe anteriormente).

apex {
  ..
  vendor: true,
  use_vndk_as_stable: true,
  native_shared_libs: ["my_standalone_lib"],
  ..
}

implementaciones HAL

Para definir una implementación de HAL, proporcione los archivos binarios y las bibliotecas correspondientes dentro de un APEX de proveedor similar a los siguientes ejemplos:

Para encapsular por completo la implementación de HAL, el APEX también debe especificar los fragmentos VINTF y las secuencias de comandos de inicio relevantes.

Fragmentos VINTF

Los fragmentos de VINTF se instalan en /vendor/etc/vintf , en lugar de estar contenidos dentro del APEX.

Utilice la propiedad vintf_fragments estándar:

apex {
  ..
  vendor: true,
  vintf_fragments: ["fragment.xml"],
  ..
}

guiones de inicio

Los APEX pueden incluir secuencias de comandos de inicio de dos maneras: (A) un archivo de texto preconstruido dentro de la carga útil de APEX, o (B) una secuencia de comandos de inicio regular en /vendor/etc . Puede configurar ambos para el mismo APEX.

Script de inicio en APEX:

prebuilt_etc {
  name: "myinit.rc",
  src: "myinit.rc"
}

apex {
  ..
  vendor: true,
  prebuilts: ["myinit.rc"],
  ..
}

Los scripts de inicio dentro de APEX solo pueden tener definiciones de service , no on <property> . Si su servicio necesita depender de algunas condiciones, debe instalar el script de inicio en /vendor .

Script de inicio en /vendor :

apex {
  ..
  vendor: true,
  init_rc: ["myinit.in.vendor.rc"],
  ..
}

Cualquier referencia a la ruta binaria dentro de un script de inicio debe reflejar la ruta dentro del APEX. Puede codificar la ruta en el archivo fuente del script de inicio o reemplazarlo desde un archivo fuente existente usando una regla gen .

firmware

Ejemplo:

Incruste el firmware en un APEX de proveedor con el tipo de módulo prebuilt_firmware , de la siguiente manera.

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
  ..
}

Los módulos prebuilt_firmware se instalan en el directorio <apex name>/etc/firmware de APEX. ueventd escanea los directorios /apex/*/etc/firmware para encontrar módulos de firmware.

Los file_contexts de APEX deben etiquetar correctamente cualquier entrada de carga útil de firmware para garantizar que ueventd acceder a estos archivos en tiempo de ejecución; normalmente, la etiqueta del vendor_file es suficiente. Por ejemplo:

(/.*)? u:object_r:vendor_file:s0

Módulos del núcleo

Incruste módulos de kernel en un APEX de proveedor como módulos preconstruidos, de la siguiente manera.

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
  ..
}

Los file_contexts de archivo de APEX deben etiquetar correctamente cualquier entrada de carga útil del módulo del kernel. Por ejemplo:

/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0

Los módulos del kernel deben instalarse explícitamente. El siguiente script de inicio de ejemplo en la partición del proveedor muestra la instalación a través insmod :

my_init.rc :

on early-boot
  insmod /apex/myapex/etc/modules/my.ko
  ..

Superposiciones de recursos de tiempo de ejecución

Ejemplo:

Incruste superposiciones de recursos de tiempo de ejecución en un APEX de proveedor mediante la propiedad rros .

runtime_resource_overlay {
    name: "my_rro",
    soc_specific: true,
}


apex {
  ..
  vendor: true,
  rros: ["my_rro"],  // installed inside APEX as /overlay/my_rro.apk
  ..
}

Otros archivos de configuración

Los APEX de proveedores admiten varios otros archivos de configuración que normalmente se encuentran en la partición del proveedor como preconstruidos dentro de los APEX de proveedores, y se están agregando más.

Ejemplos:

Funciones de desarrollo adicionales

Selección de APEX en el arranque

Ejemplo:

Los desarrolladores también pueden instalar varias versiones de APEX de proveedores que comparten el mismo nombre y clave de APEX, y luego elegir qué versión se activa durante cada arranque utilizando sysprops persistentes. Para ciertos casos de uso de desarrolladores, esto podría ser más simple que instalar una nueva copia de APEX usando adb install .

Ejemplos de casos de uso:

  • Instale 3 versiones del APEX del proveedor wifi HAL: los equipos de control de calidad pueden ejecutar pruebas manuales o automatizadas usando una versión, luego reiniciar en otra versión y volver a ejecutar las pruebas, luego comparar los resultados finales.
  • Instale 2 versiones de la cámara HAL proveedor APEX, actual y experimental : Dogfooders puede usar la versión experimental sin descargar e instalar un archivo adicional, por lo que pueden volver a cambiar fácilmente.

Durante el arranque, apexd busca sysprops siguiendo un formato específico para activar la versión APEX correcta.

Los formatos esperados para la clave de propiedad son:

  • configuración de arranque
    • Se utiliza para establecer el valor predeterminado, en BoardConfig.mk .
    • androidboot.vendor.apex.<apex name>
  • prop persistente
    • Se utiliza para cambiar el valor predeterminado, establecido en un dispositivo ya iniciado.
    • Anula el valor bootconfig si está presente.
    • persist.vendor.apex.<apex name>

El valor de la propiedad debe ser el nombre de archivo del APEX que debe activarse.

El único cambio en las definiciones de APEX Android.bp es el campo multi_install_skip_symbol_files , que debería ser true para todas las definiciones de APEX multiinstaladas no predeterminadas:

// Default version.
apex {
  name: "com.oem.camera.hal.my_apex_default",
  apex_name: "com.oem.camera.hal",
  vendor: true,
  ..
}

// Non-default version.
apex {
  name: "com.oem.camera.hal.my_apex_experimental",
  apex_name: "com.oem.camera.hal",
  vendor: true,
  multi_install_skip_symbol_files: true,
  ..
}

La versión predeterminada también debe configurarse usando bootconfig en 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

Después de iniciar el dispositivo, cambie la versión activada configurando el sysprop persistente:

$ adb root;
$ adb shell setprop \
    persist.vendor.apex.com.oem.camera.hal \
    com.oem.camera.hal.my_apex_experimental;
$ adb reboot;

Si el dispositivo admite la actualización de bootconfig después de flashear (por ejemplo, a través de los comandos fastboot oem ), al cambiar la propiedad de bootconfig para el APEX multiinstalado también cambia la versión activada en el arranque.

Para dispositivos de referencia virtual basados ​​en Cuttlefish , puede usar el comando --extra_bootconfig_args para configurar la propiedad bootconfig directamente durante el inicio. Por ejemplo:

launch_cvd --noresume \
  --extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";