AOSP Expert & Production Engineering
4 min read

Frame Drops & Jank Analysis

The Anatomy of Jank

"Jank" is the visual stuttering experienced by a user when an Android device fails to render frames at a consistent rate. For a smooth 60Hz display, the system must produce a new frame every 16.6 milliseconds. If a frame takes 20ms to produce, it misses its display window, resulting in a dropped frame and a visible stutter.

Analyzing jank in AOSP requires a comprehensive understanding of the UI rendering pipeline, from the application's Java code down to the hardware composer.

Identifying Dropped Frames in Perfetto

Perfetto is the definitive tool for identifying exactly when and why a frame was dropped.

  1. Open a Trace: Load your trace into ui.perfetto.dev.
  2. Locate the Frame Timeline: Find the Frame Timeline track for the specific application experiencing jank.
  3. Spot the Red Blocks: The timeline shows Expected vs Actual rendering times. The Actual blocks turn red if they exceed the expected deadline.
  4. Follow the Arrows: Clicking on a red Actual block draws arrows connecting the UI Thread, the RenderThread, and SurfaceFlinger. This visually isolates the three phases of rendering for that specific dropped frame.

Main Thread vs RenderThread Jank

When analyzing a dropped frame, the first step is to determine which thread is at fault.

Main Thread (UI Thread) Jank

If the Choreographer#doFrame slice on the main thread is long, the application logic is too heavy. The main thread is responsible for handling input, executing animations, measuring views, and inflating layouts.

  • Heavy Inflation: Are you inflating complex XML layouts inside RecyclerView.Adapter#onCreateViewHolder?
  • Garbage Collection (GC): Is the thread paused due to a heavy GC run? (Look for GC slices nearby).
  • Blocking I/O: Is the thread reading from disk (SharedPreferences) or waiting on a slow Binder call?

RenderThread Jank

If the main thread finishes quickly, but the DrawFrame slice on the RenderThread is long, the GPU is struggling to render the display list.

  • Complex Paths: Drawing custom Canvas paths or large numbers of text glyphs can be very expensive.
  • Hardware Layer Updates: Using View.setLayerType(LAYER_TYPE_HARDWARE, ...) can improve performance, but updating the content of that layer forces the GPU to redraw it completely, which is costly.
  • Bitmap Uploads: Loading massive, unscaled bitmaps into memory forces the RenderThread to upload them to the GPU texture memory, pausing rendering.

GPU Overdraw Analysis

Overdraw occurs when the system draws pixels on top of each other in a single frame. For example, drawing a white background, then a red background on top of it, and finally a button on top of that means the pixels were drawn three times.

Excessive overdraw forces the GPU to waste cycles rendering pixels that the user will never see, leading directly to RenderThread jank.

Debugging Overdraw

Android provides a built-in developer option to visualize overdraw: Settings > Developer Options > Debug GPU overdraw > Show overdraw areas.

The screen will tint colors based on the severity of overdraw:

  • True Color: No overdraw (1x draw).
  • Blue: 1x overdraw (2x draw).
  • Green: 2x overdraw.
  • Pink/Red: 3x overdraw or more (Critical).

Fixing Overdraw

To fix overdraw, systematically remove unnecessary backgrounds from layouts. If an Activity has a solid background, and its root layout also defines a solid background, remove one of them.

HWC Composition Type Analysis

Once the RenderThread has generated a buffer, it sends it to SurfaceFlinger. SurfaceFlinger must then combine buffers from the app, the status bar, and the navigation bar into a single image.

It can do this in two ways:

  1. Client Composition (GPU): SurfaceFlinger uses the GPU (via OpenGL or Vulkan) to composite the layers. This is power-hungry and uses CPU/GPU cycles.
  2. Device Composition (HWC): SurfaceFlinger hands the individual buffers directly to the Hardware Composer (HWC) display controller. The display hardware composites the layers on the fly as it scans them out to the screen. This is highly efficient.

Identifying Composition Issues

If a device is dropping frames, it might be relying too heavily on Client Composition.

You can inspect the composition type using dumpsys SurfaceFlinger or by looking at a Winscope trace.

  • Look at the CompositionType for each layer.
  • Ideally, most layers should be marked as Device.
  • If layers are frequently falling back to Client, investigate why. Common reasons include having too many layers (exceeding the HWC's limit), using unsupported blending modes, or utilizing complex crop transformations that the specific hardware controller cannot handle natively.