Рендерскрипт

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
  • 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

Конфигурация пространства имен компоновщика

Ограничение связывания, которое не позволяет коду поставщика использовать библиотеки, не входящие в VNDK-SP, применяется во время выполнения с использованием пространства имен компоновщика. (Подробнее см. презентацию VNDK Design .)

На устройстве под управлением Android 8.0 и более поздних версий все HAL одного и того же процесса (SP-HAL), за исключением RenderScript, загружаются внутри пространства имен компоновщика sphal . RenderScript загружается в пространство имен rs , специфичное для RenderScript, место, которое обеспечивает несколько более слабое применение библиотек RenderScript. Поскольку реализации RS необходимо загрузить скомпилированный битовый код, /data/*/*.so добавляется к пути пространства имен rs (другим SP-HAL не разрешено загружать библиотеки из раздела данных).

Кроме того, пространство имен rs позволяет использовать больше библиотек, чем предусмотрено другими пространствами имен. libmediandk.so и libft2.so доступны пространству имен rs , поскольку libRS_internal.so имеет внутреннюю зависимость от этих библиотек.

Рисунок 2. Конфигурация пространства имен для компоновщика

Загрузка драйверов

Резервный путь ЦП

В зависимости от наличия бита RS_CONTEXT_LOW_LATENCY при создании контекста RS выбирается путь CPU или GPU. Когда выбран путь ЦП, libRS_internal.so (основная реализация инфраструктуры RS) dlopen непосредственно из пространства имен компоновщика по умолчанию, где предоставляются платформенные версии библиотек RS.

Реализация RS HAL от поставщика вообще не используется, когда выбран резервный путь ЦП и создается объект RsContext с нулевым mVendorDriverName . libRSDriver.so (по умолчанию) dlopen , и библиотека драйвера загружается из пространства имен default , поскольку вызывающая сторона ( libRS_internal.so ) также загружается в пространство имен default .

Рисунок 4. Резервный путь ЦП

Путь графического процессора

Для пути к графическому процессору 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 выполняет обратный вызов структуры RS, используя функцию rsContextCreateVendor() с именем драйвера, который будет использоваться в качестве аргумента. Затем платформа RS загружает указанный драйвер при инициализации RsContext . В этом случае библиотека драйверов загружается в пространство rs , поскольку объект RsContext создается внутри пространства rs , а /vendor/lib находится в пути поиска пространства имен.

Рисунок 5. Резервный путь графического процессора

При переходе из пространства имен 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 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 с открытым исходным кодом.

Рисунок 6. Загрузка плагина bcc, Android 7.x и более ранних версий


Рисунок 7. Загрузка плагина 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 и более поздних версиях вы должны следовать определенным правилам (обеспечиваемым через neverallows ) при маркировке дополнительных файлов в разделе vendor :

  • 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 будут продолжать использовать существующий драйвер графического процессора (HAL 1.0).

В случае незначительных изменений HAL (HAL 1.1), не затрагивающих битовый код, платформам следует вернуться к процессору для этих новых добавленных API и продолжать использовать драйвер графического процессора (HAL 1.0) в другом месте.

В случае серьезных изменений HAL (HAL 2.0), влияющих на компиляцию/связывание биткода, платформы RS должны отказаться от загрузки предоставленных поставщиком драйверов графического процессора и вместо этого использовать для ускорения путь ЦП или Vulkan.

Использование биткода RenderScript происходит в три этапа:

Этап Подробности
Скомпилировать
  • Входной битовый код (.bc) для bcc должен быть в формате битового кода LLVM 3.2 , а bcc должен быть обратно совместим с существующими (устаревшими) приложениями.
  • Однако метаданные в .bc могут измениться (могут появиться новые функции времени выполнения, например, установщики распределения ∓ геттеры, математические функции и т. д.). Часть функций времени выполнения находится в libclcore.bc , часть — в LibRSDriver или его эквиваленте.
  • Новые функции времени выполнения или критические изменения метаданных требуют повышения уровня API биткода. Поскольку драйверы поставщиков не смогут его использовать, версию HAL также необходимо увеличить.
  • У поставщиков могут быть свои собственные составители, но выводы/требования для bcc также применимы и к этим составителям.
Связь
  • Скомпилированный .o будет связан с драйвером поставщика, например, libRSDriver_foo.so и libcompiler_rt.so . Путь ЦП будет связан с libRSDriver.so .
  • Если .o требует нового API времени выполнения из libRSDriver_foo , драйвер поставщика необходимо обновить для его поддержки.
  • Некоторые поставщики могут иметь свои собственные компоновщики, но аргументы в пользу ld.mc применимы и к ним.
Нагрузка
  • libRSCpuRef загружает общий объект. Если в этот интерфейс есть изменения, необходимо обновить версию HAL.
  • Поставщики либо будут полагаться на libRSCpuRef для загрузки общего объекта, либо реализуют свой собственный.

Помимо 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 для драйвера поставщика можно скомпилировать двумя способами:

  1. Вызовите компилятор RenderScript конкретного поставщика в /vendor/bin/ (предпочтительный метод компиляции с помощью графического процессора). Подобно другим модулям драйверов, двоичный файл компилятора поставщика не может зависеть от какой-либо системной библиотеки, которой нет в списке библиотек RenderScript, доступных поставщикам .
  2. Вызов системы bcc: /system/bin/bcc с помощью bcc plugin , предоставленного поставщиком; этот плагин не может зависеть от какой-либо системной библиотеки, которой нет в списке библиотек RenderScript, доступных поставщикам .

Если подключаемый bcc plugin поставщика должен вмешиваться в компиляцию ЦП и его зависимость от libLLVM.so не может быть легко удалена, поставщик должен скопировать bcc (и все зависимости, отличные от LL-NDK, включая libLLVM.so , libbcc.so ) в /vendor раздел.

Кроме того, поставщикам необходимо внести следующие изменения:

Рисунок 8. Изменения в драйвере поставщика
  1. Скопируйте libclcore.bc в раздел /vendor . Это гарантирует синхронизацию libclcore.bc , libLLVM.so и libbcc.so .
  2. Измените путь к исполняемому файлу 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

Устаревшие устройства

Устаревшие устройства – это те, которые удовлетворяют следующим условиям:

  1. PRODUCT_SHIPPING_API_LEVEL ниже 26.
  2. 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 . Информация о ресурсах для прекращения поддержки включает следующее: