RenderScript est un framework qui permet d'exécuter des tâches nécessitant beaucoup de ressources de calcul sur Android. Il est conçu pour être utilisé avec le calcul parallèle des données, même si les charges de travail en série peuvent également en bénéficier. L'environnement d'exécution RenderScript exécute les tâches en parallèle sur les processeurs disponibles sur l'appareil tels que les GPU et les processeurs multicœurs, ce qui permet aux développeurs de se concentrer sur l'expression d'algorithmes plutôt que sur la planification des tâches. RenderScript est particulièrement utile pour les applications de traitement d'images, de photographie computationnelle ou de vision par ordinateur.
Les appareils équipés d'Android 8.0 ou version ultérieure utilisent le framework RenderScript et les HAL du fournisseur suivants:
Figure 1 : Code fournisseur redirigeant vers les bibliothèques internes.
Les différences par rapport à RenderScript sur Android 7.x et versions antérieures incluent les suivantes:
- Deux instances de bibliothèques internes RenderScript dans un processus. L'un est destiné au chemin d'accès de remplacement du processeur et provient directement de
/system/lib
. L'autre est destiné au chemin d'accès du GPU et provient de/system/lib/vndk-sp
. - Les bibliothèques internes RS dans
/system/lib
sont créées dans le cadre de la plate-forme et sont mises à jour à mesure quesystem.img
est mis à niveau. Toutefois, les bibliothèques de/system/lib/vndk-sp
sont compilées pour le fournisseur et ne sont pas mises à jour lors de la mise à niveau desystem.img
(bien qu'elles puissent être mises à jour pour un correctif de sécurité, leur ABI reste la même). - Le code du fournisseur (HAL RS, pilote RS et
bcc plugin
) est associé aux bibliothèques internes de RenderScript situées dans/system/lib/vndk-sp
. Ils ne peuvent pas lier les libs dans/system/lib
, car les libs de ce répertoire sont compilées pour la plate-forme et peuvent donc ne pas être compatibles avec le code du fournisseur (c'est-à-dire que des symboles peuvent être supprimés). Cela rendrait impossible une mise à jour OTA uniquement pour le framework.
Conception
Les sections suivantes décrivent la conception de RenderScript dans Android 8.0 et versions ultérieures.
Bibliothèques RenderScript disponibles pour les fournisseurs
Cette section liste les bibliothèques RenderScript (connues sous le nom de NDK fournisseur pour les HAL Same-Process ou VNDK-SP) disponibles pour le code fournisseur et avec lesquelles elles peuvent être associées. Il détaille également les bibliothèques supplémentaires qui n'ont aucun lien avec RenderScript, mais qui sont également fournies au code du fournisseur.
Bien que la liste de bibliothèques suivante puisse varier d'une version d'Android à l'autre, elle est immuable pour une version spécifique d'Android. Pour obtenir une liste à jour des bibliothèques disponibles, reportez-vous à /system/etc/ld.config.txt
.
Bibliothèques RenderScript | Bibliothèques autres que RenderScript |
---|---|
|
|
Configuration de l'espace de noms du linker
La restriction d'association qui empêche l'utilisation des bibliothèques qui ne figurent pas dans VNDK-SP par le code du fournisseur est appliquée au moment de l'exécution à l'aide de l'espace de noms du linker. (Pour en savoir plus, consultez la présentation de la conception du VNDK.)
Sur un appareil équipé d'Android 8.0 ou version ultérieure, tous les HAL du même processus (SP-HAL) sauf RenderScript sont chargés dans l'espace de noms du linker sphal
. RenderScript est chargé dans l'espace de noms rs
spécifique à RenderScript, un emplacement qui permet une application légèrement plus souple des règles pour les bibliothèques RenderScript. Étant donné que la mise en œuvre RS doit charger le bitcode compilé, /data/*/*.so
est ajouté au chemin d'accès 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 d'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 le linker.
Charger les pilotes
Chemin de remplacement du CPU
Selon l'existence du bit RS_CONTEXT_LOW_LATENCY
lors de la création d'un contexte RS, le chemin d'accès au processeur ou au GPU est sélectionné. Lorsque le chemin d'accès au processeur est sélectionné, libRS_internal.so
(l'implémentation principale du framework RS) est dlopen
directement à partir du namespace du linker 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 remplacement du processeur est emprunté et qu'un objet RsContext
est créé avec une valeur mVendorDriverName
nulle. libRSDriver.so
est (par défaut) dlopen
ed 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 3. Chemin de remplacement du processeur.
Chemin d'accès au GPU
Pour le chemin d'accès au GPU, libRS_internal.so
est chargé différemment.
Tout d'abord, libRS.so
utilise android.hardware.renderscript@1.0.so
(et son libhidltransport.so
sous-jacent) pour charger android.hardware.renderscript@1.0-impl.so
(une implémentation du HAL RS par le fournisseur) dans un autre espace de noms de l'éditeur de liens appelé sphal
. Le HAL RS 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 compilation OVERRIDE_RS_DRIVER
, qui est intégré à l'implémentation du HAL RS (hardware/interfaces/renderscript/1.0/default/Context.cpp
). Ce nom de pilote est ensuite dlopen
é pour le contexte RS du chemin d'accès au GPU.
La création de l'objet RsContext
est déléguée à l'implémentation du HAL RS. Le HAL appelle le framework RS à l'aide de la fonction rsContextCreateVendor()
avec le nom du pilote à utiliser comme argument. Le framework RS charge ensuite le pilote spécifié lorsque 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 4. Chemin d'accès de remplacement du 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 au liant 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 est effectué indirectement par la ligne suivante dans /system/etc/ld.config.txt
:
namespace.sphal.link.rs.shared_libs = libRS_internal.so
Cette ligne indique 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-sp
où libRS_internal.so
se trouve). Avec cette configuration, un simple appel dlopen()
à libRS_internal.so
suffit à effectuer la transition d'espace de noms.
Charger le plug-in de Cci
bcc plugin
est une bibliothèque fournie par le fournisseur chargée dans le compilateur bcc
. Étant donné 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 pouvant être chargé directement dans le processus système sans être lié). En tant que SP-HAL, la bibliothèque bcc-plugin
:
- Impossible d'établir un lien avec des bibliothèques basées uniquement sur le framework, telles que
libLLVM.so
. - Ne peut lier que les bibliothèques VNDK-SP disponibles pour le fournisseur.
Cette restriction est appliquée en chargeant 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 de dlopen()
simple par libLLVM.so
. Dans Android 8.0 et versions ultérieures, cela est spécifié dans l'option -plugin
, et la bibliothèque est directement chargée par bcc
lui-même. Cette option active un chemin non spécifique à Android vers le projet LLVM Open Source.
Figure 5. Chargement du plug-in bcc, Android 7.x et versions antérieures.
Figure 6. Chargement du plug-in bcc, Android 8.0 ou version ultérieure.
Chemins de recherche pour ld.mc
Lors de l'exécution de ld.mc
, certaines bibliothèques d'exécution RS sont fournies en entrée au 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 les éléments suivants:
libcompiler_rt.so
libm.so
libc.so
- Pilote RS (
libRSDriver.so
ouOVERRIDE_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 de symbole disponible lors de l'association.
Pour ce faire, le framework RS utilise différents chemins de recherche pour les bibliothèques d'exécution lors de l'exécution de ld.mc
, selon que le framework RS lui-même est chargé à partir de /system/lib
ou de /system/lib/vndk-sp
.
Pour ce faire, lisez l'adresse d'un symbole arbitraire d'une bibliothèque de framework RS et utilisez dladdr()
pour obtenir le chemin d'accès au fichier mappé sur l'adresse.
Règle SELinux
En raison des modifications apportées aux règles SELinux dans Android 8.0 et versions ultérieures, vous devez suivre des règles spécifiques (appliquées via neverallows
) lorsque vous attribuez des libellés à des fichiers supplémentaires dans la partition vendor
:
vendor_file
doit être le libellé par défaut pour tous les fichiers de la partitionvendor
. La règle de la plate-forme nécessite cela pour accéder aux implémentations HAL de passthrough.- Tous les nouveaux
exec_types
ajoutés dans la partitionvendor
via le SEPolicy du fournisseur doivent avoir l'attributvendor_file_type
. Cette règle est appliquée vianeverallows
. - Pour éviter les conflits avec les futures mises à jour de la plate-forme/du framework, évitez d'étiqueter des fichiers autres que
exec_types
dans la partitionvendor
. - Toutes les dépendances de bibliothèque pour les HAL du même processus identifiées par l'AOSP doivent être libellées
same_process_hal_file
.
Pour en savoir plus sur la stratégie SELinux, consultez Security-Enhanced Linux dans Android.
Compatibilité avec les ABI pour le bitcode
Si aucune nouvelle API n'est ajoutée, ce qui signifie qu'aucune version HAL n'est mise à niveau, les frameworks RS continueront d'utiliser le pilote GPU (HAL 1.0) existant.
Pour les modifications mineures de l'HAL (HAL 1.1) qui n'affectent pas le bitcode, les frameworks doivent utiliser le processeur pour ces API nouvellement ajoutées et continuer à utiliser le pilote du GPU (HAL 1.0) ailleurs.
Pour les modifications majeures de l'HAL (HAL 2.0) affectant la compilation/l'association du bitcode, les frameworks RS doivent choisir de ne pas charger les pilotes de GPU fournis par le fournisseur et d'utiliser plutôt le chemin d'accès au processeur ou à Vulkan pour l'accélération.
La consommation du bitcode RenderScript se déroule en trois étapes:
Étape | Détails |
---|---|
Compilation |
|
Lien |
|
Charger |
|
En plus du HAL, les API d'exécution et les symboles exportés sont également des interfaces. Aucune de ces deux interfaces n'a changé depuis Android 7.0 (API 24), et il n'est pas prévu de la modifier dans l'immédiat sous Android 8.0 et versions ultérieures. Toutefois, si l'interface change, la version de HAL est également incrémentée.
Implémentations des fournisseurs
Android 8.0 ou version ultérieure nécessite certaines modifications du pilote de GPU pour que celui-ci fonctionne correctement.
Modules pilotes
- Les modules pilotes ne doivent pas dépendre de bibliothèques système qui ne figurent pas dans cette liste.
- Le pilote doit fournir son propre
android.hardware.renderscript@1.0-impl_{NAME}
ou déclarer l'implémentation par défautandroid.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 code binaire
Vous pouvez compiler le bitcode RenderScript pour le pilote du fournisseur de deux manières:
- Appelez le compilateur RenderScript spécifique au fournisseur dans
/vendor/bin/
(méthode de compilation du GPU recommandée). Comme les autres modules de pilotes, 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. - Appelez le bcc système:
/system/bin/bcc
avec unbcc plugin
fourni par le fournisseur. Ce plug-in 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.
Si le fournisseur bcc plugin
doit interférer avec la compilation du processeur et que sa dépendance envers libLLVM.so
ne peut pas être facilement supprimée, le fournisseur doit copier bcc
(et toutes les dépendances autres que LL-NDK, y compris libLLVM.so
, libbcc.so
) dans la partition /vendor
.
Les fournisseurs doivent également apporter les modifications suivantes:
Figure 7. Modifications apportées au pilote du fournisseur.
- Copiez
libclcore.bc
dans la partition/vendor
. Cela garantit quelibclcore.bc
,libLLVM.so
etlibbcc.so
sont synchronisés. - Modifiez le chemin d'accès à l'exécutable
bcc
en définissantRsdCpuScriptImpl::BCC_EXE_PATH
à partir de l'implémentation RS HAL.
Règle SELinux
La règle SELinux s'applique à la fois au pilote et aux exécutables du compilateur. Tous les modules de pilote doivent être étiquetés same_process_hal_file
dans le file_contexts
de l'appareil. 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, comme le fait 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 anciens
Les anciens appareils sont ceux qui remplissent les conditions suivantes:
- La valeur de PRODUCT_SHIPPING_API_LEVEL est inférieure à 26.
- PRODUCT_FULL_TREBLE_OVERRIDE n'est pas défini.
Pour les anciens appareils, les restrictions ne sont pas appliquées lors de la mise à niveau vers Android 8.0 ou version ultérieure, ce qui signifie que les pilotes peuvent continuer à associer des bibliothèques dans /system/lib[64]
. Toutefois, en raison du changement d'architecture lié à OVERRIDE_RS_DRIVER
, android.hardware.renderscript@1.0-impl
doit être installé dans la partition /vendor
. Si vous ne le faites pas, l'environnement d'exécution RenderScript est forcé de revenir au chemin d'accès du processeur.
Pour en savoir plus sur la raison de l'abandon de Renderscript, consultez le blog des développeurs Android: Android GPU Compute Going Forward (Calcul GPU Android à l'avenir). Les informations sur les ressources pour cette abandon incluent les éléments suivants:
- Abandonner Renderscript
- Exemple de migration RenderScript
- README du kit de remplacement des fonctionnalités intrinsèques
- Toolkit.kt de remplacement des fonctionnalités intrinsèques