EventHub: abort if device disappears while opening
Connecting an input device for a brief period of time — long enough
for EventHub::openDeviceLocked to open its FD and give it a class, but
not long enough for it to cache all of its absolute axis information —
can cause InputReader to crash. This happens when a mapper looks up
information for an absolute axis that it should be able to depend on,
but finds it missing. For example, TouchpadInputMapper depends on the
device having ABS_MT_POSITION_X and _Y axes, since these are required
for the device to receive InputDeviceClass::TOUCHPAD, but if this
race condition occurs those axes may not be present.
Since we're already caching all of the absolute axis information during
opening, we can just stop opening the device if we detect that it's
gone, allowing mappers to safely assume that all of the absolute axes
required for a device to be given its class will have information
available through EventHub::getAbsoluteAxisInfo.
It's still possible that the device could be removed after
openDeviceLocked finishes but before the mappers initialize themselves
using the axis information. However, in that case the information will
already have been cached, so the worst that will happen is that we'll
initialize some mappers unnecessarily and then immediately destroy them.
Test: create test-fast-disconnect.json with the following contents:
{
"id": 1, "command": "register",
"name": "BADLY CONNECTED TOUCHPAD",
"vid": 0x18d1, "pid": 0xbaad, "bus": "usb",
"configuration": [
{"type": "UI_SET_EVBIT", "data":["EV_KEY", "EV_ABS"]},
{"type": "UI_SET_KEYBIT",
"data": ["BTN_LEFT", "BTN_TOUCH", "BTN_TOOL_FINGER"]},
{"type": "UI_SET_ABSBIT",
"data": ["ABS_X", "ABS_Y", "ABS_MT_SLOT",
"ABS_MT_POSITION_X", "ABS_MT_POSITION_Y",
"ABS_MT_TRACKING_ID"]},
{"type": "UI_SET_PROPBIT",
"data": ["INPUT_PROP_POINTER", "INPUT_PROP_BUTTONPAD"]}
],
"abs_info": [
{"code": "ABS_X",
"info": {"value":0, "minimum":-255, "maximum":255,
"fuzz":0, "flat":0, "resolution":1}},
{"code": "ABS_Y",
"info": {"value":0, "minimum":-255, "maximum":255,
"fuzz":0, "flat":0, "resolution":1}},
{"code": "ABS_MT_SLOT",
"info": {"value":0, "minimum":0, "maximum":4, "fuzz":0,
"flat":0, "resolution":0}},
{"code": "ABS_MT_POSITION_X",
"info": {"value":0, "minimum":0, "maximum":1, "fuzz":0,
"flat":0, "resolution":1}},
{"code": "ABS_MT_POSITION_Y",
"info": {"value":0, "minimum":0, "maximum":1, "fuzz":0,
"flat":0, "resolution":1}},
{"code": "ABS_MT_TRACKING_ID",
"info": {"value":0, "minimum":0, "maximum":65535,
"fuzz":0, "flat":0, "resolution":0}}
]
}
Then pipe it to uinput:
$ adb shell uinput - < test-fast-disconnect.json
and check that the device does not crash. Check that the "removed
while opening" line is logged, to confirm that the fix is taking
effect rather than the timing just being nice for this case. (You
may have to repeat the uinput command a few times to see this.)
Bug: 424789999
Flag: com.android.input.flags.abort_device_opening_on_enodev
Change-Id: I8d7468eddd64854ff5b15986815999969388b375
Loading
Please register or sign in to comment