Ввод

Значок Android Input HAL

Подсистема ввода Android номинально состоит из конвейера событий, который проходит через несколько уровней системы.

Конвейер ввода

На самом нижнем уровне физическое устройство ввода создает сигналы, описывающие изменения состояния, например нажатия клавиш и точки касания. Встроенное ПО устройства кодирует и передает эти сигналы, например отправляя отчеты USB HID в систему или создавая прерывания в шине I2C.

Затем сигналы декодируются драйвером устройства в ядре Linux. Ядро Linux предоставляет драйверы для многих стандартных периферийных устройств, особенно тех, которые соответствуют протоколу HID. Однако производителю оборудования часто приходится предоставлять специальные драйверы для встроенных устройств, которые тесно интегрированы в систему на низком уровне, например сенсорных экранов.

Драйверы устройств ввода отвечают за преобразование сигналов, поступающих от устройств, в стандартный формат событий ввода с помощью протокола ввода Linux. Протокол ввода Linux определяет стандартный набор типов и кодов событий в заголовочном файле ядра linux/input.h. Таким образом, компонентам, не относящимся к ядру, не нужно знать такие детали, как физические коды сканирования, коды использования HID, сообщения I2C, контакты GPIO и т. п.

Затем компонент Android EventHub считывает события ввода из ядра, открывая драйвер evdev, связанный с каждым устройством ввода. Затем компонент InputReader Android декодирует входные события в соответствии с классом устройства и создает поток входных событий Android. В рамках этого процесса коды событий протокола ввода Linux преобразуются в коды событий Android в соответствии с конфигурацией устройства ввода, файлами раскладки клавиатуры и различными таблицами сопоставления.

Наконец, InputReader отправляет входные события в InputDispatcher, который пересылает их в нужное окно.

Контрольные точки

В конвейере ввода есть несколько этапов, которые влияют на поведение устройства ввода.

Настройка драйверов и встроенного ПО

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

Параметры конфигурации драйвера часто указываются в виде параметров модуля в пакете поддержки платы ядра (BSP), чтобы один и тот же драйвер мог поддерживать несколько разных реализаций оборудования.

В этой документации не описывается настройка драйверов или встроенного ПО, но приводятся общие рекомендации по калибровке устройств.

Свойства конфигурации доски

Пакет поддержки платы ядра (BSP) может экспортировать свойства конфигурации платы через SysFS, которые используются компонентом Android InputReader, например расположение виртуальных клавиш на сенсорном экране.

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

Оверлеи ресурсов

Некоторые действия, связанные с вводом, настраиваются с помощью наложений ресурсов в config.xml, например работа переключателя крышки.

Вот несколько примеров:

  • config_lidKeyboardAccessibility – определяет, как переключатель крышки влияет на доступность аппаратной клавиатуры.

  • config_lidNavigationAccessibility – определяет, как переключатель крышки влияет на доступность сенсорной панели.

  • config_longPressOnPowerBehavior – определяет, что должно произойти, когда пользователь удерживает кнопку питания.

  • config_lidOpenRotation: определяет, как закрытие крышки влияет на ориентацию экрана.

Подробная информация о каждом варианте конфигурации приведена в документации в frameworks/base/core/res/res/values/config.xml.

Назначение клавиш

Файлы сопоставления клавиш используются компонентами Android EventHub и InputReader, чтобы настроить сопоставление кодов событий Linux с кодами событий Android для клавиш, кнопок и осей джойстика. Сопоставление может зависеть от устройства или языка.

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

Файлы конфигурации устройств ввода

Файлы конфигурации устройств ввода используются компонентами Android EventHub и InputReader для настройки специальных характеристик устройств, например способа передачи информации о размере касания.

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

Как работают коды событий и использования HID

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

Физический скан-код

Физический код сканирования – это идентификатор, относящийся к определенному устройству и связанный с каждой клавишей, кнопкой или другим элементом управления. Поскольку физические коды сканирования часто различаются на разных устройствах, встроенное ПО или драйвер устройства отвечает за их сопоставление со стандартными идентификаторами, такими как коды использования HID или коды клавиш Linux.

Коды сканирования в основном используются для клавиатур. Другие устройства обычно обмениваются данными на низком уровне, используя контакты GPIO, сообщения I2C или другие средства. Поэтому верхние уровни программного стека полагаются на драйверы устройств, чтобы понять, что происходит.

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

Использование HID – это стандартный идентификатор, который используется для сообщения о состоянии элемента управления, например клавиши клавиатуры, оси джойстика, кнопки мыши или точки касания. Большинство устройств ввода с интерфейсом USB и Bluetooth соответствуют спецификации HID, которая позволяет системе взаимодействовать с ними единообразно.

Фреймворк Android использует драйверы HID ядра Linux для преобразования кодов использования HID в коды клавиш Linux и другие идентификаторы. Поэтому использование HID в основном интересно производителям периферийных устройств.

Код ключа Linux

Код клавиши Linux – это стандартный идентификатор клавиши или кнопки. Коды клавиш Linux определяются в заголовочном файле linux/input.h с помощью констант, начинающихся с префикса KEY_ или BTN_. Драйверы ввода ядра Linux отвечают за преобразование физических кодов сканирования, использования HID и других сигналов, относящихся к устройству, в коды клавиш Linux и передачу информации о них в составе событий EV_KEY.

В Android API код клавиши Linux иногда называется кодом сканирования. Технически это неверно, но помогает отличать коды клавиш Linux от кодов клавиш Android в API.

Код относительной или абсолютной оси Linux

Относительный или абсолютный код оси Linux – это стандартный идентификатор для передачи данных об относительном движении или абсолютном положении по оси, например относительном движении мыши по оси X или абсолютном положении джойстика по оси X. Коды осей в Linux определяются в заголовочном файле linux/input.h с помощью констант, начинающихся с префикса REL_ или ABS_. Драйверы ввода ядра Linux преобразуют сигналы HID и другие сигналы устройств в коды осей Linux и передают информацию о них в составе событий EV_REL и EV_ABS.

Код переключения Linux

Код переключателя Linux – это стандартный идентификатор, который сообщает о состоянии переключателя на устройстве, например переключателя крышки. Коды переключателей Linux определяются в файле заголовка linux/input.h с помощью констант, начинающихся с префикса SW_. Драйверы ввода ядра Linux сообщают об изменении состояния переключателя как о событиях EV_SW.

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

Код ключа Android

Код клавиши Android – это стандартный идентификатор, определенный в API Android для обозначения определенной клавиши, например "Домой". Коды клавиш Android определяются классом android.view.KeyEvent как константы, начинающиеся с префикса KEYCODE_.

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

Комбинации кодов клавиш Android преобразуются в коды символов с помощью раскладки клавиатуры, которая зависит от устройства и региональных настроек. Например, если одновременно нажать клавиши KEYCODE_SHIFT и KEYCODE_A, система найдет это сочетание в раскладке и вставит заглавную букву "А" в активное текстовое поле.

Код оси Android

Код оси Android – это стандартный идентификатор, определенный в API Android для обозначения определенной оси устройства. Коды осей Android определяются классом android.view.MotionEvent как константы, начинающиеся с префикса AXIS_.

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

Android Meta State

Метасостояние Android – это стандартный идентификатор, определенный в API Android, который указывает, какие клавиши-модификаторы нажаты. Метасостояния Android определяются классом android.view.KeyEvent как константы, начинающиеся с префикса META_.

Текущее состояние мета определяется компонентом Android InputReader, который отслеживает нажатие и отпускание клавиш-модификаторов, таких как KEYCODE_SHIFT_LEFT, и устанавливает или сбрасывает соответствующий флаг состояния мета.

Связь между клавишами-модификаторами и метасостояниями задана в коде, но раскладка клавиатуры может изменить сопоставление клавиш-модификаторов, что, в свою очередь, повлияет на метасостояния.

Состояние кнопки Android

Состояние кнопки Android – это стандартный идентификатор, определенный в Android API и указывающий, какие кнопки (на мыши или стилусе) нажаты. Состояния кнопок в Android определяются классом android.view.MotionEvent как константы, начинающиеся с префикса BUTTON_.

Текущее состояние кнопки определяется компонентом InputReader в Android, который отслеживает, когда кнопки (на мыши или стилусе) нажимаются / отпускаются, и устанавливает / сбрасывает соответствующий флаг состояния кнопки.

Связь между кнопками и их состояниями задана в коде.

Дополнительные ресурсы

  1. Коды событий ввода Linux
  2. Протокол мультисенсорного ввода Linux
  3. Драйверы устройств ввода для Linux
  4. Силовая обратная связь в Linux
  5. Информация об устройствах HID, в том числе таблицы использования HID