APRÈS DU Fournisseur

Vous pouvez utiliser le format de fichier APEX pour empaqueter et installer des modules d'OS Android de niveau inférieur. Il permet de créer et d'installer de manière indépendante des composants tels que des bibliothèques et des services 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 compilation 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 le regroupement et la modularisation naturels des implémentations de fonctionnalités sur les images du fournisseur.

Lorsque les images des fournisseurs sont créées en combinant des apex de fournisseurs indépendants, les fabricants d'appareils peuvent facilement sélectionner les implémentations de fournisseurs spécifiques souhaitées sur leur appareil. Les fabricants peuvent même créer un nouvel APEX de fournisseur 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 APEX du Wi-Fi AOSP, l'implémentation APEX du Bluetooth du SoC et une implémentation APEX de téléphonie OEM personnalisée.

Sans APEX du fournisseur, une implémentation avec autant de dépendances entre les composants du fournisseur 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 moment de la communication entre les fonctionnalités, les différents composants deviennent interchangeables.

Itération du développeur

Les APEX du fournisseur aident les développeurs à itérer plus rapidement lors du développement de modules de fournisseurs en regroupant l'implémentation complète d'une fonctionnalité, comme le HAL Wi-Fi, dans un APEX du fournisseur. Les développeurs peuvent ensuite créer et transférer individuellement l'APEX du fournisseur pour tester les modifications, au lieu de recréer l'image complète 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é et qui souhaitent effectuer une itération uniquement sur ce domaine.

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

Le regroupement d'une zone de fonctionnalité dans un APEX simplifie également le débogage ou le rétablissement lorsqu'un mauvais comportement de l'appareil 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 à flasher un build complet) et voir si le bon comportement est restauré.

Exemple de workflow :

# 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

Principes de base

Consultez la page principale sur le format de fichier APEX pour obtenir des informations génériques sur APEX, y compris les exigences concernant les appareils, les détails sur le format de fichier et les étapes d'installation.

Dans Android.bp, définir la propriété vendor: true fait d'un module APEX un APEX du fournisseur.

apex {
  ..
  vendor: true,
  ..
}

Binaires et bibliothèques partagées

Un APEX inclut des dépendances transitives dans la charge utile APEX, sauf s'il dispose d'interfaces stables.

Les interfaces natives stables pour les dépendances APEX des fournisseurs incluent cc_library avec les bibliothèques stubs et LLNDK. Ces dépendances sont exclues du packaging et sont enregistrées dans le fichier manifeste APEX. Le fichier manifeste est traité par linkerconfig afin que les dépendances natives externes soient disponibles au moment de l'exécution.

Dans l'extrait de code suivant, APEX contient à la fois le binaire (my_service) et ses dépendances non stables (fichiers *.so).

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

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

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

Réduire APEX

APEX peut augmenter, car il regroupe les dépendances instables. Nous vous recommandons d'utiliser l'association statique. Les bibliothèques courantes telles que libc++.so et libbase.so peuvent être associées de manière statique à des binaires HAL. Une autre option consiste à créer une dépendance pour fournir une interface stable. La dépendance ne sera pas regroupée dans l'apex.

Implémentations HAL

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

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

Fragments VINTF

Les fragments VINTF peuvent être diffusés à partir d'un APEX du 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",
}

API de requête

Lorsque des fragments VINTF sont ajoutés à APEX, utilisez les API libbinder_ndk pour obtenir les mappages des interfaces HAL et des noms APEX.

  • AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default") : true si l'instance HAL est définie dans APEX.
  • AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...) : obtient le nom APEX qui définit l'instance HAL.
  • AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...) : utilisez-le pour ouvrir un HAL de passthrough.

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 dans les apex de fournisseurs peuvent avoir des définitions service et des directives on <property or event>.

Assurez-vous qu'une définition service pointe vers un binaire dans le même APEX. Par exemple, com.android.foo APEX peut définir un service nommé foo-service.

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

Soyez prudent lorsque vous utilisez des directives on. É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 dès que possible. Les APEX d'amorçage peuvent utiliser on init, mais pas on early-init.

Micrologiciel

Exemple :

Intégrez le micrologiciel dans un APEX de 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 de micrologiciels.

Le file_contexts de l'apex doit étiqueter correctement toutes les entrées de charge utile du micrologiciel pour s'assurer que ces fichiers sont accessibles par ueventd au moment de l'exécution. Le libellé vendor_file est généralement suffisant. Exemple :

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

Modules du noyau

Intégrez les modules du noyau dans un système APEX de 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
  ..
}

Le file_contexts de l'APEX doit étiqueter correctement toutes les entrées de charge utile du kernel module. 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 précompilés dans les APEX du fournisseur. D'autres sont en cours d'ajout.

Exemples:

Amorçage des fournisseurs

Certains services HAL tels que keymint doivent être disponibles avant l'activation des APEX. Ces HAL définissent généralement early_hal dans leur définition de service dans le script d'initialisation. Un autre exemple est la classe animation, qui est généralement démarrée avant l'événement post-fs-data. Lorsqu'un tel service HAL précoce est empaqueté dans l'APEX du fournisseur, définissez l'apex sur "vendorBootstrap": true dans son fichier manifeste APEX afin qu'il puisse être activé plus tôt. Notez que les APEX de démarrage ne peuvent être activés qu'à partir de l'emplacement prédéfini, comme /vendor/apex, et non à partir de /data/apex.

Propriétés système

Voici les propriétés système que le framework lit pour prendre en charge les APEX du fournisseur :

  • input_device.config_file.apex=<apex name> : lorsqu'il est défini, les fichiers de configuration d'entrée (*.idc, *.kl et *.kcm) sont recherchés à partir du répertoire /etc/usr de l'apex.
  • ro.vulkan.apex=<apex name> : lorsque cette valeur est définie, le pilote Vulkan est chargé à partir de l'APEX. Étant donné que le pilote Vulkan est utilisé par les premiers HAL, définissez l'APEX sur APEX de démarrage et configurez ce nom d'espace de nommage du linker comme visible.

Définissez les propriétés système dans les scripts d'initialisation à l'aide de la commande setprop.

Fonctionnalités de développement supplémentaires

Sélection d'APEX au démarrage

Exemple :

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

Exemples de cas d'utilisation :

  • Installez trois versions de l'APEX du fournisseur de HAL Wi-Fi:les équipes de contrôle qualité peuvent effectuer des tests manuels ou automatisés à l'aide d'une version, puis redémarrer dans une autre version et exécuter à nouveau les tests, puis comparer les résultats finaux.
  • Installez deux versions du fournisseur HAL de la caméra APEX, actuelle et expérimentale:les dogfoodeurs peuvent utiliser la version expérimentale sans télécharger ni installer de fichier supplémentaire, ce qui leur permet de revenir facilement à la version précédente.

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

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

  • Bootconfig
    • Permet de définir la valeur par défaut, dans BoardConfig.mk.
    • androidboot.vendor.apex.<apex name>
  • Propriété système persistante
    • Permet de modifier la valeur par défaut définie sur un appareil déjà démarré.
    • Remplace la valeur de bootconfig, le cas échéant.
    • persist.vendor.apex.<apex name>

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

// 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 la propriété système persistante :

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

Si l'appareil prend en charge la mise à jour de bootconfig après le flashage (par exemple, via des 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 appareils de référence virtuels basés sur Cuttlefish, vous pouvez utiliser la commande --extra_bootconfig_args pour définir directement la propriété bootconfig lors du lancement. Exemple :

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