Renderscript

RenderScript ist ein Framework zum Ausführen rechenintensiver Aufgaben mit hoher Leistung auf Android. Es ist für die Verwendung mit datenparalleler Berechnung konzipiert, obwohl auch serielle Workloads davon profitieren können. Die RenderScript-Laufzeitumgebung parallelisiert die Arbeit aller auf einem Gerät verfügbaren Prozessoren, wie z. B. Multi-Core-CPUs und GPUs, sodass sich Entwickler auf das Ausdrücken von Algorithmen statt auf die Planung von Arbeiten konzentrieren können. RenderScript ist besonders nützlich für Anwendungen zur Bildverarbeitung, Computerfotografie oder Computer Vision.

Geräte mit Android 8.0 und höher verwenden das folgende RenderScript-Framework und die folgenden Anbieter-HALs:

Abbildung 1. Anbietercode, der mit internen Bibliotheken verknüpft ist

Zu den Unterschieden zu RenderScript in Android 7.x und niedriger gehören:

  • Zwei Instanzen interner RenderScript-Bibliotheken in einem Prozess. Ein Satz ist für den CPU-Fallback-Pfad und stammt direkt von /system/lib ; Der andere Satz ist für den GPU-Pfad und stammt aus /system/lib/vndk-sp .
  • Interne RS-Bibliotheken in /system/lib werden als Teil der Plattform erstellt und aktualisiert, wenn system.img aktualisiert wird. Allerdings werden Bibliotheken in /system/lib/vndk-sp für den Anbieter erstellt und nicht aktualisiert, wenn system.img aktualisiert wird (sie können zwar für einen Sicherheitsupdate aktualisiert werden, ihr ABI bleibt jedoch gleich).
  • Herstellercode (RS HAL, RS-Treiber und das bcc plugin ) sind mit den internen RenderScript-Bibliotheken verknüpft, die sich unter /system/lib/vndk-sp befinden. Sie können keine Verknüpfung mit Bibliotheken in /system/lib herstellen, da Bibliotheken in diesem Verzeichnis für die Plattform erstellt wurden und daher möglicherweise nicht mit dem Herstellercode kompatibel sind (dh Symbole werden möglicherweise entfernt). Dies würde eine reine Framework-OTA unmöglich machen.

Design

In den folgenden Abschnitten wird das RenderScript-Design in Android 8.0 und höher detailliert beschrieben.

Für Anbieter verfügbare RenderScript-Bibliotheken

In diesem Abschnitt werden die RenderScript-Bibliotheken (bekannt als Vendor NDK für Same-Process HALs oder VNDK-SP) aufgeführt, die für Anbietercode verfügbar sind und mit denen verknüpft werden können. Außerdem werden zusätzliche Bibliotheken beschrieben, die nichts mit RenderScript zu tun haben, aber auch dem Code des Anbieters zur Verfügung gestellt werden.

Während sich die folgende Liste der Bibliotheken je nach Android-Version unterscheiden kann, ist sie für eine bestimmte Android-Version unveränderlich. Eine aktuelle Liste der verfügbaren Bibliotheken finden Sie unter /system/etc/ld.config.txt .

RenderScript-Bibliotheken Nicht-RenderScript-Bibliotheken
  • 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

Linker-Namespace-Konfiguration

Die Verknüpfungseinschränkung, die verhindert, dass Bibliotheken, die nicht in VNDK-SP enthalten sind, vom Herstellercode verwendet werden, wird zur Laufzeit mithilfe des Linker-Namespace erzwungen. (Einzelheiten finden Sie in der VNDK Design- Präsentation.)

Auf einem Gerät mit Android 8.0 und höher werden alle Same-Process HALs (SP-HALs) außer RenderScript in den Linker-Namespace sphal geladen. RenderScript wird in den RenderScript-spezifischen Namespace rs geladen, einen Speicherort, der eine etwas lockerere Durchsetzung für RenderScript-Bibliotheken ermöglicht. Da die RS-Implementierung den kompilierten Bitcode laden muss, wird /data/*/*.so zum Pfad des rs Namespace hinzugefügt (andere SP-HALs dürfen keine Bibliotheken aus der Datenpartition laden).

Darüber hinaus erlaubt der rs Namespace mehr Bibliotheken als andere Namespaces bieten. libmediandk.so und libft2.so sind dem rs Namespace ausgesetzt, da libRS_internal.so eine interne Abhängigkeit zu diesen Bibliotheken aufweist.

Abbildung 2. Namespace-Konfiguration für Linker

Treiber werden geladen

CPU-Fallback-Pfad

Abhängig vom Vorhandensein des Bits RS_CONTEXT_LOW_LATENCY beim Erstellen eines RS-Kontexts 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 Standard-Linker-Namensraum dlopen , in dem die Plattformversion der RS-Bibliotheken bereitgestellt wird.

Die RS-HAL-Implementierung des Anbieters wird überhaupt nicht verwendet, wenn der CPU-Fallback-Pfad verwendet wird, und ein RsContext Objekt mit null mVendorDriverName erstellt wird. libRSDriver.so ist (standardmäßig) dlopen und die Treiberbibliothek wird aus dem default Namespace geladen, da der Aufrufer ( libRS_internal.so ) auch im default Namespace geladen wird.

Abbildung 4. CPU-Fallback-Pfad

GPU-Pfad

Für den GPU-Pfad wird libRS_internal.so anders geladen. Erstens verwendet libRS.so android.hardware.renderscript@1.0.so (und das zugrunde liegende libhidltransport.so ), um android.hardware.renderscript@1.0-impl.so (eine Herstellerimplementierung von RS HAL) in einen anderen Linker-Namespace namens zu laden sphal . Die RS-HAL dlopen dann libRS_internal.so in einem anderen Linker-Namespace namens rs .

Anbieter können ihren eigenen RS-Treiber bereitstellen, indem sie das Build-Time-Flag OVERRIDE_RS_DRIVER setzen, das in die RS-HAL-Implementierung eingebettet ist ( hardware/interfaces/renderscript/1.0/default/Context.cpp ). Dieser Treibername wird dann für den RS-Kontext für den GPU-Pfad dlopen .

Die Erstellung des RsContext Objekts wird an die RS-HAL-Implementierung delegiert. Der HAL ruft mit der Funktion rsContextCreateVendor() mit dem Namen des zu verwendenden Treibers als Argument an das RS-Framework zurück. Das RS-Framework lädt dann den angegebenen Treiber, wenn der RsContext initialisiert wird. In diesem Fall wird die Treiberbibliothek in den rs Namespace geladen, da das RsContext Objekt innerhalb des rs Namespace erstellt wird und sich /vendor/lib im Suchpfad des Namespace befindet.

Abbildung 5. GPU-Fallback-Pfad

Beim Übergang vom default Namespace zum sphal Namespace verwendet libhidltransport.so die Funktion android_load_sphal_library() , um den dynamischen Linker explizit anzuweisen, die Bibliothek -impl.so aus dem sphal Namespace zu laden.

Beim Übergang vom sphal Namespace zum rs Namespace erfolgt das Laden indirekt über die folgende Zeile in /system/etc/ld.config.txt :

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

Diese Zeile gibt an, dass der dynamische Linker libRS_internal.so aus dem rs -Namespace laden soll, wenn die Bibliothek nicht im sphal Namespace gefunden/geladen werden kann (was immer der Fall ist, da sphal Namespace nicht nach /system/lib/vndk-sp sucht libRS_internal.so liegt). Bei dieser Konfiguration reicht ein einfacher dlopen() -Aufruf an libRS_internal.so aus, um den Namespace-Übergang durchzuführen.

Bcc-Plugin wird geladen

bcc plugin ist eine vom Anbieter bereitgestellte Bibliothek, die in den bcc Compiler geladen wird. Da bcc ein Systemprozess im Verzeichnis /system/bin ist, kann die bcc plugin Bibliothek als SP-HAL betrachtet werden (d. h. als Anbieter-HAL, der direkt in den Systemprozess geladen werden kann, ohne gebunden zu werden). Als SP-HAL ist die bcc-plugin Bibliothek:

  • Eine Verknüpfung mit reinen Framework-Bibliotheken wie libLLVM.so ist nicht möglich.
  • Kann nur mit den VNDK-SP-Bibliotheken verknüpft werden, die dem Anbieter zur Verfügung stehen.

Diese Einschränkung wird erzwungen, indem das bcc plugin mithilfe der Funktion android_sphal_load_library() in den sphal Namespace geladen wird. In früheren Android-Versionen wurde der Plugin-Name mit der Option -load angegeben und die Bibliothek wurde mit dem einfachen dlopen() von libLLVM.so geladen. In Android 8.0 und höher wird dies in der Option -plugin angegeben und die Bibliothek wird direkt vom bcc selbst geladen. Diese Option ermöglicht einen nicht Android-spezifischen Pfad zum Open-Source-LLVM-Projekt.

Abbildung 6. Laden des BCC-Plugins, Android 7.x und niedriger


Abbildung 7. Laden des BCC-Plugins, Android 8.0 und höher

Suchpfade für ld.mc

Beim Ausführen von ld.mc werden einige RS-Laufzeitbibliotheken als Eingaben an den Linker übergeben. Der RS-Bitcode aus der App wird mit den Laufzeitbibliotheken verknüpft und wenn der konvertierte Bitcode in einen App-Prozess geladen wird, werden die Laufzeitbibliotheken erneut dynamisch aus dem konvertierten Bitcode verknüpft.

Zu den Laufzeitbibliotheken gehören:

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • RS-Treiber (entweder libRSDriver.so oder OVERRIDE_RS_DRIVER )

Stellen Sie beim Laden des kompilierten Bitcodes in den App-Prozess genau dieselbe Bibliothek bereit, die von ld.mc verwendet wurde. Andernfalls findet der kompilierte Bitcode möglicherweise kein Symbol, das zum Zeitpunkt der Verknüpfung verfügbar war.

Zu diesem Zweck verwendet das RS-Framework beim Ausführen 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. Dies kann ermittelt werden, indem die Adresse eines beliebigen Symbols einer RS-Framework-Bibliothek gelesen und dladdr() verwendet wird, um den der Adresse zugeordneten Dateipfad abzurufen.

SELinux-Richtlinie

Aufgrund der SELinux-Richtlinienänderungen in Android 8.0 und höher müssen Sie beim Kennzeichnen zusätzlicher Dateien in vendor bestimmte Regeln befolgen (durchgesetzt durch neverallows ):

  • vendor_file muss die Standardbezeichnung für alle Dateien in vendor Partition sein. Die Plattformrichtlinie erfordert dies, um auf Passthrough-HAL-Implementierungen zuzugreifen.
  • Alle neuen exec_types , die über die Vendor-SEPolicy in der vendor Partition hinzugefügt werden, müssen über das Attribut vendor_file_type verfügen. Dies wird durch neverallows erzwungen.
  • Um Konflikte mit zukünftigen Plattform-/Framework-Updates zu vermeiden, vermeiden Sie die Kennzeichnung anderer Dateien als exec_types in der vendor .
  • Alle Bibliotheksabhängigkeiten für AOSP-identifizierte HALs desselben Prozesses müssen als same_process_hal_file gekennzeichnet sein.

Einzelheiten zur SELinux-Richtlinie finden Sie unter Security-Enhanced Linux in Android .

ABI-Kompatibilität für Bitcode

Wenn keine neuen APIs hinzugefügt werden, was bedeutet, dass es keinen HAL-Versionssprung gibt, 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 an anderer Stelle weiterhin den GPU-Treiber (HAL 1.0) verwenden.

Bei größeren HAL-Änderungen (HAL 2.0), die sich auf die Bitcode-Kompilierung/-Verknüpfung auswirken, sollten sich RS-Frameworks dafür entscheiden, keine vom Hersteller bereitgestellten GPU-Treiber zu laden und stattdessen den CPU- oder Vulkan-Pfad zur Beschleunigung zu verwenden.

Der Konsum von RenderScript-Bitcode erfolgt in drei Phasen:

Bühne Einzelheiten
Kompilieren
  • Der Eingabebitcode (.bc) für bcc muss im LLVM 3.2 Bitcodeformat vorliegen und bcc muss abwärtskompatibel mit vorhandenen (älteren) Apps sein.
  • Allerdings könnten sich die Metadaten in .bc ändern (es könnten neue Laufzeitfunktionen entstehen, z. B. Allocation Setter ∓ Getter, mathematische Funktionen usw.). Ein Teil der Laufzeitfunktionen befindet sich in libclcore.bc , ein Teil davon in LibRSDriver oder einem entsprechenden Anbieter.
  • Neue Laufzeitfunktionen oder wichtige Metadatenänderungen erfordern eine Erhöhung der Bitcode-API-Ebene. Da Herstellertreiber es nicht nutzen können, muss auch die HAL-Version erhöht werden.
  • Anbieter haben möglicherweise ihre eigenen Compiler, aber die Schlussfolgerungen/Anforderungen für bcc gelten auch für diese Compiler.
Verknüpfung
  • Die kompilierte .o-Datei wird mit dem Herstellertreiber verknüpft, z. B. libRSDriver_foo.so und libcompiler_rt.so . Der CPU-Pfad wird mit libRSDriver.so verknüpft.
  • Wenn .o eine neue Laufzeit-API von libRSDriver_foo erfordert, muss der Herstellertreiber aktualisiert werden, um dies zu unterstützen.
  • Bestimmte Anbieter verfügen möglicherweise über eigene Linker, die Argumente für ld.mc gelten jedoch auch für sie.
Belastung
  • libRSCpuRef lädt das gemeinsam genutzte Objekt. Wenn es Änderungen an dieser Schnittstelle gibt, ist eine Aktualisierung der HAL-Version erforderlich.
  • Anbieter würden sich entweder auf libRSCpuRef verlassen, um das gemeinsam genutzte Objekt zu laden, oder ihr eigenes implementieren.

Neben der HAL sind auch Laufzeit-APIs und die exportierten Symbole Schnittstellen. Keine der Schnittstellen hat sich seit Android 7.0 (API 24) geändert und es gibt keine unmittelbaren Pläne, sie in Android 8.0 und höher zu ändern. Wenn sich jedoch die Schnittstelle ändert, wird auch die HAL-Version erhöht.

Anbieterimplementierungen

Android 8.0 und höher erfordert einige GPU-Treiberänderungen, damit der GPU-Treiber ordnungsgemäß funktioniert.

Treibermodule

  • Treibermodule dürfen nicht von Systembibliotheken abhängen, die nicht in der Liste aufgeführt sind.
  • Der Treiber muss sein eigenes android.hardware.renderscript@1.0-impl_{NAME} bereitstellen oder die Standardimplementierung android.hardware.renderscript@1.0-impl als seine Abhängigkeit deklarieren.
  • Die CPU-Implementierung libRSDriver.so ist ein gutes Beispiel dafür, wie Nicht-VNDK-SP-Abhängigkeiten entfernt werden können.

Bitcode-Compiler

Sie können RenderScript-Bitcode für den Herstellertreiber auf zwei Arten kompilieren:

  1. Rufen Sie den herstellerspezifischen RenderScript-Compiler in /vendor/bin/ auf (bevorzugte Methode der GPU-Kompilierung). Ähnlich wie bei anderen Treibermodulen kann die Compiler-Binärdatei des Anbieters nicht von einer Systembibliothek abhängen, die nicht in der Liste der für Anbieter verfügbaren RenderScript-Bibliotheken enthalten ist.
  2. Rufen Sie System bcc auf: /system/bin/bcc mit einem vom Anbieter bereitgestellten bcc plugin . Dieses Plugin kann nicht von einer Systembibliothek abhängen, die nicht in der Liste der für Anbieter verfügbaren RenderScript-Bibliotheken aufgeführt ist.

Wenn das bcc plugin des Anbieters die CPU-Kompilierung beeinträchtigen muss und seine Abhängigkeit von libLLVM.so nicht einfach entfernt werden kann, sollte der Anbieter bcc (und alle Nicht-LL-NDK-Abhängigkeiten, einschließlich libLLVM.so und libbcc.so ) kopieren /vendor Partition.

Darüber hinaus müssen Anbieter folgende Änderungen vornehmen:

Abbildung 8. Änderungen am Herstellertreiber
  1. Kopieren Sie libclcore.bc in die /vendor Partition. Dadurch wird sichergestellt, dass libclcore.bc , libLLVM.so und libbcc.so synchron sind.
  2. Ändern Sie den Pfad zur ausführbaren bcc Datei, indem Sie RsdCpuScriptImpl::BCC_EXE_PATH aus der RS ​​HAL-Implementierung festlegen.

SELinux-Richtlinie

Die SELinux-Richtlinie wirkt sich sowohl auf den Treiber als auch auf die ausführbaren Dateien des Compilers aus. Alle Treibermodule müssen im file_contexts des Geräts same_process_hal_file gekennzeichnet sein. Zum 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 Herstellerkopie von bcc ( /vendor/bin/bcc ). Zum Beispiel:

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

Ältere Geräte

Legacy-Geräte sind solche, die die folgenden Bedingungen erfüllen:

  1. PRODUCT_SHIPPING_API_LEVEL ist niedriger als 26.
  2. 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, was bedeutet, dass die Treiber weiterhin auf Bibliotheken in /system/lib[64] verlinken können. Aufgrund der Architekturänderung im Zusammenhang mit OVERRIDE_RS_DRIVER muss jedoch android.hardware.renderscript@1.0-impl auf der Partition /vendor installiert werden; Andernfalls wird ein RenderScript-Laufzeit-Fallback auf den CPU-Pfad erzwungen.

Informationen zur Motivation für die Einstellung von Renderscript finden Sie im Android Developers Blog: Android GPU Compute Going Forward . Zu den Ressourceninformationen für diese Einstellung gehören: