Google is committed to advancing racial equity for Black communities. See how.
Эта страница была переведа с помощью Cloud Translation API.
Switch to English

Использование Binder IPC

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

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

Начиная с Android 8, платформа Android и HAL теперь взаимодействуют друг с другом с помощью связывателя. Поскольку это взаимодействие резко увеличивает трафик связывателей, Android 8 включает в себя несколько улучшений, предназначенных для быстрой работы Binder 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: binder: не проверять приоритетные разрешения при восстановлении.
  • Обычный-4.4
    76b376eac7a2 ANDROID: binder: не проверять приоритетные разрешения при восстановлении.
  • Обычный-4.9
    ecd972d4f9b5 ANDROID: binder: не проверять приоритетные разрешения при восстановлении.

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

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

vndbinder

Android 8 поддерживает новый домен Связующее для использования услуг поставщика, доступ , используя /dev/vndbinder вместо /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 , которая открывает драйвер libbinder . Добавление метода для ::android::ProcessState() выбирает драйвер libbinder для libbinder . Процессы поставщика должны вызывать этот метод перед вызовом ProcessState, IPCThreadState или перед выполнением каких-либо вызовов связующего в целом. Для использования поместите следующий вызов после main() процесса поставщика (клиента и сервера):

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

vndservicemanager

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

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

vndservicemanager файл vndservicemanager включен в make- vndservicemanager устройства 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, которым необходимо binder_call(A, B) через binder_call(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

Ранее правила предоставляли доменам доступ для добавления или поиска сервисов из 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;