Input routing

In Android 9 and lower, there was no way to interact with multiple displays via touch, because there was no association mechanism between displays and input devices. For example, a touchscreen display could provide an HDMI video output (that would register as a display on Android) and a USB output for touchscreen (that would register as an input device). If multiple devices were connected in this manner, there would be no way to determine which input device belongs to which display. The same issue applies to foldable devices with multiple built-in displays.

Android 10 added a mechanism to specify which input devices belong to which displays. The association is done by port numbers where port refers to the physical port to which a display is connected.

For example, if an Android device has two HDMI ports labeled hdmi1 and hdmi2, then the display port values could be 1 and 2. The port values remain the same even when a different display is connected (such as a different display model or manufacturer) to the same physical HDMI port. This enables device manufacturers to provide instructions to assemble and upgrade displays.

The association is configured in /vendor/etc/input-port-associations.xml. For example:

<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>

In the example above, display="0" specifies the port to which the display is connected. input="usb-xhci-hcd.0.auto-1.1/input0" specifies the port to which the input device is connected. To determine the ports associated with specific devices, use the following terminal command, and then review thelocation property of those devices in the Event Hub State.

adb shell dumpsys input

If many devices are connected, tap a specific device to examine the RecentQueue array in the Input Dispatcher State. You can then identify those devices that generated the most recent event. You can then find the corresponding device in the Event Hub State.

To determine the display ports assigned to the connected displays, use adb shell dumpsys display and then look for the address property of DisplayDeviceInfo for each display under Display Devices. Alternatively, use adb shell dumpsys SurfaceFlinger --display-id to dump identification information for all connected displays. See also Static display identifiers.

If you specify an association for a specific input device and the corresponding display isn't present in the system, the input device is disabled until the respective display appears. The association is performed only for touch devices.

Routing for dynamic multi-displays

Android 10 enables you to set up static multi-display devices. Dynamic associations are not yet enabled. However, some use cases can be addressed by providing routing information for displays and input panels that aren't always present or using virtual input devices and then providing additional routing information to those virtual devices. If a device implementation supports a:

  • Desktop-like experience with a docking station, then a routing config could be provided to target input from input accessory connected to the dock (identified uniquely by port) to the external display (identified by port).
  • Primary screen acting as an input source (such as a touchpad) when connected to the external display, then a routing config could be provided to target input from virtual touch panel (identified by unique virtual ID) to the external display (identified by port).

Implementation

  • For physical devices, the port to which the input device is connected and the port to which the display is connected, are used to match the displays with touchscreens.
  • The mappings are stored in InputReaderConfiguration.
  • TouchInputMapper.mViewport is set to the viewport that matches the port specified for InputDevice.location.
  • If an input device port is specified in the mapping file, and there currently isn't a viewport that has a matching display port, then the input device on that port is disabled.
  • If a port isn't specified for a particular input device, then viewport is set according to the existing rules.
  • No kernel changes are required in the input drivers.
  • The input device ports are determined using the EVIOCGPHYS ioctl.