AOSP Expert & Production Engineering
3 min read

Rendering Pipeline - Full

The Android Rendering Pipeline

The rendering pipeline in Android is a highly parallelized system designed to deliver smooth 60fps or 120fps UI updates. It spans the application process, system services, and hardware layers.

1. View Invalidation and the UI Thread

The process begins in the application's Main Thread (UI Thread). When a UI component changes state, it calls invalidate(). This schedules a traversal of the view hierarchy during the next Choreographer vsync signal.

During the Choreographer.doFrame() callback, the UI thread performs the Measure, Layout, and Draw passes. However, the UI thread does not actually draw pixels. Instead, it records high-level drawing commands into a DisplayList.

2. The RenderThread and GPU Commands

Once the UI thread finishes recording the DisplayList, it syncs this data to a dedicated background thread within the application process called the RenderThread.

The RenderThread is responsible for converting the high-level DisplayList operations into low-level graphics API calls (OpenGL ES or Vulkan). This separation ensures that complex GPU command generation does not block the UI thread from processing the next frame's input events.

// frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp
void DrawFrameTask::run() {
    bool canUnblockUiThread;
    bool canDrawThisFrame;
    syncFrameState(canUnblockUiThread, canDrawThisFrame);
    if (canUnblockUiThread) {
        unblockUiThread();
    }
    if (canDrawThisFrame) {
        mContext->draw();
    }
}

The RenderThread renders into a GraphicBuffer provided by the system. Once the frame is completely rendered by the GPU, the RenderThread queues the buffer to SurfaceFlinger.

3. SurfaceFlinger and the Hardware Composer

SurfaceFlinger is the system service responsible for compositing all visible surfaces on the screen (the app window, the status bar, the navigation bar, etc.).

When SurfaceFlinger wakes up on its vsync signal, it gathers all the updated GraphicBuffers from various processes. Instead of compositing them using the GPU (which consumes significant power), it attempts to delegate the composition to the Hardware Composer (HWC) via the Display HAL.

The HWC uses dedicated hardware overlays to combine the layers directly on the display controller, achieving highly efficient composition.

Jank Root Cause Mapping

A "jank" occurs when a frame misses its vsync deadline. Identifying the bottleneck requires analyzing the pipeline stage:

  • UI Thread Jank: The app spent too much time in onMeasure, onLayout, or allocating objects. The Choreographer took longer than 16.6ms.
  • RenderThread Jank: The UI thread was fast, but the GPU took too long to execute the draw commands (e.g., complex shaders, overdraw).
  • SurfaceFlinger Jank: Extremely rare, usually indicates system-level resource starvation or driver bugs.

Frame Timeline Tracing

To diagnose rendering issues, developers use the Frame Timeline. It tracks the lifecycle of a frame from application creation to physical display.

You can trace the rendering pipeline using Perfetto or by enabling HWUI profiling:

adb shell setprop debug.hwui.profile true
adb shell dumpsys gfxinfo <package_name> framestats

This outputs precise timing data for every stage of the pipeline, allowing you to pinpoint exactly where a frame missed its deadline.