WALT (What an Awesome Latency Tester) is a tool for testing latency on Android devices. This document will show you how to set up and use your WALT.
About WALT:
WALT kit:
If anything is missing from the list above, please contact the person from whom you received your WALT.
A test device and cables:
Below is an example of WALT app log when it starts and successfully connects to a WALT device. Note the first line and make sure that you use the latest version. The last line means that the WALT device clock is behind the Android clock but by no more than 161 microseconds. Values about about 1000 us are a sign of clock synchronization problems.
WALT v0.1.5 (versionCode=6) WALT protocol version 4 DEVICE INFO: google/volantis/flounder:6.0.1/MMB29K/2419427:user/release-keys Build.SDK_INT=23 os.version=3.10.40-ga54a4f4 Requesting permission for USB device. Interface claimed successfully Synced clocks, maxE=161us
This section describes how to run each test and interpret the results.
The Teensy will generate a pulse of audio data which will be received at the 3.5mm headset jack. The time delta between the audio pulse being generated and being received by the WALT application is measured.
Below is the output of a test on Nexus 9. The last two lines show the 6 individual measurements and their median. The time measured here is the time that passed from the recording of the last frame in the buffer and until the software callback fired. The length of the optimal buffer in time units can be calculated using the first two lines: 128 frames divided by 48kHz frame rate is about 2.67 ms.
Optimal frame rate is: 48000 Optimal frames per buffer is: 128 Audio engine created Audio recorder created; starting test Synced clocks, maxE=154us Beeped, reply: 1039241 Processed: L_cb = 1.167 ms, L_eq = 171.558 ms, noisy frame = 16799 ... Beeped, reply: 13621259 Processed: L_cb = 0.907 ms, L_eq = 203.991 ms, noisy frame = 14465 Remote clock delayed between -30 and 892 us deltas: [1.1671666666666278, 1.1871666666666278, 0.984, 0.9981666666666279, 1.7278333333333722, 0.9071666666666278] Median audio recording latency 1.1 ms
The WALT app will generate a pulse of audio data which will be transmitted over the 3.5mm headset jack and received by the Teensy. The time delta between audio being transmitted by the app and received by the Teensy is measured
Beeping... Beeped, dtJ2N = 0.059 ms beep detected, total latency = 10.44, normal latency = 10.09, mInitiatedBeeps = 1, mDetectedBeeps = 1 ... Remote clock delayed between -53 and 349 us deltas: [10.439, 12.272, 11.708, 12.194, 12.919, 11.458, 12.985, 10.914, 10.935, 10.631] Median Java to native latency 0.006 ms Median total audio latency 11.6 ms Median callback to output time 9.9 ms
The callback to output time on the last line, 9.9 ms is the time from the execution of the OpenSLES BufferQueue callback that enqueued the buffer until the first frames of that buffer were detected by WALT device via the headphone jack.
Starting screen response measurement Synced clocks, maxE=162us Blink count was: 0 Synced clocks, maxE=857us Starting Listener ====== doBlink.run(), mInitiatedBlinks = 0 mDetectedBlinks = 0 blink counts 1 1 ====== ... ====== doBlink.run(), mInitiatedBlinks = 20 mDetectedBlinks = 20 Stopping Listener Listener stopped Remote clock delayed between -16 and 628 us deltas: [69.908, 53.902, 54.715, 50.867, 70.73, 50.188, 71.344, 85.259, 40.691, 68.554, 72.016, 51.666, 71.826, 51.234, 71.896, 52.131, 68.943, 51.768, 71.919, 48.812] Median latency 61.6 ms
At the time of this writing (WALT v0.1.5) the number reported on the last line of the log above is the time from a call to View.setBackgroundColor() until the measured screen brightness crosses a threshold hard coded in WALT firmware. This has significant drawbacks and will change in future versions.
WALT has an accelerometer that is used to detect when the copper tip collides with the glass. The copper tip is grounded and triggers the touch sensor. The stylus springy action helps generate a collision shock detectable by accelerometer on the way back, away from the glass.
In the log below the following abbreviations are used:
## Restarting tap latency measurement. Re-sync clocks ... Synced clocks, maxE=158us ... ACTION_DOWN event received: Event: t=10269422 x=871.7 y=1026.1 slot=-1 num=0 ACTION_DOWN Received S reply: 10247405 ACTION_DOWN: dt_p2k = 22.0 ms Ignoring ACTION_MOVE 11 Ignoring ACTION_MOVE 12 Ignoring ACTION_MOVE 13 Ignoring ACTION_MOVE 14 Ignoring ACTION_MOVE 15 ACTION_UP event received: Event: t=10365071 x=871.7 y=1026.1 slot=-1 num=0 ACTION_UP Received S reply: 10348526 ACTION_UP: dt_p2k = 16.5 ms ... ## Processing tap latency data Remote clock delayed between -60 and 93 us Counts: ACTION_DOWN 20 (bad 1), ACTION_UP 21 (bad 0), ACTION_MOVE 162 ACTION_DOWN: [26.515, 22.017, 26.952, 29.363, 29.63, 26.624, 31.581, 26.565, 31.335, 26.83, 31.786, 14.702, 19.796, 20.626, 16.688, 18.001, 19.044, 20.261, 17.66, 26.044] [1.774, 0.872, 0.888, 0.948, 1.749, 1.781, 1.698, 1.375, 1.709, 1.985, 2.522, 0.994, 1.008, 0.813, 0.746, 1.289, 1.158, 1.093, 0.891, 3.755] Medians, p2k & k2c [ms]: 26.3 1.2 ACTION_UP: [16.572, 19.515, 16.545, 18.724, 15.188, 14.682, 18.156, 11.69, 20.367, 15.135, 20.601, 44.948, 17.517, 129.513, 24.681, 21.21, 21.979, 22.805, 133.306, 23.876, 17.579] [2.161, 2.02, 1.761, 2.222, 1.228, 1.24, 1.48, 1.42, 1.315, 4.034, 1.279, 1.957, 1.041, 2.058, 2.903, 1.725, 0.99, 2.124, 1.398, 3.018, 0.945] Medians, p2k & k2c [ms]: 19.5 1.7
Drag latency is measured by dragging a finger up and down along the screen. The finger interrupts a laser beam positioned across the screen. By comparing the timings of those beam interruptions with Android touch events the WALT app calculates the delay.
WALT is able to log physical events as well as system events into systrace. This allows us to look at the system-level calls that occur between the application triggering a change and the WALT device receiving a physical response.
Enable systrace logging
.android-sdk/platform-tools/systrace
directory, run python systrace.py --walt
. If --walt
is not recognized as an option, clone the latest version of systrace repo and from the catapult/systrace/systrace
directory run python run_systrace.py --walt
.