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

Рисунок 1. Код поставщика, ссылающийся на внутренние библиотеки.
Отличия от RenderScript в Android 7.x и ниже включают в себя:
- Два экземпляра внутренних библиотек RenderScript в процессе. Один набор предназначен для резервного пути ЦП и находится непосредственно в
/system/lib
; другой набор предназначен для пути ГП и находится в/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» ).
На устройствах под управлением Android 8.0 и выше все однопроцессные HAL (SP-HAL), за исключением RenderScript, загружаются в пространство имён компоновщика sphal
. RenderScript загружается в специфичное для RenderScript пространство имён rs
, что обеспечивает несколько более мягкое ограничение прав доступа к библиотекам RenderScript. Поскольку реализация RS должна загружать скомпилированный биткод, к пути пространства имён rs
добавляется /data/*/*.so
(другим 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. Путь отката ЦП.
Путь графического процессора
Для графического процессора библиотека 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
libRS_internal.so
в другом пространстве имён компоновщика, называемом rs
.
Поставщики могут предоставлять собственный драйвер RS, установив флаг OVERRIDE_RS_DRIVER
во время сборки, который встроен в реализацию RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp
). Затем это имя драйвера dlopen
в контексте RS для пути к графическому процессору.
Создание объекта 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
, если библиотека не может быть найдена/загружена из пространства имён sphal
(что происходит всегда, поскольку пространство имён sphal
не ищет в /system/lib/vndk-sp
, где находится libRS_internal.so
). При такой конфигурации для перехода между пространствами имён достаточно простого вызова libRS_internal.so
с помощью dlopen()
.
Загрузить плагин скрытой копии
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
. Этот параметр позволяет указать путь к проекту 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
В результате изменений политики SELinux в Android 8.0 и выше при маркировке дополнительных файлов в разделе vendor
необходимо следовать определенным правилам (применяемым через neverallows
):
-
vendor_file
должно быть меткой по умолчанию для всех файлов в разделеvendor
. Политика платформы требует этого для доступа к реализациям HAL через сквозной доступ. - Все новые
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 для набора инструментов замены внутренних компонентов
- Intrinsics Replacement Toolkit.kt