Использование связывателя IPC

На этой странице описываются изменения в драйвере связывателя в Android 8, приводятся сведения об использовании IPC связывателя и перечислены необходимые политики SELinux.

Изменения в драйвере связующего

Начиная с Android 8, платформа Android и HAL теперь взаимодействуют друг с другом с помощью связывателя. Поскольку эта связь значительно увеличивает трафик связующих, Android 8 включает несколько улучшений, предназначенных для обеспечения быстрой IPC связующих. Поставщики SoC и OEM-производители должны объединяться непосредственно из соответствующих ветвей android-4.4, android-4.9 и выше проекта ядра/общего .

Несколько доменов связывания (контексты)

Common-4.4 и выше, включая апстрим

Чтобы четко разделить трафик связывателя между фреймворком (независимым от устройства) и вендорным (зависящим от устройства) кодом, в Android 8 была введена концепция контекста связывателя . Каждый контекст связывателя имеет свой собственный узел устройства и свой менеджер контекста (службы). Вы можете получить доступ к диспетчеру контекста только через узел устройства, которому он принадлежит, и при передаче узла привязки через определенный контекст он доступен из этого же контекста только другим процессом, таким образом, полностью изолируя домены друг от друга. Дополнительные сведения об использовании см. в разделе vndbinder и vndservicemanager .

Разбрасывать-собирать

Common-4.4 и выше, включая апстрим

В предыдущих выпусках Android каждая часть данных в вызове связывателя копировалась три раза:

  • Один раз, чтобы сериализовать его в Parcel в вызывающем процессе
  • Один раз в драйвере ядра скопировать Parcel в целевой процесс
  • Один раз, чтобы десериализовать Parcel в целевом процессе

Android 8 использует оптимизацию разброса-сбора , чтобы уменьшить количество копий с 3 до 1. Вместо того, чтобы сначала сериализовать данные в Parcel , данные остаются в своей исходной структуре и расположении в памяти, и драйвер немедленно копирует их в целевой процесс. После того, как данные находятся в целевом процессе, структура и структура памяти остаются прежними, и данные можно прочитать, не требуя еще одной копии.

Мелкозернистая блокировка

Common-4.4 и выше, включая апстрим

В предыдущих выпусках Android драйвер связывателя использовал глобальную блокировку для защиты от одновременного доступа к важным структурам данных. Хотя конкуренция за блокировку была минимальной, основная проблема заключалась в том, что если поток с низким приоритетом получил блокировку, а затем был вытеснен, это могло серьезно задержать потоки с более высоким приоритетом, которым необходимо было получить ту же блокировку. Это вызвало рывки в платформе.

Первоначальные попытки решить эту проблему включали отключение вытеснения при удерживании глобальной блокировки. Однако это был скорее взлом, чем настоящее решение, и в конечном итоге оно было отвергнуто апстримом и отброшено. Последующие попытки были направлены на то, чтобы сделать блокировку более детальной, версия которой работает на устройствах Pixel с января 2017 года. Хотя большинство этих изменений были обнародованы, в последующих версиях были внесены существенные улучшения.

После выявления небольших проблем в мелкомодульной реализации блокировки мы разработали улучшенное решение с другой архитектурой блокировки и отправили изменения во все распространенные ветки ядра. Мы продолжаем тестировать эту реализацию на большом количестве различных устройств; поскольку нам неизвестно о каких-либо нерешенных проблемах, это рекомендуемая реализация для устройств, поставляемых с Android 8.

Наследование приоритета в реальном времени

Common-4.4 и common-4.9 (скоро появится апстрим)

Драйвер связывателя всегда поддерживал красивое наследование приоритетов. Поскольку все большее число процессов в Android запускается с приоритетом реального времени, в некоторых случаях теперь имеет смысл, если поток в реальном времени выполняет вызов связывателя, поток в процессе, который обрабатывает этот вызов, также выполняется с приоритетом в реальном времени. . Для поддержки этих вариантов использования Android 8 теперь реализует наследование приоритетов в реальном времени в драйвере связывателя.

В дополнение к наследованию приоритета на уровне транзакции, наследование приоритета узла позволяет узлу (объекту службы связывателя) указывать минимальный приоритет, при котором должны выполняться вызовы в этот узел. Предыдущие версии Android уже поддерживали наследование узлов с хорошими значениями, но в Android 8 добавлена ​​поддержка наследования узлов политик планирования в реальном времени.

Изменения пользовательского пространства

Android 8 включает все изменения пользовательского пространства, необходимые для работы с текущим драйвером связывателя в общем ядре, за одним исключением: исходная реализация для отключения наследования приоритетов в реальном времени для /dev/binder использовала ioctl . Последующая разработка переключила управление наследованием приоритетов на более детализированный метод, основанный на режиме связывания (а не на контексте). Таким образом, ioctl не находится в общей ветке Android, а вместо этого отправляется в наши общие ядра .

Результатом этого изменения является то, что наследование приоритета в реальном времени отключено по умолчанию для каждого узла. Группа производительности Android сочла полезным включить наследование приоритетов в реальном времени для всех узлов в домене hwbinder . Чтобы добиться того же эффекта, выберите это изменение в пользовательском пространстве.

SHA для обычных ядер

Чтобы получить необходимые изменения в драйвере связывателя, выполните синхронизацию с соответствующим SHA:

  • Общий-3.18
    cc8b90c121de ANDROID: связующее: не проверяйте приоритетные разрешения при восстановлении.
  • Общий-4.4
    76b376eac7a2 ANDROID: связующее: не проверять приоритетные разрешения при восстановлении.
  • Общий-4.9
    ecd972d4f9b5 ANDROID: связующее: не проверять приоритетные разрешения при восстановлении.

Использование связующего IPC

Исторически сложилось так, что процессы поставщиков использовали для связи межпроцессное взаимодействие (IPC). В Android 8 узел устройства /dev/binder становится эксклюзивным для процессов платформы, то есть процессы поставщиков больше не имеют к нему доступа. Процессы поставщиков могут получить доступ к /dev/hwbinder , но должны преобразовать свои интерфейсы AIDL для использования HIDL. Для поставщиков, которые хотят продолжать использовать интерфейсы AIDL между процессами поставщиков, Android поддерживает связывание IPC, как описано ниже.

вндбиндер

Android 8 поддерживает новый домен связывания для использования службами поставщиков, доступ к которому осуществляется с помощью /dev/vndbinder вместо /dev/binder dev/binder . С добавлением /dev/vndbinder Android теперь имеет следующие три домена IPC:

IPC-домен Описание
/dev/binder IPC между процессами платформы/приложения с интерфейсами AIDL
/dev/hwbinder IPC между процессами платформы/поставщика с интерфейсами HIDL
IPC между процессами поставщиков с интерфейсами HIDL
/dev/vndbinder IPC между процессами поставщика/поставщика с интерфейсами AIDL

Чтобы /dev/vndbinder появился, убедитесь, что для элемента конфигурации ядра CONFIG_ANDROID_BINDER_DEVICES установлено значение "binder,hwbinder,vndbinder" (это значение по умолчанию в общих деревьях ядра Android).

Обычно процессы поставщика не открывают драйвер связывателя напрямую, а вместо этого связываются с библиотекой пользовательского пространства libbinder , которая открывает драйвер связывателя. Добавление метода для ::android::ProcessState() выбирает драйвер связывателя для libbinder . Процессы поставщиков должны вызывать этот метод перед вызовом ProcessState, IPCThreadState или перед выполнением любых вызовов связывателя в целом. Чтобы использовать, поместите следующий вызов после main() процесса поставщика (клиент и сервер):

ProcessState::initWithDriver("/dev/vndbinder");

vndservicemanager

Раньше службы связывания регистрировались в servicemanager , откуда их могли получать другие процессы. В Android 8 servicemanager теперь используется исключительно процессами фреймворка и приложения, а процессы поставщика больше не могут получить к нему доступ.

Однако сервисы поставщиков теперь могут использовать vndservicemanager — новый экземпляр servicemanager , который использует /dev/vndbinder вместо /dev/binder dev/binder и создан из тех же источников, что и framework servicemanager . Процессам поставщика не нужно вносить изменения, чтобы общаться с vndservicemanager ; когда процесс поставщика открывает / dev/vndbinder , поиск службы автоматически переходит к vndservicemanager .

Двоичный файл vndservicemanager включен в make-файлы устройств Android по умолчанию.

Политика SELinux

Процессам поставщика, которые хотят использовать функциональные возможности связывателя для связи друг с другом, необходимо следующее:

  1. Доступ к /dev/vndbinder .
  2. Binder {transfer, call} подключается к vndservicemanager .
  3. binder_call(A, B) для любого домена поставщика A, который хочет вызвать домен поставщика B через интерфейс связывателя поставщика.
  4. Разрешение на {add, find} службы в vndservicemanager .

Чтобы выполнить требования 1 и 2, используйте vndbinder_use() :

vndbinder_use(some_vendor_process_domain);

Чтобы выполнить требование 3, binder_call(A, B) для процессов поставщика A и B, которым требуется взаимодействие через связующее, может оставаться на месте и не требует переименования.

Чтобы выполнить требование 4, вы должны внести изменения в способ обработки имен служб, меток служб и правил.

Дополнительные сведения о SELinux см. в разделе Linux с улучшенной безопасностью в Android . Дополнительные сведения о SELinux в Android 8.0 см. в разделе SELinux для Android 8.0 .

Имена сервисов

Раньше поставщики обрабатывали зарегистрированные имена служб в файле service_contexts и добавляли соответствующие правила для доступа к этому файлу. Пример файла service_contexts из device/google/marlin/sepolicy :

AtCmdFwd                              u:object_r:atfwd_service:s0
cneservice                            u:object_r:cne_service:s0
qti.ims.connectionmanagerservice      u:object_r:imscm_service:s0
rcs                                   u:object_r:radio_service:s0
uce                                   u:object_r:uce_service:s0
vendor.qcom.PeripheralManager         u:object_r:per_mgr_service:s0

В Android 8 vndservicemanager вместо этого загружает файл vndservice_contexts . Службы поставщиков, переносимые на vndservicemanager (и уже находящиеся в старом файле service_contexts ), должны быть добавлены в новый файл vndservice_contexts .

Сервисные этикетки

Ранее метки служб, такие как u:object_r:atfwd_service:s0 , определялись в файле service.te . Пример:

type atfwd_service,      service_manager_type;

В Android 8 необходимо изменить тип на vndservice_manager_type и перенести правило в файл vndservice.te . Пример:

type atfwd_service,      vndservice_manager_type;

Правила сервис-менеджера

Ранее правила предоставляли доменам доступ для добавления или поиска служб из servicemanager . Пример:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;

В Android 8 такие правила могут оставаться в силе и использовать тот же класс. Пример:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;