Маршрутизация входных данных

В Android 9 и более ранних версиях нельзя было взаимодействовать с несколькими дисплеями с помощью сенсорного ввода, поскольку не было механизма связи между дисплеями и устройствами ввода. Например, сенсорный экран может иметь видеовыход HDMI (который будет зарегистрирован как дисплей на Android) и выход USB для сенсорного экрана (который будет зарегистрирован как устройство ввода). Если бы к устройству было подключено несколько дисплеев, было бы невозможно определить, какое устройство ввода относится к какому дисплею. Та же проблема возникает на складных устройствах с несколькими встроенными экранами.

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

Например, если у устройства Android есть два HDMI-порта с маркировкой hdmi1 и hdmi2, то значениями портов дисплея могут быть 1 и 2. Значения портов остаются прежними, даже если к тому же физическому порту HDMI подключен другой дисплей (например, другая модель или производитель). Это позволяет производителям устройств предоставлять инструкции по сборке и обновлению дисплеев.

Связь настраивается в /vendor/etc/input-port-associations.xml. Пример:

<ports>
    <port display="0" input="usb-xhci-hcd.0.auto-1.1/input0" />
    <port display="1" input="usb-xhci-hcd.0.auto-1.2/input0" />
</ports>

В примере выше display="0" указывает на порт, к которому подключен дисплей. input="usb-xhci-hcd.0.auto-1.1/input0" указывает порт, к которому подключено устройство ввода. Чтобы определить порты, связанные с определенными устройствами, используйте следующую команду терминала, а затем проверьте свойство location этих устройств в состоянии центра событий.

adb shell dumpsys input

Если подключено много устройств, нажмите на нужное, чтобы посмотреть массив RecentQueue в разделе Input Dispatcher State (Состояние диспетчера ввода). Затем вы сможете определить, какие устройства сгенерировали последнее событие. Затем вы можете найти соответствующее устройство в разделе "Состояние центра событий".

Чтобы определить порты дисплея, назначенные подключенным дисплеям, используйте команду adb shell dumpsys display и найдите свойство address объекта DisplayDeviceInfo для каждого дисплея в разделе "Устройства отображения". Вы также можете использовать команду adb shell dumpsys SurfaceFlinger --display-id, чтобы получить идентификационную информацию обо всех подключенных дисплеях. См. также идентификаторы статических дисплеев.

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

Маршрутизация для динамических многоэкранных систем

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

  • Если вы используете док-станцию, чтобы работать с устройством как с компьютером, можно задать конфигурацию маршрутизации, чтобы направлять входные данные от подключенного к док-станции аксессуара (идентифицируемого по порту) на внешний дисплей (идентифицируемый по порту).
  • Основной экран используется в качестве источника ввода (например, сенсорной панели) при подключении к внешнему дисплею. В этом случае можно настроить маршрутизацию, чтобы ввод с виртуальной сенсорной панели (идентифицируемой по уникальному виртуальному идентификатору) направлялся на внешний дисплей (идентифицируемый по порту).

Реализация

  • Для физических устройств порт, к которому подключено устройство ввода, и порт, к которому подключен дисплей, используются для сопоставления дисплеев с сенсорными экранами.
  • Сопоставления хранятся в InputReaderConfiguration.
  • TouchInputMapper.mViewport соответствует области просмотра, заданной для InputDevice.location.
  • Если в файле сопоставления указан порт устройства ввода, но в данный момент нет окна просмотра с соответствующим портом дисплея, устройство ввода в этом порту будет отключено.
  • Если порт для определенного устройства ввода не указан, область просмотра настраивается в соответствии с существующими правилами.
  • Входные драйверы не требуют изменений ядра.
  • Порты устройств ввода определяются с помощью ioctl EVIOCGPHYS.