RenderScript ist ein Framework zum Ausführen rechenintensiver Aufgaben mit hoher Leistung auf Android-Geräten. Sie wurde für die Verwendung mit datenparrallel arbeitenden Berechnungen entwickelt, kann aber auch für serielle Arbeitslasten genutzt werden. Die RenderScript-Laufzeit parallelisiert die Arbeit zwischen den auf einem Gerät verfügbaren Prozessoren, z. B. Mehrkern-CPUs und GPUs. So können sich Entwickler auf die Formulierung von Algorithmen konzentrieren, anstatt Aufgaben zu planen. RenderScript ist besonders nützlich für Anwendungen, die Bildverarbeitung, computergestützte Fotografie oder maschinelles Sehen nutzen.
Auf Geräten mit Android 8.0 und höher werden das folgende RenderScript-Framework und die folgenden HALs von Anbietern verwendet:
Abbildung 1. Anbietercode, der mit internen libs verknüpft ist.
Zu den Unterschieden zu RenderScript in Android 7.x und niedriger gehören:
- Zwei Instanzen interner RenderScript-Bibliotheken in einem Prozess. Eine Gruppe ist für den CPU-Fallbackpfad und beginnt direkt bei
/system/lib
. Die andere Gruppe ist für den GPU-Pfad und beginnt bei/system/lib/vndk-sp
. - Interne RS-Bibliotheken in
/system/lib
werden im Rahmen der Plattform erstellt und bei der Umstellung vonsystem.img
aktualisiert. Die/system/lib/vndk-sp
-Bibliotheken werden jedoch für den Anbieter erstellt und nicht aktualisiert, wennsystem.img
aktualisiert wird. Sie können zwar für eine Sicherheitskorrektur aktualisiert werden, ihr ABI bleibt jedoch gleich. - Der Anbietercode (RS HAL, RS-Treiber und
bcc plugin
) ist mit den internen RenderScript-Bibliotheken unter/system/lib/vndk-sp
verknüpft. Sie können nicht mit Bibliotheken in/system/lib
verknüpft werden, da Bibliotheken in diesem Verzeichnis für die Plattform erstellt werden und daher möglicherweise nicht mit dem Anbietercode kompatibel sind (d.h. Symbole können entfernt werden). Das würde ein reines Framework-OTA-Verfahren unmöglich machen.
Design
In den folgenden Abschnitten wird das RenderScript-Design unter Android 8.0 und höher beschrieben.
Für Anbieter verfügbare RenderScript-Bibliotheken
In diesem Abschnitt werden die RenderScript-Bibliotheken (bekannt als Anbieter NDK für Same-Process-HALs oder VNDK-SP) aufgeführt, die für Anbietercode zur Verfügung stehen und mit denen verknüpft werden können. Außerdem werden zusätzliche Bibliotheken aufgeführt, die nichts mit RenderScript zu tun haben, aber auch für Anbietercode bereitgestellt werden.
Die folgende Liste der Bibliotheken kann sich zwischen Android-Releases unterscheiden, ist aber für einen bestimmten Android-Release unveränderlich. Eine aktuelle Liste der verfügbaren Bibliotheken finden Sie unter /system/etc/ld.config.txt
.
RenderScript-Bibliotheken | Nicht RenderScript-Bibliotheken |
---|---|
|
|
Linker-Namespace-Konfiguration
Die Verknüpfungsbeschränkung, die verhindert, dass ‑Libs, die nicht in VNDK-SP enthalten sind, von Anbietercode verwendet werden, wird zur Laufzeit mithilfe des Linker-Namespace erzwungen. Weitere Informationen finden Sie in der Präsentation VNDK Design.
Auf einem Gerät mit Android 8.0 und höher werden alle SP-HALs (Same-Process HALs, HALs mit demselben Prozess) mit Ausnahme von RenderScript im Linker-Namespace sphal
geladen. RenderScript wird in den RenderScript-spezifischen Namespace rs
geladen. Dies ist ein Speicherort, der eine etwas lockerere Erzwingung für RenderScript-Bibliotheken ermöglicht. Da die RS-Implementierung den kompilierten Bitcode laden muss, wird /data/*/*.so
dem Pfad des rs
-Namespace hinzugefügt. Andere SP-HALs dürfen keine Bibliothken aus der Datenpartition laden.
Außerdem erlaubt der Namespace rs
mehr Bibliotheken, als von anderen Namespaces zur Verfügung gestellt werden. libmediandk.so
und libft2.so
sind für den rs
-Namespace verfügbar, da libRS_internal.so
eine interne Abhängigkeit von diesen Bibliotheken hat.
Abbildung 2: Namespace-Konfiguration für den Linker.
Treiber laden
CPU-Fallback-Pfad
Je nachdem, ob das RS_CONTEXT_LOW_LATENCY
-Bit beim Erstellen eines RS-Kontexts vorhanden ist, wird entweder der CPU- oder der GPU-Pfad ausgewählt. Wenn der CPU-Pfad ausgewählt wird, wird libRS_internal.so
(die Hauptimplementierung des RS-Frameworks) direkt aus dem Standardverknüpfungs-Namespace, in dem die Plattformversion der RS-Bibliotheken bereitgestellt wird, mit dlopen
abgerufen.
Die RS HAL-Implementierung des Anbieters wird nicht verwendet, wenn der CPU-Fallbackpfad verwendet wird, und ein RsContext
-Objekt wird mit null mVendorDriverName
erstellt. libRSDriver.so
wird standardmäßig dlopen
ed und die Treiberbibliothek wird aus dem Namespace default
geladen, da auch der Aufrufer (libRS_internal.so
) im Namespace default
geladen wird.
Abbildung 3 CPU-Fallback-Pfad.
GPU-Pfad
Für den GPU-Pfad wird die libRS_internal.so
anders geladen.
Zuerst verwendet libRS.so
android.hardware.renderscript@1.0.so
(und die zugrunde liegende libhidltransport.so
), um android.hardware.renderscript@1.0-impl.so
(eine Anbieterimplementierung der RS HAL) in einen anderen Linker-Namespace namens sphal
zu laden. Die RS-HAL dlopen
s libRS_internal.so
dann in einem anderen Linker-Namespace namens rs
.
Anbieter können ihren eigenen RS-Treiber bereitstellen, indem sie das Buildzeit-Flag OVERRIDE_RS_DRIVER
festlegen, das in die RS HAL-Implementierung (hardware/interfaces/renderscript/1.0/default/Context.cpp
) eingebettet ist. Dieser Treibername wird dann für den RS-Kontext für den GPU-Pfad dlopen
ed.
Die Erstellung des RsContext
-Objekts wird an die RS HAL-Implementierung delegiert. Der HAL ruft das RS-Framework mithilfe der Funktion rsContextCreateVendor()
mit dem Namen des Treibers, der als Argument verwendet werden soll, auf. Das RS-Framework lädt dann den angegebenen Treiber, wenn RsContext
initialisiert wird. In diesem Fall wird die Treiberbibliothek in den Namespace rs
geladen, da das Objekt RsContext
innerhalb des Namespace rs
erstellt wird und sich /vendor/lib
im Suchpfad des Namespace befindet.
Abbildung 4 GPU-Fallback-Pfad.
Bei der Umstellung vom Namespace default
auf den Namespace sphal
verwendet libhidltransport.so
die Funktion android_load_sphal_library()
, um dem dynamischen Linker explizit zu befehlen, die -impl.so
-Bibliothek aus dem Namespace sphal
zu laden.
Beim Übergang vom Namespace sphal
zum Namespace rs
erfolgt das Laden indirekt über die folgende Zeile in /system/etc/ld.config.txt
:
namespace.sphal.link.rs.shared_libs = libRS_internal.so
In dieser Zeile wird angegeben, dass der dynamische Linker libRS_internal.so
aus dem Namespace rs
laden soll, wenn die Bibliothek nicht im Namespace sphal
gefunden oder geladen werden kann. Das ist immer der Fall, da im Namespace sphal
nicht nach /system/lib/vndk-sp
gesucht wird, wo sich libRS_internal.so
befindet. Bei dieser Konfiguration reicht ein einfacher dlopen()
-Aufruf an libRS_internal.so
aus, um den Namespace-Übergang durchzuführen.
Bcc-Plug-in laden
bcc plugin
ist eine vom Anbieter bereitgestellte Bibliothek, die in den bcc
-Compiler geladen wird. Da es sich bei bcc
um einen Systemprozess im Verzeichnis /system/bin
handelt, kann die Bibliothek bcc plugin
als SP-HAL betrachtet werden (d.h. als Anbieter-HAL, der direkt in den Systemprozess geladen werden kann, ohne im Bindestrich zu speichern). Als SP-HAL kann die bcc-plugin
-Bibliothek Folgendes umfassen:
- Verknüpfung mit Bibliotheken, die nur für das Framework bestimmt sind, wie
libLLVM.so
, ist nicht möglich. - Es kann nur mit den VNDK-SP-Bibliotheken verknüpft werden, die dem Anbieter zur Verfügung stehen.
Diese Einschränkung wird erzwungen, indem bcc plugin
mithilfe der Funktion android_sphal_load_library()
in den Namespace sphal
geladen wird. In früheren Versionen von Android wurde der Plug-in-Name mit der Option -load
angegeben und die Lib wurde mit dem einfachen dlopen()
von libLLVM.so
geladen. Ab Android 8.0 wird dies in der Option -plugin
angegeben und die lib-Bibliothek wird direkt von der bcc
selbst geladen. Mit dieser Option wird ein nicht Android-spezifischer Pfad zum Open-Source-LLVM-Projekt aktiviert.
Abbildung 5: bcc-Plug-in wird geladen, Android 7.x und niedriger
Abbildung 6 Laden des BCC-Plug-ins, Android 8.0 und höher
Suchpfade für ld.mc
Beim Ausführen von ld.mc
werden einige RS-Laufzeitbibliotheken als Eingaben an die Verknüpfung übergeben. Der RS-Bitcode der Anwendung wird mit den Laufzeitbibliotheken verknüpft. Wenn der konvertierte Bitcode in einen Anwendungsprozess geladen wird, werden die Laufzeitbibliotheken wieder dynamisch vom konvertierten Bitcode verknüpft.
Zu den Laufzeitbibliotheken gehören:
libcompiler_rt.so
libm.so
libc.so
- RS-Fahrer (entweder
libRSDriver.so
oderOVERRIDE_RS_DRIVER
)
Wenn Sie den kompilierten Bitcode in den App-Prozess laden, müssen Sie genau dieselbe Bibliothek angeben, die von ld.mc
verwendet wurde. Andernfalls wird im kompilierten Bitcode möglicherweise kein Symbol gefunden, das bei der Verknüpfung verfügbar war.
Dazu verwendet das RS-Framework beim Ausführen von ld.mc
unterschiedliche Suchpfade für die Laufzeitbibliotheken, je nachdem, ob das RS-Framework selbst von /system/lib
oder von /system/lib/vndk-sp
geladen wird.
Dazu wird die Adresse eines beliebigen Symbols einer RS-Framework-Bibliothek gelesen und mit dladdr()
der Dateipfad abgerufen, der der Adresse zugeordnet ist.
SELinux-Richtlinie
Aufgrund der Änderungen an der SELinux-Richtlinie in Android 8.0 und höher müssen Sie beim Hinzufügen von Labels zu zusätzlichen Dateien in der Partition vendor
bestimmte Regeln befolgen (durchgeführt durch neverallows
):
vendor_file
muss das Standardlabel für alle Dateien in dervendor
-Partition sein. Gemäß der Plattformrichtlinie ist dies für den Zugriff auf Passthrough-HAL-Implementierungen erforderlich.- Alle neuen
exec_types
, die über die SEPolicy des Anbieters dervendor
-Partition hinzugefügt werden, müssen das Attributvendor_file_type
haben. Dies wird überneverallows
erzwungen. - Um Konflikte mit zukünftigen Plattform-/Framework-Updates zu vermeiden, sollten Sie Dateien in der Partition
vendor
nicht mit anderen Labels alsexec_types
versehen. - Alle Bibliotheksabhängigkeiten für von AOSP identifizierte HALs für denselben Prozess müssen als
same_process_hal_file
gekennzeichnet sein.
Weitere Informationen zu SELinux-Richtlinien finden Sie unter Security-Enhanced Linux in Android.
ABI-Kompatibilität für Bitcode
Wenn keine neuen APIs hinzugefügt werden, d. h. keine HAL-Version erhöht wird, verwenden die RS-Frameworks weiterhin den vorhandenen GPU-Treiber (HAL 1.0).
Bei geringfügigen HAL-Änderungen (HAL 1.1), die sich nicht auf den Bitcode auswirken, sollten die Frameworks für diese neu hinzugefügten APIs auf die CPU zurückgreifen und den GPU-Treiber (HAL 1.0) an anderer Stelle weiter verwenden.
Bei größeren HAL-Änderungen (HAL 2.0), die sich auf die Bitcode-Kompilierung/-Verknüpfung auswirken, sollten RS-Frameworks keine vom Anbieter bereitgestellten GPU-Treiber laden, sondern stattdessen den CPU- oder Vulkan-Pfad für die Beschleunigung verwenden.
Die Verwendung von RenderScript-Bitcode erfolgt in drei Phasen:
Bühne | Details |
---|---|
Kompilieren |
|
Link |
|
Laden |
|
Neben der HAL sind auch die Laufzeit-APIs und die exportierten Symbole Schnittstellen. Keine der Benutzeroberfläche hat sich seit Android 7.0 (API 24) geändert und es gibt keine unmittelbaren Pläne, dies in Android 8.0 und höher zu ändern. Wenn sich die Schnittstelle jedoch ändert, wird auch die HAL-Version erhöht.
Implementierungen von Anbietern
Unter Android 8.0 und höher sind einige Änderungen am GPU-Treiber erforderlich, damit er ordnungsgemäß funktioniert.
Treibermodule
- Treibermodule dürfen nicht von Systembibliotheken abhängen, die nicht in der Liste enthalten sind.
- Der Treiber muss eine eigene
android.hardware.renderscript@1.0-impl_{NAME}
bereitstellen oder die Standardimplementierungandroid.hardware.renderscript@1.0-impl
als Abhängigkeit deklarieren. - Die CPU-Implementierung
libRSDriver.so
ist ein gutes Beispiel dafür, wie Sie Abhängigkeiten, die nicht zu VNDK-SP gehören, entfernen.
Bitcode-Compiler
Sie haben zwei Möglichkeiten, RenderScript-Bitcode für den Anbietertreiber zu kompilieren:
- Anbieterspezifischen RenderScript-Compiler in
/vendor/bin/
aufrufen (bevorzugte Methode der GPU-Kompilierung) Ähnlich wie bei anderen Treibermodulen darf das Binärprogramm des Anbietercompilers nicht von einer Systembibliothek abhängen, die nicht in der Liste der für Anbieter verfügbaren RenderScript-Bibliotheken enthalten ist. - System-bcc:
/system/bin/bcc
mit einer vom Anbieter bereitgestelltenbcc plugin
aufrufen; dieses Plug-in darf nicht von einer Systembibliothek abhängen, die nicht in der Liste der für Anbieter verfügbaren RenderScript-Bibliotheken enthalten ist.
Wenn der Anbieter bcc plugin
in die CPU-Kompilierung eingreifen muss und seine Abhängigkeit von libLLVM.so
nicht einfach entfernt werden kann, sollte er bcc
(und alle nicht LL-NDK-Abhängigkeiten, einschließlich libLLVM.so
, libbcc.so
) in die Partition /vendor
kopieren.
Darüber hinaus müssen Anbieter folgende Änderungen vornehmen:
Abbildung 7. Änderungen am Anbietertreiber.
- Kopieren Sie
libclcore.bc
in die Partition/vendor
. Dadurch wird sichergestellt, dasslibclcore.bc
,libLLVM.so
undlibbcc.so
synchron sind. - Ändern Sie den Pfad zur ausführbaren Datei
bcc
, indem SieRsdCpuScriptImpl::BCC_EXE_PATH
aus der RS HAL-Implementierung festlegen.
SELinux-Richtlinie
Die SELinux-Richtlinie wirkt sich sowohl auf die Treiber als auch auf die ausführbaren Compiler-Dateien aus. Alle Treibermodule müssen in der file_contexts
des Geräts mit same_process_hal_file
gekennzeichnet sein. Beispiel:
/vendor/lib(64)?/libRSDriver_EXAMPLE\.so u:object_r:same_process_hal_file:s0
Die ausführbare Compilerdatei muss von einem App-Prozess aufgerufen werden können, ebenso wie die Anbieterkopie von bcc (/vendor/bin/bcc
). Beispiel:
device/vendor_foo/device_bar/sepolicy/file_contexts: /vendor/bin/bcc u:object_r:same_process_hal_file:s0
Ältere Geräte
Zu den Legacy-Geräten gehören Geräte, die die folgenden Bedingungen erfüllen:
- PRODUCT_SHIPPING_API_LEVEL ist kleiner als 26.
- PRODUCT_FULL_TREBLE_OVERRIDE ist nicht definiert.
Bei älteren Geräten werden die Einschränkungen beim Upgrade auf Android 8.0 und höher nicht erzwungen. Das bedeutet, dass die Treiber weiterhin mit Bibliotheken in /system/lib[64]
verknüpft werden können. Aufgrund der Architekturänderung aufgrund von OVERRIDE_RS_DRIVER
muss android.hardware.renderscript@1.0-impl
jedoch auf der Partition /vendor
installiert werden. Andernfalls wird das RenderScript-Laufzeit-Fallback auf den CPU-Pfad erzwungen.
Informationen zur Beweggründe für die Einstellung von Renderscript finden Sie im Blog für Android-Entwickler: Android GPU Compute Going Forward. Zu den Ressourceninformationen für diese Einstellung gehören:
- Von Renderscript migrieren
- RenderScriptMigration Sample
- Intrinsics Replacement Toolkit README
- Intrinsics ReplacementToolkit.kt