RenderScript là một khung để chạy các tác vụ tính toán chuyên sâu với hiệu suất cao trên Android. RenderScript được thiết kế để sử dụng với tính năng tính toán song song dữ liệu (data-parallel computation), mặc dù khối lượng công việc nối tiếp (serial workloads) cũng có thể hưởng lợi. Môi trường thời gian chạy RenderScript tải song song công việc trên các bộ xử lý hiện có trên thiết bị, chẳng hạn như GPU và CPU đa nhân, cho phép nhà phát triển tập trung vào việc thể hiện thuật toán thay vì lên lịch công việc. RenderScript đặc biệt hữu ích cho các ứng dụng xử lý hình ảnh, nhiếp ảnh điện toán hoặc thị giác máy tính.
Các thiết bị chạy Android 8.0 trở lên sử dụng khung RenderScript và HAL của nhà cung cấp sau đây:

Hình 1. Mã nhà cung cấp liên kết đến các thư viện nội bộ.
Những điểm khác biệt so với RenderScript trong Android 7.x trở xuống bao gồm:
- Hai phiên bản của các thư viện nội bộ RenderScript trong một quy trình. Một nhóm dành cho đường dẫn dự phòng của CPU và nằm ngay tại
/system/lib
; nhóm còn lại dành cho đường dẫn GPU và nằm tại/system/lib/vndk-sp
. - Các thư viện nội bộ RS trong
/system/lib
được xây dựng trong nền tảng và được cập nhật khisystem.img
được nâng cấp. Tuy nhiên, các thư viện trong/system/lib/vndk-sp
được tạo cho nhà cung cấp và không được cập nhật khisystem.img
được nâng cấp (mặc dù có thể được cập nhật để khắc phục vấn đề bảo mật, nhưng ABI của các thư viện này vẫn giữ nguyên). - Mã nhà cung cấp (RS HAL, trình điều khiển RS và
bcc plugin
) được liên kết với các thư viện nội bộ RenderScript nằm tại/system/lib/vndk-sp
. Chúng không thể liên kết với các thư viện trong/system/lib
vì các thư viện trong thư mục đó được tạo cho nền tảng và do đó có thể không tương thích với mã nhà cung cấp (tức là các biểu tượng có thể bị xoá). Làm như vậy sẽ khiến OTA chỉ có khung không thể thực hiện được.
Thiết kế
Các phần sau đây trình bày chi tiết thiết kế RenderScript trong Android 8.0 trở lên.
Các thư viện RenderScript dành cho nhà cung cấp
Phần này liệt kê các thư viện RenderScript (được gọi là Vendor NDK cho các HAL cùng quy trình hoặc VNDK-SP) có sẵn cho mã nhà cung cấp và có thể được liên kết. Phần này cũng trình bày chi tiết các thư viện bổ sung không liên quan đến RenderScript nhưng cũng được cung cấp cho mã nhà cung cấp.
Mặc dù danh sách thư viện sau đây có thể khác nhau giữa các bản phát hành Android, nhưng danh sách này là bất biến đối với một bản phát hành Android cụ thể; để xem danh sách mới nhất về các thư viện có sẵn, hãy tham khảo /system/etc/ld.config.txt
.
RenderScript Libs | Thư viện không phải RenderScript |
---|---|
|
|
Cấu hình không gian tên của trình liên kết
Hạn chế liên kết ngăn mã nhà cung cấp sử dụng các thư viện không có trong VNDK-SP được thực thi trong thời gian chạy bằng cách sử dụng không gian tên trình liên kết. (Để biết thông tin chi tiết, hãy tham khảo bản trình bày Thiết kế VNDK.)
Trên thiết bị chạy Android 8.0 trở lên, tất cả HAL trong cùng quy trình (SP-HAL) ngoại trừ RenderScript đều được tải trong không gian tên trình liên kết sphal
. RenderScript được tải vào không gian tên rs
dành riêng cho RenderScript, một vị trí cho phép thực thi lỏng lẻo hơn một chút đối với các thư viện RenderScript. Vì quá trình triển khai RS cần tải mã bit đã biên dịch, nên /data/*/*.so
được thêm vào đường dẫn của không gian tên rs
(các SP-HAL khác không được phép tải các thư viện từ phân vùng dữ liệu).
Ngoài ra, không gian tên rs
cho phép nhiều thư viện hơn so với các không gian tên khác. libmediandk.so
và libft2.so
được hiển thị cho không gian tên rs
vì libRS_internal.so
có một phần phụ thuộc nội bộ vào các thư viện này.

Hình 2. Cấu hình không gian tên cho trình liên kết.
Trình điều khiển tải
Đường dẫn dự phòng của CPU
Tuỳ thuộc vào sự tồn tại của bit RS_CONTEXT_LOW_LATENCY
khi tạo một ngữ cảnh RS, đường dẫn CPU hoặc GPU sẽ được chọn. Khi đường dẫn CPU được chọn, libRS_internal.so
(chế độ triển khai chính của khung RS) sẽ được dlopen
trực tiếp từ không gian tên trình liên kết mặc định, nơi cung cấp phiên bản nền tảng của các thư viện RS.
Hoàn toàn không sử dụng việc triển khai RS HAL của nhà cung cấp khi sử dụng đường dẫn dự phòng CPU và một đối tượng RsContext
được tạo bằng mVendorDriverName
rỗng. libRSDriver.so
được dlopen
(theo mặc định) và thư viện trình điều khiển được tải từ không gian tên default
vì phương thức gọi (libRS_internal.so
) cũng được tải trong không gian tên default
.

Hình 3. Đường dẫn dự phòng của CPU.
Đường dẫn GPU
Đối với đường dẫn GPU, libRS_internal.so
được tải theo cách khác.
Trước tiên, libRS.so
dùng android.hardware.renderscript@1.0.so
(và libhidltransport.so
cơ bản của nó) để tải android.hardware.renderscript@1.0-impl.so
(một cách triển khai RS HAL của nhà cung cấp) vào một không gian tên trình liên kết khác có tên là sphal
. Sau đó, HAL RS sẽ dlopen
libRS_internal.so
trong một không gian tên trình liên kết khác có tên là rs
.
Các nhà cung cấp có thể cung cấp trình điều khiển RS của riêng họ bằng cách đặt cờ thời gian xây dựng OVERRIDE_RS_DRIVER
, được nhúng vào quá trình triển khai RS HAL (hardware/interfaces/renderscript/1.0/default/Context.cpp
). Sau đó, tên trình điều khiển này sẽ được dlopen
cho ngữ cảnh RS cho đường dẫn GPU.
Việc tạo đối tượng RsContext
được uỷ quyền cho việc triển khai RS HAL. HAL gọi lại khung RS bằng hàm rsContextCreateVendor()
có tên của trình điều khiển để dùng làm đối số. Sau đó, khung RS sẽ tải trình điều khiển đã chỉ định khi RsContext
được khởi tạo. Trong trường hợp này, thư viện trình điều khiển được tải vào vùng chứa tên rs
vì đối tượng RsContext
được tạo bên trong vùng chứa tên rs
và /vendor/lib
nằm trong đường dẫn tìm kiếm của vùng chứa tên.

Hình 4. Đường dẫn dự phòng của GPU.
Khi chuyển đổi từ không gian tên default
sang không gian tên sphal
, libhidltransport.so
sẽ dùng hàm android_load_sphal_library()
để sắp xếp rõ ràng trình liên kết động nhằm tải thư viện -impl.so
từ không gian tên sphal
.
Khi chuyển đổi từ không gian tên sphal
sang không gian tên rs
, quá trình tải được thực hiện gián tiếp bằng dòng sau trong /system/etc/ld.config.txt
:
namespace.sphal.link.rs.shared_libs = libRS_internal.so
Dòng này chỉ định trình liên kết động sẽ tải libRS_internal.so
từ không gian tên rs
khi không tìm thấy/không tải được lib từ không gian tên sphal
(trường hợp này luôn xảy ra vì không gian tên sphal
không tìm kiếm /system/lib/vndk-sp
nơi libRS_internal.so
cư trú). Với cấu hình này, bạn chỉ cần gọi dlopen()
đơn giản đến libRS_internal.so
là đủ để thực hiện quá trình chuyển đổi không gian tên.
Tải trình bổ trợ bcc
bcc plugin
là một thư viện do nhà cung cấp cung cấp, được tải vào trình biên dịch bcc
. Vì bcc
là một quy trình hệ thống trong thư mục /system/bin
, nên thư viện bcc plugin
có thể được coi là SP-HAL (tức là một HAL của nhà cung cấp có thể được tải trực tiếp vào quy trình hệ thống mà không cần được liên kết). Là một SP-HAL, thư viện bcc-plugin
:
- Không thể liên kết với các thư viện chỉ dành cho khung như
libLLVM.so
. - Chỉ có thể liên kết với các thư viện VNDK-SP mà nhà cung cấp có thể sử dụng.
Hạn chế này được thực thi bằng cách tải bcc plugin
vào không gian tên sphal
bằng hàm android_sphal_load_library()
. Trong các phiên bản trước của Android, tên trình bổ trợ được chỉ định bằng cách sử dụng lựa chọn -load
và lib được tải bằng cách sử dụng dlopen()
đơn giản theo libLLVM.so
. Trong Android 8.0 trở lên, điều này được chỉ định trong lựa chọn -plugin
và lib được bcc
tự động tải trực tiếp. Tuỳ chọn này cho phép một đường dẫn không dành riêng cho Android đến dự án LLVM nguồn mở.

Hình 5. Đang tải trình bổ trợ bcc, Android 7.x trở xuống.

Hình 6. Đang tải trình bổ trợ bcc, Android 8.0 trở lên.
Đường dẫn tìm kiếm cho ld.mc
Khi thực thi ld.mc
, một số thư viện thời gian chạy RS được cung cấp dưới dạng đầu vào cho trình liên kết. Mã bit RS từ ứng dụng được liên kết với các thư viện thời gian chạy và khi mã bit đã chuyển đổi được tải vào một quy trình ứng dụng, các thư viện thời gian chạy sẽ được liên kết lại một cách linh động từ mã bit đã chuyển đổi.
Các thư viện thời gian chạy bao gồm:
libcompiler_rt.so
libm.so
libc.so
- Trình điều khiển RS (
libRSDriver.so
hoặcOVERRIDE_RS_DRIVER
)
Khi tải mã đối tượng đã biên dịch vào quy trình ứng dụng, hãy cung cấp chính xác thư viện mà ld.mc
đã dùng. Nếu không, bitcode đã biên dịch có thể không tìm thấy một biểu tượng có sẵn khi được liên kết.
Để làm như vậy, khung RS sử dụng các đường dẫn tìm kiếm khác nhau cho các thư viện thời gian chạy khi thực thi ld.mc
, tuỳ thuộc vào việc chính khung RS được tải từ /system/lib
hay từ /system/lib/vndk-sp
.
Bạn có thể xác định điều này bằng cách đọc địa chỉ của một biểu tượng tuỳ ý của thư viện khung RS và sử dụng dladdr()
để lấy đường dẫn tệp được liên kết với địa chỉ.
Chính sách SELinux
Do các thay đổi về chính sách SELinux trong Android 8.0 trở lên, bạn phải tuân theo các quy tắc cụ thể (được thực thi thông qua neverallows
) khi gắn nhãn các tệp bổ sung trong phân vùng vendor
:
vendor_file
phải là nhãn mặc định cho tất cả các tệp trong phân vùngvendor
. Chính sách nền tảng yêu cầu điều này để truy cập vào các chế độ triển khai HAL truyền qua.- Tất cả
exec_types
mới được thêm vào phân vùngvendor
thông qua SEPolicy của nhà cung cấp đều phải có thuộc tínhvendor_file_type
. Việc này được thực thi thông quaneverallows
. - Để tránh xung đột với các bản cập nhật nền tảng/khung trong tương lai, hãy tránh gắn nhãn cho các tệp khác ngoài
exec_types
trong phân vùngvendor
. - Tất cả các phần phụ thuộc thư viện cho các HAL cùng quy trình do AOSP xác định đều phải được gắn nhãn là
same_process_hal_file
.
Để biết thông tin chi tiết về chính sách SELinux, hãy xem bài viết Security-Enhanced Linux trong Android.
Khả năng tương thích ABI cho mã bit
Nếu không có API mới nào được thêm, tức là không có sự gia tăng phiên bản HAL, thì các khung RS sẽ tiếp tục sử dụng trình điều khiển GPU hiện có (HAL 1.0).
Đối với các thay đổi nhỏ về HAL (HAL 1.1) không ảnh hưởng đến mã đối tượng, các khung sẽ dự phòng cho CPU đối với những API mới được thêm này và tiếp tục sử dụng trình điều khiển GPU (HAL 1.0) ở nơi khác.
Đối với các thay đổi lớn về HAL (HAL 2.0) ảnh hưởng đến quá trình biên dịch/liên kết mã đối tượng, các khung RS không nên tải trình điều khiển GPU do nhà cung cấp cung cấp mà thay vào đó, hãy sử dụng đường dẫn CPU hoặc Vulkan để tăng tốc.
Việc sử dụng mã bit RenderScript diễn ra theo 3 giai đoạn:
Giai đoạn | Chi tiết |
---|---|
Biên dịch |
|
Đường liên kết |
|
Tải |
|
Ngoài HAL, các API thời gian chạy và các biểu tượng đã xuất cũng là các giao diện. Cả hai giao diện này đều không thay đổi kể từ Android 7.0 (API 24) và hiện không có kế hoạch thay đổi trong Android 8.0 trở lên. Tuy nhiên, nếu giao diện thay đổi, phiên bản HAL cũng sẽ tăng lên.
Triển khai nhà cung cấp
Android 8.0 trở lên yêu cầu một số thay đổi đối với trình điều khiển GPU để trình điều khiển GPU hoạt động đúng cách.
Mô-đun trình điều khiển
- Các mô-đun trình điều khiển không được phụ thuộc vào bất kỳ thư viện hệ thống nào không có trong danh sách.
- Trình điều khiển phải cung cấp
android.hardware.renderscript@1.0-impl_{NAME}
riêng hoặc khai báo chế độ triển khai mặc địnhandroid.hardware.renderscript@1.0-impl
làm phần phụ thuộc. - Việc triển khai CPU
libRSDriver.so
là một ví dụ điển hình về cách xoá các phần phụ thuộc không phải VNDK-SP.
Trình biên dịch mã bit
Bạn có thể biên dịch mã bit RenderScript cho trình điều khiển của nhà cung cấp theo hai cách:
- Gọi trình biên dịch RenderScript dành riêng cho nhà cung cấp trong
/vendor/bin/
(phương thức biên dịch GPU được ưu tiên). Tương tự như các mô-đun trình điều khiển khác, tệp nhị phân trình biên dịch của nhà cung cấp không thể phụ thuộc vào bất kỳ thư viện hệ thống nào không có trong danh sách các thư viện RenderScript mà nhà cung cấp có thể sử dụng. - Gọi bcc hệ thống:
/system/bin/bcc
bằngbcc plugin
do nhà cung cấp cung cấp; trình bổ trợ này không thể phụ thuộc vào bất kỳ thư viện hệ thống nào không có trong danh sách các thư viện RenderScript mà nhà cung cấp có thể sử dụng.
Nếu nhà cung cấp bcc plugin
cần can thiệp vào quá trình biên dịch CPU và không thể dễ dàng xoá phần phụ thuộc của quá trình này trên libLLVM.so
, thì nhà cung cấp nên sao chép bcc
(và tất cả các phần phụ thuộc không phải LL-NDK, bao gồm cả libLLVM.so
, libbcc.so
) vào phân vùng /vendor
.
Ngoài ra, nhà cung cấp cần thực hiện những thay đổi sau:

Hình 7. Thay đổi đối với trình điều khiển của nhà cung cấp.
- Sao chép
libclcore.bc
vào phân vùng/vendor
. Điều này đảm bảolibclcore.bc
,libLLVM.so
vàlibbcc.so
được đồng bộ hoá. - Thay đổi đường dẫn đến tệp thực thi
bcc
bằng cách thiết lậpRsdCpuScriptImpl::BCC_EXE_PATH
từ quá trình triển khai RS HAL.
Chính sách SELinux
Chính sách SELinux ảnh hưởng đến cả trình điều khiển và các tệp thực thi của trình biên dịch. Tất cả các mô-đun trình điều khiển phải được gắn nhãn same_process_hal_file
trong file_contexts
của thiết bị. Ví dụ:
/vendor/lib(64)?/libRSDriver_EXAMPLE\.so u:object_r:same_process_hal_file:s0
Quy trình của ứng dụng phải có khả năng gọi tệp thực thi của trình biên dịch, cũng như bản sao của nhà cung cấp bcc (/vendor/bin/bcc
). Ví dụ:
device/vendor_foo/device_bar/sepolicy/file_contexts: /vendor/bin/bcc u:object_r:same_process_hal_file:s0
Thiết bị cũ
Thiết bị cũ là những thiết bị đáp ứng các điều kiện sau:
- PRODUCT_SHIPPING_API_LEVEL thấp hơn 26.
- PRODUCT_FULL_TREBLE_OVERRIDE chưa được xác định.
Đối với các thiết bị cũ, các hạn chế sẽ không được thực thi khi nâng cấp lên Android 8.0 trở lên, tức là các trình điều khiển có thể tiếp tục liên kết với các thư viện trong /system/lib[64]
. Tuy nhiên, do thay đổi về cấu trúc liên quan đến OVERRIDE_RS_DRIVER
, nên android.hardware.renderscript@1.0-impl
phải được cài đặt vào phân vùng /vendor
; nếu không, thời gian chạy RenderScript sẽ buộc phải quay lại đường dẫn CPU.
Để biết thông tin về lý do khiến Renderscript không được dùng nữa, hãy xem bài đăng trên Blog dành cho nhà phát triển Android: Android GPU Compute Going Forward (Điện toán GPU trên Android trong tương lai). Thông tin về tài nguyên cho việc ngừng sử dụng này bao gồm những nội dung sau:
- Di chuyển từ RenderScript
- Mẫu RenderScriptMigration
- README của Bộ công cụ thay thế hàm nội tại
- Bộ công cụ thay thế hàm nội tại Toolkit.kt