RenderScript

RenderScript è un framework per l'esecuzione di attività ad alta intensità di calcolo su Android ad alte prestazioni. È progettata per l'utilizzo con il calcolo parallelo dei dati, anche se i carichi di lavoro seriali possono trarre vantaggio. Il runtime di RenderScript esegue in parallelo il lavoro sui processori disponibili su un dispositivo, ad esempio 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 visione artificiale.

I dispositivi con Android 8.0 e versioni successive utilizzano il seguente framework RenderScript e gli HAL del fornitore:

Figura 1. Codice del fornitore che rimanda alle librerie interne.

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

  • Due istanze di librerie interne di RenderScript in un processo. Un set è per il percorso di riserva della CPU e parte direttamente da /system/lib; l'altro set è per il percorso della GPU e parte da /system/lib/vndk-sp.
  • Le librerie interne di RSA in /system/lib sono create come parte della piattaforma e vengono aggiornate all'upgrade di system.img. Tuttavia, le librerie in /system/lib/vndk-sp vengono compilate per il fornitore e non vengono aggiornate quando viene eseguito l'upgrade di system.img (sebbene possano essere aggiornate per una correzione di sicurezza, il loro ABI rimane invariato).
  • Il codice del fornitore (HAL RS, driver RS e bcc plugin) è collegato alle librerie interne di RenderScript situate in /system/lib/vndk-sp. Non possono eseguire il collegamento alle librerie in /system/lib perché le librerie in quella directory sono compilate per la piattaforma e potrebbero non essere compatibili con il codice del fornitore (ad es. i simboli potrebbero essere rimossi). In questo modo, un aggiornamento OTA solo del framework sarebbe impossibile.

Design

Le sezioni seguenti descrivono nel 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 Vendor NDK per HAL nello stesso processo o VNDK-SP) disponibili per il codice del fornitore e a cui è possibile eseguire il collegamento. Descrive inoltre librerie aggiuntive non correlate a RenderScript, ma fornite anche al codice del fornitore.

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

Librerie RenderScript Libre non di rendering
  • 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 del 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 esecuzione 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, tutti gli HAL dello stesso processo (SP-HAL) tranne RenderScript vengono caricati 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 rigorosa delle librerie RenderScript. Poiché l'implementazione RS deve caricare il bitcode compilato, /data/*/*.so viene aggiunto al percorso dello spazio dei nomi rs (altri SP-HAL non possono caricare librerie dalla partizione dati).

Inoltre, lo spazio dei nomi rs consente più librerie rispetto a 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 riserva 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 dal namespace del linker predefinito in cui è fornita la versione della piattaforma delle librerie RS.

L'implementazione RS HAL del fornitore non viene utilizzata quando si utilizza il percorso di fallback della CPU e viene creato un oggetto RsContext con mVendorDriverName nullo. libRSDriver.so è (per impostazione predefinita) dlopened e il driver lib viene caricato dallo spazio dei nomi default perché il chiamante (libRS_internal.so) viene caricato anche nello spazio dei nomi default.

Figura 3. Percorso di riserva della CPU.

Percorso GPU

Per il percorso della 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 dell'HAL RS) in uno spazio dei nomi del linker diverso chiamato sphal. L'HAL RSdlopen 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 HAL RS (hardware/interfaces/renderscript/1.0/default/Context.cpp). Il nome di questo driver viene quindi dlopen per il contesto RS per il percorso GPU.

La creazione dell'oggetto RsContext è delegata all'implementazione RS HAL. L'HAL richiama il framework RS utilizzando la funzione rsContextCreateVendor() con il nome del driver da usare come argomento. Il framework RS carica quindi il driver specificato quando RsContext viene inizializzato. 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 riserva della GPU.

Durante 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 passa 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 esegue ricerche in /system/lib/vndk-sp, dove risiede 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 raccolta bcc plugin può essere considerata un HAL SP (ovvero un HAL del fornitore che può essere caricato direttamente nel processo di sistema senza essere associato). In qualità di SP-HAL, la libreria bcc-plugin:

  • Non è possibile eseguire il collegamento a librerie solo per framework come libLLVM.so.
  • Può eseguire il collegamento 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, questo valore è specificato nell'opzione -plugin e la libreria viene caricata direttamente da -plugin.bcc Questa opzione abilita un percorso non specifico di Android al progetto LLVM open source.

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 per il 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 la stessa identica libreria utilizzata da ld.mc. In caso contrario, il bitcode compilato potrebbe non trovare un simbolo disponibile quando è stato collegato.

A tale 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.

Criterio SELinux

A seguito delle modifiche ai criteri 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 della vendor partizione. Il criterio della piattaforma lo richiede 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 impostazione viene applicata tramite neverallows.
  • Per evitare conflitti con i 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 contrassegnate come same_process_hal_file.

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

Compatibilità ABI per il codice bit

Se non vengono aggiunte nuove API, ovvero non viene eseguito l'upgrade della versione HAL, i framework RS continueranno a utilizzare il driver GPU esistente (HAL 1.0).

Per modifiche minori all'HAL (HAL 1.1) che non influiscono sul codice bit, i framework dovrebbero eseguire il fallback alla CPU per queste API appena aggiunte e continuare a utilizzare il driver GPU (HAL 1.0) altrove.

Per modifiche importanti all'HAL (HAL 2.0) che interessano la compilazione/il collegamento del codice bit, i framework RS devono scegliere di non caricare i driver GPU forniti dal fornitore e utilizzare invece il percorso CPU o Vulkan per l'accelerazione.

Il consumo del codice bit RenderScript avviene in tre fasi:

Palcoscenico Dettagli
Compila
  • Il codice bit di input (.bc) per bcc deve essere in formato codice bit LLVM 3.2 e bcc deve essere compatibile con le versioni precedenti delle app esistenti.
  • Tuttavia, i metadati in .bc potrebbero cambiare (potrebbero essere presenti nuove funzioni di runtime, ad es. Setter e getter di allocazione, funzioni matematiche e così via). Parte delle funzioni di runtime si trova in libclcore.bc, mentre un'altra parte si trova in LibRSDriver o nell'equivalente del fornitore.
  • Le nuove funzioni di runtime o l'interruzione delle modifiche ai metadati richiedono l'incremento del livello API bitcode. Poiché i driver del fornitore non potranno 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 si applica anche a loro.
Carica
  • libRSCpuRef carica l'oggetto condiviso. In caso di modifiche a questa interfaccia, è necessario un bumper della versione HAL.
  • I fornitori possono fare affidamento su libRSCpuRef per caricare l'oggetto condiviso o implementare il proprio.

Oltre all'HAL, anche le API di runtime e i simboli esportati sono interfacce. Nessuna delle due interfacce è cambiata da Android 7.0 (API 24) e non sono previsti piani immediati per modificarle in Android 8.0 e versioni successive. Tuttavia, se l'interfaccia cambia, aumenta anche la versione HAL.

Implementazioni dei fornitori

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

Moduli del driver

  • 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 di bitcode

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

  1. Richiama il compilatore RenderScript specifico del fornitore in /vendor/bin/ (metodo preferito di compilazione della GPU). Come per gli altri moduli del driver, il codice binario del compilatore del fornitore non può dipendere da librerie di sistema non presenti nell'elenco delle librerie RenderScript disponibili per i fornitori.
  2. Richiama il Ccn del sistema: /system/bin/bcc con un bcc plugin fornito dal fornitore; questo plug-in non può dipendere da alcuna libreria di sistema che non è nell'elenco delle librerie di 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 facilmente rimossa, il fornitore deve copiare bcc (e tutte le dipendenze non LL-NDK, tra cui libLLVM.so, 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 dell'HAL RS.

Criterio SELinux

Il criterio SELinux influisce sia sul driver sia sugli eseguibili del compilatore. Tutti i moduli del driver devono essere etichettati come 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 essere richiamabile 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 precedenti, 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 fallback del runtime di RenderScript viene forzato sul percorso della CPU.

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