面显示在屏幕上的完整链路,从 View 的 measure/layout/draw 到 SurfaceFlinger 合成 再到 LCD 像素发光 ,共经历 8 个阶段。
一、整体链路

二、Stage 1: View 体系 --- measure / layout / draw
这是应用开发最熟悉的部分,但发生在应用进程中。
2.1 View 树结构

2.2 三大遍历
| 方法 | 作用 | 关键类 |
|---|---|---|
measure() |
确定自身及子 View 的宽高 | MeasureSpec (EXACTLY / AT_MOST / UNSPECIFIED) |
layout() |
确定自身及子 View 的位置 (left/top/right/bottom) | ViewGroup.onLayout() |
draw() |
在 Canvas 上绘制内容 | Canvas.drawText() / drawBitmap() / drawRect() |
2.3 源码入口
java
// ViewRootImpl.java --- 核心入口
private void performTraversals() {
// 1. MEASURE
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
// -> DecorView.onMeasure() -> 递归测量所有子 View
// 2. LAYOUT
performLayout(lp, desiredWindowWidth, desiredWindowHeight);
// -> DecorView.onLayout() -> 递归布局所有子 View
// 3. DRAW
performDraw();
// -> 从 Surface 获取 Canvas -> DecorView.draw() -> 递归绘制
}
三、Stage 2: ViewRootImpl --- 连接 View 与 SurfaceFlinger 的桥梁
3.1 ViewRootImpl 的核心作用
| 功能 | 说明 |
|---|---|
setView() |
建立与 WMS 的连接,创建 Surface,启动 Choreographer |
Choreographer |
同步 VSync 信号(60Hz 每 16.67ms 触发一次),驱动 doFrame() |
Surface |
图形缓冲区句柄,应用在上面绘制,SF 合成它 |
SurfaceControl |
WMS 通过 SurfaceFlinger 创建,应用获得引用用于绘制 |
3.2 绘制提交
java
// ViewRootImpl.performDraw()
private void performDraw() {
// 1. 从 Surface 获取 Canvas
Canvas canvas = mSurface.lockHardwareCanvas();
// 硬件加速:lockHardwareCanvas() → OpenGL ES 后端
// 软件渲染:lockCanvas() → Bitmap 后端
// 2. 绘制整个 View 树
mView.draw(canvas); // DecorView.draw()
// -> ViewGroup.dispatchDraw() → 每个子 View 的 draw()
// -> TextView.onDraw(): canvas.drawText()
// -> ImageView.onDraw(): canvas.drawBitmap()
// 3. 提交缓冲区给 SurfaceFlinger
mSurface.unlockCanvasAndPost(canvas);
// -> queueBuffer() 到 BufferQueue
// -> SurfaceFlinger 收到新缓冲区就绪通知
}
四、Stage 3: BufferQueue --- 生产者-消费者模型
每个 Surface 对应一个 BufferQueue,应用是生产者 ,SurfaceFlinger 是消费者 。

Triple Buffering(三缓冲):
- Front Buffer:正在显示
- Back Buffer:SF 正在合成
- Free Buffer:App 正在绘制
三缓冲防止 App 绘制和 SF 合成互相阻塞。
五、Stage 4: SurfaceFlinger --- 图层合成
5.1 SurfaceFlinger 的职责
- 收集所有应用的 Surface(Layer)
- 按 Z-Order 排序
- 合成(Composite)为单一帧缓冲区
- 通过 HWComposer 提交到显示硬件
5.2 合成流程
java
// SurfaceFlinger::onMessageReceived()
void SurfaceFlinger::onMessageReceived(int32_t what) {
// 1. VSync 到达
// 2. 收集所有有新缓冲区的 Layer
for (const auto& layer : mLayers) {
if (layer->hasNewBuffer()) {
layer->updateTexImage(); // acquire 新缓冲区
}
}
// 3. 请求 HWC 合成
hwcDevice->setDisplayContents(display, layers);
// 4. 如果 HWC 能处理所有 Layer → 硬件 overlay 合成
// 如果不能 → GPU 通过 OpenGL 合成剩余 Layer
// 5. 提交到显示
hwcDevice->presentDisplay(display);
}
5.3 合成方式
| 方式 | 说明 | 性能 |
|---|---|---|
| HWC Overlay | 硬件直接把 Layer 送到显示控制器,绕过 GPU | 最优,零 GPU 开销 |
| GPU Composition | GPU 把所有 Layer 合成到一个 framebuffer | 耗电,但兼容性好 |
| Mixed | HWC 处理部分 Layer,GPU 处理剩余 | 平衡 |
六、Stage 5: VSync 与帧率控制
6.1 VSync 机制
| 概念 | 说明 |
|---|---|
| VSync | 显示器垂直同步信号,60Hz 屏幕每 16.67ms 发一次 |
| Choreographer | App 注册 doFrame() 回调,VSync 到达时触发 |
| Jank(掉帧) | App 绘制超过 16ms,错过 VSync → 重复显示上一帧 |
6.2 时序示例
bash
VSync 0: App 绘制 Frame 0 ──> SF 合成 Frame 0 ──> 显示 Frame 0
VSync 1: App 绘制 Frame 1 ──> SF 合成 Frame 1 ──> 显示 Frame 1
VSync 2: App 绘制 Frame 2 (慢)
VSync 3: App 还在画 Frame 2 ──> SF 合成 Frame 1 ──> 显示 Frame 1 (JANK!)
VSync 4: App 完成 Frame 2 ──> SF 合成 Frame 2 ──> 显示 Frame 2
七、Stage 6: 显示硬件 --- 从 Framebuffer 到像素发光
7.1 硬件链路
| 组件 | 作用 |
|---|---|
| Framebuffer | 最终合成图像在内存中的存储 |
| Display Controller | 硬件读取 framebuffer,通过 DSI/MIPI 发送给 LCD 面板 |
| LCD Panel | 物理像素:TFT 控制液晶偏转 + RGB 滤光片 + LED 背光 |
| OLED Panel | 每个像素自发光(R/G/B 子像素),无背光 |
7.2 LCD vs OLED
| 特性 | LCD | OLED |
|---|---|---|
| 发光原理 | 背光穿透液晶 + 滤色片 | 有机材料自发光 |
| 对比度 | 有背光漏光,对比度低 | 纯黑像素不发光,对比度无限 |
| 响应速度 | 液晶偏转慢,有拖影 | 纳秒级响应 |
| 功耗 | 背光常亮,功耗固定 | 暗色场景功耗低 |
| 寿命 | 长 | 有机材料老化,可能烧屏 |
八、特殊渲染路径
| 类型 | 特点 | 适用场景 |
|---|---|---|
| 普通 View | 走完整 measure/layout/draw,硬件加速 | 大多数 UI |
| TextureView | 渲染到 OpenGL Texture,支持变换 | 视频播放、Camera 预览 |
| SurfaceView | 独立 Surface,绕过 View 层级,直接到 SF | 游戏、视频(性能最优) |
| WebView | 独立 Surface + GPU 进程 | 网页内容 |
| Compose | 直接操作 Canvas,无 View 层级 | Jetpack Compose UI |
九、完整链路总结
| 阶段 | 所在进程 | 核心操作 | 输出 |
|---|---|---|---|
| 1. measure | App | View.measure() 递归计算宽高 |
每个 View 的 measuredWidth/Height |
| 2. layout | App | View.layout() 递归确定位置 |
每个 View 的 left/top/right/bottom |
| 3. draw | App | View.draw() 递归绘制到 Canvas |
图形缓冲区(Buffer) |
| 4. submit | App | unlockCanvasAndPost() → queueBuffer() |
Buffer 进入 BufferQueue |
| 5. acquire | SurfaceFlinger | acquireBuffer() 获取新缓冲区 |
Layer 更新 |
| 6. composite | SurfaceFlinger | 合成所有 Layer 到 framebuffer | 最终帧图像 |
| 7. present | HWComposer | presentDisplay() 提交到显示控制器 |
显示控制器读取 |
| 8. display | Hardware | 像素发光 | 人眼看到图像 |