Proveedor APEX

Puedes usar el formato de archivo APEX para empaquetar y instalar módulos de SO Android de nivel inferior. Permite la construcción independiente instalación de componentes como bibliotecas y servicios nativos, HAL implementaciones, firmware, archivos de configuración, etcétera.

El sistema de compilación instala automáticamente los APEX del proveedor en el /vendor y activada en el tiempo de ejecución por apexd al igual que APEX en otros y particiones.

Casos de uso

Modularización de las imágenes de proveedores

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

Cuando las imágenes de un proveedor se crean como una combinación de imágenes de proveedores creadas de forma independiente APEX, los fabricantes de dispositivos pueden elegir fácilmente el software de las implementaciones de proveedores que los proveedores quisieran en su dispositivo. Los fabricantes incluso pueden crear nuevo APEX del proveedor si ninguno de los APEX proporcionados satisface sus necesidades o si tiene hardware personalizado nuevo.

Por ejemplo, un OEM puede elegir componer su dispositivo con la red Wi-Fi de AOSP. implementación de APEX, APEX de implementación de SoC Bluetooth y un OEM personalizado de implementación de telefonía APEX.

Sin APEX de proveedores, una implementación con tantas dependencias componentes de proveedores requiere una cuidadosa coordinación y seguimiento. Uniendo todo (archivos de configuración y bibliotecas adicionales) en APEX con interfaces definidas con claridad en cualquier punto de comunicación 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 Cómo agrupar una implementación de función completa, como la HAL de Wi-Fi, dentro de un proveedor APEX Luego, los desarrolladores pueden compilar y enviar individualmente el APEX del proveedor para que lo pruebe. en lugar de reconstruir toda la imagen del proveedor.

Esto simplifica y acelera el ciclo de iteración de los desarrolladores que trabajan principalmente en un área de funciones y quieren iterar solo en esa función en una sola área de almacenamiento en etapa intermedia.

La agrupación natural de un área de atributos en un APEX también simplifica el proceso. de crear, enviar y probar cambios en esa área de funciones. Por ejemplo: La reinstalación de APEX actualiza automáticamente las bibliotecas o los archivos de configuración agrupados. que incluye APEX.

Agrupar un área de atributos en un APEX también simplifica la depuración o la reversión cuando y se observa un mal comportamiento del dispositivo. Por ejemplo, si la telefonía funciona mal en una compilación nueva, los desarrolladores podrían intentar instalar un sistema de implementación de APEX en un dispositivo (sin necesidad de escribir una compilación completa en la memoria flash) y ver si se restablece 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

Conceptos básicos

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

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

apex {
  ..
  vendor: true,
  ..
}

Objetos binarios y bibliotecas compartidas

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

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

A diferencia de los APEX de la partición /system, los APEX de los proveedores suelen vincularse a un específica de VNDK. Las bibliotecas del VNDK garantizan la estabilidad de las ABI en la por lo que podemos tratar las bibliotecas de VNDK como estables y reducir el tamaño del proveedor los APEX excluyéndolos de los APEX con el use_vndk_as_stable propiedad.

En el siguiente fragmento, APEX contendrá el objeto binario (my_service) y sus dependencias no estables (archivos *.so) No contendrá bibliotecas de VNDK, incluso cuando my_service se compila con bibliotecas de VNDK, como libbase. En cambio, en tiempo de ejecución my_service usará libbase de las bibliotecas del VNDK proporcionadas por la en un sistema de archivos.

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

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

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

Implementaciones de HAL

Para definir una implementación de HAL, proporciona los objetos 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, APEX también debe especificar secuencias de comandos init y fragmentos de VINTF relevantes.

Fragmentos de VINTF

Los fragmentos de VINTF se pueden entregar desde un APEX de un proveedor cuando se ubican los fragmentos en etc/vintf de APEX.

Usa la propiedad prebuilts para incorporar los fragmentos de VINTF en APEX.

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

prebuilt_etc {
  name: "fragment.xml",
  src: "fragment.xml",
  sub_dir: "vintf",
}

Secuencias de comandos Init

Los APEX pueden incluir secuencias de comandos de inicio de dos maneras: (A) con un archivo de texto precompilado dentro del Carga útil de APEX o (B) una secuencia de comandos init normal en /vendor/etc Puedes establecer ambos para el mismo APEX.

Secuencia de comandos Init en APEX:

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

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

Las secuencias de comandos Init dentro de APEX pueden tener solo definiciones de service. Secuencias de comandos Init En los APEX del proveedor, también pueden tener directivas on <property>.

Ten cuidado cuando uses directivas on. Dado que las secuencias de comandos init en APEX son analizarse y ejecutarse después de que se activen los APEX, algunos eventos o propiedades no se pueden usar. Usa apex.all.ready=true para activar acciones lo antes posible.

Firmware

Ejemplo:

Incorporar firmware en el APEX de un proveedor con el tipo de módulo prebuilt_firmware, como sigue.

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 <apex name>/etc/firmware de APEX. ueventd analiza /apex/*/etc/firmware directorios para buscar módulos de firmware.

El file_contexts de APEX debe etiquetar todas las entradas de carga útil del firmware. de forma correcta para garantizar que ueventd pueda acceder a estos archivos en el tiempo de ejecución. por lo general, la etiqueta vendor_file es suficiente. Por ejemplo:

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

Módulos de kernel

Incorpora módulos de kernel en un APEX de proveedor como módulos compilados previamente, 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
  ..
}

El file_contexts de APEX debe etiquetar cualquier entrada de carga útil del módulo kernel correctamente. Por ejemplo:

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

Los módulos de kernel se deben instalar de manera explícita. El siguiente ejemplo de secuencia de comandos init En la partición de proveedor, se muestra la instalación a través de insmod:

my_init.rc:

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

Superposiciones de recursos en tiempo de ejecución

Ejemplo:

Incorporar superposiciones de recursos de tiempo de ejecución en el APEX de un proveedor con 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 archivos APEX del proveedor admiten otros archivos de configuración que suelen encontrarse en el proveedor. como compilaciones previas dentro de APEX de proveedores, y se están agregando más.

Ejemplos:

Funciones de desarrollo adicionales

Selección de APEX durante el inicio

Ejemplo:

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

Casos de uso de ejemplo:

  • Instalar 3 versiones de APEX del proveedor de la HAL de Wi-Fi: Los equipos de control de calidad pueden ejecutar o automatizadas con una versión, luego reiniciar en otra versión y vuelve a ejecutar las pruebas y, luego, compara los resultados finales.
  • Instala 2 versiones de APEX del proveedor de la HAL de la cámara, actual y experimental: Los participantes de la prueba interna pueden usar la versión experimental sin descargar e instalar un archivo adicional, de modo que se puedan revertir fácilmente.

Durante el inicio, apexd busca sysprops siguiendo un formato específico para lo siguiente: activar la versión de APEX correcta.

Los formatos esperados para la clave de propiedad son los siguientes:

  • Configuración de inicio
    • Se usa para establecer el valor predeterminado, en BoardConfig.mk.
    • androidboot.vendor.apex.<apex name>
  • Propósito del sistema persistente
    • Se usa para cambiar el valor predeterminado, que se establece en un dispositivo que ya se inició.
    • Anula el valor bootconfig si está presente.
    • persist.vendor.apex.<apex name>

El valor de la propiedad debe ser el nombre de archivo de APEX, activado.

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

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

Luego de que se haya iniciado el dispositivo, cambia la versión activada al configurar 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 actualizar bootconfig después de escribirlo en la memoria flash (por ejemplo, a través de comandos fastboot oem), cambiar la propiedad bootconfig para multiinstalado APEX también cambia la versión que se activa durante el inicio.

Para dispositivos de referencia virtuales basados en Cuttlefish, puedes usar el comando --extra_bootconfig_args para establecer 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";