There are two ways to use the uinput command:
uinput - reads commands from standard input until End-of-File (Ctrl+D) is sent. This mode can be used interactively from a terminal or used to control uinput from another program or app (such as the CTS tests via UinputDevice).uinput <filename> reads commands from a file instead of standard input.There are also two supported input formats, described in the sections below. The tool will automatically detect which format is being used.
uinput supports the evemu format, as used by the FreeDesktop project's evemu suite. This is a simple text-based format compatible with recording and replay tools on other platforms. However, it only supports playback of events from one device from a single recording. Recordings can be made using the evemu-record command on Android or other Linux-based OSes.
The other supported format is JSON-based, though the parser is in lenient mode to allow comments, and integers can be specified in hexadecimal (e.g. 0xABCD). The input file (or standard input) can contain multiple commands, which will be executed in sequence. Simply add multiple JSON objects to the file, one after the other without separators:
{ "id": 1, "command": "register", // ... } { "id": 1, "command": "delay", // ... }
Many examples of command files can be found in the CTS tests.
registerRegister a new uinput device
| Field | Type | Description |
|---|---|---|
id | integer | Device ID |
command | string | Must be set to "register" |
name | string | Device name |
vid | 16-bit integer | Vendor ID |
pid | 16-bit integer | Product ID |
bus | string | Bus that device should use |
port | string | phys value to report |
configuration | object array | uinput device configuration |
ff_effects_max | integer | ff_effects_max value |
abs_info | array | Absolute axes information |
id is used for matching the subsequent commands to a specific device to avoid ambiguity when multiple devices are registered.
bus is used to determine how the uinput device is connected to the host. The options are "usb" and "bluetooth".
Device configuration is used to configure the uinput device. The type field provides a UI_SET_* control code as an integer value or a string label (e.g. "UI_SET_EVBIT"), and data is a vector of control values to be sent to the uinput device, which depends on the control code.
| Field | Type | Description |
|---|---|---|
type | integer|string | UI_SET_ control type |
data | integer|string array | control values |
Due to the sequential nature in which this is parsed, the type field must be specified before the data field in this JSON Object.
Every register command will need a "UI_SET_EVBIT" configuration entry that lists what types of axes it declares. This entry should be the first in the list. For example, if the uinput device has "UI_SET_KEYBIT" and "UI_SET_RELBIT" configuration entries, it will also need a "UI_SET_EVBIT" entry with data of ["EV_KEY", "EV_REL"] or the other configuration entries will be ignored.
ff_effects_max must be provided if UI_SET_FFBIT is used in configuration.
abs_info fields are provided to set the device axes information. It is an array of below objects:
| Field | Type | Description |
|---|---|---|
code | integer|string | Axis code or label |
info | object | Axis information object |
The axis information object is defined as below, with the fields having the same meaning as those Linux's struct input_absinfo:
| Field | Type | Description |
|---|---|---|
value | integer | Latest reported value |
minimum | integer | Minimum value for the axis |
maximum | integer | Maximum value for the axis |
fuzz | integer | fuzz value for noise filter |
flat | integer | values to be discarded |
resolution | integer | resolution of axis |
Example:
{ "id": 1, "command": "register", "name": "Keyboard (Test)", "vid": 0x18d2, "pid": 0x2c42, "bus": "usb", "configuration":[ {"type":"UI_SET_EVBIT", "data":["EV_KEY", "EV_FF"]}, {"type":"UI_SET_KEYBIT", "data":["KEY_0", "KEY_1", "KEY_2", "KEY_3"]}, {"type":"UI_SET_ABSBIT", "data":["ABS_Y", "ABS_WHEEL"]}, {"type":"UI_SET_FFBIT", "data":["FF_RUMBLE"]} ], "ff_effects_max" : 1, "abs_info": [ {"code":"ABS_Y", "info": {"value":20, "minimum":-255, "maximum":255, "fuzz":0, "flat":0, "resolution":1} }, {"code":"ABS_WHEEL", "info": {"value":-50, "minimum":-255, "maximum":255, "fuzz":0, "flat":0, "resolution":1} } ] }
After the command is sent, there will be a delay before the device is set up by the Android input stack, and uinput does not wait for that process to finish. Any commands sent to the device during that time will be dropped. If you are controlling uinput by sending commands through standard input from an app, you need to wait for onInputDeviceAdded to be called on an InputDeviceListener before issuing commands to the device. If you are passing a file to uinput, add a delay after the register command to let registration complete. You can add a sync in certain positions, like at the end of the file to get a response when all commands have finished processing.
As soon as EOF is reached (either in interactive mode, or in file mode), the device that was created will be unregistered. There is no explicit command for unregistering a device.
delayAdd a delay between the processing of commands.
The delay will be timed relative to the time base, a reference time which is set when the device is registered or by the updateTimeBase command. Take the following set of example commands:
register devicedelay 500msinject some eventsdelay 10msinject more eventsIf the register command is executed at time X, the injection at step 3 will be scheduled for time X+500ms. Since scheduling isn't precise, they might actually be injected a few milliseconds later, but regardless of that the injection at step 5 will always be scheduled for X+510ms. This prevents scheduling delays from building up over time and slowing down the playback of recordings. However, it does mean that when you expect to wait for an indeterminate period of time, you should send updateTimeBase afterwards to prevent following events being scheduled in the past — see that command's section for an example.
| Field | Type | Description |
|---|---|---|
id | integer | Device ID |
command | string | Must be set to "delay" |
duration | integer | Delay in milliseconds |
Example:
{ "id": 1, "command": "delay", "duration": 10 }
updateTimeBaseUpdate the time base from which the following events are scheduled to the current time. When controlling uinput over standard input, you should send this command if you want following events to be scheduled relative to now, rather than the last injection. See the following example set of commands and the times they will be scheduled to run at:
register (say this occurs at time X)delay 500msinject: scheduled for X+500msdelay 10msinject: scheduled for X+510msupdateTimeBase (say this occurs at time Y)delay 10msinject: scheduled for Y+10msWithout the updateTimeBase command, the final injection would be scheduled for X+520ms, which would be in the past.
This is useful if you are issuing commands in multiple stages with long or unknown delays in between them. For example, say you have a test that does the following:
register a deviceinject a few events that should launch an appinject commands separated by delay commands of 10msWithout updateTimeBase, the inject commands of step 4 will be scheduled to start immediately after the events from step 2. That time is probably in the past, so many of the 1000 injections will be sent immediately. This will likely fill the kernel's event buffers, causing events to be dropped. Sending updateTimeBase before the inject commands in step 4 will schedule them relative to the current time, meaning that they will be all injected with the intended 10ms delays between them.
| Field | Type | Description |
|---|---|---|
id | integer | Device ID |
command | string | Must be set to "updateTimeBase" |
injectSend an array of uinput event packets to the uinput device
| Field | Type | Description |
|---|---|---|
id | integer | Device ID |
command | string | Must be set to "inject" |
events | integer|string array | events to inject |
The events parameter is an array of integers in sets of three: a type, an axis code, and an axis value, like you'd find in Linux's struct input_event. For example, sending presses of the 0 and 1 keys would look like this:
{ "id": 1, "command": "inject", "events": ["EV_KEY", "KEY_0", 1, "EV_SYN", "SYN_REPORT", 0, "EV_KEY", "KEY_0", 0, "EV_SYN", "SYN_REPORT", 0, "EV_KEY", "KEY_1", 1, "EV_SYN", "SYN_REPORT", 0, "EV_KEY", "KEY_1", 0, "EV_SYN", "SYN_REPORT", 0 ] }
syncA command used to get a response once the command is processed. When several inject and delay commands are used in a row, the sync command can be used to track the progress of the command queue.
| Field | Type | Description |
|---|---|---|
id | integer | Device ID |
command | string | Must be set to "sync" |
syncToken | string | The token used to identify this sync command |
Example:
{ "id": 1, "command": "syncToken", "syncToken": "finished_injecting_events" }
This command will result in the following response when it is processed:
{ "id": 1, "result": "sync", "syncToken": "finished_injecting_events" }
The getevent utility can used to print out the key events for debugging purposes.