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), dùng vậy 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ộ.
Sau đây là những điểm khác biệt so với RenderScript trong Android 7.x trở xuống:
- Hai thực thể của lib nội bộ RenderScript trong một quy trình. Một tập hợp là dành cho đường dẫn dự phòng của CPU và bắt đầu từ
/system/lib
; tập hợp còn lại là dành cho đường dẫn GPU và bắt đầu từ/system/lib/vndk-sp
. - Các thư viện nội bộ RS trong
/system/lib
được tạo trong nền tảng và được cập nhật khisystem.img
được nâng cấp. Tuy nhiên, lib 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ập nhật để sửa lỗi bảo mật, nhưng ABI của các thư viện này vẫn giữ nguyên). - Mã của 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
. Các thư viện này 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ã của nhà cung cấp (tức là các biểu tượng có thể bị xoá). Nếu làm như vậy, bạn sẽ không thể thực hiện OTA chỉ dành cho khung.
Thiết kế
Các phần sau đây trình bày chi tiết về 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òn gọi là NDK của nhà cung cấp cho HAL cùng quy trình hoặc VNDK-SP) có sẵn cho mã của nhà cung cấp và có thể được liên kết. Tài liệu 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ã của 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 không thể thay đổi cho một bản phát hành Android cụ thể. Để xem danh sách cập nhật các thư viện có sẵn, hãy tham khảo /system/etc/ld.config.txt
.
Lib RenderScript | Lib 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 cùng quy trình (SP-HAL) ngoại trừ RenderScript đều được tải bên trong không gian tên trình liên kết sphal
. RenderScript được tải vào không gian tên dành riêng cho RenderScript rs
, một vị trí cho phép thực thi hơi lỏng lẻo hơn cho 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
sẽ đượ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 lib 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
hiển thị với không gian tên rs
vì libRS_internal.so
có phần phụ thuộc nội bộ với 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.
Tải trình điều khiển
Đườ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 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
(phương thức 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 thư viện RS.
Việc triển khai RS HAL của nhà cung cấp hoàn toàn không được sử dụng khi CPU sử dụng đường dẫn dự phòng và đố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
sử 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
.
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 HAL RS (hardware/interfaces/renderscript/1.0/default/Context.cpp
). Sau đó, tên trình điều khiển này đượ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 quá trình triển khai HAL RS. HAL gọi lại khung RS bằng cách sử dụng hàm rsContextCreateVendor()
với 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 khởi tạo RsContext
. Trong trường hợp này, thư viện trình điều khiển sẽ được tải vào không gian tên rs
, vì đối tượng RsContext
được tạo bên trong không gian tên rs
và /vendor/lib
nằm trong đường dẫn tìm kiếm của không gian tên.
Hình 4. Đường dẫn dự phòng 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()
để yêu cầu rõ ràng trình liên kết động 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 sẽ đượ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/tải thư viện từ không gian tên sphal
(luôn là trường hợp này vì không gian tên sphal
không tìm kiếm /system/lib/vndk-sp
nơi libRS_internal.so
nằm). Với cấu hình này, một lệnh 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à 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à 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 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ó.
Quy định 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
thông qua hàm android_sphal_load_library()
. Trong các phiên bản Android trước, tên trình bổ trợ được chỉ định bằng tuỳ chọn -load
và thư viện được tải bằng dlopen()
đơn giản của libLLVM.so
. Trong Android 8.0 trở lên, điều này được chỉ định trong tuỳ chọn -plugin
và lib được tải trực tiếp bởi chính bcc
. 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. 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 dữ liệu đầ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 lại được liên kết độ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ã bit đã 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
đã sử dụng. Nếu không, mã bit đã 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 khung RS có đượ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 ký hiệu tuỳ ý của thư viện khung RS và sử dụng dladdr()
để liên kết đường dẫn tệp 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ả 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 phương thức 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 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ông phải là
exec_types
trong phân vùngvendor
. - Tất cả phần phụ thuộc thư viện cho các HAL cùng quy trình do AOSP xác định 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 bạn không thêm API mới nào, tức là không tăng phiên bản HAL, khung RS sẽ tiếp tục sử dụng trình điều khiển GPU (HAL 1.0) hiện có.
Đối với các thay đổi nhỏ về HAL (HAL 1.1) không ảnh hưởng đến mã bit, các khung này nên sử dụng lại CPU cho các API mới 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 việc biên dịch/liên kết mã bit, khung RS nên chọn không tải trình điều khiển GPU do nhà cung cấp cung cấp mà thay vào đó sử dụng CPU hoặc đường dẫn Vulkan để tăng tốc.
Quá trình sử dụng mã bit RenderScript diễn ra theo 3 giai đoạn:
Giai đoạn | Thông tin chi tiết |
---|---|
Biên dịch |
|
Đường liên kết |
|
Tải |
|
Ngoài HAL, API thời gian chạy và những biểu tượng được xuất cũng là giao diện. Không có giao diện nào thay đổi kể từ Android 7.0 (API 24) và hiện vẫn chưa có kế hoạch thay đổi giao diện này 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 của nhà cung cấp
Android 8.0 trở lên yêu cầu một số thay đổi về trình điều khiển GPU để trình điều khiển GPU hoạt động chính xác.
Mô-đun trình điều khiển
- 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 phương thức 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ụ hay 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 được 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 hệ thống bcc:
/system/bin/bcc
bằngbcc plugin
do nhà cung cấp cung cấp; trình bổ trợ này 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 các thư viện RenderScript có sẵn cho nhà cung cấp.
Nếu nhà cung cấp bcc plugin
cần can thiệp vào quá trình biên dịch CPU và phần phụ thuộc của nó trên libLLVM.so
không thể dễ dàng xoá được, thì nhà cung cấp phải 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
đồng bộ hoá. - Thay đổi đường dẫn đến tệp thực thi
bcc
bằng cách đặtRsdCpuScriptImpl::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ả các tệp thực thi của trình điều khiển và 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
Trình biên dịch có thể thực thi phải có thể được một quy trình ứng dụng gọi, cũng như bản sao bcc của nhà cung cấp (/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_shippingPING_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 quy định hạn chế này sẽ không được thực thi khi nâng cấp lên Android 8.0 trở lên, nghĩa là 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
, bạn phải cài đặt android.hardware.renderscript@1.0-impl
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 ngừng sử dụng Renderscript, hãy xem Blog dành cho nhà phát triển Android: Tính năng điện toán GPU của Android trong tương lai. Thông tin tài nguyên về việc ngừng sử dụng này bao gồm:
- Di chuyển từ Renderscript
- Mẫu RenderScriptMigration
- README của Bộ công cụ thay thế hàm nội tại
- Toolkit.kt thay thế hàm nội tại