RenderScript 是一種架構,可用於在 Android 上以高效能執行需要進行大量運算的工作。RenderScript 適用於資料平行運算,但也可為序列工作負載帶來好處。RenderScript 執行階段會透過裝置上可用的各個處理器 (例如多核心 CPU 和 GPU) 平行處理工作,讓開發人員專注於表示演算法,而非安排執行工作。RenderScript 特別適合用於執行圖片處理作業、計算攝影或電腦視覺的應用程式。
搭載 Android 8.0 以上版本的裝置會使用下列 RenderScript 架構和供應商 HAL:

圖 1. 供應商程式碼連結至內部程式庫。
與 Android 7.x 以下版本的 RenderScript 相比,差異包括:
- 程序中的兩個 RenderScript 內部程式庫執行個體。一組適用於 CPU 回退路徑,且直接來自
/system/lib
;另一組適用於 GPU 路徑,且來自/system/lib/vndk-sp
。 /system/lib
中的 RS 內部程式庫是平台的一部分,會隨著system.img
升級而更新。不過,/system/lib/vndk-sp
中的程式庫是為供應商建構,且在system.img
升級時不會更新 (雖然可以更新以修正安全性問題,但 ABI 仍維持不變)。- 供應商程式碼 (RS HAL、RS 驅動程式和
bcc plugin
) 會連結至/system/lib/vndk-sp
中的 RenderScript 內部程式庫。因為該目錄中的程式庫是為平台建構,因此可能與供應商程式碼不相容 (即符號可能會移除),所以無法連結/system/lib
中的程式庫。否則就無法進行僅限架構的 OTA。
設計
下列各節詳細說明 Android 8.0 以上版本的 RenderScript 設計。
供應商可用的 RenderScript 程式庫
本節列出供應商程式碼可用的 RenderScript 程式庫 (稱為「適用於相同程序 HAL 的供應商 NDK」或「VNDK-SP」),以及可連結的程式庫。此外,這份文件也詳細說明與 RenderScript 無關,但同樣提供給供應商程式碼的其他程式庫。
雖然下列程式庫清單可能因 Android 版本而異,但特定 Android 版本的清單不會變動。如需最新可用程式庫清單,請參閱 /system/etc/ld.config.txt
。
RenderScript 程式庫 | 非 RenderScript 程式庫 |
---|---|
|
|
連結器命名空間設定
系統會在執行階段使用連結器命名空間,強制執行連結限制,防止供應商程式碼使用 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 環境時,系統會根據 RS_CONTEXT_LOW_LATENCY
位元是否存在,選取 CPU 或 GPU 路徑。選取 CPU 路徑時,系統會直接從提供 RS 程式庫平台版本的預設連結器命名空間,dlopen
libRS_internal.so
(RS 架構的主要實作項目)。
採用 CPU 回退路徑時,完全不會使用供應商的 RS HAL 實作,且會使用空值 mVendorDriverName
建立 RsContext
物件。libRSDriver.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
的不同連結器命名空間。RS HAL 接著會將 dlopen
s libRS_internal.so
放入名為 rs
的另一個連結器命名空間。
供應商可以設定建構時間標記 OVERRIDE_RS_DRIVER
,提供自己的 RS 驅動程式,並將該標記嵌入 RS HAL 實作 (hardware/interfaces/renderscript/1.0/default/Context.cpp
)。接著,系統會為 GPU 路徑的 RS 環境 dlopen
這個驅動程式名稱。
RsContext
物件的建立作業會委派給 RS HAL 實作。HAL 會使用 rsContextCreateVendor()
函式回呼 RS 架構,並將要使用的驅動程式名稱做為引數。接著,RS 架構會在初始化 RsContext
時載入指定的驅動程式。在本例中,驅動程式程式庫會載入 rs
命名空間,因為 RsContext
物件是在 rs
命名空間內建立,且 /vendor/lib
位於命名空間的搜尋路徑中。

圖 4. GPU 備援路徑。
從 default
命名空間轉換至 sphal
命名空間時,libhidltransport.so
會使用 android_load_sphal_library()
函式,明確指示動態連結器從 sphal
命名空間載入 -impl.so
程式庫。
從 sphal
命名空間轉換至 rs
命名空間時,載入作業會透過 /system/etc/ld.config.txt
中的下列程式碼行間接完成:
namespace.sphal.link.rs.shared_libs = libRS_internal.so
這行會指定動態連結器應從 rs
命名空間載入 libRS_internal.so
,前提是無法從 sphal
命名空間找到/載入程式庫 (一律如此,因為 sphal
命名空間不會搜尋 /system/lib/vndk-sp
,而 libRS_internal.so
就位於 /system/lib/vndk-sp
中)。完成這項設定後,只要對 libRS_internal.so
進行簡單的 dlopen()
呼叫,即可完成命名空間轉換。
載入 bcc 外掛程式
bcc plugin
是載入 bcc
編譯器的供應商提供程式庫。由於 bcc
是 /system/bin
目錄中的系統程序,因此 bcc plugin
程式庫可視為 SP-HAL (即供應商 HAL,可直接載入系統程序,而不需繫結)。做為 SP-HAL,bcc-plugin
程式庫:
- 無法連結至僅限架構的程式庫,例如
libLLVM.so
。 - 只能連結至供應商可用的 VNDK-SP 程式庫。
這項限制是透過使用 android_sphal_load_library()
函式,將 bcc plugin
載入 sphal
命名空間來強制執行。在舊版 Android 中,外掛程式名稱是使用 -load
選項指定,而程式庫是透過 libLLVM.so
簡單的 dlopen()
載入。在 Android 8.0 以上版本中,這項設定是在 -plugin
選項中指定,且程式庫是由 bcc
本身直接載入。這個選項可啟用開放原始碼 LLVM 專案的非 Android 特定路徑。

圖 5. 正在載入 bcc 外掛程式,適用於 Android 7.x 以下版本。

圖 6. 載入 bcc 外掛程式,適用於 Android 8.0 以上版本。
搜尋 ld.mc 的路徑
執行 ld.mc
時,系統會將部分 RS 執行階段程式庫做為輸入內容提供給連結器。應用程式的 RS 位元碼會連結至執行階段程式庫,而當轉換後的位元碼載入應用程式程序時,執行階段程式庫會再次從轉換後的位元碼動態連結。
執行階段程式庫包括:
libcompiler_rt.so
libm.so
libc.so
- RS 驅動程式 (
libRSDriver.so
或OVERRIDE_RS_DRIVER
)
將編譯的位元碼載入應用程式程序時,請提供 ld.mc
使用的相同程式庫。否則,編譯的位元碼可能找不到連結時可用的符號。
為此,RS 架構會在執行 ld.mc
時,根據 RS 架構本身是從 /system/lib
或 /system/lib/vndk-sp
載入,使用不同的執行階段程式庫搜尋路徑。
方法是讀取 RS 架構程式庫任意符號的位址,並使用 dladdr()
取得對應至該位址的檔案路徑。
SELinux 政策
由於 Android 8.0 以上版本中的 SELinux 政策有所變更,您必須遵循特定規則 (透過 neverallows
強制執行),才能在 vendor
分區中標記其他檔案:
vendor_file
必須是vendor
分區中所有檔案的預設標籤。如要存取直通 HAL 實作項目,必須遵守平台政策。- 透過供應商 SEPolicy 在
vendor
分區中新增的所有exec_types
都必須具備vendor_file_type
屬性。這項限制會透過neverallows
強制執行。 - 為避免與日後的平台/架構更新發生衝突,請勿在
vendor
分區中標記exec_types
以外的檔案。 - 針對 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) 驅動程式。
如果重大 HAL 變更 (HAL 2.0) 會影響位元碼編譯/連結,RS 架構應選擇不載入供應商提供的 GPU 驅動程式,改為使用 CPU 或 Vulkan 路徑進行加速。
使用 RenderScript 中間碼的過程分為三個階段:
步驟 | 詳細說明 |
---|---|
編譯 |
|
連結 |
|
載入 |
|
除了 HAL 之外,執行階段 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 中間碼:
- 在
/vendor/bin/
中叫用供應商專屬的 RenderScript 編譯器 (GPU 編譯的偏好方法)。與其他驅動程式模組類似,供應商編譯器二進位檔不得依附於任何不在供應商可用的 RenderScript 程式庫清單中的系統程式庫。 - 使用供應商提供的
bcc plugin
叫用系統 bcc:/system/bin/bcc
;這個外掛程式不得依附於任何不在供應商可用的 RenderScript 程式庫清單中的系統程式庫。
如果供應商bcc plugin
需要干擾 CPU 編譯,且無法輕易移除對 libLLVM.so
的依附元件,供應商應將 bcc
(和所有非 LL-NDK 的依附元件,包括 libLLVM.so
、libbcc.so
) 複製到 /vendor
分區。
此外,供應商也需要進行下列變更:

圖 7. 變更供應商驅動程式。
- 將
libclcore.bc
複製到/vendor
分區。這可確保libclcore.bc
、libLLVM.so
和libbcc.so
保持同步。 - 透過 RS HAL 實作設定
RsdCpuScriptImpl::BCC_EXE_PATH
,即可變更bcc
可執行檔的路徑。
SELinux 政策
SELinux 政策會影響驅動程式和編譯器可執行檔。所有驅動程式模組都必須在裝置的 file_contexts
中標示為 same_process_hal_file
。例如:
/vendor/lib(64)?/libRSDriver_EXAMPLE\.so u:object_r:same_process_hal_file:s0
應用程式程序必須能夠叫用編譯器可執行檔,就像 bcc 的供應商副本 (/vendor/bin/bcc
) 一樣。舉例來說:
device/vendor_foo/device_bar/sepolicy/file_contexts: /vendor/bin/bcc u:object_r:same_process_hal_file:s0
舊版裝置
舊版裝置是指符合下列條件的裝置:
- PRODUCT_SHIPPING_API_LEVEL 低於 26。
- 未定義 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 Compute Going Forward。這項淘汰作業的資源資訊包括:
- 從 Renderscript 遷移
- RenderScript 遷移範例
- 內建函式替換工具包 README
- 內建函式替換工具包.kt