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

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 загружается в специфичное для 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. Когда выбран путь ЦП, libRS_internal.so (основная реализация инфраструктуры RS) напрямую dlopen из пространства имен компоновщика по умолчанию, где предоставляется версия библиотеки RS для платформы.

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

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

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

Для пути 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 libRS_internal.so dlopen другом пространстве имен компоновщика с именем rs .

Поставщики могут предоставить свой собственный драйвер RS, установив флаг времени сборки OVERRIDE_RS_DRIVER , встроенный в реализацию RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp ). Это имя драйвера затем dlopen для контекста RS для пути GPU.

Создание объекта RsContext делегировано реализации RS HAL. HAL обращается к платформе RS, используя rsContextCreateVendor() с именем драйвера для использования в качестве аргумента. Затем платформа RS загружает указанный драйвер при инициализации RsContext . В этом случае библиотека драйверов загружается в пространство имен rs , поскольку объект RsContext создается внутри пространства имен rs , а /vendor/lib находится в пути поиска пространства имен.

Рис. 5. Резервный путь GPU

При переходе от пространства имен по 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 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/ (предпочтительный метод компиляции GPU). Подобно другим модулям драйверов, двоичный файл компилятора поставщика не может зависеть ни от какой системной библиотеки, которой нет в списке библиотек 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 . Информация о ресурсах для этого устаревания включает следующее: