На этой странице описаны изменения в драйвере связывания в 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
Процессам поставщика, которые хотят использовать функциональность связующего для взаимодействия друг с другом, необходимо следующее:
- Доступ к
/dev/vndbinder
. - Binder
{transfer, call}
перехватываетvndservicemanager
. -
binder_call(A, B)
для любого домена поставщика A, который хочет позвонить в домен поставщика B через интерфейс связующего поставщика. - Разрешение на
{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;