RenderScript

RenderScript là một khung để chạy các phép tính toán chuyên sâu nhiệm vụ có hiệu suất cao trên Android. Trình quản lý thẻ của Google được thiết kế để sử dụng với tính toán song song dữ liệu, mặc dù khối lượng công việc nối tiếp cũng có thể hưởng lợi. Chiến lược phát hành đĩa đơn Thời gian chạy RenderScript tải song song công việc trên các bộ xử lý có sẵn trên trên thiết bị, chẳng hạn như CPU và GPU đa nhân, cho phép các nhà phát triển tập trung vào 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, dữ liệu nhiếp ảnh hoặc thị giác máy tính.

Thiết bị chạy Android 8.0 trở lên sử dụng RenderScript sau đây HAL khung và nhà cung cấp:

Hình 1. Mã nhà cung cấp liên kết đến các thư viện nội bộ.

Điểm khác biệt so với RenderScript trong Android 7.x trở xuống bao gồm:

  • Hai thực thể của lib nội bộ RenderScript trong một quy trình. Một bộ dành cho Đường dẫn dự phòng của CPU và trực tiếp từ /system/lib; thiết bị khác 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 xây dựng dưới dạng một phần của nền tảng và được cập nhật khi system.img được nâng cấp. Tuy nhiên, libs trong /system/lib/vndk-sp được tạo cho nhà cung cấp và không phải là cập nhật khi system.img được nâng cấp (trong khi chúng có thể được cập nhật để sửa lỗi bảo mật, ABI của họ vẫn như cũ).
  • Mã nhà cung cấp (RS HAL, trình điều khiển RS và bcc plugin) là được liên kết với thư viện nội bộ RenderScript được đặt tại /system/lib/vndk-sp. Chúng không thể liên kết với lib trong /system/lib vì lib trong thư mục đó được xây dựng cho nền tảng và do đó có thể không tương thích với mã nhà cung cấp (ví dụ: các ký hiệu có thể bị xoá). Việc này sẽ khiến OTA chỉ có khung trở nên không thể thực hiện được.

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 nhà cung cấp có thể sử dụng các thư viện RenderScript

Phần này liệt kê các thư viện RenderScript (được gọi là NDK nhà cung cấp cho cùng một quá trình) HAL hoặc VNDK-SP) có sẵn cho mã nhà cung cấp và có thể liên kết chống lại. Tài liệu này cũng trình bày chi tiết các thư viện khác 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, 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 thư viện hiện có, hãy tham khảo /system/etc/ld.config.txt.

Lib RenderScript Thư viện không phải 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

Cấu hình không gian tên của trình liên kết

Quy định hạn chế về việc liên kết khiến các lib không thuộc VNDK-SP không sử dụng được mã nhà cung cấp được thực thi trong thời gian chạy bằng không gian tên trình liên kết. (Để biết thông tin chi tiết, tham khảo nội dung Thiết kế VNDK bản trình bày).

Trên thiết bị chạy Android 8.0 trở lên, tất cả HAL (Lớp trừu tượng phần cứng) cùng tiến trình (SP-HAL) ngoại trừ RenderScript được tải bên trong không gian tên trình liên kết sphal. RenderScript được tải vào RenderScript dành riêng cho RenderScript không gian tên rs, một vị trí cho phép mở rộng hơn một chút Thực thi đối với thư viện RenderScript. Vì quá trình triển khai RS cần tải mã bit được biên dịch, /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 libs từ phân vùng dữ liệu).

Ngoài ra, không gian tên rs cho phép có nhiều lib hơn so với phạm vi cung cấp theo các không gian tên khác. libmediandk.solibft2.so đều hiển thị với không gian tên rslibRS_internal.so có một 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 cho 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 Đã chọn đường dẫn CPU, libRS_internal.so (phương thức triển khai chính của khung RS) được dlopen trực tiếp từ trình liên kết mặc định không gian tên nơi cung cấp phiên bản nền tảng của lib RS.

Việc triển khai RS HAL (Lớp trừu tượng phần cứng) của nhà cung cấp không được sử dụng khi CPU đã sử dụng đường dẫn dự phòng và tạo đối tượng RsContext bằng rỗng mVendorDriverName. libRSDriver.so là (theo mặc định) dlopened và thư viện trình điều khiển được tải từ Không gian tên default do phương thức gọi (libRS_internal.so) cũng được tải trong default không gian tên.

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à cơ sở dữ liệu này libhidltransport.so) để tải android.hardware.renderscript@1.0-impl.so (nhà cung cấp triển khai RS HAL) vào một không gian tên trình liên kết khác có tên là sphal. RS HAL sau đó dlopens libRS_internal.so trong một áp dụng khác không gian tên của trình liên kết có tên rs.

Nhà cung cấp có thể cung cấp trình điều khiển RS của riêng mình bằng cách đặt cờ thời gian xây dựng OVERRIDE_RS_DRIVER (được nhúng vào HAL RS) triển khai (hardware/interfaces/renderscript/1.0/default/Context.cpp). Chiến dịch này sau đó, tên trình điều khiển 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 RS HAL trong quá trình triển khai. HAL gọi lại khung RS bằng cách sử dụng Hàm rsContextCreateVendor() có tên của trình điều khiển sử dụng làm đối số. Sau đó, khung RS sẽ tải trình điều khiển được chỉ định khi Đã khởi chạy 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 rsRsContext sẽ được tạo bên trong không gian tên rs/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 android_load_sphal_library() để sắp xếp thứ tự 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 rs không gian tên, việc 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 trong không gian tên rs khi lib không thể tìm thấy/tải từ không gian tên sphal (luôn luôn là vì không gian tên sphal không tìm kiếm /system/lib/vndk-sp, trong đó libRS_internal.so thường trú). 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 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 và được tải vào Trình biên dịch bcc. Vì bcc là một quy trình hệ thống trong /system/bin, thì thư viện bcc plugin có thể là đượ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 không bị liên kết). Là 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 có sẵn cho nhà cung cấp.

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 sử dụ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 tuỳ chọn -load và lib được tải bằng cách sử dụng dlopen() đơn giản bằng cách libLLVM.so. Trong Android 8.0 trở lên, điều này được chỉ định trong Tùy chọn -plugin và lib được tải trực tiếp bằng Chính bcc. Tùy chọn này bật một đường dẫn không dành riêng cho Android để 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ố lib thời gian chạy RS được cung cấp làm 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 lib 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, lib 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ặc OVERRIDE_RS_DRIVER)

Khi tải mã bit đã biên dịch vào quy trình của ứng dụng, hãy cung cấp cùng một thư viện đã được ld.mc sử dụng. Nếu không, mã bit được biên dịch có thể không tìm thấy một biểu tượng có sẵn khi liên kết.

Để thực hiện việc này, khung RS sử dụng các đường dẫn tìm kiếm khác nhau cho lib thời gian chạy khi thực thi ld.mc, tuỳ thuộc vào việc chính khung RS có được tải từ /system/lib hoặc từ /system/lib/vndk-sp. Địa chỉ này có thể được xác định bằng cách đọc địa chỉ của một ký hiệu tuỳ ý của RS khung lib và sử dụng dladdr() để lấy đường dẫn tệp được ánh xạ tới địa chỉ.

Chính sách SELinux

Do những thay đổi về chính sách SELinux trong Android 8.0 trở lên, bạn phải tuân thủ 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ùng vendor. Chính sách nền tảng yêu cầu quyền này để truy cập triển khai HAL truyền qua.
  • Đã thêm tất cả exec_types mới vào phân vùng vendor phải có thuộc tính vendor_file_type thông qua SEPolicy của nhà cung cấp. Việc này được thực thi thông qua neverallows.
  • Để 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 các tệp khác exec_types trong phân vùng vendor.
  • Tất cả phần phụ thuộc thư viện cho HAL quy trình tương tự do AOSP xác định đều phải được gắn nhãn là same_process_hal_file.

Để biết chi tiết về chính sách SELinux, hãy xem Linux tăng cường bảo mật trong Android.

Khả năng tương thích với ABI (Giao diện nhị phân ứng dụng) đối với mã bit

Nếu bạn không thêm API mới nào, tức là sẽ không có phiên bản HAL (Lớp trừu tượng phần cứng) cho 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ỏ HAL (HAL 1.1) không ảnh hưởng đến bitcode, các khung phải dự phòng cho CPU cho các 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 việc biên dịch/liên kết mã bit, RS các khung nên chọn không tải trình điều khiển GPU do nhà cung cấp cung cấp và thay vào đó sử dụng đường dẫn CPU hoặc Vulkan để tăng tốc.

Việc sử dụng mã bit RenderScript xảy ra theo 3 giai đoạn:

Giai đoạn Thông tin chi tiết
Biên dịch
  • Mã bit đầu vào (.bc) cho bcc phải nằm trong Định dạng mã bit LLVM 3.2bcc phải là mã lùi tương thích với các ứng dụng (cũ) hiện tại.
  • Tuy nhiên, siêu dữ liệu trong .bc có thể thay đổi (có thể có thời gian chạy mới các hàm, ví dụ: Phương thức setter phân bổ ∓ phương thức getter, hàm toán học, v.v.). Phần của các hàm thời gian chạy nằm trong libclcore.bc, một phần trong số đó sống trong LibRSDriver hoặc nhà cung cấp tương đương.
  • Các hàm thời gian chạy mới hoặc có thể gây lỗi cho những thay đổi về siêu dữ liệu cần tăng dần cấp độ API bitcode. Vì trình điều khiển của nhà cung cấp sẽ không thể tiêu thụ thực phẩm này, phiên bản HAL cũng phải được tăng lên.
  • Nhà cung cấp có thể có trình biên dịch riêng, nhưng phần kết luận/yêu cầu cho bcc cũng áp dụng cho các trình biên dịch đó.
Đường liên kết
  • Miền .o đã biên dịch sẽ được liên kết với trình điều khiển của nhà cung cấp, ví dụ: libRSDriver_foo.solibcompiler_rt.so. CPU đường dẫn sẽ liên kết với libRSDriver.so.
  • Nếu miền .o yêu cầu một API thời gian chạy mới từ libRSDriver_foo, trình điều khiển của nhà cung cấp phải được cập nhật để hỗ trợ trình điều khiển đó.
  • Một số nhà cung cấp có thể có trình liên kết riêng, nhưng lập luận về ld.mc cũng áp dụng cho các trường này.
Tải
  • libRSCpuRef tải đối tượng dùng chung. Nếu có thay đổi đối với giao diện này, cần tăng phiên bản HAL.
  • Nhà cung cấp sẽ dựa vào libRSCpuRef để tải dữ liệu được chia sẻ hoặc triển khai đối tượng của riêng chúng.

Ngoài HAL, API thời gian chạy và biểu tượng được xuất cũng giao diện. Không có giao diện nào thay đổi kể từ Android 7.0 (API 24) và ở đó hiện chưa có kế hoạch thay đổi nó trong Android 8.0 trở lên. Tuy nhiên, nếu giao diện không thay đổi, phiên bản HAL cũng sẽ tăng.

Triển khai nhà cung cấp

Android 8.0 trở lên yêu cầu thay đổi một số 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

  • 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 nằm trong danh sách.
  • Người lái xe phải cung cấp android.hardware.renderscript@1.0-impl_{NAME} hoặc khai báo cách triển khai mặc định android.hardware.renderscript@1.0-impl dưới dạng 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 2 cách:

  1. Gọi trình biên dịch RenderScript dành riêng cho nhà cung cấp trong /vendor/bin/ (phương pháp biên dịch GPU ưu tiên). Tương tự như các mô-đun trình điều khiển khác, tệp nhị phân của trình biên dịch 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 nằm trong danh sách Thư viện RenderScript dành cho nhà cung cấp.
  2. Gọi hệ thống bcc: /system/bin/bcc bằng một nhà cung cấp do nhà cung cấp cung cấp bcc plugin; plugin này không thể phụ thuộc vào bất kỳ thư viện hệ thống nào không nằm trong danh sách Có các thư viện RenderScript cho nhà cung cấp.

Nếu nhà cung cấp bcc plugin cần can thiệp vào CPU quá trình biên dịch và phần phụ thuộc của nó trên libLLVM.so không thể dễ dàng bị xoá, nhà cung cấp sẽ sao chép bcc (và tất cả các mã không phải LL-NDK các phần phụ thuộc, bao gồm libLLVM.so, libbcc.so) vào phân vùng /vendor.

Ngoài ra, nhà cung cấp cần phải thực hiện các thay đổi sau:

Hình 7. Các thay đổi đối với trình điều khiển của nhà cung cấp.

  1. Sao chép libclcore.bc vào phân vùng /vendor. Chiến dịch này đảm bảo libclcore.bc, libLLVM.solibbcc.so đang đồng bộ hoá.
  2. Thay đổi đường dẫn đến tệp thực thi bcc bằng cách đặt RsdCpuScriptImpl::BCC_EXE_PATH trong quá trình triển khai HAL RS.

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 gọi bằng một quy trình ứng dụng, cũng như vậy bản sao của nhà cung cấp của 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:

  1. PRODUCT_shippingPING_API_LEVEL thấp hơn 26.
  2. PRODUCT_FULL_TREBLE_OVERRIDE không được xác định.

Đối với các thiết bị cũ, hạn chế 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 thư viện trong /system/lib[64]. Tuy nhiên, do kiến trúc thay đổi liên quan đến OVERRIDE_RS_DRIVER, Bạn phải cài đặt android.hardware.renderscript@1.0-impl để Phân vùng /vendor; không làm được việc này buộc thời gian chạy RenderScript dự phòng cho đường dẫn CPU.

Để biết thông tin về động lực ngừng sử dụng Renderscript, hãy xem bài viết Nhà phát triển Android Blog: Tính toán GPU Android trong tương lai. Sau đây là thông tin về tài nguyên để ngừng sử dụng: