RenderScript

RenderScript è un framework per l'esecuzione di attività ad alta intensità di calcolo con prestazioni elevate su Android. È progettata per l'utilizzo con il calcolo parallelo dei dati, anche se possono trarne vantaggio anche i workload seriali. Il runtime di RenderScript parallelizza il lavoro tra i processori disponibili su un dispositivo, come CPU e GPU multi-core, consentendo agli sviluppatori di concentrarsi sull'espressione degli algoritmi anziché sulla pianificazione del lavoro. RenderScript è particolarmente utile per le app che eseguono l'elaborazione delle immagini, la fotografia computazionale o la computer vision.

I dispositivi con Android 8.0 e versioni successive utilizzano i seguenti framework RenderScript e HAL dei fornitori:

Figura 1. Collegamento del codice fornitore alle librerie interne.

Le differenze rispetto a RenderScript in Android 7.x e versioni precedenti includono:

  • Due istanze delle librerie interne di RenderScript in un processo. Un set è per il percorso di fallback della CPU e proviene direttamente da /system/lib; l'altro set è per il percorso della GPU e proviene da /system/lib/vndk-sp.
  • Le librerie interne RS in /system/lib vengono create nell'ambito della piattaforma e vengono aggiornate man mano che system.img viene sottoposto a upgrade. Tuttavia, le librerie in /system/lib/vndk-sp sono create per il fornitore e non vengono aggiornate quando system.img viene aggiornato (anche se possono essere aggiornate per una correzione di sicurezza, la loro ABI rimane la stessa).
  • Il codice del fornitore (RS HAL, RS driver e bcc plugin) è collegato alle librerie interne di RenderScript che si trovano in /system/lib/vndk-sp. Non possono essere collegati a librerie in /system/lib perché le librerie in questa directory sono create per la piattaforma e pertanto potrebbero non essere compatibili con il codice del fornitore (ovvero i simboli potrebbero essere rimossi). In questo modo, un aggiornamento OTA solo del framework sarebbe impossibile.

Design

Le sezioni seguenti descrivono in dettaglio la progettazione di RenderScript in Android 8.0 e versioni successive.

Librerie RenderScript disponibili per i fornitori

Questa sezione elenca le librerie RenderScript (note come NDK for Same-Process HAL o VNDK-SP) disponibili per il codice del fornitore e che possono essere collegate a. Inoltre, vengono descritte in dettaglio librerie aggiuntive non correlate a RenderScript, ma fornite anche al codice del fornitore.

Sebbene il seguente elenco di librerie possa variare tra le release di Android, è immutabile per una release specifica di Android. Per un elenco aggiornato delle librerie disponibili, consulta /system/etc/ld.config.txt.

Librerie RenderScript Librerie 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

Configurazione dello spazio dei nomi Linker

La limitazione del collegamento che impedisce l'utilizzo delle librerie non presenti in VNDK-SP da parte del codice del fornitore viene applicata in fase di runtime utilizzando lo spazio dei nomi del linker. Per maggiori dettagli, consulta la presentazione VNDK Design.

Su un dispositivo con Android 8.0 e versioni successive, tutte le HAL Same-Process (SP-HAL) ad eccezione di RenderScript vengono caricate all'interno dello spazio dei nomi del linker sphal. RenderScript viene caricato nello spazio dei nomi rs specifico di RenderScript, una posizione che consente un'applicazione leggermente meno rigida per le librerie RenderScript. Poiché l'implementazione di RS deve caricare il bitcode compilato, /data/*/*.so viene aggiunto al percorso dello spazio dei nomi rs (altre SP-HAL non sono autorizzate a caricare librerie dalla partizione di dati).

Inoltre, lo spazio dei nomi rs consente più librerie di quelle fornite da altri spazi dei nomi. libmediandk.so e libft2.so sono esposti allo spazio dei nomi rs perché libRS_internal.so ha una dipendenza interna da queste librerie.

Figura 2. Configurazione dello spazio dei nomi per il linker.

Carica i driver

Percorso di fallback della CPU

A seconda dell'esistenza del bit RS_CONTEXT_LOW_LATENCY durante la creazione di un contesto RS, viene selezionato il percorso della CPU o della GPU. Quando viene selezionato il percorso della CPU, libRS_internal.so (l'implementazione principale del framework RS) viene dlopen direttamente dallo spazio dei nomi del linker predefinito in cui vengono fornite le versioni della piattaforma delle librerie RS.

L'implementazione dell'HAL RS del fornitore non viene utilizzata affatto quando viene utilizzato il percorso di riserva della CPU e viene creato un oggetto RsContext con mVendorDriverName null. libRSDriver.so è (per impostazione predefinita) dlopened e la libreria del driver viene caricata dallo spazio dei nomi default perché anche il chiamante (libRS_internal.so) viene caricato nello spazio dei nomi default.

Figura 3. Percorso di fallback della CPU.

Percorso GPU

Per il percorso GPU, libRS_internal.so viene caricato in modo diverso. Innanzitutto, libRS.so utilizza android.hardware.renderscript@1.0.so (e il relativo libhidltransport.so) per caricare android.hardware.renderscript@1.0-impl.so (un'implementazione del fornitore di RS HAL) in uno spazio dei nomi del linker diverso chiamato sphal. L'HAL RS dlopen libRS_internal.so in un altro spazio dei nomi del linker chiamato rs.

I fornitori possono fornire il proprio driver RS impostando il flag di compilazione OVERRIDE_RS_DRIVER, incorporato nell'implementazione dell'HAL RS (hardware/interfaces/renderscript/1.0/default/Context.cpp). Il nome del driver viene quindi dlopen per il contesto RS per il percorso della GPU.

La creazione dell'oggetto RsContext viene delegata all'implementazione di RS HAL. L'HAL richiama il framework RS utilizzando la funzione rsContextCreateVendor() con il nome del driver da utilizzare come argomento. Il framework RS carica quindi il driver specificato quando viene inizializzato RsContext. In questo caso, la libreria del driver viene caricata nello spazio dei nomi rs perché l'oggetto RsContext viene creato all'interno dello spazio dei nomi rs e /vendor/lib si trova nel percorso di ricerca dello spazio dei nomi.

Figura 4. Percorso di fallback della GPU.

Quando esegui la transizione dallo spazio dei nomi default allo spazio dei nomi sphal, libhidltransport.so utilizza la funzione android_load_sphal_library() per ordinare esplicitamente al linker dinamico di caricare la libreria -impl.so dallo spazio dei nomi sphal.

Quando si esegue la transizione dallo spazio dei nomi sphal allo spazio dei nomi rs, il caricamento viene eseguito indirettamente dalla seguente riga in /system/etc/ld.config.txt:

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

Questa riga specifica che il linker dinamico deve caricare libRS_internal.so dallo spazio dei nomi rs quando la libreria non può essere trovata/caricata dallo spazio dei nomi sphal (il che accade sempre perché lo spazio dei nomi sphal non cerca /system/lib/vndk-sp dove si trova libRS_internal.so). Con questa configurazione, una semplice chiamata dlopen() a libRS_internal.so è sufficiente per eseguire la transizione dello spazio dei nomi.

Carica il plug-in Ccn

bcc plugin è una libreria fornita dal fornitore caricata nel compilatore bcc. Poiché bcc è un processo di sistema nella directory /system/bin, la libreria bcc plugin può essere considerata una SP-HAL (ovvero una HAL del fornitore che può essere caricata direttamente nel processo di sistema senza essere binderizzata). In qualità di SP-HAL, la libreria bcc-plugin:

  • Impossibile eseguire il collegamento a librerie solo framework come libLLVM.so.
  • Può essere collegato solo alle librerie VNDK-SP disponibili per il fornitore.

Questa limitazione viene applicata caricando bcc plugin nello spazio dei nomi sphal utilizzando la funzione android_sphal_load_library(). Nelle versioni precedenti di Android, il nome del plug-in veniva specificato utilizzando l'opzione -load e la libreria veniva caricata utilizzando il semplice dlopen() da libLLVM.so. In Android 8.0 e versioni successive, questa opzione è specificata in -plugin e la libreria viene caricata direttamente da bcc. Questa opzione consente un percorso non specifico per Android al progetto open source LLVM.

Figura 5. Caricamento del plug-in bcc, Android 7.x e versioni precedenti.



Figura 6. Caricamento del plug-in bcc, Android 8.0 e versioni successive.

Percorsi di ricerca per ld.mc

Durante l'esecuzione di ld.mc, alcune librerie di runtime RS vengono fornite come input al linker. Il bitcode RS dell'app è collegato alle librerie di runtime e quando il bitcode convertito viene caricato in un processo dell'app, le librerie di runtime vengono nuovamente collegate dinamicamente dal bitcode convertito.

Le librerie di runtime includono:

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • Driver RS (libRSDriver.so o OVERRIDE_RS_DRIVER)

Quando carichi il bitcode compilato nel processo dell'app, fornisci esattamente la stessa libreria utilizzata da ld.mc. In caso contrario, il bitcode compilato potrebbe non trovare un simbolo disponibile al momento del collegamento.

A questo scopo, il framework RS utilizza percorsi di ricerca diversi per le librerie di runtime durante l'esecuzione di ld.mc, a seconda che il framework RS stesso sia caricato da /system/lib o da /system/lib/vndk-sp. Questo può essere determinato leggendo l'indirizzo di un simbolo arbitrario di una libreria del framework RS e utilizzando dladdr() per ottenere il percorso del file mappato all'indirizzo.

Policy SELinux

A seguito delle modifiche alle norme SELinux in Android 8.0 e versioni successive, devi seguire regole specifiche (applicate tramite neverallows) quando etichetti file aggiuntivi nella partizione vendor:

  • vendor_file deve essere l'etichetta predefinita per tutti i file nella partizione vendor. Il criterio della piattaforma richiede questo per accedere alle implementazioni HAL passthrough.
  • Tutti i nuovi exec_types aggiunti nella partizione vendor tramite SEPolicy del fornitore devono avere l'attributo vendor_file_type. Questa operazione viene applicata tramite neverallows.
  • Per evitare conflitti con futuri aggiornamenti della piattaforma/del framework, evita di etichettare file diversi da exec_types nella partizione vendor.
  • Tutte le dipendenze della libreria per gli HAL dello stesso processo identificati da AOSP devono essere etichettate come same_process_hal_file.

Per informazioni dettagliate sui criteri SELinux, vedi Security-Enhanced Linux in Android.

Compatibilità ABI per bitcode

Se non vengono aggiunte nuove API, il che significa nessun aumento della versione HAL, i framework RS continueranno a utilizzare il driver GPU (HAL 1.0) esistente.

Per le modifiche HAL secondarie (HAL 1.1) che non influiscono sul bitcode, i framework devono tornare alla CPU per queste API appena aggiunte e continuare a utilizzare il driver della GPU (HAL 1.0) altrove.

Per le modifiche principali all'HAL (HAL 2.0) che influiscono sulla compilazione/collegamento del bitcode, i framework RS non devono caricare i driver GPU forniti dal fornitore e devono invece utilizzare il percorso della CPU o di Vulkan per l'accelerazione.

L'utilizzo del bitcode RenderScript avviene in tre fasi:

Palco Dettagli
Compila
  • Il bitcode di input (.bc) per bcc deve essere nel formato bitcode LLVM 3.2 e bcc deve essere compatibile con le versioni precedenti delle app esistenti (legacy).
  • Tuttavia, i metadati in .bc potrebbero cambiare (potrebbero esserci nuove funzioni di runtime, ad esempio setter e getter di allocazione, funzioni matematiche e così via. Parte delle funzioni di runtime si trova in libclcore.bc, parte in LibRSDriver o nell'equivalente del fornitore.
  • Le nuove funzioni di runtime o le modifiche ai metadati che causano interruzioni richiedono l'incremento del livello API bitcode. Poiché i driver del fornitore non saranno in grado di utilizzarlo, anche la versione HAL deve essere incrementata.
  • I fornitori potrebbero avere i propri compilatori, ma le conclusioni/i requisiti per bcc si applicano anche a questi compilatori.
Link
  • Il file .o compilato verrà collegato al driver del fornitore, ad esempio: libRSDriver_foo.so e libcompiler_rt.so. Il percorso della CPU si collegherà a libRSDriver.so.
  • Se .o richiede una nuova API di runtime da libRSDriver_foo, il driver del fornitore deve essere aggiornato per supportarla.
  • Alcuni fornitori potrebbero avere i propri linker, ma l'argomento per ld.mc vale anche per loro.
Carica
  • libRSCpuRef carica l'oggetto condiviso. Se vengono apportate modifiche a questa interfaccia, è necessario aumentare la versione HAL.
  • I fornitori si affidano a libRSCpuRef per caricare l'oggetto condiviso o implementano il proprio.

Oltre all'HAL, anche le API di runtime e i simboli esportati sono interfacce. Nessuna interfaccia è stata modificata da Android 7.0 (API 24) e non sono previste modifiche immediate in Android 8.0 e versioni successive. Tuttavia, se l'interfaccia cambia, anche la versione HAL aumenterà.

Implementazioni dei fornitori

Android 8.0 e versioni successive richiedono alcune modifiche al driver della GPU per il corretto funzionamento del driver.

Moduli del conducente

  • I moduli del driver non devono dipendere da librerie di sistema non presenti nell'elenco.
  • Il driver deve fornire il proprio android.hardware.renderscript@1.0-impl_{NAME} o dichiarare l'implementazione predefinita android.hardware.renderscript@1.0-impl come dipendenza.
  • L'implementazione della CPU libRSDriver.so è un buon esempio di come rimuovere le dipendenze non VNDK-SP.

Compilatore bitcode

Puoi compilare il bitcode RenderScript per il driver del fornitore in due modi:

  1. Invoca il compilatore RenderScript specifico del fornitore in /vendor/bin/ (metodo preferito di compilazione della GPU). Analogamente ad altri moduli del driver, il binario del compilatore del fornitore non può dipendere da alcuna libreria di sistema che non sia presente nell'elenco delle librerie RenderScript disponibili per i fornitori.
  2. Richiama il sistema Ccn: /system/bin/bcc con un bcc plugin fornito dal fornitore; questo plug-in non può dipendere da alcuna libreria di sistema che non sia presente nell'elenco delle librerie RenderScript disponibili per i fornitori.

Se il fornitore bcc plugin deve interferire con la compilazione della CPU e la sua dipendenza da libLLVM.so non può essere rimossa facilmente, deve copiare bcc (e tutte le dipendenze non LL-NDK, incluse libLLVM.so e libbcc.so) nella partizione /vendor.

Inoltre, i fornitori devono apportare le seguenti modifiche:

Figura 7. Modifiche al driver del fornitore.

  1. Copia libclcore.bc nella partizione /vendor. In questo modo libclcore.bc, libLLVM.so e libbcc.so sono sincronizzati.
  2. Modifica il percorso del file eseguibile bcc impostando RsdCpuScriptImpl::BCC_EXE_PATH dall'implementazione di RS HAL.

Policy SELinux

Il criterio SELinux interessa sia il driver che gli eseguibili del compilatore. Tutti i moduli driver devono essere etichettati same_process_hal_file nel file_contexts del dispositivo. Ad esempio:

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

L'eseguibile del compilatore deve poter essere richiamato da un processo dell'app, così come la copia del fornitore di bcc (/vendor/bin/bcc). Ad esempio:

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

Dispositivi legacy

I dispositivi legacy sono quelli che soddisfano le seguenti condizioni:

  1. PRODUCT_SHIPPING_API_LEVEL è inferiore a 26.
  2. PRODUCT_FULL_TREBLE_OVERRIDE non è definito.

Per i dispositivi legacy, le limitazioni non vengono applicate durante l'upgrade ad Android 8.0 e versioni successive, il che significa che i driver possono continuare a collegarsi alle librerie in /system/lib[64]. Tuttavia, a causa della modifica dell'architettura relativa a OVERRIDE_RS_DRIVER, android.hardware.renderscript@1.0-impl deve essere installato nella partizione /vendor; in caso contrario, il runtime di RenderScript torna al percorso della CPU.

Per informazioni sul motivo del ritiro di RenderScript, consulta il blog per sviluppatori Android: Android GPU Compute Going Forward. Le informazioni sulle risorse per questo ritiro includono quanto segue: