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 для HAL, работающих в одном процессе, или VNDK-SP), доступные для кода сторонних разработчиков и которые могут быть связаны с ним. Также подробно описаны дополнительные библиотеки, не связанные с RenderScript, но также предоставляемые коду сторонних разработчиков.
Хотя приведенный ниже список библиотек может отличаться в зависимости от версии Android, он является неизменяемым для конкретной версии Android; актуальный список доступных библиотек см. в файле /system/etc/ld.config.txt .
| Библиотеки RenderScript | Библиотеки, не использующие RenderScript |
|---|---|
|
|
Конфигурация пространства имен компоновщика
Ограничение на компоновку, препятствующее использованию библиотек, не входящих в VNDK-SP, кодом сторонних разработчиков, обеспечивается во время выполнения с помощью пространства имен компоновщика. (Подробнее см. презентацию по проектированию VNDK .)
На устройствах под управлением Android 8.0 и выше все S-HAL (Same-Process HAL), кроме RenderScript, загружаются в пространство имен компоновщика sphal . RenderScript загружается в специфичное для RenderScript пространство имен rs , что позволяет несколько ослабить контроль за библиотеками RenderScript. Поскольку реализации RS необходимо загружать скомпилированный битовый код, /data/*/*.so добавляется к пути пространства имен rs (другим S-HAL не разрешается загружать библиотеки из раздела данных).
Кроме того, пространство имен rs позволяет использовать больше библиотек, чем это предусмотрено другими пространствами имен. libmediandk.so и libft2.so доступны в пространстве имен rs , поскольку libRS_internal.so имеет внутреннюю зависимость от этих библиотек.

Рисунок 2. Конфигурация пространства имен для компоновщика.
Загрузка драйверов
резервный путь ЦП
В зависимости от наличия бита RS_CONTEXT_LOW_LATENCY при создании контекста RS выбирается либо путь для ЦП, либо путь для ГП. При выборе пути для ЦП, 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 s libRS_internal.so в другом пространстве имен компоновщика под названием rs .
Производители могут предоставить собственный драйвер RS, установив флаг OVERRIDE_RS_DRIVER во время сборки, который встроен в реализацию RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp ). Затем это имя драйвера используется для dlopen контекста RS для пути к графическому процессору.
Создание объекта RsContext делегируется реализации RS HAL. HAL вызывает функцию rsContextCreateVendor() из фреймворка RS, передавая в качестве аргумента имя драйвера. Затем фреймворк 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 ). При такой конфигурации достаточно простого вызова 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 . Этот параметр позволяет указать путь к проекту 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. - Во избежание конфликтов с будущими обновлениями платформы/фреймворка, не следует присваивать файлам в разделе
vendorметки, отличные отexec_types. - Все библиотечные зависимости для HAL, идентифицированных AOSP как принадлежащие одному процессу, должны быть помечены как
same_process_hal_file.
Подробную информацию о политике SELinux см. в разделе «Повышение безопасности Linux в Android» .
Совместимость ABI для битового кода
Если новые API не будут добавлены, то есть не произойдет повышения версии HAL, фреймворки RS продолжат использовать существующий драйвер GPU (HAL 1.0).
При незначительных изменениях HAL (HAL 1.1), не затрагивающих битовый код, фреймворки должны переключаться на использование ЦП для этих новых API, а в остальных случаях продолжать использовать драйвер ГП (HAL 1.0).
В случае существенных изменений в HAL (HAL 2.0), затрагивающих компиляцию/линковку битового кода, RS-фреймворкам следует отказаться от загрузки драйверов GPU, предоставляемых поставщиком, и вместо этого использовать путь ускорения через ЦП или 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, доступных поставщикам . - Вызовите системную команду 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
- Пример миграции RenderScript
- README инструментария для замены внутренних параметров
- Intrinsics Replacement Toolkit.kt