RenderScript

RenderScript est un framework permettant d'exécuter des tâches gourmandes en calcul à hautes performances sur Android. Il est conçu pour être utilisé avec le calcul parallèle aux données, bien que les charges de travail en série puissent également en bénéficier. Le runtime RenderScript parallélise le travail sur les processeurs disponibles sur un appareil, tels que les processeurs multicœurs et les GPU, permettant aux développeurs de se concentrer sur l'expression des algorithmes plutôt que sur la planification du travail. RenderScript est particulièrement utile pour les applications effectuant du traitement d'images, de la photographie informatique ou de la vision par ordinateur.

Les appareils exécutant Android 8.0 et versions ultérieures utilisent le framework RenderScript et les HAL des fournisseurs suivants :

Figure 1. Code du fournisseur lié aux bibliothèques internes

Les différences par rapport à RenderScript dans Android 7.x et versions antérieures incluent :

  • Deux instances de bibliothèques internes RenderScript dans un processus. Un ensemble est destiné au chemin de secours du processeur et provient directement de /system/lib ; l'autre ensemble concerne le chemin du GPU et provient de /system/lib/vndk-sp .
  • Les bibliothèques internes RS dans /system/lib sont construites dans le cadre de la plate-forme et sont mises à jour à mesure que system.img est mis à niveau. Cependant, les bibliothèques dans /system/lib/vndk-sp sont créées pour le fournisseur et ne sont pas mises à jour lorsque system.img est mis à niveau (bien qu'elles puissent être mises à jour pour un correctif de sécurité, leur ABI reste le même).
  • Le code du fournisseur (RS HAL, le pilote RS et le bcc plugin ) sont liés aux bibliothèques internes RenderScript situées dans /system/lib/vndk-sp . Ils ne peuvent pas établir de lien avec les bibliothèques de /system/lib car les bibliothèques de ce répertoire sont construites pour la plate-forme et peuvent donc ne pas être compatibles avec le code du fournisseur (c'est-à-dire que les symboles peuvent être supprimés). Cela rendrait impossible une OTA uniquement basée sur un cadre.

Conception

Les sections suivantes détaillent la conception de RenderScript dans Android 8.0 et versions ultérieures.

Bibliothèques RenderScript disponibles pour les fournisseurs

Cette section répertorie les bibliothèques RenderScript (appelées Vendor NDK pour Same-Process HAL ou VNDK-SP) qui sont disponibles pour le code du fournisseur et qui peuvent être liées. Il détaille également des bibliothèques supplémentaires qui ne sont pas liées à RenderScript mais qui sont également fournies au code du fournisseur.

Bien que la liste de bibliothèques suivante puisse différer d'une version d'Android à l'autre, elle est immuable pour une version d'Android spécifique ; pour une liste à jour des bibliothèques disponibles, reportez-vous à /system/etc/ld.config.txt .

Bibliothèques RenderScript Bibliothèques non RenderScript
  • android.hardware.graphics.renderscript@1.0.so
  • libRS_internal.so
  • libRSCpuRef.so
  • libblas.so
  • libbcinfo.so
  • libcompiler_rt.so
  • libRSDriver.so
  • libc.so
  • libm.so
  • libdl.so
  • libstdc++.so
  • liblog.so
  • libnativewindow.so
  • libsync.so
  • libvndksupport.so
  • libbase.so
  • libc++.so
  • libcutils.so
  • libutils.so
  • libhardware.so
  • libhidlbase.so
  • libhidltransport.so
  • libhwbinder.so
  • liblzma.so
  • libz.so
  • libEGL.so
  • libGLESv1_CM.so
  • libGLESv2.so

Configuration de l'espace de noms de l'éditeur de liens

La restriction de liaison qui empêche les bibliothèques ne figurant pas dans VNDK-SP d'être utilisées par le code du fournisseur est appliquée au moment de l'exécution à l'aide de l'espace de noms de l'éditeur de liens. (Pour plus de détails, reportez-vous à la présentation VNDK Design .)

Sur un appareil exécutant Android 8.0 et versions ultérieures, tous les HAL de même processus (SP-HAL), à l'exception de RenderScript, sont chargés dans l'espace de noms de l'éditeur de liens sphal . RenderScript est chargé dans l'espace de noms spécifique à RenderScript rs , un emplacement qui permet une application légèrement plus souple pour les bibliothèques RenderScript. Étant donné que l'implémentation RS doit charger le bitcode compilé, /data/*/*.so est ajouté au chemin de l'espace de noms rs (les autres SP-HAL ne sont pas autorisés à charger des bibliothèques à partir de la partition de données).

De plus, l'espace de noms rs autorise plus de bibliothèques que celles fournies par les autres espaces de noms. libmediandk.so et libft2.so sont exposés à l'espace de noms rs car libRS_internal.so a une dépendance interne envers ces bibliothèques.

Figure 2. Configuration de l'espace de noms pour l'éditeur de liens

Chargement des pilotes

Chemin de secours du processeur

En fonction de l'existence du bit RS_CONTEXT_LOW_LATENCY lors de la création d'un contexte RS, soit le chemin CPU soit le chemin GPU est sélectionné. Lorsque le chemin CPU est sélectionné, libRS_internal.so (l'implémentation principale du framework RS) est directement dlopen de l'espace de noms de l'éditeur de liens par défaut où la version de plate-forme des bibliothèques RS est fournie.

L'implémentation RS HAL du fournisseur n'est pas utilisée du tout lorsque le chemin de secours du processeur est emprunté et qu'un objet RsContext est créé avec null mVendorDriverName . libRSDriver.so est (par défaut) dlopen et la bibliothèque du pilote est chargée à partir de l'espace de noms default car l'appelant ( libRS_internal.so ) est également chargé dans l'espace de noms default .

Figure 4. Chemin de secours du processeur

Chemin du GPU

Pour le chemin GPU, libRS_internal.so est chargé différemment. Tout d'abord, libRS.so utilise android.hardware.renderscript@1.0.so (et son sous-jacent libhidltransport.so ) pour charger android.hardware.renderscript@1.0-impl.so (une implémentation fournisseur de RS HAL) dans un espace de noms d'éditeur de liens différent appelé sphal . Le RS HAL dlopen ensuite libRS_internal.so dans un autre espace de noms de l'éditeur de liens appelé rs .

Les fournisseurs peuvent fournir leur propre pilote RS en définissant l'indicateur de temps de construction OVERRIDE_RS_DRIVER , qui est intégré dans l'implémentation RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp ). Ce nom de pilote est ensuite dlopen pour le contexte RS pour le chemin GPU.

La création de l'objet RsContext est déléguée à l'implémentation RS HAL. Le HAL rappelle le framework RS en utilisant la fonction rsContextCreateVendor() avec le nom du pilote à utiliser comme argument. Le framework RS charge ensuite le pilote spécifié lorsque le RsContext est initialisé. Dans ce cas, la bibliothèque de pilotes est chargée dans l'espace de noms rs car l'objet RsContext est créé dans l'espace de noms rs et /vendor/lib se trouve dans le chemin de recherche de l'espace de noms.

Figure 5. Chemin de secours du GPU

Lors de la transition de l'espace de noms default à l'espace de noms sphal , libhidltransport.so utilise la fonction android_load_sphal_library() pour ordonner explicitement à l'éditeur de liens dynamique de charger la bibliothèque -impl.so à partir de l'espace de noms sphal .

Lors de la transition de l'espace de noms sphal vers l'espace de noms rs , le chargement se fait indirectement par la ligne suivante dans /system/etc/ld.config.txt :

namespace.sphal.link.rs.shared_libs = libRS_internal.so

Cette ligne spécifie que l'éditeur de liens dynamique doit charger libRS_internal.so à partir de l'espace de noms rs lorsque la bibliothèque ne peut pas être trouvée/chargée à partir de l'espace de noms sphal (ce qui est toujours le cas car l'espace de noms sphal ne recherche pas /system/lib/vndk-splibRS_internal.so réside). Avec cette configuration, un simple appel dlopen() à libRS_internal.so suffit pour effectuer la transition d'espace de noms.

Chargement du plugin Cci

bcc plugin est une bibliothèque fournie par le fournisseur chargée dans le compilateur bcc . Parce que bcc est un processus système dans le répertoire /system/bin , la bibliothèque bcc plugin peut être considérée comme un SP-HAL (c'est-à-dire un HAL du fournisseur qui peut être directement chargé dans le processus système sans être lié). En tant que SP-HAL, la bibliothèque bcc-plugin :

  • Impossible de créer un lien avec des bibliothèques uniquement framework telles que libLLVM.so .
  • Peut être lié uniquement aux bibliothèques VNDK-SP disponibles pour le fournisseur.

Cette restriction est appliquée en chargeant le bcc plugin dans l'espace de noms sphal à l'aide de la fonction android_sphal_load_library() . Dans les versions précédentes d'Android, le nom du plugin était spécifié à l'aide de l'option -load et la bibliothèque était chargée à l'aide du simple dlopen() par libLLVM.so . Sous Android 8.0 et versions ultérieures, cela est spécifié dans l'option -plugin et la bibliothèque est directement chargée par le bcc lui-même. Cette option active un chemin non spécifique à Android vers le projet open source LLVM.

Figure 6. Chargement du plugin bcc, Android 7.x et versions antérieures


Figure 7. Chargement du plugin bcc, Android 8.0 et supérieur

Chemins de recherche pour ld.mc

Lors de l'exécution ld.mc , certaines bibliothèques d'exécution RS sont fournies comme entrées à l'éditeur de liens. Le bitcode RS de l'application est lié aux bibliothèques d'exécution et lorsque le bitcode converti est chargé dans un processus d'application, les bibliothèques d'exécution sont à nouveau liées dynamiquement à partir du bitcode converti.

Les bibliothèques d'exécution incluent :

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • Pilote RS (soit libRSDriver.so ou OVERRIDE_RS_DRIVER )

Lors du chargement du bitcode compilé dans le processus d'application, fournissez exactement la même bibliothèque que celle utilisée par ld.mc . Sinon, le bitcode compilé risque de ne pas trouver un symbole qui était disponible lors de sa liaison.

Pour ce faire, le framework RS utilise différents chemins de recherche pour les bibliothèques d'exécution lors de l'exécution ld.mc , selon que le framework RS lui-même est chargé depuis /system/lib ou depuis /system/lib/vndk-sp . Cela peut être déterminé en lisant l'adresse d'un symbole arbitraire d'une bibliothèque de framework RS et en utilisant dladdr() pour obtenir le chemin du fichier mappé à l'adresse.

Politique SELinux

En raison des changements de politique SELinux dans Android 8.0 et versions ultérieures, vous devez suivre des règles spécifiques (appliquées via neverallows ) lors de l'étiquetage de fichiers supplémentaires dans la partition vendor :

  • vendor_file doit être l'étiquette par défaut pour tous les fichiers de la partition vendor . La politique de la plate-forme l’exige pour accéder aux implémentations passthrough HAL.
  • Tous les nouveaux exec_types ajoutés dans la partition vendor via SEPolicy du fournisseur doivent avoir l'attribut vendor_file_type . Ceci est appliqué via neverallows .
  • Pour éviter les conflits avec les futures mises à jour de la plate-forme/du framework, évitez d'étiqueter les fichiers autres que exec_types dans la partition vendor .
  • Toutes les dépendances de bibliothèque pour les HAL de même processus identifiés par AOSP doivent être étiquetées comme same_process_hal_file .

Pour plus de détails sur la politique SELinux, consultez Linux à sécurité améliorée sous Android .

Compatibilité ABI pour le bitcode

Si aucune nouvelle API n'est ajoutée, ce qui signifie qu'il n'y a pas de changement de version HAL, les frameworks RS continueront à utiliser le pilote GPU existant (HAL 1.0).

Pour les modifications mineures de HAL (HAL 1.1) n'affectant pas le bitcode, les frameworks doivent recourir au CPU pour ces API nouvellement ajoutées et continuer à utiliser le pilote GPU (HAL 1.0) ailleurs.

Pour les modifications majeures de HAL (HAL 2.0) affectant la compilation/liaison de bitcode, les frameworks RS doivent choisir de ne pas charger les pilotes GPU fournis par le fournisseur et d'utiliser à la place le chemin CPU ou Vulkan pour l'accélération.

La consommation du bitcode RenderScript se déroule en trois étapes :

Scène Détails
Compiler
  • Le bitcode d'entrée (.bc) pour bcc doit être au format de bitcode LLVM 3.2 et bcc doit être rétrocompatible avec les applications (héritées) existantes.
  • Cependant, les métadonnées dans .bc pourraient changer (il pourrait y avoir de nouvelles fonctions d'exécution, par exemple des setters d'allocation ∓ getters, des fonctions mathématiques, etc.). Une partie des fonctions d'exécution réside dans libclcore.bc , une partie d'entre elles réside dans LibRSDriver ou l'équivalent d'un fournisseur.
  • Les nouvelles fonctions d'exécution ou les modifications importantes des métadonnées nécessitent une incrémentation du niveau de l'API bitcode. Étant donné que les pilotes des fournisseurs ne pourront pas l'utiliser, la version HAL doit également être incrémentée.
  • Les fournisseurs peuvent avoir leurs propres compilateurs, mais les conclusions/exigences de bcc s'appliquent également à ces compilateurs.
Lien
  • Le .o compilé sera lié au pilote du fournisseur, par exemple libRSDriver_foo.so et libcompiler_rt.so . Le chemin du CPU sera lié à libRSDriver.so .
  • Si le .o nécessite une nouvelle API d'exécution de libRSDriver_foo , le pilote du fournisseur doit être mis à jour pour la prendre en charge.
  • Certains fournisseurs peuvent avoir leurs propres éditeurs de liens, mais l'argument en faveur de ld.mc s'applique également à eux.
Charger
  • libRSCpuRef charge l'objet partagé. Si des modifications sont apportées à cette interface, une modification de la version HAL est nécessaire.
  • Les fournisseurs s'appuieraient soit sur libRSCpuRef pour charger l'objet partagé, soit implémenteraient le leur.

En plus du HAL, les API d'exécution et les symboles exportés sont également des interfaces. Aucune des deux interfaces n'a changé depuis Android 7.0 (API 24) et il n'est pas prévu dans l'immédiat de la modifier dans Android 8.0 et au-delà. Cependant, si l'interface change, la version HAL augmentera également.

Implémentations des fournisseurs

Android 8.0 et versions ultérieures nécessitent certaines modifications du pilote GPU pour que le pilote GPU fonctionne correctement.

Modules pilotes

  • Les modules pilotes ne doivent dépendre d'aucune bibliothèque système qui ne figure pas dans la liste .
  • Le pilote doit fournir son propre android.hardware.renderscript@1.0-impl_{NAME} , ou déclarer l'implémentation par défaut android.hardware.renderscript@1.0-impl comme dépendance.
  • L'implémentation du processeur libRSDriver.so est un bon exemple de la façon de supprimer les dépendances non VNDK-SP.

Compilateur de codes binaires

Vous pouvez compiler le bitcode RenderScript pour le pilote du fournisseur de deux manières :

  1. Appelez le compilateur RenderScript spécifique au fournisseur dans /vendor/bin/ (méthode préférée de compilation GPU). Semblable à d'autres modules de pilotes, le binaire du compilateur du fournisseur ne peut dépendre d'aucune bibliothèque système qui ne figure pas dans la liste des bibliothèques RenderScript disponibles pour les fournisseurs .
  2. Appelez le système bcc : /system/bin/bcc avec un bcc plugin fourni par le fournisseur ; ce plugin ne peut dépendre d'aucune bibliothèque système qui ne figure pas dans la liste des bibliothèques RenderScript disponibles pour les fournisseurs .

Si le bcc plugin du fournisseur doit interférer avec la compilation du processeur et que sa dépendance sur libLLVM.so ne peut pas être facilement supprimée, le fournisseur doit copier bcc (et toutes les dépendances non LL-NDK, y compris libLLVM.so , libbcc.so ) dans /vendor .

De plus, les fournisseurs doivent apporter les modifications suivantes :

Figure 8. Modifications apportées au pilote du fournisseur
  1. Copiez libclcore.bc sur la partition /vendor . Cela garantit que libclcore.bc , libLLVM.so et libbcc.so sont synchronisés.
  2. Modifiez le chemin d'accès à l'exécutable bcc en définissant RsdCpuScriptImpl::BCC_EXE_PATH à partir de l'implémentation RS HAL.

Politique SELinux

La politique SELinux affecte à la fois les exécutables du pilote et du compilateur. Tous les modules de pilote doivent être étiquetés same_process_hal_file dans le file_contexts du périphérique. Par exemple:

/vendor/lib(64)?/libRSDriver_EXAMPLE\.so     u:object_r:same_process_hal_file:s0

L'exécutable du compilateur doit pouvoir être invoqué par un processus d'application, tout comme la copie du fournisseur de bcc ( /vendor/bin/bcc ). Par exemple:

device/vendor_foo/device_bar/sepolicy/file_contexts:
/vendor/bin/bcc                    u:object_r:same_process_hal_file:s0

Appareils hérités

Les appareils existants sont ceux qui satisfont aux conditions suivantes :

  1. PRODUCT_SHIPPING_API_LEVEL est inférieur à 26.
  2. PRODUCT_FULL_TREBLE_OVERRIDE n'est pas défini.

Pour les appareils existants, les restrictions ne sont pas appliquées lors de la mise à niveau vers Android 8.0 et versions ultérieures, ce qui signifie que les pilotes peuvent continuer à être liés aux bibliothèques dans /system/lib[64] . Cependant, en raison du changement d'architecture lié à OVERRIDE_RS_DRIVER , android.hardware.renderscript@1.0-impl doit être installé sur la partition /vendor ; à défaut de le faire, le temps d'exécution de RenderScript se replie sur le chemin du processeur.

Pour plus d'informations sur la motivation de l'abandon de Renderscript, consultez le blog des développeurs Android : Android GPU Compute Going Forward . Les informations sur les ressources pour cette dépréciation incluent les éléments suivants :