Fournisseur APEX

Vous pouvez utiliser le format de fichier APEX pour empaqueter et installer des modules du système d'exploitation Android de niveau inférieur. Il permet la création et l'installation indépendantes de composants tels que des services et bibliothèques natifs, des implémentations HAL, des micrologiciels, des fichiers de configuration, etc.

Les APEX du fournisseur sont installés automatiquement par le système de build dans la partition /vendor et activés au moment de l'exécution par apexd , tout comme les APEX dans d'autres partitions.

Cas d'utilisation

Modularisation des images des fournisseurs

Les APEX facilitent un regroupement et une modularisation naturels des implémentations de fonctionnalités sur les images des fournisseurs.

Lorsque les images des fournisseurs sont créées sous la forme d'une combinaison d'APEX de fournisseurs indépendants, les fabricants d'appareils sont en mesure de sélectionner facilement les implémentations spécifiques des fournisseurs souhaitées sur leur appareil. Les fabricants peuvent même créer un nouveau fournisseur APEX si aucun des APEX fournis ne répond à leurs besoins ou s'ils disposent d'un tout nouveau matériel personnalisé.

Par exemple, un OEM peut choisir de composer son appareil avec l'implémentation wifi AOSP APEX, l'implémentation Bluetooth SoC APEX et une implémentation de téléphonie OEM personnalisée APEX.

Sans APEX des fournisseurs, une implémentation avec autant de dépendances entre les composants des fournisseurs nécessite une coordination et un suivi minutieux. En encapsulant tous les composants (y compris les fichiers de configuration et les bibliothèques supplémentaires) dans des APEX avec des interfaces clairement définies à tout point de communication entre fonctionnalités, les différents composants deviennent interchangeables.

Itération du développeur

Les APEX de fournisseur aident les développeurs à itérer plus rapidement lors du développement de modules de fournisseur en regroupant une implémentation complète de fonctionnalités, comme le HAL wifi, dans un APEX de fournisseur. Les développeurs peuvent ensuite créer et pousser individuellement l'APEX du fournisseur pour tester les modifications, au lieu de reconstruire l'intégralité de l'image du fournisseur.

Cela simplifie et accélère le cycle d'itération des développeurs pour les développeurs qui travaillent principalement dans un domaine de fonctionnalités et souhaitent itérer uniquement sur ce domaine de fonctionnalités.

Le regroupement naturel d'une zone de fonctionnalités dans un APEX simplifie également le processus de création, de diffusion et de test des modifications pour cette zone de fonctionnalités. Par exemple, la réinstallation d'un APEX met automatiquement à jour toute bibliothèque groupée ou tous les fichiers de configuration inclus dans l'APEX.

Le regroupement d'une zone de fonctionnalités dans un APEX simplifie également le débogage ou la restauration lorsqu'un mauvais comportement du périphérique est observé. Par exemple, si la téléphonie fonctionne mal dans une nouvelle version, les développeurs peuvent essayer d'installer une ancienne implémentation de téléphonie APEX sur un appareil (sans avoir besoin de flasher une version complète) et voir si le bon comportement est restauré.

Exemple de flux de travail :

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

Exemples

Les bases

Consultez la page principale Format de fichier APEX pour obtenir des informations génériques sur APEX, notamment la configuration requise pour le périphérique, les détails du format de fichier et les étapes d'installation.

Dans Android.bp , la définition de la vendor: true fait d'un module APEX un APEX de fournisseur.

apex {
  ..
  vendor: true,
  ..
}

Binaires et bibliothèques partagées

Un APEX inclut des dépendances transitives à l’intérieur de la charge utile APEX, à moins qu’elles n’aient des interfaces stables.

Les interfaces natives stables pour les dépendances APEX du fournisseur incluent cc_library avec stubs , ndk_library ou llndk_library . Ces dépendances sont exclues du packaging et les dépendances sont enregistrées dans le manifeste APEX. Le manifeste est traité par linkerconfig afin que les dépendances natives externes soient disponibles au moment de l'exécution.

Contrairement aux APEX de la partition /system , les APEX du fournisseur sont généralement liés à une version spécifique du VNDK. Les bibliothèques VNDK garantissent la stabilité de l'ABI dans la version, nous pouvons donc traiter les bibliothèques VNDK comme stables et réduire la taille des APEX des fournisseurs en les excluant des APEX à l'aide de la propriété use_vndk_as_stable .

Dans l'extrait ci-dessous, l'APEX contiendra à la fois le binaire ( my_service ) et ses dépendances non stables (fichiers *.so ). Il ne contiendra pas de bibliothèques VNDK, même lorsque my_service est construit avec des bibliothèques VNDK comme libbase . Au lieu de cela, au moment de l'exécution, my_service utilisera libbase à partir des bibliothèques VNDK fournies par le système.

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

Dans l'extrait ci-dessous, l'APEX contiendra la bibliothèque partagée my_standalone_lib et toutes ses dépendances non stables (comme décrit ci-dessus).

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

Implémentations HAL

Pour définir une implémentation HAL, fournissez les binaires et bibliothèques correspondants dans un APEX de fournisseur similaire aux exemples suivants :

Pour encapsuler complètement l'implémentation de HAL, l'APEX doit également spécifier tous les fragments VINTF et scripts d'initialisation pertinents.

Fragments VINTF

Les fragments VINTF peuvent être servis à partir d'un APEX de fournisseur lorsque les fragments se trouvent dans etc/vintf de l'APEX.

Utilisez la propriété prebuilts pour intégrer les fragments VINTF dans l'APEX.

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

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

Scripts d'initialisation

Les APEX peuvent inclure des scripts d'initialisation de deux manières : (A) un fichier texte prédéfini dans la charge utile APEX, ou (B) un script d'initialisation standard dans /vendor/etc . Vous pouvez définir les deux pour le même APEX.

Script d'initialisation dans APEX :

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

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

Les scripts d'initialisation au sein des APEX ne peuvent avoir que des définitions service . Les scripts d'initialisation dans les APEX des fournisseurs peuvent également avoir des directives on <property> .

Soyez prudent lorsque vous utilisez on directives. Étant donné que les scripts d'initialisation dans les APEX sont analysés et exécutés après l'activation des APEX, certains événements ou propriétés ne peuvent pas être utilisés. Utilisez apex.all.ready=true pour déclencher des actions le plus tôt possible.

Micrologiciel

Exemple:

Intégrez le micrologiciel dans un APEX du fournisseur avec le type de module prebuilt_firmware , comme suit.

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

Les modules prebuilt_firmware sont installés dans le répertoire <apex name>/etc/firmware de l'APEX. ueventd analyse les répertoires /apex/*/etc/firmware pour trouver les modules du micrologiciel.

Les file_contexts de l'APEX doivent étiqueter correctement toutes les entrées de charge utile du micrologiciel pour garantir que ces fichiers sont accessibles par ueventd au moment de l'exécution ; généralement, l'étiquette vendor_file est suffisante. Par exemple:

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

Modules du noyau

Intégrez les modules du noyau dans un APEX d'un fournisseur en tant que modules prédéfinis, comme suit.

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

Les file_contexts de l'APEX doivent étiqueter correctement toutes les entrées de charge utile du module du noyau. Par exemple:

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

Les modules du noyau doivent être installés explicitement. L'exemple de script d'initialisation suivant dans la partition du fournisseur montre l'installation via insmod :

my_init.rc :

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

Superpositions de ressources d'exécution

Exemple:

Intégrez des superpositions de ressources d'exécution dans un APEX de fournisseur à l'aide de la propriété rros .

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


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

Autres fichiers de configuration

Les APEX du fournisseur prennent en charge divers autres fichiers de configuration généralement trouvés sur la partition du fournisseur en tant que fichiers prédéfinis dans les APEX du fournisseur, et d'autres sont ajoutés.

Exemples:

Fonctionnalités de développement supplémentaires

Sélection APEX au démarrage

Exemple:

Les développeurs peuvent également installer plusieurs versions d'APEX de fournisseurs partageant le même nom et la même clé APEX, puis choisir quelle version est activée lors de chaque démarrage à l'aide de sysprops persistants. Pour certains cas d'utilisation des développeurs, cela peut être plus simple que d'installer une nouvelle copie d'APEX à l'aide de adb install .

Exemples de cas d'utilisation :

  • Installez 3 versions du fournisseur wifi HAL APEX : les équipes d'assurance qualité peuvent exécuter des tests manuels ou automatisés en utilisant une version, puis redémarrer dans une autre version et réexécuter les tests, puis comparer les résultats finaux.
  • Installez 2 versions de la caméra HAL du fournisseur APEX, actuelle et expérimentale : les Dogfooders peuvent utiliser la version expérimentale sans télécharger ni installer de fichier supplémentaire, afin qu'ils puissent facilement revenir en arrière.

Lors du démarrage, apexd recherche les sysprops suivant un format spécifique pour activer la bonne version d'APEX.

Les formats attendus pour la clé de propriété sont :

  • Configuration de démarrage
    • Utilisé pour définir la valeur par défaut, dans BoardConfig.mk .
    • androidboot.vendor.apex.<apex name>
  • Sysprop persistant
    • Utilisé pour modifier la valeur par défaut, définie sur un périphérique déjà démarré.
    • Remplace la valeur bootconfig si elle est présente.
    • persist.vendor.apex.<apex name>

La valeur de la propriété doit être le nom de fichier de l'APEX qui doit être activé.

// 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 version par défaut doit également être configurée à l'aide de bootconfig dans 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

Une fois l'appareil démarré, modifiez la version activée en définissant le sysprop persistant :

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

Si le périphérique prend en charge la mise à jour de bootconfig après le flashage (par exemple via les commandes fastboot oem ), la modification de la propriété bootconfig pour l'APEX multi-installé modifie également la version activée au démarrage.

Pour les périphériques de référence virtuelle basés sur Cuttlefish , vous pouvez utiliser la commande --extra_bootconfig_args pour définir la propriété bootconfig directement lors du lancement. Par exemple:

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

Vous pouvez utiliser le format de fichier APEX pour empaqueter et installer des modules du système d'exploitation Android de niveau inférieur. Il permet la création et l'installation indépendantes de composants tels que des services et bibliothèques natifs, des implémentations HAL, des micrologiciels, des fichiers de configuration, etc.

Les APEX du fournisseur sont installés automatiquement par le système de build dans la partition /vendor et activés au moment de l'exécution par apexd , tout comme les APEX dans d'autres partitions.

Cas d'utilisation

Modularisation des images des fournisseurs

Les APEX facilitent un regroupement et une modularisation naturels des implémentations de fonctionnalités sur les images des fournisseurs.

Lorsque les images des fournisseurs sont créées sous la forme d'une combinaison d'APEX de fournisseurs indépendants, les fabricants d'appareils sont en mesure de sélectionner facilement les implémentations spécifiques des fournisseurs souhaitées sur leur appareil. Les fabricants peuvent même créer un nouveau fournisseur APEX si aucun des APEX fournis ne répond à leurs besoins ou s'ils disposent d'un tout nouveau matériel personnalisé.

Par exemple, un OEM peut choisir de composer son appareil avec l'implémentation wifi AOSP APEX, l'implémentation Bluetooth SoC APEX et une implémentation de téléphonie OEM personnalisée APEX.

Sans APEX des fournisseurs, une implémentation avec autant de dépendances entre les composants des fournisseurs nécessite une coordination et un suivi minutieux. En encapsulant tous les composants (y compris les fichiers de configuration et les bibliothèques supplémentaires) dans des APEX avec des interfaces clairement définies à tout point de communication entre fonctionnalités, les différents composants deviennent interchangeables.

Itération du développeur

Les APEX de fournisseur aident les développeurs à itérer plus rapidement lors du développement de modules de fournisseur en regroupant une implémentation complète de fonctionnalités, comme le HAL wifi, dans un APEX de fournisseur. Les développeurs peuvent ensuite créer et pousser individuellement l'APEX du fournisseur pour tester les modifications, au lieu de reconstruire l'intégralité de l'image du fournisseur.

Cela simplifie et accélère le cycle d'itération des développeurs pour les développeurs qui travaillent principalement dans un domaine de fonctionnalités et souhaitent itérer uniquement sur ce domaine de fonctionnalités.

Le regroupement naturel d'une zone de fonctionnalités dans un APEX simplifie également le processus de création, de diffusion et de test des modifications pour cette zone de fonctionnalités. Par exemple, la réinstallation d'un APEX met automatiquement à jour toute bibliothèque groupée ou tous les fichiers de configuration inclus dans l'APEX.

Le regroupement d'une zone de fonctionnalités dans un APEX simplifie également le débogage ou la restauration lorsqu'un mauvais comportement du périphérique est observé. Par exemple, si la téléphonie fonctionne mal dans une nouvelle version, les développeurs peuvent essayer d'installer une ancienne implémentation de téléphonie APEX sur un appareil (sans avoir besoin de flasher une version complète) et voir si le bon comportement est restauré.

Exemple de flux de travail :

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

Exemples

Les bases

Consultez la page principale Format de fichier APEX pour obtenir des informations génériques sur APEX, notamment la configuration requise pour le périphérique, les détails du format de fichier et les étapes d'installation.

Dans Android.bp , la définition de la vendor: true fait d'un module APEX un APEX de fournisseur.

apex {
  ..
  vendor: true,
  ..
}

Binaires et bibliothèques partagées

Un APEX inclut des dépendances transitives à l’intérieur de la charge utile APEX, à moins qu’elles n’aient des interfaces stables.

Les interfaces natives stables pour les dépendances APEX du fournisseur incluent cc_library avec stubs , ndk_library ou llndk_library . Ces dépendances sont exclues du packaging et les dépendances sont enregistrées dans le manifeste APEX. Le manifeste est traité par linkerconfig afin que les dépendances natives externes soient disponibles au moment de l'exécution.

Contrairement aux APEX de la partition /system , les APEX du fournisseur sont généralement liés à une version spécifique du VNDK. Les bibliothèques VNDK garantissent la stabilité de l'ABI dans la version, nous pouvons donc traiter les bibliothèques VNDK comme stables et réduire la taille des APEX des fournisseurs en les excluant des APEX à l'aide de la propriété use_vndk_as_stable .

Dans l'extrait ci-dessous, l'APEX contiendra à la fois le binaire ( my_service ) et ses dépendances non stables (fichiers *.so ). Il ne contiendra pas de bibliothèques VNDK, même lorsque my_service est construit avec des bibliothèques VNDK comme libbase . Au lieu de cela, au moment de l'exécution, my_service utilisera libbase à partir des bibliothèques VNDK fournies par le système.

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

Dans l'extrait ci-dessous, l'APEX contiendra la bibliothèque partagée my_standalone_lib et toutes ses dépendances non stables (comme décrit ci-dessus).

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

Implémentations HAL

Pour définir une implémentation HAL, fournissez les binaires et bibliothèques correspondants dans un APEX de fournisseur similaire aux exemples suivants :

Pour encapsuler complètement l'implémentation de HAL, l'APEX doit également spécifier tous les fragments VINTF et scripts d'initialisation pertinents.

Fragments VINTF

Les fragments VINTF peuvent être servis à partir d'un APEX de fournisseur lorsque les fragments se trouvent dans etc/vintf de l'APEX.

Utilisez la propriété prebuilts pour intégrer les fragments VINTF dans l'APEX.

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

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

Scripts d'initialisation

Les APEX peuvent inclure des scripts d'initialisation de deux manières : (A) un fichier texte prédéfini dans la charge utile APEX, ou (B) un script d'initialisation standard dans /vendor/etc . Vous pouvez définir les deux pour le même APEX.

Script d'initialisation dans APEX :

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

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

Les scripts d'initialisation au sein des APEX ne peuvent avoir que des définitions service . Les scripts d'initialisation dans les APEX des fournisseurs peuvent également avoir des directives on <property> .

Soyez prudent lorsque vous utilisez on directives. Étant donné que les scripts d'initialisation dans les APEX sont analysés et exécutés après l'activation des APEX, certains événements ou propriétés ne peuvent pas être utilisés. Utilisez apex.all.ready=true pour déclencher des actions le plus tôt possible.

Micrologiciel

Exemple:

Intégrez le micrologiciel dans un APEX du fournisseur avec le type de module prebuilt_firmware , comme suit.

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

Les modules prebuilt_firmware sont installés dans le répertoire <apex name>/etc/firmware de l'APEX. ueventd analyse les répertoires /apex/*/etc/firmware pour trouver les modules du micrologiciel.

Les file_contexts de l'APEX doivent étiqueter correctement toutes les entrées de charge utile du micrologiciel pour garantir que ces fichiers sont accessibles par ueventd au moment de l'exécution ; généralement, l'étiquette vendor_file est suffisante. Par exemple:

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

Modules du noyau

Intégrez les modules du noyau dans un APEX d'un fournisseur en tant que modules prédéfinis, comme suit.

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

Les file_contexts de l'APEX doivent étiqueter correctement toutes les entrées de charge utile du module du noyau. Par exemple:

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

Les modules du noyau doivent être installés explicitement. L'exemple de script d'initialisation suivant dans la partition du fournisseur montre l'installation via insmod :

my_init.rc :

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

Superpositions de ressources d'exécution

Exemple:

Intégrez des superpositions de ressources d'exécution dans un APEX de fournisseur à l'aide de la propriété rros .

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


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

Autres fichiers de configuration

Les APEX du fournisseur prennent en charge divers autres fichiers de configuration généralement trouvés sur la partition du fournisseur en tant que fichiers prédéfinis dans les APEX du fournisseur, et d'autres sont ajoutés.

Exemples:

Fonctionnalités de développement supplémentaires

Sélection APEX au démarrage

Exemple:

Les développeurs peuvent également installer plusieurs versions d'APEX de fournisseurs partageant le même nom et la même clé APEX, puis choisir quelle version est activée lors de chaque démarrage à l'aide de sysprops persistants. Pour certains cas d'utilisation des développeurs, cela peut être plus simple que d'installer une nouvelle copie d'APEX à l'aide adb install .

Exemples de cas d'utilisation :

  • Installez 3 versions du fournisseur wifi HAL APEX : les équipes d'assurance qualité peuvent exécuter des tests manuels ou automatisés en utilisant une version, puis redémarrer dans une autre version et réexécuter les tests, puis comparer les résultats finaux.
  • Installez 2 versions de la caméra HAL du fournisseur APEX, actuelle et expérimentale : les Dogfooders peuvent utiliser la version expérimentale sans télécharger ni installer de fichier supplémentaire, afin qu'ils puissent facilement revenir en arrière.

Lors du démarrage, apexd recherche les sysprops suivant un format spécifique pour activer la bonne version d'APEX.

Les formats attendus pour la clé de propriété sont :

  • Configuration de démarrage
    • Utilisé pour définir la valeur par défaut, dans BoardConfig.mk .
    • androidboot.vendor.apex.<apex name>
  • Sysprop persistant
    • Utilisé pour modifier la valeur par défaut, définie sur un périphérique déjà démarré.
    • Remplace la valeur bootconfig si elle est présente.
    • persist.vendor.apex.<apex name>

La valeur de la propriété doit être le nom de fichier de l'APEX qui doit être activé.

// 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 version par défaut doit également être configurée à l'aide de bootconfig dans 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

Une fois l'appareil démarré, modifiez la version activée en définissant le sysprop persistant :

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

Si le périphérique prend en charge la mise à jour de bootconfig après le flashage (par exemple via les commandes fastboot oem ), la modification de la propriété bootconfig pour l'APEX multi-installé modifie également la version activée au démarrage.

Pour les périphériques de référence virtuelle basés sur Cuttlefish , vous pouvez utiliser la commande --extra_bootconfig_args pour définir la propriété bootconfig directement lors du lancement. Par exemple:

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

Vous pouvez utiliser le format de fichier APEX pour empaqueter et installer des modules du système d'exploitation Android de niveau inférieur. Il permet la création et l'installation indépendantes de composants tels que des services et bibliothèques natifs, des implémentations HAL, des micrologiciels, des fichiers de configuration, etc.

Les APEX du fournisseur sont installés automatiquement par le système de build dans la partition /vendor et activés au moment de l'exécution par apexd , tout comme les APEX dans d'autres partitions.

Cas d'utilisation

Modularisation des images des fournisseurs

Les APEX facilitent un regroupement et une modularisation naturels des implémentations de fonctionnalités sur les images des fournisseurs.

Lorsque les images des fournisseurs sont créées sous la forme d'une combinaison d'APEX de fournisseurs indépendants, les fabricants d'appareils sont en mesure de sélectionner facilement les implémentations spécifiques des fournisseurs souhaitées sur leur appareil. Les fabricants peuvent même créer un nouveau fournisseur APEX si aucun des APEX fournis ne répond à leurs besoins ou s'ils disposent d'un tout nouveau matériel personnalisé.

Par exemple, un OEM peut choisir de composer son appareil avec l'implémentation wifi AOSP APEX, l'implémentation Bluetooth SoC APEX et une implémentation de téléphonie OEM personnalisée APEX.

Sans APEX des fournisseurs, une implémentation avec autant de dépendances entre les composants des fournisseurs nécessite une coordination et un suivi minutieux. En encapsulant tous les composants (y compris les fichiers de configuration et les bibliothèques supplémentaires) dans des APEX avec des interfaces clairement définies à tout point de communication entre fonctionnalités, les différents composants deviennent interchangeables.

Itération du développeur

Les APEX de fournisseur aident les développeurs à itérer plus rapidement lors du développement de modules de fournisseur en regroupant une implémentation complète de fonctionnalités, comme le HAL wifi, dans un APEX de fournisseur. Les développeurs peuvent ensuite créer et pousser individuellement l'APEX du fournisseur pour tester les modifications, au lieu de reconstruire l'intégralité de l'image du fournisseur.

Cela simplifie et accélère le cycle d'itération des développeurs pour les développeurs qui travaillent principalement dans un domaine de fonctionnalités et souhaitent itérer uniquement sur ce domaine de fonctionnalités.

Le regroupement naturel d'une zone de fonctionnalités dans un APEX simplifie également le processus de création, de diffusion et de test des modifications pour cette zone de fonctionnalités. Par exemple, la réinstallation d'un APEX met automatiquement à jour toute bibliothèque groupée ou tous les fichiers de configuration inclus dans l'APEX.

Le regroupement d'une zone de fonctionnalités dans un APEX simplifie également le débogage ou la restauration lorsqu'un mauvais comportement du périphérique est observé. Par exemple, si la téléphonie fonctionne mal dans une nouvelle version, les développeurs peuvent essayer d'installer une ancienne implémentation de téléphonie APEX sur un appareil (sans avoir besoin de flasher une version complète) et voir si le bon comportement est restauré.

Exemple de flux de travail :

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

Exemples

Les bases

Consultez la page principale Format de fichier APEX pour obtenir des informations génériques sur APEX, notamment la configuration requise pour le périphérique, les détails du format de fichier et les étapes d'installation.

Dans Android.bp , la définition de la vendor: true fait d'un module APEX un APEX de fournisseur.

apex {
  ..
  vendor: true,
  ..
}

Binaires et bibliothèques partagées

Un APEX inclut des dépendances transitives à l’intérieur de la charge utile APEX, à moins qu’elles n’aient des interfaces stables.

Les interfaces natives stables pour les dépendances APEX du fournisseur incluent cc_library avec stubs , ndk_library ou llndk_library . Ces dépendances sont exclues du packaging et les dépendances sont enregistrées dans le manifeste APEX. Le manifeste est traité par linkerconfig afin que les dépendances natives externes soient disponibles au moment de l'exécution.

Contrairement aux APEX de la partition /system , les APEX du fournisseur sont généralement liés à une version spécifique du VNDK. Les bibliothèques VNDK garantissent la stabilité de l'ABI dans la version, nous pouvons donc traiter les bibliothèques VNDK comme stables et réduire la taille des APEX des fournisseurs en les excluant des APEX à l'aide de la propriété use_vndk_as_stable .

Dans l'extrait ci-dessous, l'APEX contiendra à la fois le binaire ( my_service ) et ses dépendances non stables (fichiers *.so ). Il ne contiendra pas de bibliothèques VNDK, même lorsque my_service est construit avec des bibliothèques VNDK comme libbase . Au lieu de cela, au moment de l'exécution, my_service utilisera libbase à partir des bibliothèques VNDK fournies par le système.

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

Dans l'extrait ci-dessous, l'APEX contiendra la bibliothèque partagée my_standalone_lib et toutes ses dépendances non stables (comme décrit ci-dessus).

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

Implémentations HAL

Pour définir une implémentation HAL, fournissez les binaires et bibliothèques correspondants dans un APEX de fournisseur similaire aux exemples suivants :

Pour encapsuler complètement l'implémentation de HAL, l'APEX doit également spécifier tous les fragments VINTF et scripts d'initialisation pertinents.

Fragments VINTF

Les fragments VINTF peuvent être servis à partir d'un APEX de fournisseur lorsque les fragments se trouvent dans etc/vintf de l'APEX.

Utilisez la propriété prebuilts pour intégrer les fragments VINTF dans l'APEX.

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

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

Scripts d'initialisation

Les APEX peuvent inclure des scripts d'initialisation de deux manières : (A) un fichier texte prédéfini dans la charge utile APEX, ou (B) un script d'initialisation standard dans /vendor/etc . Vous pouvez définir les deux pour le même APEX.

Script d'initialisation dans APEX :

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

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

Les scripts d'initialisation au sein des APEX ne peuvent avoir que des définitions service . Les scripts d'initialisation dans les APEX des fournisseurs peuvent également avoir des directives on <property> .

Soyez prudent lorsque vous utilisez on directives. Étant donné que les scripts d'initialisation dans les APEX sont analysés et exécutés après l'activation des APEX, certains événements ou propriétés ne peuvent pas être utilisés. Utilisez apex.all.ready=true pour déclencher des actions le plus tôt possible.

Micrologiciel

Exemple:

Intégrez le micrologiciel dans un APEX du fournisseur avec le type de module prebuilt_firmware , comme suit.

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

Les modules prebuilt_firmware sont installés dans le répertoire <apex name>/etc/firmware de l'APEX. ueventd analyse les répertoires /apex/*/etc/firmware pour trouver les modules du micrologiciel.

Les file_contexts de l'APEX doivent étiqueter correctement toutes les entrées de charge utile du micrologiciel pour garantir que ces fichiers sont accessibles par ueventd au moment de l'exécution ; généralement, l'étiquette vendor_file est suffisante. Par exemple:

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

Modules du noyau

Intégrez les modules du noyau dans un APEX d'un fournisseur en tant que modules prédéfinis, comme suit.

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

Les file_contexts de l'APEX doivent étiqueter correctement toutes les entrées de charge utile du module du noyau. Par exemple:

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

Les modules du noyau doivent être installés explicitement. L'exemple de script d'initialisation suivant dans la partition du fournisseur montre l'installation via insmod :

my_init.rc :

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

Superpositions de ressources d'exécution

Exemple:

Intégrez des superpositions de ressources d'exécution dans un APEX de fournisseur à l'aide de la propriété rros .

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


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

Autres fichiers de configuration

Les APEX du fournisseur prennent en charge divers autres fichiers de configuration généralement trouvés sur la partition du fournisseur en tant que fichiers prédéfinis dans les APEX du fournisseur, et d'autres sont ajoutés.

Exemples:

Fonctionnalités de développement supplémentaires

Sélection APEX au démarrage

Exemple:

Les développeurs peuvent également installer plusieurs versions d'APEX de fournisseurs partageant le même nom et la même clé APEX, puis choisir quelle version est activée lors de chaque démarrage à l'aide de sysprops persistants. Pour certains cas d'utilisation des développeurs, cela peut être plus simple que d'installer une nouvelle copie d'APEX à l'aide adb install .

Exemples de cas d'utilisation :

  • Installez 3 versions du fournisseur wifi HAL APEX : les équipes d'assurance qualité peuvent exécuter des tests manuels ou automatisés en utilisant une version, puis redémarrer dans une autre version et réexécuter les tests, puis comparer les résultats finaux.
  • Installez 2 versions de la caméra HAL du fournisseur APEX, actuelle et expérimentale : les Dogfooders peuvent utiliser la version expérimentale sans télécharger ni installer de fichier supplémentaire, afin qu'ils puissent facilement revenir en arrière.

Lors du démarrage, apexd recherche les sysprops suivant un format spécifique pour activer la bonne version d'APEX.

Les formats attendus pour la clé de propriété sont :

  • Configuration de démarrage
    • Utilisé pour définir la valeur par défaut, dans BoardConfig.mk .
    • androidboot.vendor.apex.<apex name>
  • Sysprop persistant
    • Utilisé pour modifier la valeur par défaut, définie sur un périphérique déjà démarré.
    • Remplace la valeur bootconfig si elle est présente.
    • persist.vendor.apex.<apex name>

La valeur de la propriété doit être le nom de fichier de l'APEX qui doit être activé.

// 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 version par défaut doit également être configurée à l'aide de bootconfig dans 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

Une fois l'appareil démarré, modifiez la version activée en définissant le sysprop persistant :

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

Si le périphérique prend en charge la mise à jour de bootconfig après le flashage (par exemple via les commandes fastboot oem ), la modification de la propriété bootconfig pour l'APEX multi-installé modifie également la version activée au démarrage.

Pour les périphériques de référence virtuelle basés sur Cuttlefish , vous pouvez utiliser la commande --extra_bootconfig_args pour définir la propriété bootconfig directement lors du lancement. Par exemple:

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