跪拜 Guibai
← All articles
Android · Computer Graphics

The Six Layers That Turn an Android View.draw Call Into Screen Pixels

By 恐龙君 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Android graphics debugging is notoriously opaque because the stack is deep and the terminology dense. Knowing which layer owns a given problem — a dropped frame, a screenshot that comes back black, a SurfaceView tearing artifact — cuts diagnosis time from hours to minutes.

Summary

Every frame on an Android screen travels through six distinct layers: App UI, Drawing Interface, Rendering Engine, Buffer Channel, Composition Coordination, and Hardware Display. The top three layers live on the application side and turn View trees into pixel data; the bottom three live on the system and hardware side and handle buffer management, multi-window composition, and physical output. Two parallel threads run through the stack — a data flow that moves pixels from Canvas to Display, and a control flow where WindowManager configures layers and SurfaceFlinger composites them. The whole system is glued together by the Producer/Consumer model: rendering engines, Camera, and video decoders act as producers writing into BufferQueues, while SurfaceFlinger, ImageReader, and encoders act as consumers. Gralloc-allocated buffers pass between GPU, HWC, and CPU with zero copy, and Fence primitives keep asynchronous hardware operations correctly ordered. Different graphics scenarios — a game, a camera preview, a DRM-protected video — differ only in which layer they plug into and which consumer sits at the other end of the BufferQueue.

Takeaways
Android graphics is organized into six layers: App UI, Drawing Interface, Rendering Engine, Buffer Channel, Composition Coordination, and Hardware Display.
Hardware-accelerated View drawing records commands into a DisplayList on the main thread; RenderThread replays them asynchronously through Skia to the GPU.
Surface is the universal producer entry point — Canvas, GLES, Vulkan, Camera, and MediaCodec all write into a Surface.
BufferQueue connects producers and consumers with a pool of GraphicBuffers; multiple buffering lets mismatched speeds coexist without blocking.
SurfaceFlinger composites all visible layers; it delegates to the Hardware Composer (HWC) when possible and falls back to GPU composition only when HWC capabilities are exceeded.
Gralloc allocates graphics memory shareable across GPU, HWC, and CPU, enabling zero-copy buffer handoffs throughout the pipeline.
Fence is a kernel synchronization primitive that signals when an asynchronous hardware operation completes, preventing consumers from reading half-written buffers.
SurfaceView owns an independent Surface composited as a separate layer by SurfaceFlinger; TextureView integrates content as a texture into the View hierarchy at the cost of an extra composition step.
DRM-protected video surfaces are marked secure; SurfaceFlinger skips them during screenshot capture, which is why some videos appear black in screenshots.
WindowManager handles window policy and layer configuration; SurfaceFlinger handles pixel composition. They communicate through SurfaceControl.
Conclusions

The six-layer model reveals that Canvas sits at an awkward boundary — it is both the app's drawing API and the rendering engine's input format, which explains why Canvas behavior differs subtly between software and hardware rendering paths.

BufferQueue is the single most load-bearing abstraction in the system. Nearly every graphics scenario — game rendering, camera preview, video playback, screen recording — is just a different producer-consumer pair connected through a BufferQueue.

SurfaceFlinger's preference for HWC over GPU composition is a power-saving strategy baked into the architecture, not an optimization afterthought. The system will burn GPU cycles only when the display controller hardware literally cannot handle the layer count or blend mode.

The separation of WindowManager (policy) and SurfaceFlinger (pixels) into different processes is a real-time constraint decision: composition cannot afford to be blocked by window lifecycle logic, so it runs in its own process with SurfaceControl as the narrow bridge.

Concepts & terms
DisplayList / RenderNode
Under hardware acceleration, Android records View drawing commands into a DisplayList (modern name: RenderNode) rather than executing them immediately. RenderThread replays these commands asynchronously, keeping the main thread free.
BufferQueue
A producer-consumer queue managing a pool of GraphicBuffers. Producers dequeue, write, and enqueue buffers; consumers acquire, use, and release them. It is the central handoff mechanism for all graphics data in Android.
Gralloc
The graphics memory allocator that carves out buffers shareable across GPU, display controller, and CPU. It is what makes zero-copy buffer passing possible between hardware blocks.
HWC (Hardware Composer)
Dedicated display controller hardware that composites multiple layers directly, without involving the GPU. SurfaceFlinger uses it by default for power efficiency and falls back to GPU composition only when HWC capabilities are exceeded.
Fence
A kernel synchronization primitive that signals completion of an asynchronous hardware operation (GPU render, display read). It prevents consumers from reading buffers still being written and producers from overwriting buffers still being read.
SurfaceControl
The handle through which WindowManager configures a layer's position, size, z-order, transform, and visibility. It bridges the control plane (WindowManager) and the composition plane (SurfaceFlinger).
Source: juejin.cn ↗ Google Translate ↗ Backup ↗