RenderScript — это фреймворк для выполнения ресурсоемких вычислительных задач с высокой производительностью на Android. Он разработан для использования с параллельными вычислениями данных, хотя последовательные рабочие нагрузки также могут принести пользу. Среда выполнения RenderScript распараллеливает работу между процессорами, доступными на устройстве, такими как многоядерные ЦП и ГП, позволяя разработчикам сосредоточиться на выражении алгоритмов, а не на планировании работы. RenderScript особенно полезен для приложений, выполняющих обработку изображений, вычислительную фотографию или компьютерное зрение.
Устройства под управлением Android 8.0 и выше используют следующую инфраструктуру RenderScript и HAL-файлы поставщиков:

Рисунок 1. Код поставщика, связывающийся с внутренними библиотеками.
Отличия от RenderScript в Android 7.x и ниже включают в себя:
- Два экземпляра внутренних библиотек RenderScript в процессе. Один набор предназначен для пути отката CPU и находится непосредственно в
/system/lib
; другой набор предназначен для пути GPU и находится в/system/lib/vndk-sp
. - Внутренние библиотеки RS в
/system/lib
собираются как часть платформы и обновляются при обновленииsystem.img
. Однако библиотеки в/system/lib/vndk-sp
собираются для поставщика и не обновляются при обновленииsystem.img
(хотя их можно обновить для исправления безопасности, их ABI остается прежним). - Код поставщика (RS HAL, драйвер RS и
bcc plugin
) связаны с внутренними библиотеками RenderScript, расположенными в/system/lib/vndk-sp
. Они не могут быть связаны с библиотеками в/system/lib
поскольку библиотеки в этом каталоге созданы для платформы и, следовательно, могут быть несовместимы с кодом поставщика (т. е. символы могут быть удалены). Это сделало бы OTA только для фреймворка невозможным.
Дизайн
В следующих разделах подробно описывается разработка RenderScript в Android 8.0 и выше.
Библиотеки RenderScript доступны поставщикам
В этом разделе перечислены библиотеки RenderScript (известные как Vendor NDK for Same-Process HALs или VNDK-SP), которые доступны для кода поставщика и с которыми можно выполнить линковку. Также подробно описаны дополнительные библиотеки, которые не связаны с RenderScript, но которые также предоставляются для кода поставщика.
Хотя следующий список библиотек может отличаться в разных версиях Android, он неизменен для конкретной версии Android; актуальный список доступных библиотек см. в файле /system/etc/ld.config.txt
.
RenderScript библиотеки | Библиотеки, не относящиеся к RenderScript |
---|---|
|
|
Конфигурация пространства имен компоновщика
Ограничение на связывание, которое не позволяет использовать библиотеки, не входящие в VNDK-SP, кодом поставщика, применяется во время выполнения с использованием пространства имен компоновщика. (Подробности см. в презентации VNDK Design .)
На устройстве под управлением 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. Конфигурация пространства имен для компоновщика.
Загрузить драйверы
Резервный путь ЦП
В зависимости от наличия бита RS_CONTEXT_LOW_LATENCY
при создании контекста RS выбирается путь CPU или GPU. Когда выбирается путь CPU, libRS_internal.so
(основная реализация фреймворка RS) напрямую dlopen
из пространства имен компоновщика по умолчанию, где предоставляются платформенные версии библиотек RS.
Реализация RS HAL от поставщика вообще не используется, когда выбирается резервный путь ЦП, а объект RsContext
создается с пустым mVendorDriverName
. libRSDriver.so
(по умолчанию) открывается с dlopen
, а библиотека драйвера загружается из пространства имен default
, поскольку вызывающая сторона ( libRS_internal.so
) также загружена в пространство имен default
.

Рисунок 3. Путь восстановления ЦП.
Путь графического процессора
Для пути 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
.
Поставщики могут предоставить свой собственный драйвер RS, установив флаг времени сборки OVERRIDE_RS_DRIVER
, который встроен в реализацию RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp
). Это имя драйвера затем dlopen
ed для контекста RS для пути GPU.
Создание объекта RsContext
делегируется реализации RS HAL. HAL вызывает фреймворк RS, используя функцию rsContextCreateVendor()
с именем драйвера для использования в качестве аргумента. Затем фреймворк RS загружает указанный драйвер при инициализации RsContext
. В этом случае библиотека драйвера загружается в пространство имен rs
, поскольку объект RsContext
создается внутри пространства имен rs
, а /vendor/lib
находится в пути поиска пространства имен.

Рисунок 4. Резервный путь графического процессора.
При переходе из пространства имен default
в пространство имен sphal
libhidltransport.so
использует функцию android_load_sphal_library()
чтобы явно приказать динамическому компоновщику загрузить библиотеку -impl.so
из пространства имен sphal
.
При переходе из пространства имен sphal
в пространство имен rs
загрузка выполняется косвенно с помощью следующей строки в /system/etc/ld.config.txt
:
namespace.sphal.link.rs.shared_libs = libRS_internal.so
Эта строка указывает, что динамический компоновщик должен загрузить libRS_internal.so
из пространства имен rs
, когда lib не может быть найдена/загружена из пространства имен sphal
(что всегда так, поскольку пространство имен sphal
не ищет /system/lib/vndk-sp
, где находится libRS_internal.so
). При такой конфигурации простого вызова dlopen()
для libRS_internal.so
достаточно для перехода пространства имен.
Загрузить плагин BCC
bcc plugin
— это библиотека, предоставляемая поставщиком, загружаемая в компилятор bcc
. Поскольку bcc
— это системный процесс в каталоге /system/bin
, библиотеку bcc plugin
можно считать SP-HAL (т. е. HAL поставщика, который может быть напрямую загружен в системный процесс без привязки). Как SP-HAL, библиотека bcc-plugin
:
- Невозможно выполнить компоновку с библиотеками, предназначенными только для фреймворков, такими как
libLLVM.so
. - Возможна связь только с библиотеками VNDK-SP, доступными поставщику.
Это ограничение обеспечивается загрузкой bcc plugin
в пространство имен sphal
с помощью функции android_sphal_load_library()
. В предыдущих версиях Android имя плагина указывалось с помощью опции -load
, а библиотека загружалась с помощью простого dlopen()
с помощью libLLVM.so
. В Android 8.0 и выше это указывается в опции -plugin
, а библиотека загружается непосредственно самим bcc
. Эта опция включает неспецифичный для Android путь к проекту LLVM с открытым исходным кодом.

Рисунок 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 Framework и используя dladdr()
для получения пути к файлу, сопоставленного с адресом.
Политика SELinux
В результате изменений политики SELinux в Android 8.0 и выше необходимо соблюдать определенные правила (применяемые с помощью neverallows
) при маркировке дополнительных файлов в разделе vendor
:
-
vendor_file
должен быть меткой по умолчанию для всех файлов в разделеvendor
. Политика платформы требует этого для доступа к реализациям HAL passthrough. - Все новые
exec_types
добавленные в разделvendor
через SEPolicy поставщика, должны иметь атрибутvendor_file_type
. Это обеспечивается черезneverallows
. - Чтобы избежать конфликтов с будущими обновлениями платформы/фреймворка, не маркируйте файлы, отличные от
exec_types
в разделеvendor
. - Все зависимости библиотек для тех же процессов HAL, которые идентифицированы AOSP, должны быть помечены как
same_process_hal_file
.
Подробную информацию о политике SELinux см. в разделе Безопасность Linux в Android .
Совместимость ABI для биткода
Если не будут добавлены новые API, что означает отсутствие повышения версии HAL, фреймворки RS продолжат использовать существующий драйвер GPU (HAL 1.0).
Для незначительных изменений HAL (HAL 1.1), не влияющих на биткод, фреймворки должны вернуться к использованию CPU для этих новых API и продолжать использовать драйвер GPU (HAL 1.0) в других местах.
В случае серьезных изменений HAL (HAL 2.0), влияющих на компиляцию/связывание биткода, фреймворки RS должны не загружать предоставленные поставщиком драйверы графического процессора, а вместо этого использовать путь ЦП или Vulkan для ускорения.
Использование биткода RenderScript происходит в три этапа:
Этап | Подробности |
---|---|
Компилировать |
|
Связь |
|
Нагрузка |
|
В дополнение к HAL, интерфейсами также являются API среды выполнения и экспортированные символы. Ни один из интерфейсов не изменился с Android 7.0 (API 24), и нет никаких непосредственных планов изменить его в Android 8.0 и далее. Однако, если интерфейс изменится, версия HAL также увеличится.
Реализации поставщиков
Для корректной работы драйвера графического процессора в Android 8.0 и выше требуются некоторые изменения в драйвере графического процессора.
Модули драйверов
- Модули драйверов не должны зависеть от каких-либо системных библиотек, отсутствующих в списке .
- Драйвер должен предоставить свой собственный
android.hardware.renderscript@1.0-impl_{NAME}
или объявить реализацию по умолчаниюandroid.hardware.renderscript@1.0-impl
в качестве своей зависимости. - Реализация ЦП
libRSDriver.so
является хорошим примером того, как удалить зависимости, не относящиеся к VNDK-SP.
Компилятор биткода
Скомпилировать биткод RenderScript для драйвера поставщика можно двумя способами:
- Вызовите специфичный для поставщика компилятор RenderScript в
/vendor/bin/
(предпочтительный метод компиляции GPU). Подобно другим модулям драйвера, двоичный файл компилятора поставщика не может зависеть от какой-либо системной библиотеки, которая не входит в список библиотек RenderScript, доступных поставщикам . - Вызовите system bcc:
/system/bin/bcc
с помощьюbcc plugin
, предоставленного поставщиком; этот плагин не может зависеть от какой-либо системной библиотеки, которая не входит в список библиотек RenderScript, доступных поставщикам .
Если bcc plugin
необходимо вмешаться в компиляцию ЦП, а его зависимость от libLLVM.so
нельзя легко удалить, поставщик должен скопировать bcc
(и все зависимости, не относящиеся к LL-NDK, включая libLLVM.so
, libbcc.so
) в раздел /vendor
.
Кроме того, поставщикам необходимо внести следующие изменения:

Рисунок 7. Изменения в драйвере поставщика.
- Скопируйте
libclcore.bc
в раздел/vendor
. Это гарантирует синхронизациюlibclcore.bc
,libLLVM.so
иlibbcc.so
. - Измените путь к исполняемому файлу
bcc
, установивRsdCpuScriptImpl::BCC_EXE_PATH
из реализации RS HAL.
Политика SELinux
Политика SELinux влияет как на драйвер, так и на исполняемые файлы компилятора. Все модули драйвера должны быть помечены как same_process_hal_file
в file_contexts
устройства. Например:
/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 будет откатываться к пути ЦП.
Информацию о мотивации устаревания Renderscript см. в блоге разработчиков Android: Android GPU Compute Going Forward . Информация о ресурсах для этого устаревания включает следующее:
- Миграция с Renderscript
- Пример RenderScriptMigration
- README для набора инструментов замены внутренних компонентов
- Набор инструментов для замены внутренних компонентов.kt