How to Use the dumpsys SurfaceFlinger Command via ADB to Measure Display Frame Latency and Jitter

In mobile application engineering and Android system performance profiling, rendering consistency and frame pacing are vital for delivering fluid user interfaces. While graphical profile bars in Android Developer Options (such as “Profile HWUI rendering”) offer visual cues regarding whether an individual frame exceeds the standard 16.67 ms (60 Hz) or 8.33 ms (120 Hz) rendering budget, they cannot provide raw, microsecond-accurate hardware timestamps for automated QA testing or deep performance analysis. To capture exact presentation timestamps, quantify display jitter, and diagnose dropped vs. jank frames at the compositor level, Android engineers turn to the dumpsys SurfaceFlinger command via the Android Debug Bridge (ADB).

SurfaceFlinger is Android’s core system compositor. It accepts graphical buffers from multiple active producers—including WindowManager, the Android View framework, and Vulkan/OpenGL ES renderers—and coordinates with the Hardware Composer (HWC) HAL to display composite layers on the physical screen. By interrogating SurfaceFlinger over ADB, developers can inspect frame lifecycle stages, calculate display latency, and verify variable refresh rate (VRR) synchronisation. This comprehensive technical guide details the SurfaceFlinger frame pipeline, explains how to extract and interpret latency metrics, and demonstrates automated profiling workflows.

The Android Compositor Pipeline and SurfaceFlinger Architecture

To accurately interpret SurfaceFlinger latency metrics, it is essential to understand the lifecycle stages of an Android graphic buffer:

Pipeline Stage Executing Component Timestamp Captured by SurfaceFlinger
1. Buffer Queueing Application UI Thread / RenderThread The precise nanosecond timestamp when the application submits a finished frame to the BufferQueue.
2. Latch / Acquisition SurfaceFlinger Compositor The timestamp when SurfaceFlinger dequeues (latches) the buffer for compositing during the next VSYNC pulse.
3. Hardware Presentation Hardware Composer (HWC) / Display Controller The hardware interrupt timestamp confirming the frame was physically scanned out to the display panel.

Prerequisites and Connecting via ADB

Before querying SurfaceFlinger, prepare your Android device:

  1. Enable Developer Options by navigating to Settings > About phone and tapping Build number seven times.
  2. Open Settings > System > Developer options and enable USB debugging (or Wireless debugging).
  3. Connect your workstation to the Android device via USB or Wi-Fi, then confirm active ADB communication from your desktop terminal:
adb devices

Ensure the device reports as device rather than unauthorized.

Querying SurfaceFlinger Frame Timestamps via ADB

To measure latency on a specific running application, first identify its window layer name. Run the following command while the target application is visible on screen:

adb shell dumpsys SurfaceFlinger --list | grep "com.example.app"

SurfaceFlinger will output the precise active window surface tag, such as com.example.app/com.example.app.MainActivity#0.

Clearing the Frame Latency Buffer

SurfaceFlinger stores the last 127 frame timestamps in a circular buffer. To capture fresh metrics for a specific interaction—such as scrolling a list or triggering an animation—reset the buffer immediately beforehand:

adb shell dumpsys SurfaceFlinger --latency-clear "com.example.app/com.example.app.MainActivity#0"

Capturing Raw Latency Data

Perform the scrolling gesture on your device, then dump the latency data immediately:

adb shell dumpsys SurfaceFlinger --latency "com.example.app/com.example.app.MainActivity#0"

The command produces structured numerical output in nanoseconds. The first line represents the display’s VSYNC period, followed by 127 three-column rows:

16666666
1723485002134567	1723485002148902	1723485002166667
1723485002151234	1723485002165431	1723485002183333
1723485002167890	1723485002182109	1723485002200000
1723485002184512	1723485002198765	1723485002216667

Interpreting SurfaceFlinger Nanosecond Timestamps

Each line in the --latency output reveals the exact mechanics of a single frame:

  • Line 1 (VSYNC Period): 16666666 ns corresponds to 16.67 ms (a standard 60 Hz display). On a 120 Hz display panel, this value will read approximately 8333333 ns (8.33 ms).
  • Column 1 (App Queued): The nanosecond timestamp when the application called queueBuffer() to hand the rendered frame to SurfaceFlinger.
  • Column 2 (SurfaceFlinger Latched): The timestamp when SurfaceFlinger acquired the buffer during the composition cycle.
  • Column 3 (HWC Presented): The actual hardware timestamp when the display controller scanned the frame to the glass. If Column 3 displays 9223372036854775807 (INT64_MAX), the frame is pending hardware presentation or was skipped due to triple buffering backpressure.

Calculating Key Frame Metrics

Using these three columns, developers can extract vital quality-of-service indicators:

  • App Latency (Turnaround Time): Column 3 - Column 1. This measures the total elapsed time from when the software completed rendering until the user’s eyes physically saw the pixels.
  • Compositor Overhead: Column 2 - Column 1. This reveals how long the frame waited in the queue before SurfaceFlinger processed it. Long delays here point to compositor bottlenecking rather than application rendering flaws.
  • Hardware Frame Interval: Column 3 (Current Frame) - Column 3 (Previous Frame). If the interval equals the VSYNC period, the frame pace is mathematically perfect. If the interval jumps to double or triple the VSYNC period, a jank frame occurred.

Auditing Discarded and Dropped Frames with dumpsys gfxinfo

To supplement SurfaceFlinger compositor telemetry with application-level pipeline statistics, run dumpsys gfxinfo on the same package:

adb shell dumpsys gfxinfo com.example.app framestats

This command provides a breakdown of each phase inside the application’s RenderThread (Intended vs. Actual VSYNC, Input Handling, Animation, Traverse/Measure, Draw, Sync, and Command Issue), allowing you to pinpoint whether dropped frames originated from excessive layout passes or GPU shader compilation stalls.

Automating Performance Regression Checks in CI/CD

Modern mobile development pipelines frequently wrap the dumpsys SurfaceFlinger --latency command into automated Python or bash scripts during instrumented UI tests:

#!/usr/bin/env bash
# Profile Android UI Jank
PACKAGE="com.example.app"
WINDOW=$(adb shell dumpsys SurfaceFlinger --list | grep "$PACKAGE" | head -n 1)

adb shell dumpsys SurfaceFlinger --latency-clear "$WINDOW"
# Trigger automated monkey test or UI automation gesture here...
sleep 2
adb shell dumpsys SurfaceFlinger --latency "$WINDOW" > frame_profile.txt
echo "Latency profile captured to frame_profile.txt"

By parsing frame_profile.txt, test suites can compute the 95th and 99th percentile frame latencies and automatically fail pull requests that introduce UI micro-stutter.

Utilising dumpsys SurfaceFlinger via ADB equips mobile engineers with low-level, authoritative insight into Android’s rendering subsystem, ensuring applications maintain smooth, responsive animations across diverse hardware configurations.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.