Script di rendering

RenderScript è un framework per l'esecuzione di attività computazionalmente intensive ad alte prestazioni su Android. È progettato per l'uso con il calcolo parallelo dei dati, sebbene anche i carichi di lavoro seriali possano trarne vantaggio. Il runtime RenderScript parallelizza il lavoro tra i processori disponibili su un dispositivo, come CPU e GPU multi-core, consentendo agli sviluppatori di concentrarsi sull'espressione di algoritmi piuttosto che sulla pianificazione del lavoro. RenderScript è particolarmente utile per le applicazioni 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 dei fornitori:

Figura 1. Codice del fornitore collegato 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 fallback della CPU e proviene direttamente da /system/lib ; l'altro set è per il percorso GPU e proviene da /system/lib/vndk-sp .
  • Le librerie interne di RS in /system/lib sono create come parte della piattaforma e vengono aggiornate man mano che system.img viene aggiornato. Tuttavia, le librerie in /system/lib/vndk-sp sono create per il fornitore e non vengono aggiornate quando system.img viene aggiornato (sebbene possano essere aggiornate per una correzione di sicurezza, il loro ABI rimane lo stesso).
  • Il codice del fornitore (RS HAL, driver RS ​​e bcc plugin ) è collegato alle librerie interne di RenderScript situate in /system/lib/vndk-sp . Non possono collegarsi alle librerie in /system/lib perché le librerie in quella directory sono costruite per la piattaforma e quindi potrebbero non essere compatibili con il codice del fornitore (cioè i simboli potrebbero essere rimossi). Ciò renderebbe impossibile un’OTA basata solo sul framework.

Progetto

Le sezioni seguenti descrivono in dettaglio la progettazione 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 Same-Process o VNDK-SP) disponibili per il codice del fornitore e a cui è possibile collegare. Fornisce inoltre dettagli sulle librerie aggiuntive che non sono correlate a RenderScript ma che vengono fornite anche al codice del fornitore.

Sebbene il seguente elenco di librerie possa differire tra le versioni Android, è immutabile per una specifica versione Android; per un elenco aggiornato delle librerie disponibili, fare riferimento a /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 del linker

La restrizione di collegamento che impedisce alle librerie non presenti in VNDK-SP di essere utilizzate dal codice del fornitore viene applicata in fase di esecuzione utilizzando lo spazio dei nomi del linker. (Per i dettagli, fare riferimento alla presentazione VNDK Design .)

Su un dispositivo che esegue Android 8.0 e versioni successive, tutti gli HAL Same-Process (SP-HAL) tranne RenderScript vengono caricati all'interno dello spazio dei nomi del linker sphal . RenderScript viene caricato nello spazio dei nomi specifico di RenderScript rs , una posizione che consente un'applicazione leggermente più flessibile per le librerie RenderScript. Poiché l'implementazione RS deve caricare il codice bit compilato, /data/*/*.so viene aggiunto al percorso dello spazio dei nomi rs (ad altri SP-HAL non è consentito caricare librerie dalla partizione 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

Caricamento dei 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 CPU o 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 viene fornita la versione della piattaforma delle librerie RS.

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

Figura 4. 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 suo sottostante 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 quindi 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 del tempo di compilazione OVERRIDE_RS_DRIVER , che è incorporato nell'implementazione RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp ). Questo nome di 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 utilizzare come argomento. Il framework RS carica quindi il driver specificato quando viene inizializzato RsContext . In questo caso, la libreria dei 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 5. Percorso di fallback 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 .

Durante 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 dovrebbe caricare libRS_internal.so dallo spazio dei nomi rs quando la lib non può essere trovata/caricata dallo spazio dei nomi sphal (che è sempre così perché lo spazio dei nomi sphal non cerca /system/lib/vndk-sp dove risiede libRS_internal.so ). Con questa configurazione, una semplice chiamata dlopen() a libRS_internal.so è sufficiente per effettuare la transizione dello spazio dei nomi.

Caricamento del plugin 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 un SP-HAL (ovvero un HAL del fornitore che può essere caricato direttamente nel processo di sistema senza essere binderizzato). Come SP-HAL, la libreria bcc-plugin :

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

Questa restrizione viene applicata caricando il bcc plugin nello spazio dei nomi sphal utilizzando la funzione android_sphal_load_library() . Nelle versioni precedenti di Android, il nome del plugin veniva specificato utilizzando l'opzione -load e la lib veniva caricata utilizzando il semplice dlopen() di libLLVM.so . In Android 8.0 e versioni successive, questo è specificato nell'opzione -plugin e la lib viene caricata direttamente dal bcc stesso. Questa opzione abilita un percorso non specifico per Android al progetto LLVM open source.

Figura 6. Caricamento del plugin bcc, Android 7.x e versioni precedenti


Figura 7. Caricamento del plugin bcc, Android 8.0 e versioni successive

Percorsi di ricerca per ld.mc

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

Le librerie di runtime includono:

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

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

Per fare ciò, il framework RS utilizza diversi percorsi di ricerca per le librerie di runtime durante l'esecuzione ld.mc , a seconda che il framework RS stesso venga 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.

Politica SELinux

Come risultato delle modifiche alla policy SELinux in Android 8.0 e versioni successive, è necessario seguire regole specifiche (applicate tramite neverallows ) quando si etichettano file aggiuntivi nella partizione vendor :

  • vendor_file deve essere l'etichetta predefinita per tutti i file nella partizione vendor . La policy 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 . Questo viene applicato tramite neverallows .
  • Per evitare conflitti con futuri aggiornamenti della piattaforma/framework, evitare 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 etichettati come same_process_hal_file .

Per dettagli sulla policy SELinux, vedere Linux con sicurezza avanzata in Android .

Compatibilità ABI per bitcode

Se non vengono aggiunte nuove API, il che significa che non viene apportata alcuna modifica alla 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 bitcode, i framework dovrebbero eseguire il fallback sulla CPU per queste API appena aggiunte e continuare a utilizzare il driver GPU (HAL 1.0) altrove.

Per le principali modifiche HAL (HAL 2.0) che influiscono sulla compilazione/collegamento del codice bit, i framework RS dovrebbero 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
Compilare
  • Il codice bit di input (.bc) per bcc deve essere nel formato codice bit 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 runtime, ad esempio, setter di allocazione ∓ getter, funzioni matematiche, ecc.). Parte delle funzioni runtime si trova in libclcore.bc , parte di esse si trova in LibRSDriver o in un equivalente del fornitore.
  • Nuove funzioni di runtime o modifiche sostanziali ai metadati richiedono l'incremento del livello API del codice bit. Poiché i driver del fornitore non saranno in grado di utilizzarlo, è necessario incrementare anche la versione dell'HAL.
  • I fornitori possono avere i propri compilatori, ma le conclusioni/requisiti per bcc si applicano anche a tali compilatori.
Collegamento
  • Il file .o compilato sarà 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 runtime da libRSDriver_foo , il driver del fornitore deve essere aggiornato per supportarlo.
  • Alcuni fornitori potrebbero avere i propri linker, ma l'argomento a favore di ld.mc si applica anche a loro.
Carico
  • libRSCpuRef carica l'oggetto condiviso. Se sono presenti modifiche a questa interfaccia, è necessario un upgrade della versione HAL.
  • I fornitori si affiderebbero a libRSCpuRef per caricare l'oggetto condiviso o ne implementerebbero uno proprio.

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

Implementazioni del fornitore

Android 8.0 e versioni successive richiedono alcune modifiche al driver GPU affinché il driver GPU funzioni correttamente.

Moduli driver

  • I moduli 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 codici bit

È possibile 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 GPU). Similmente ad altri moduli driver, il binario del compilatore del fornitore non può dipendere da alcuna libreria di sistema che non sia nell'elenco delle librerie RenderScript disponibili ai fornitori .
  2. Richiama system bcc: /system/bin/bcc con un bcc plugin fornito dal fornitore; questo plugin non può dipendere da alcuna libreria di sistema che non sia nell'elenco delle librerie RenderScript disponibili per i fornitori .

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

Inoltre, i fornitori devono apportare le seguenti modifiche:

Figura 8. Modifiche al driver del fornitore
  1. Copia libclcore.bc nella partizione /vendor . Ciò garantisce libclcore.bc , libLLVM.so e libbcc.so siano sincronizzati.
  2. Modificare il percorso dell'eseguibile bcc impostando RsdCpuScriptImpl::BCC_EXE_PATH dall'implementazione RS HAL.

Politica SELinux

La politica di SELinux influenza sia il driver che gli eseguibili del compilatore. Tutti i moduli driver devono essere etichettati same_process_hal_file nel file_contexts del dispositivo. Per 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 ). Per 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 restrizioni non vengono applicate durante l'aggiornamento 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, si forza il fallback del runtime RenderScript sul percorso della CPU.

Per informazioni sulla motivazione della deprecazione di Renderscript, vedere il blog degli sviluppatori Android: Android GPU Compute Going Forward . Le informazioni sulle risorse per questa deprecazione includono quanto segue: