Android Record and Playback

October 24, 2014

There are a bunch of suggestions online about how to record a series of touchscreen touches and play them back. None of them really work for me though. I’m looking for something that doesn’t require another app and optimally would work over USB debugging with adb. So I’ve hacked something together myself. I started out by just capturing all the events from my touchscreen like this:

adb shell getevent /dev/input/event1 > events.log

The events look like this:

0003 0039 0000009f
0003 0039 00000000
0003 0035 00000142
0003 0036 00000189
0000 0000 00000000
0003 0039 ffffffff
0000 0000 00000000

Those columns are the event type, code and data, all in hex. I used a little python script to reformat them into sendevent calls that look like this:

adb shell sendevent /dev/input/event1 3 57 159
adb shell sendevent /dev/input/event1 3 57 0
adb shell sendevent /dev/input/event1 3 53 322
adb shell sendevent /dev/input/event1 3 54 393
adb shell sendevent /dev/input/event1 0 0 0
adb shell sendevent /dev/input/event1 3 57 4294967295
adb shell sendevent /dev/input/event1 0 0 0

That works pretty well but doesn’t take into account the delay between each event so I modified my event capture to prepend a timestamp:

adb shell getevent /dev/input/event1 | ts "%Y-%m-%d %H:%M:%.S" > event.log

Then I modified my python script to add sleeps in between the sendevent calls:

adb shell sendevent /dev/input/event1 3 57 159
adb shell sendevent /dev/input/event1 3 57 0
adb shell sendevent /dev/input/event1 3 53 322
adb shell sendevent /dev/input/event1 3 54 393
adb shell sendevent /dev/input/event1 0 0 0
sleep 0.041
adb shell sendevent /dev/input/event1 3 57 4294967295
adb shell sendevent /dev/input/event1 0 0 0

Now when I execute that I get an exact playback(or pretty close)! Here’s the final record script:

1
2
3
#!/bin/bash

adb shell getevent /dev/input/event1 | ts "%Y-%m-%d %H:%M:%.S"

…and the python script that converts the output of the record script to something that can get played back:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python
import sys
import re
import datetime

line_re = re.compile(r"^(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d+) (\S+) (\S+) (\S+)$")
event_log = sys.stdin
last_ts = None
for line in event_log:
    match = line_re.match(line.strip())
    ts, etype, ecode, data = match.groups()
    ts = datetime.datetime.strptime(ts, "%Y-%m-%d %H:%M:%S.%f")
    etype, ecode, data = int(etype, 16), int(ecode, 16), int(data, 16)
    if last_ts:
        delta = ts - last_ts
        sleeptime = '%.3f' % (delta.total_seconds())
        if float(sleeptime):
            print "sleep %s" % sleeptime
    last_ts = ts
    print "adb shell sendevent /dev/input/event1 %s %s %s" % (etype, ecode, data)

So now, to record I do:

./record > event.log

…and to playback I do

./convert_event_log_to_sendevents < event.log | bash