Renderskrypt

RenderScript to framework do wykonywania zadań wymagających dużej mocy obliczeniowej z dużą wydajnością na Androidzie. Jest przeznaczony do stosowania w obliczeniach równoległych do danych, chociaż obciążenia szeregowe również mogą na tym skorzystać. Środowisko wykonawcze RenderScript umożliwia równoległą pracę procesorów dostępnych na urządzeniu, takich jak wielordzeniowe procesory CPU i procesory graficzne, umożliwiając programistom skupienie się na wyrażaniu algorytmów zamiast na planowaniu pracy. RenderScript jest szczególnie przydatny w aplikacjach przetwarzających obrazy, fotografię obliczeniową lub wizję komputerową.

Urządzenia z systemem Android 8.0 i nowszym korzystają z następującej platformy RenderScript i warstw HAL dostawców:

Rysunek 1. Kod dostawcy łączący się z bibliotekami wewnętrznymi

Różnice w stosunku do RenderScript w systemie Android 7.x i starszych obejmują:

  • Dwie instancje wewnętrznych bibliotek RenderScript w procesie. Jeden zestaw dotyczy ścieżki awaryjnej procesora i pochodzi bezpośrednio z /system/lib ; drugi zestaw dotyczy ścieżki GPU i pochodzi z /system/lib/vndk-sp .
  • Wewnętrzne biblioteki RS w /system/lib są budowane jako część platformy i są aktualizowane w miarę aktualizacji system.img . Jednakże biblioteki w /system/lib/vndk-sp są zbudowane dla dostawcy i nie są aktualizowane podczas aktualizacji system.img (chociaż można je zaktualizować w celu poprawy bezpieczeństwa, ich ABI pozostaje takie samo).
  • Kod dostawcy (RS HAL, sterownik RS i bcc plugin ) są powiązane z wewnętrznymi bibliotekami RenderScript znajdującymi się w /system/lib/vndk-sp . Nie mogą łączyć się z bibliotekami w /system/lib , ponieważ biblioteki w tym katalogu są zbudowane dla danej platformy i dlatego mogą nie być kompatybilne z kodem dostawcy (tj. symbole mogą zostać usunięte). Takie postępowanie uniemożliwiłoby OTA oparte wyłącznie na frameworku.

Projekt

W poniższych sekcjach szczegółowo opisano projekt RenderScript w systemie Android 8.0 i nowszych wersjach.

Biblioteki RenderScript dostępne dla dostawców

W tej sekcji wymieniono biblioteki RenderScript (znane jako Vendor NDK dla HAL tego samego procesu lub VNDK-SP), które są dostępne dla kodu dostawcy i z którymi można powiązać. Zawiera także szczegółowe informacje na temat dodatkowych bibliotek, które nie są powiązane z RenderScript, ale które są również dostarczane do kodu dostawcy.

Chociaż poniższa lista bibliotek może się różnić w zależności od wersji Androida, jest ona niezmienna w przypadku konkretnej wersji Androida; aktualna lista dostępnych bibliotek znajduje się w /system/etc/ld.config.txt .

Biblioteki RenderScript Biblioteki inne niż 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

Konfiguracja przestrzeni nazw linkera

Ograniczenie łączenia, które zapobiega używaniu przez kod dostawcy bibliotek spoza VNDK-SP, jest wymuszane w czasie wykonywania przy użyciu przestrzeni nazw konsolidatora. (Szczegółowe informacje można znaleźć w prezentacji VNDK Design .)

Na urządzeniu z systemem Android 8.0 i nowszym wszystkie warstwy HAL tego samego procesu (SP-HAL) z wyjątkiem RenderScript są ładowane w przestrzeni nazw konsolidatora sphal . RenderScript jest ładowany do specyficznej dla RenderScript przestrzeni nazw rs , lokalizacji, która umożliwia nieco luźniejsze egzekwowanie bibliotek RenderScript. Ponieważ implementacja RS musi załadować skompilowany kod bitowy, /data/*/*.so jest dodawany do ścieżki przestrzeni nazw rs (inne SP-HAL nie mogą ładować bibliotek z partycji danych).

Ponadto przestrzeń nazw rs umożliwia korzystanie z większej liczby bibliotek, niż jest to przewidziane w innych przestrzeniach nazw. libmediandk.so i libft2.so są dostępne w przestrzeni nazw rs , ponieważ libRS_internal.so ma wewnętrzną zależność od tych bibliotek.

Rysunek 2. Konfiguracja przestrzeni nazw dla linkera

Ładowanie sterowników

Ścieżka zastępcza procesora

W zależności od obecności bitu RS_CONTEXT_LOW_LATENCY podczas tworzenia kontekstu RS wybierana jest ścieżka procesora lub procesora graficznego. Kiedy wybrana jest ścieżka procesora, libRS_internal.so (główna implementacja frameworka RS) jest bezpośrednio dlopen z domyślnej przestrzeni nazw linkera, w której dostępna jest platforma bibliotek RS.

Implementacja RS HAL od dostawcy nie jest w ogóle używana, gdy używana jest ścieżka zastępcza procesora i tworzony jest obiekt RsContext z wartością null mVendorDriverName . libRSDriver.so jest (domyślnie) dlopen , a biblioteka sterownika jest ładowana z default przestrzeni nazw, ponieważ obiekt wywołujący ( libRS_internal.so ) jest również ładowany w default przestrzeni nazw.

Rysunek 4. Ścieżka rezerwowa procesora

Ścieżka GPU

W przypadku ścieżki GPU plik libRS_internal.so jest ładowany inaczej. Po pierwsze, libRS.so używa android.hardware.renderscript@1.0.so (i bazowej libhidltransport.so ) do załadowania android.hardware.renderscript@1.0-impl.so (implementacja RS HAL dostawcy) do innej przestrzeni nazw linkera zwanej sphal . Następnie RS HAL dlopen s libRS_internal.so w innej przestrzeni nazw linkera o nazwie rs .

Dostawcy mogą zapewnić własny sterownik RS, ustawiając flagę czasu kompilacji OVERRIDE_RS_DRIVER , która jest osadzona w implementacji RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp ). Ta nazwa sterownika jest następnie dlopen w kontekście RS dla ścieżki GPU.

Tworzenie obiektu RsContext jest delegowane do implementacji RS HAL. HAL odwołuje się do struktury RS przy użyciu funkcji rsContextCreateVendor() z nazwą sterownika, która ma być używana jako argument. Struktura RS następnie ładuje określony sterownik po zainicjowaniu RsContext . W tym przypadku biblioteka sterowników jest ładowana do przestrzeni rs , ponieważ obiekt RsContext jest tworzony w przestrzeni rs , a /vendor/lib znajduje się w ścieżce wyszukiwania tej przestrzeni nazw.

Rysunek 5. Ścieżka zastępcza GPU

Podczas przejścia z default przestrzeni nazw do przestrzeni nazw sphal , libhidltransport.so używa funkcji android_load_sphal_library() , aby jawnie nakazać dynamicznemu linkerowi załadowanie biblioteki -impl.so z przestrzeni nazw sphal .

Podczas przejścia z przestrzeni nazw sphal do przestrzeni nazw rs ładowanie odbywa się pośrednio za pomocą następującego wiersza w /system/etc/ld.config.txt :

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

Ta linia określa, że ​​dynamiczny linker powinien załadować libRS_internal.so z przestrzeni nazw rs , gdy nie można znaleźć/załadować biblioteki z przestrzeni nazw sphal (co zawsze ma miejsce, ponieważ przestrzeń nazw sphal nie przeszukuje /system/lib/vndk-sp gdzie znajduje się libRS_internal.so ). W tej konfiguracji proste wywołanie dlopen() do libRS_internal.so wystarczy, aby dokonać przejścia przestrzeni nazw.

Ładowanie wtyczki bcc

bcc plugin to biblioteka dostarczona przez dostawcę, załadowana do kompilatora bcc . Ponieważ bcc jest procesem systemowym w katalogu /system/bin , bibliotekę bcc plugin można uznać za SP-HAL (tj. warstwę HAL dostawcy, którą można bezpośrednio załadować do procesu systemowego bez tworzenia powiązania). Jako SP-HAL, biblioteka bcc-plugin :

  • Nie można połączyć się z bibliotekami przeznaczonymi wyłącznie dla platformy, takimi jak libLLVM.so .
  • Można łączyć tylko z bibliotekami VNDK-SP dostępnymi dla dostawcy.

To ograniczenie jest wymuszane poprzez załadowanie bcc plugin do przestrzeni nazw sphal przy użyciu funkcji android_sphal_load_library() . W poprzednich wersjach Androida nazwa wtyczki była określana za pomocą opcji -load , a biblioteka była ładowana za pomocą prostej dlopen() przez libLLVM.so . W Androidzie 8.0 i nowszych jest to określone w opcji -plugin , a biblioteka jest ładowana bezpośrednio przez sam bcc . Ta opcja włącza ścieżkę inną niż Android do projektu LLVM typu open source.

Rysunek 6. Ładowanie wtyczki bcc, Android 7.x i starsze


Rysunek 7. Ładowanie wtyczki bcc, Android 8.0 i nowsze

Wyszukaj ścieżki dla ld.mc

Podczas wykonywania ld.mc niektóre biblioteki wykonawcze RS są podawane jako dane wejściowe do linkera. Kod bitowy RS z aplikacji jest łączony z bibliotekami wykonawczymi, a gdy przekonwertowany kod bitowy jest ładowany do procesu aplikacji, biblioteki wykonawcze są ponownie dynamicznie łączone z przekonwertowanego kodu bitowego.

Biblioteki wykonawcze obejmują:

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • Sterownik RS ( libRSDriver.so lub OVERRIDE_RS_DRIVER )

Ładując skompilowany kod bitowy do procesu aplikacji, podaj dokładnie tę samą bibliotekę, która była używana przez ld.mc . W przeciwnym razie skompilowany kod bitowy może nie znaleźć symbolu, który był dostępny w momencie łączenia.

Aby to zrobić, framework RS używa różnych ścieżek wyszukiwania bibliotek wykonawczych podczas wykonywania ld.mc , w zależności od tego, czy sam framework RS jest ładowany z /system/lib czy z /system/lib/vndk-sp . Można to ustalić, czytając adres dowolnego symbolu biblioteki frameworka RS i używając dladdr() , aby uzyskać odwzorowanie ścieżki pliku na adres.

Polityka SELinuksa

W wyniku zmian zasad SELinux w systemie Android 8.0 i nowszych, musisz przestrzegać określonych zasad (wymuszanych przez neverallows ) podczas oznaczania dodatkowych plików na partycji vendor :

  • vendor_file musi być domyślną etykietą dla wszystkich plików w partycji vendor . Zasady platformy wymagają tego, aby uzyskać dostęp do implementacji warstwy HAL z przekazywaniem.
  • Wszystkie nowe exec_types dodane do partycji vendor za pośrednictwem SEPolicy dostawcy muszą mieć atrybut vendor_file_type . Jest to wymuszane poprzez neverallows .
  • Aby uniknąć konfliktów z przyszłymi aktualizacjami platformy/frameworka, unikaj etykietowania plików innych niż exec_types na partycji vendor .
  • Wszystkie zależności bibliotek dla warstw HAL tego samego procesu zidentyfikowanych przez AOSP muszą być oznaczone etykietą same_process_hal_file .

Aby uzyskać szczegółowe informacje na temat zasad SELinux, zobacz Linux o zwiększonych zabezpieczeniach w systemie Android .

Zgodność ABI z kodem bitowym

Jeśli nie zostaną dodane żadne nowe interfejsy API, co oznacza brak zmiany wersji HAL, frameworki RS będą nadal korzystać z istniejącego sterownika GPU (HAL 1.0).

W przypadku drobnych zmian HAL (HAL 1.1), które nie wpływają na kod bitowy, frameworki powinny powrócić do procesora dla nowo dodanych interfejsów API i nadal używać sterownika GPU (HAL 1.0) w innym miejscu.

W przypadku głównych zmian HAL (HAL 2.0) wpływających na kompilację/łączenie kodu bitowego, platformy RS powinny zdecydować się nie ładować sterowników GPU dostarczonych przez dostawcę i zamiast tego używać ścieżki CPU lub Vulkan do przyspieszania.

Zużywanie kodu bitowego RenderScript odbywa się w trzech etapach:

Scena Detale
Skompilować
  • Wejściowy kod bitowy (.bc) dla bcc musi być w formacie kodu bitowego LLVM 3.2 , a bcc musi być wstecznie kompatybilny z istniejącymi (starszymi) aplikacjami.
  • Jednakże metadane w pliku .bc mogą ulec zmianie (mogą pojawić się nowe funkcje wykonawcze, np. elementy ustawiające alokację ∓ pobierające, funkcje matematyczne itp.). Część funkcji wykonawczych znajduje się w libclcore.bc , część w LibRSDriver lub odpowiedniku dostawcy.
  • Nowe funkcje wykonawcze lub zakłócające zmiany metadanych wymagają zwiększenia poziomu API kodu bitowego. Ponieważ sterowniki dostawców nie będą mogły z niego korzystać, należy również zwiększyć wersję HAL.
  • Dostawcy mogą mieć własne kompilatory, ale wnioski/wymagania dotyczące bcc mają zastosowanie również do tych kompilatorów.
Połączyć
  • Skompilowany plik .o zostanie połączony ze sterownikiem dostawcy, np. libRSDriver_foo.so i libcompiler_rt.so . Ścieżka procesora będzie połączona z libRSDriver.so .
  • Jeśli plik .o wymaga nowego interfejsu API środowiska wykonawczego z libRSDriver_foo , sterownik dostawcy musi zostać zaktualizowany, aby go obsługiwał.
  • Niektórzy dostawcy mogą mieć własne linkery, ale argument za ld.mc ma również zastosowanie do nich.
Obciążenie
  • libRSCpuRef ładuje udostępniony obiekt. Jeśli w tym interfejsie zostaną wprowadzone zmiany, konieczna jest aktualizacja wersji HAL.
  • Dostawcy albo polegają na libRSCpuRef , aby załadować udostępniony obiekt, albo implementują własny.

Oprócz warstwy HAL interfejsami są także interfejsy API środowiska wykonawczego i eksportowane symbole. Żaden z interfejsów nie uległ zmianie od czasu Androida 7.0 (API 24) i nie ma bezpośrednich planów jego zmiany w Androidzie 8.0 i nowszych wersjach. Jeśli jednak interfejs ulegnie zmianie, wersja HAL również ulegnie zmianie.

Wdrożenia dostawców

Android 8.0 i nowsze wymagają pewnych zmian w sterowniku GPU, aby sterownik GPU działał poprawnie.

Moduły sterowników

  • Moduły sterowników nie mogą zależeć od żadnych bibliotek systemowych, których nie ma na liście .
  • Sterownik musi dostarczyć własny android.hardware.renderscript@1.0-impl_{NAME} lub zadeklarować domyślną implementację android.hardware.renderscript@1.0-impl jako swoją zależność.
  • Implementacja procesora libRSDriver.so jest dobrym przykładem usuwania zależności innych niż VNDK-SP.

Kompilator kodu bitowego

Kod bitowy RenderScript dla sterownika dostawcy można skompilować na dwa sposoby:

  1. Wywołaj kompilator RenderScript specyficzny dla dostawcy w /vendor/bin/ (preferowana metoda kompilacji GPU). Podobnie jak inne moduły sterowników, plik binarny kompilatora dostawcy nie może zależeć od żadnej biblioteki systemowej, której nie ma na liście bibliotek RenderScript dostępnych dla dostawców .
  2. Wywołaj system bcc: /system/bin/bcc za pomocą bcc plugin dostarczonej przez dostawcę; ta wtyczka nie może zależeć od żadnej biblioteki systemowej, której nie ma na liście bibliotek RenderScript dostępnych dla dostawców .

Jeśli bcc plugin dostawcy musi zakłócać kompilację procesora i nie można łatwo usunąć jej zależności od libLLVM.so , sprzedawca powinien skopiować bcc (i wszystkie zależności inne niż LL-NDK, w tym libLLVM.so , libbcc.so ) do partycja /vendor .

Ponadto dostawcy muszą wprowadzić następujące zmiany:

Rysunek 8. Zmiany w sterowniku dostawcy
  1. Skopiuj libclcore.bc na partycję /vendor . Zapewnia to synchronizację libclcore.bc , libLLVM.so i libbcc.so .
  2. Zmień ścieżkę do pliku wykonywalnego bcc , ustawiając RsdCpuScriptImpl::BCC_EXE_PATH z implementacji RS HAL.

Polityka SELinuksa

Polityka SELinux dotyczy zarówno sterownika, jak i plików wykonywalnych kompilatora. Wszystkie moduły sterowników muszą być oznaczone etykietą same_process_hal_file w file_contexts urządzenia. Na przykład:

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

Plik wykonywalny kompilatora musi umożliwiać wywołanie procesu aplikacji, podobnie jak kopia bcc dostawcy ( /vendor/bin/bcc ). Na przykład:

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

Starsze urządzenia

Starsze urządzenia to takie, które spełniają następujące warunki:

  1. PRODUCT_SHIPPING_API_LEVEL jest niższy niż 26.
  2. PRODUCT_FULL_TREBLE_OVERRIDE nie jest zdefiniowany.

W przypadku starszych urządzeń ograniczenia nie są egzekwowane podczas aktualizacji do Androida 8.0 i nowszych wersji, co oznacza, że ​​sterowniki mogą nadal łączyć się z bibliotekami w /system/lib[64] . Jednakże ze względu na zmianę architektury związaną z OVERRIDE_RS_DRIVER , android.hardware.renderscript@1.0-impl musi być zainstalowany na partycji /vendor ; w przeciwnym razie zmusza środowisko wykonawcze RenderScript do powrotu do ścieżki procesora.

Informacje na temat powodów wycofania skryptu Renderscript można znaleźć na blogu deweloperów systemu Android: Android GPU Compute Going Forward . Informacje o zasobach dotyczące tego wycofania obejmują: