RenderScript

RenderScript 是一種架構,用於執行大量運算 在 Android 裝置上提供高效能的任務專為搭配 即便是序列工作負載也能受益。 RenderScript 執行階段會透過 例如多核心 CPU 和 GPU 而非安排工作時程。RenderScript 特別容易 對於執行影像處理、計算圖像的應用程式 像是「攝影、攝影或電腦視覺」

搭載 Android 8.0 以上版本的裝置使用下列 RenderScript 架構與供應商 HAL:

圖 1. 連結至內部程式庫的供應商程式碼。

Android 7.x 以下版本的 RenderScript 差異包括:

  • 程序中有兩個 RenderScript 內部程式庫執行個體。一組適用於 CPU 備用路徑,且來自於 /system/lib;另一個 設定的是 /system/lib/vndk-sp 路徑,且用於 GPU 路徑。
  • /system/lib 中的 RS 內部程式庫內建 且會在升級 system.img 時更新。不過,libs /system/lib/vndk-sp 是為供應商所設計,而非 system.img 升級時更新 (可更新) 如要解決安全性問題,則 ABI 將保持不變)。
  • 供應商代碼 (RS HAL、RS 驅動程式和 bcc plugin) 為 連結至位於下列位置的 RenderScript 內部程式庫 /system/lib/vndk-sp。無法與 的程式庫建立連結 /system/lib,因為該目錄中的程式庫是為 平台,因此可能與供應商程式碼 (即符號) 不相容 可能會遭到移除)。否則就無法使用僅適用於架構的 OTA。

設計

以下各節將詳細說明 Android 8.0 以上版本的 RenderScript 設計。

供應商可使用的 RenderScript 程式庫

本節列出 RenderScript 程式庫 (也稱為 Same-Process 的廠商 NDK) HAL 或 VNDK-SP)。 下定決心其中也會列出與 RenderScript,但也會提供給供應商程式碼使用。

雖然下列程式庫清單可能因 Android 版本而異, 在特定 Android 版本中無法變更即可查看最新 請參閱 /system/etc/ld.config.txt

RenderScript 程式庫 非 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

連接器命名空間設定

連結限制可避免有人使用不在 VNDK-SP 中的程式庫 系統會在執行階段使用連接器命名空間強制執行供應商程式碼。(詳情請參閱 請參閱 VNDK 設計 簡報)。

在搭載 Android 8.0 以上版本的裝置上,所有相同程序 HAL (SP-HAL) RenderScript 除外 sphal。RenderScript 會載入 RenderScript 專屬 命名空間 rs,這個位置會稍微增加 RenderScript 程式庫的違規處置由於必須載入 RS 實作 經過編譯的位元碼,/data/*/*.so 會新增到 rs 命名空間 (不允許其他 SP-HAL 從 資料分區)。

此外,rs 命名空間允許的程式庫比提供給 其他命名空間「libmediandk.so」和「libft2.so」 暴露在 rs 命名空間中 libRS_internal.so 對這些程式庫具有內部依附元件。

圖 2. 連接器的命名空間設定。

載入驅動程式

CPU 備用路徑

RS_CONTEXT_LOW_LATENCY 位元的存在而定 建立 RS 結構定義時,系統會選取 CPU 或 GPU 路徑。當 已選取 CPU 路徑,libRS_internal.so (主要實作方式) 的 RS 架構) 直接dlopen自預設連接器 提供 RS 程式庫平台版本的命名空間。

CPU 作業期間完全不使用供應商的 RS HAL 實作 建立備用路徑後,系統就會建立 RsContext 物件 空值 mVendorDriverNamelibRSDriver.so 是 (撰寫者: 預設值) dlopen 以及從 default 命名空間,因為呼叫端 (libRS_internal.so) 也會在 default 中載入 命名空間

圖 3. CPU 備用路徑。

GPU 路徑

對於 GPU 路徑,libRS_internal.so 的載入方式會有所不同。 首先,libRS.so 會使用 android.hardware.renderscript@1.0.so (及其基礎) libhidltransport.so) 以載入 android.hardware.renderscript@1.0-impl.so (供應商 RS HAL) 導入另一個名為 sphal。零售業務員 HAL,然後在另一個情境下 dlopenlibRS_internal.so 名為 rs 的連結器命名空間。

供應商可以設定建構時間標記,提供自己的 RS 驅動程式 OVERRIDE_RS_DRIVER,已嵌入 RS HAL 模式 (hardware/interfaces/renderscript/1.0/default/Context.cpp)。這個 然後針對 GPU 路徑的 RS 結構定義執行 dlopen 的驅動程式名稱。

RsContext 物件的建立作業會委派給 RS HAL 。HAL 會使用 rsContextCreateVendor() 函式,其中包含要接收資料的驅動程式名稱 做為引數接著,RS 架構會在 RsContext 已初始化。在這個案例中,驅動程式程式庫 載入到 rs 命名空間中,因為 RsContext 物件是在 rs 命名空間內建立 /vendor/lib 位於命名空間的搜尋路徑中。

圖 4. GPU 備用路徑。

default 命名空間轉換至 sphal 命名空間,libhidltransport.so 會使用 android_load_sphal_library() 函式,明確排序 要從 HTTP 連接器載入 -impl.so 程式庫 sphal 命名空間。

sphal 命名空間轉換至 rs 命名空間,載入作業是由下列程式碼間接完成, /system/etc/ld.config.txt:

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

此行會指定應載入動態連接器 在執行 lib 時,來自 rs 命名空間的 libRS_internal.sosphal 命名空間找不到/載入該命名空間 (系統一律會 這是因為 sphal 命名空間 /system/lib/vndk-sp地點libRS_internal.so 居住地)。使用這項設定時,您只需要呼叫一個簡單的 dlopen() 呼叫, libRS_internal.so 已足以進行命名空間轉換。

載入密件副本外掛程式

bcc plugin」是供應商提供的程式庫,會載入到 bcc 編譯器。因為 bcc 是以下項目的系統程序: /system/bin 目錄,bcc plugin 程式庫可以是 視為 SP-HAL (亦即可直接載入至 無法繫結至容器的系統程序)。做為 SP-HAL bcc-plugin 程式庫:

  • 無法連結至僅限架構的程式庫,例如 libLLVM.so
  • 只能連結至供應商可用的 VNDK-SP 程式庫。

bcc plugin 載入至 sphal 命名空間使用 android_sphal_load_library() 函式。舊版 Android 的外掛程式名稱使用 -load 選項指定,然後 是透過以下簡單的 dlopen() 載入 lib libLLVM.so。如果是 Android 8.0 以上版本,可以在 -plugin 選項和 lib 會由 bcc 本身。這個選項可讓 開放原始碼 LLVM 專案

圖 5. 正在載入密件副本外掛程式 (Android 7.x 以下版本)。



圖 6. 正在載入密件副本外掛程式 (Android 8.0 以上版本)。

ld.mc 的搜尋路徑

執行 ld.mc 時,系統會將某些 RS 執行階段程式庫做為輸入內容 然後加入連結器應用程式的 RS 位元碼會連結至執行階段程式庫 當轉換的位元碼載入應用程式程序中時,執行階段 會從轉換後的位元碼動態連結。

執行階段程式庫包括:

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • RS 驅動程式 (libRSDriver.soOVERRIDE_RS_DRIVER)

將已編譯的位元碼載入應用程式程序時,請提供完全相同 ld.mc 所用的程式庫。否則,經過編譯的位元碼 可能找不到可用的符號。

為此,RS 架構會在執行階段程式庫使用不同的搜尋路徑 執行 ld.mc,具體取決於 RS 架構本身 從 /system/lib/system/lib/vndk-sp 載入。 我們可以讀取任意 RS 符號的地址來判斷其位置 Framework lib,並使用 dladdr() 取得對應於 網址。

SELinux 政策

基於 Android 8.0 以上版本的 SELinux 政策變更,您必須 遵守特定規則 (透過 neverallows 強制執行) 為 vendor 分區中的其他檔案加上標籤:

  • vendor_file」必須是以下項目的預設標籤: vendor 個分區。根據平台政策,你必須進行這項設定才能存取 直通式 HAL 實作。
  • 所有新的 exec_types 已新增至 vendor 分區 透過供應商 SEPolicy 必須含有 vendor_file_type 屬性。 這會透過 neverallows 強制執行。
  • 為了避免與日後的平台/架構更新發生衝突,請避免加上標籤 vendor 分區中的 exec_types 以外的檔案。
  • 所有與 Android 開放原始碼計畫 (AOSP) 識別相同的程序 HAL 的程式庫依附元件,都必須 已標示為 same_process_hal_file

如要進一步瞭解 SELinux 政策,請參閱 Android 中的 Linux 安全防護機制。

中間碼的 ABI 相容性

如未新增任何 API,也就是沒有 HAL 版本,則 RS 架構 才能繼續使用現有的 GPU (HAL 1.0) 驅動程式。

如果小幅 HAL 變更 (HAL 1.1) 不會影響位元碼,架構應 將這些新增的 API 改回 CPU,並繼續使用 GPU (HAL 1.0) 驅動程式 如果其他位置需要使用資源 Compute Engine 有權終止工作

針對影響位元碼編譯/連結的重大 HAL 變更 (HAL 2.0),RS 架構應選擇不載入廠商提供的 GPU 驅動程式 請使用 CPU 或 Vulkan 路徑進行加速。

使用 RenderScript 位元碼的流程分為三個階段:

征途城市 詳細說明
編譯
  • bcc 的輸入位元碼 (.bc) 必須位於 LLVM 3.2 位元格式,且 bcc 必須為反向 。
  • 不過,.bc 中的中繼資料可能會改變 (可能會發生新的執行階段 和函式 (例如配置 setter ∓getter、數學函式等)。零件 (部分執行階段函式位於 libclcore.bc) 居住在 LibRSDriver 或同等廠商中。
  • 使用新的執行階段函式或破壞中繼資料變更時必須遞增 位元碼 API 級別因為廠商司機無法使用 HAL 版本也必須遞增。
  • 供應商可能各自有編譯器,但最終結論/要求 的 bcc 也適用於這些編譯器。
連結
  • 經過編譯的 .o 會與廠商驅動程式連結,例如 libRSDriver_foo.solibcompiler_rt.so。CPU 路徑會連結至 libRSDriver.so
  • 如果 .o 需要從 libRSDriver_foo 取得新的執行階段 API, 供應商驅動程式 必須經過更新才能支援
  • 某些供應商可能會有專屬的連接器,不過 ld.mc 亦適用。
載入
  • libRSCpuRef 會載入共用物件。如果有 但這個介面的變更需要 HAL 版本
  • 供應商將利用 libRSCpuRef 載入共用的 物件,或實作自己的物件。

除了 HAL 外,執行階段 API 和匯出的符號 存取 API從 Android 7.0 (API 24) 開始,沒有任何介面變更, 並沒有立即在 Android 8.0 以上版本變更這項功能。不過, 介面變更時,HAL 版本也會遞增。

供應商實作

Android 8.0 以上版本需要對 GPU 驅動程式變更部分 GPU 驅動程式,才能 就能正常運作

驅動程式模組

  • 驅動程式模組不得依附於不在 清單
  • 駕駛必須自行提供 android.hardware.renderscript@1.0-impl_{NAME},或宣告 預設實作 android.hardware.renderscript@1.0-impl 為 依附元件
  • CPU 實作 libRSDriver.so 是說明如何 移除非 VNDK-SP 依附元件。

位元碼編譯器

您可以用兩種方式為供應商驅動程式編譯 RenderScript 位元碼:

  1. /vendor/bin/ 中叫用供應商專屬的 RenderScript 編譯器 (建議的 GPU 編譯方法)。如同其他驅動程式模組 供應商編譯器二進位檔無法依賴不在 RenderScript 程式庫清單 向供應商提供授權
  2. 叫用系統密件副本:/system/bin/bcc (由供應商提供) bcc plugin;此外掛程式無法依附於 不在 可以使用 RenderScript 程式庫 供應商提供

如果廠商 bcc plugin 需要幹擾 CPU 編譯和依附元件在 libLLVM.so 上的依附元件並不容易 已移除,供應商應複製 bcc (以及所有非 LL-NDK) 包括 libLLVM.solibbcc.so 等依附元件 /vendor 個分區。

此外,供應商也必須進行以下變更:

圖 7. 供應商驅動程式變更。

  1. libclcore.bc 複製到 /vendor 分區。這個 確保 libclcore.bclibLLVM.solibbcc.so 已同步。
  2. 透過設定變更 bcc 執行檔的路徑 來自 RS HAL 實作的 RsdCpuScriptImpl::BCC_EXE_PATH
,瞭解如何調查及移除這項存取權。

SELinux 政策

SELinux 政策會影響驅動程式和編譯器執行檔。所有語言 驅動程式模組的same_process_hal_file 裝置的「file_contexts」。例如:

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

編譯器執行檔必須能由應用程式程序叫用 密件副本的廠商副本 (/vendor/bin/bcc)。例如:

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

舊版裝置

舊版裝置須符合下列條件:

  1. PRODUCT_SHIPPING_API_LEVEL 低於 26。
  2. 未定義 PRODUCT_FULL_TREBLE_OVERRIDE

如果是舊版裝置,裝置升級至以下版本時不會強制執行限制: Android 8.0 以上版本:代表驅動程式可以繼續連結到程式庫 在「/system/lib[64]」中。不過,由於架構變更 與「OVERRIDE_RS_DRIVER」有關, 必須安裝「android.hardware.renderscript@1.0-impl/vendor 個分區;如未執行這些動作,就會強制 RenderScript 執行階段 採用備用 CPU 路徑

如要瞭解 Renderscript 淘汰的動機,請參閱 Android 開發人員網站 網誌:Android GPU 實施未來規劃。 這項淘汰作業的資源資訊包括: