Emulating touchscreen interaction with sendevent in Android

Android provides these two convenient tools for dealing with input events:

getevent

for dumping input events and providing information about input devices

sendevent - for injecting input events

Every sendevent command requires 4 parameters:
device_name (string)
event_type (decimal int)
event_code (decimal int)
value (decimal int)

First you need to find the name of touchscreen device.
in adb

getevent -p

get the event list
Let's assume it printed out "/dev/input/event0" - this would be the first parameter.

For touch events only 2 event types are used:
EV_ABS (3)
EV_SYN (0)

Touching the display (in case of Type A protocol) will result in an input report (sequence of input events) containing the following event codes:
ABS_MT_TRACKING_ID (57) - ID of the touch (important for multi-touch reports)
ABS_MT_POSITION_X (53) - x coordinate of the touch
ABS_MT_POSITION_Y (54) - y coordinate of the touch
ABS_MT_TOUCH_MAJOR (48) - basically width of your finger tip in pixels
ABS_MT_PRESSURE (58) - pressure of the touch
SYN_MT_REPORT (2) - end of separate touch data
SYN_REPORT (0) - end of report

Let's say we want to emulate a touch down event at the point with coordinates x=300, y=400. We will need to execute the following sendevent commands:

sendevent /dev/input/event0 3 57 0
sendevent /dev/input/event0 3 53 300
sendevent /dev/input/event0 3 54 400
sendevent /dev/input/event0 3 48 5
sendevent /dev/input/event0 3 58 50
sendevent /dev/input/event0 0 2 0
sendevent /dev/input/event0 0 0 0

I used arbitrary values of 5 for the ABS_MT_TOUCH_MAJOR (makes for very small finger tip for high precision) and 50 for the ABS_MT_PRESSURE (a slight tap) which work good enough for most applications.

For most touch screens on the market it takes 20 to 50 milliseconds to reliably register the touch. So I would recommend to wait at least 50 milliseconds before sending the release event report. If you want to emulate the long touch - then you wait longer. You can use busybox usleep command:

busybox usleep 50000

The release report is really simple. To let the input device know that all previous touches have been released - you just send the empty report with ABS_MT_TRACKING_ID = -1:

ABS_MT_TRACKING_ID (57)
SYN_MT_REPORT (2)
SYN_REPORT (0)

sendevent /dev/input/event0 3 57 -1 `
sendevent /dev/input/event0 0 2 0
sendevent /dev/input/event0 0 0 0

This is how injecting touch events could be implemented in python:

#!/usr/bin/python

import subprocess
import os

def adbshell(command, serial=None, adbpath='adb'):
    args = [adbpath]
    if serial is not None:
        args.append('-s')
        args.append(serial)
    args.append('shell')
    args.append(command)
    return os.linesep.join(subprocess.check_output(args).split('\r\n')[0:-1])

def adbdevices(adbpath='adb'):
return [dev.split('\t')[0] for dev in subprocess.check_output([adbpath, 'devices']).splitlines() if dev.endswith('\tdevice')]

def touchscreen_devices(serial=None, adbpath='adb'):
return [dev.splitlines()[0].split()[-1] for dev in adbshell('getevent -il', serial, adbpath).split('add device ') if dev.find('ABS_MT_POSITION_X') > -1]

def tap(devicename, x, y, serial=None, adbpath='adb'):
adbshell('S="sendevent {}";$S 3 57 0;$S 3 53 {};$S 3 54 {};$S 3 58 50;$S 3 50 5;$S 0 2 0;$S 0 0 0;'.format(devicename, x, y), serial, adbpath)
adbshell('S="sendevent {}";$S 3 57 -1;$S 0 2 0;$S 0 0 0;'.format(devicename), serial, adbpath)

serial = adbdevices()[0]
touchdev = touchscreen_devices(serial)[0]
tap(touchdev, 100, 100, serial)

view rawtouch_test.py hosted with ❤ by GitHub
Labels: adb, android, busybox, getevent, sendevent
2 comments:

NavigatorJuly 5, 2013 at 4:43 AM
At least on my Motorola Defy with CM7 (Android 2.3.7) things look a bit different.
It looks like
0 2 0
0 0 0
is NOT a release report, but some kind of activation of the previous sendevent commands.
To release you have to send an additional command (including activation):

sendevent /dev/input/event3 3 57 -1
sendevent /dev/input/event3 0 2 0
sendevent /dev/input/event3 0 0 0

你可能感兴趣的:(Emulating touchscreen interaction with sendevent in Android)