Renderscript

RenderScript est un framework permettant d'exécuter des tâches intensives 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. L'environnement d'exécution RenderScript met en parallèle le travail entre 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 le traitement d'images, la photographie informatique ou la vision par ordinateur.

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

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

Les différences avec RenderScript dans Android 7.x et les versions antérieures incluent :

  • Deux instances de bibliothèques internes RenderScript dans un processus. Un ensemble est pour le chemin de secours du processeur et provient directement de /system/lib ; l'autre ensemble est pour le chemin 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 lorsque system.img est mis à niveau. Cependant, les bibliothèques dans /system/lib/vndk-sp sont conçues 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 ) est lié aux bibliothèques internes RenderScript situées dans /system/lib/vndk-sp . Ils ne peuvent pas être liés aux bibliothèques dans /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 un OTA uniquement structuré.

Concevoir

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 (connues sous le nom de Vendor NDK pour Same-Process HALs ou VNDK-SP) qui sont disponibles pour le code 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 spécifique d'Android ; 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 non présentes 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, toutes les HAL de même processus (SP-HAL) , à l'exception de RenderScript, sont chargées 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 à ces bibliothèques.

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

Chargement des pilotes

Chemin de secours du processeur

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

L'implémentation RS HAL du fournisseur n'est pas du tout utilisée lorsque le chemin de secours du processeur est emprunté et 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 processeur graphique

Pour le chemin GPU, le 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 de liens différent appelé sphal . La HAL RS libRS_internal.so dlopen 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 du chemin GPU.

La création de l'objet RsContext est déléguée à l'implémentation RS HAL. 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éé à l'intérieur de 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 GPU

Lors de la transition de l'espace de noms default vers 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 de l'espace de noms.

Chargement du plug-in bcc

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 du bcc plugin peut être considérée comme une SP-HAL (c'est-à-dire une HAL fournisseur qui peut être directement chargée dans le processus système sans être liée). En tant que SP-HAL, la bibliothèque bcc-plugin :

  • Impossible d'établir un lien avec les bibliothèques de framework uniquement 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 plug-in était spécifié à l'aide de l'option -load et la bibliothèque était chargée à l'aide du simple dlopen() par libLLVM.so . Dans Android 8.0 et supérieur, 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 d'accès non spécifique à Android vers le projet LLVM open source.

Figure 6. Chargement du plug-in 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 en tant qu'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 soit OVERRIDE_RS_DRIVER )

Lors du chargement du bitcode compilé dans le processus de l'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 la 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 du vendor . La politique de la plate-forme l'exige pour accéder aux implémentations HAL de relais.
  • Tous les nouveaux exec_types ajoutés dans la partition vendor via SEPolicy fournisseur doivent avoir l'attribut vendor_file_type . Ceci est appliqué par neverallows .
  • Pour éviter les conflits avec les futures mises à jour de plate-forme/framework, évitez d'étiqueter des fichiers autres que exec_types dans la partition du vendor .
  • Toutes les dépendances de bibliothèque pour les mêmes HAL de processus identifiés par AOSP doivent être étiquetées comme same_process_hal_file .

Pour plus de détails sur la politique SELinux, consultez Security-Enhanced Linux in 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 se rabattre sur le processeur 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/la 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 CPU ou le chemin Vulkan pour l'accélération.

L'utilisation du bitcode RenderScript se déroule en trois étapes :

Étape Des 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, les setters d'allocation ∓ getters, les fonctions mathématiques, etc.). Une partie des fonctions d'exécution vit dans libclcore.bc , une autre vit dans LibRSDriver ou un fournisseur équivalent.
  • Les nouvelles fonctions d'exécution ou les changements de méta-données avec rupture 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 pour 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 CPU sera lié à libRSDriver.so .
  • Si le .o nécessite une nouvelle API d'exécution à partir de libRSDriver_foo , le pilote du fournisseur doit être mis à jour pour le prendre en charge.
  • Certains fournisseurs peuvent avoir leurs propres éditeurs de liens, mais l'argument de ld.mc s'applique également à eux.
Charge
  • libRSCpuRef charge l'objet partagé. S'il y a des changements à cette interface, un changement de version HAL est nécessaire.
  • Les fournisseurs s'appuieraient soit sur libRSCpuRef pour charger l'objet partagé, soit implémenteraient le leur.

En plus de 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 de la modifier dans Android 8.0 et au-delà. Cependant, si l'interface change, la version HAL sera également incrémentée.

Implémentations du fournisseur

Android 8.0 et supérieur nécessite certaines modifications du pilote GPU pour que le pilote GPU fonctionne correctement.

Modules pilotes

  • Les modules de pilote 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 sa dépendance.
  • Implémentation du processeur libRSDriver.so est un bon exemple de suppression des dépendances non-VNDK-SP.

Compilateur de bitcode

Vous pouvez compiler le bitcode RenderScript pour le pilote 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 pilote, le binaire du compilateur du fournisseur ne peut pas dépendre d'une bibliothèque système qui ne figure pas dans la liste des bibliothèques RenderScript disponibles pour les fournisseurs .
  2. Invoquez le système bcc : /system/bin/bcc avec un bcc plugin fourni par le fournisseur ; ce plug-in 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 à 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 dans la partition /vendor . Cela garantit 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 le pilote et les exécutables du compilateur. Tous les modules de pilote doivent être étiquetés same_process_hal_file dans les 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 appelé 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 hérités 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 hérités, 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 ; si vous ne le faites pas, le runtime de RenderScript se replie sur le chemin du processeur.

Pour plus d'informations sur les raisons 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 :