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 indépendamment des composants tels que des services et des bibliothèques natives, 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 le /vendor. partition et activée au moment de l'exécution par apexd, comme les apex dans d'autres des 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 de manière indépendante APEX, les fabricants d’appareils peuvent facilement choisir les besoins spécifiques les implémentations des fournisseurs voulaient 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 le Wi-Fi AOSP l'apex d'implémentation Bluetooth pour le SoC, et un OEM personnalisé APEX pour l'implémentation des services de téléphonie.

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 tout (y compris les fichiers de configuration et les bibliothèques supplémentaires) dans les APEX avec des interfaces clairement définies à tout point de 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 qui travaillent principalement dans un seul domaine de fonctionnalités et ne souhaitent itérer que sur ce domaine.

Le regroupement naturel d'une zone de caractéristiques dans un apex simplifie également le processus. pour créer, transmettre et tester des modifications pour ce domaine. Par exemple : la réinstallation d’un APEX met automatiquement à jour tout fichier de bibliothèque ou fichier de configuration groupé de 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 ne fonctionne pas bien un nouveau build, les développeurs peuvent alors essayer d'installer une ancienne implémenter APEX sur un appareil (sans qu'il soit nécessaire de flasher un build complet) et pour voir si le bon comportement est rétabli.

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 APEX File Format (Format de fichier apex) pour trouver les valeurs génériques. y compris la configuration requise pour l'appareil, les détails sur le format des fichiers et la procédure d'installation.

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

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 stubs et LLNDK. Ces dépendances sont exclues de le packaging et les dépendances sont enregistrés dans le fichier manifeste APEX. Le fichier manifeste est traités 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 son dépendances non stables (fichiers *.so).

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

Dans l'extrait de code suivant, l'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 être plus volumineux, 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 liées de manière statique aux 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 de fournisseur, comme dans les exemples suivants:

Pour encapsuler entièrement l'implémentation HAL, l'apex doit également spécifier les fragments VINTF et les 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 une couche HAL passthrough.

Scripts d'initialisation

Les apex peuvent inclure des scripts d'initialisation de deux manières: (A) dans un fichier texte prédéfini charge utile APEX, ou (B) un script d'initialisation standard dans /vendor/etc. Vous pouvez définir à la fois 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 comporter des définitions service et des directives on <property or event>.

Assurez-vous qu'une définition service pointe un binaire dans le même Apex. Par exemple, l'apex com.android.foo 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ées. 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 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 de micrologiciels.

Le file_contexts de l'apex doit étiqueter toutes les entrées de charge utile du micrologiciel correctement pour s'assurer que ces fichiers sont accessibles par ueventd lors de l'exécution. l'étiquette vendor_file suffit généralement. 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 toutes les entrées de charge utile de module du noyau correctement. Exemple :

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

Les modules kernel 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 de fournisseur prennent en charge divers autres fichiers de configuration généralement disponibles sur le fournisseur partition en tant que composants prédéfinis dans les APR des fournisseurs, et d'autres sont en cours d'ajout.

Exemples :

APEX de fournisseurs d'amorçage

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 init. 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 d’amorçage peuvent être activé uniquement à partir de l'emplacement prédéfini comme /vendor/apex, et non depuis /data/apex

Propriétés système

Il s'agit des propriétés système lues par le framework pour permettre au fournisseur APERÇU:

  • input_device.config_file.apex=<apex name> : lorsque ce paramètre 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 premières HAL, assurez-vous que l'apex Amorcer APEX et configurer cet espace de noms de l'éditeur de liens 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 de l'apex au démarrage

Exemple :

Les développeurs peuvent également installer plusieurs versions d'APEX de fournisseurs qui partagent le le même nom et la même clé d'apex, puis de choisir la version à activer lors de chaque à l'aide de Sysprops persistants. Pour certains cas d'utilisation des développeurs, 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 HAL Wi-Fi : les équipes de contrôle qualité peuvent exécuter des tests manuels ou automatisés à l'aide d'une version, puis redémarrer dans une autre version et réexécuter les tests, puis comparer les résultats finaux.
  • Installez deux versions du fournisseur HAL de la caméra APEX, current et expérimental:les dogfoodeurs peuvent utiliser la version expérimentale sans télécharger et installer un fichier supplémentaire, afin de pouvoir facilement revenir en arrière.

Lors du démarrage, apexd recherche 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>
  • Système persistant "sysprop"
    • 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 la propriété bootconfig directement lors du lancement. Exemple :

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