它们之间可以理解成“上半场:View/UI 框架负责画各自窗口的内容,下半场:SurfaceFlinger 负责把所有窗口的内容合成到屏幕”。
一、从 View 框架到 SurfaceFlinger 的“接力点”
【App 进程 / UI 线程侧:负责画出各自窗口的内容】
Activity
└─ Window(PhoneWindow)
└─ DecorView (根 ViewGroup)
└─ ViewGroup / View 树
└─ onDraw(Canvas)
└─ Canvas → Skia → OpenGL ES (GPU)
└─ 渲染到 Surface 的 buffer
ViewRootImpl
├─ 驱动 measure/layout/draw
├─ 持有 Surface(写入端)
└─ 通过 BufferQueue 作为 Producer 提交图像
Surface / SurfaceView / GLSurfaceView
└─ 每个对应一个 BufferQueue 的 Producer 端
Choreographer / Handler
└─ 按 VSync 节奏驱动 ViewRootImpl.doTraversal()(每帧 UI 渲染)
【System Server / 图形系统:负责合成所有 Surface,并送到屏幕】
WindowManagerService (WMS)
├─ 管理所有 Window(位置、大小、Z 序、可见性)
└─ 为每个 Window / SurfaceView 创建对应的 Layer/Surface 记录
SurfaceFlinger
├─ 作为所有 Surface 的 Consumer 端
├─ 从 BufferQueue 取出每个 Surface 最新的 buffer
├─ 按 WMS 提供的窗口/Layer 信息进行合成
└─ 通过 HWC / GPU 合成到最终帧缓冲
Hardware Composer (HWC) / GPU / 显示驱动
└─ 真正在硬件上完成 Layer 合成、输出到屏幕
关键链接点:
-
App 侧所有 View/UI 最终都画到 某个 Surface 的 buffer;
-
而 SurfaceFlinger 是所有 Surface buffer 的 唯一消费者。
二、App → Surface
先快速再梳理一下这些概念在 “App → Surface” 这半程中的作用:
Activity / Window / DecorView / View / ViewGroup
-
Activity 管理一个界面的生命周期,通过
setContentView()告诉系统“我要显示这棵 View 树”。 -
Window (PhoneWindow) Activity 的窗口外壳,持有 DecorView。
-
DecorView Window 的根 ViewGroup,上面挂开发写布局的 View 树。
-
View / ViewGroup 完成
onMeasure()/onLayout()/onDraw(Canvas),只负责“画自己”,不知道屏幕、也不知道 SurfaceFlinger 的存在。
ViewRootImpl / WindowManager / WMS / Surface
-
WindowManager (WindowManagerImpl) App 侧“申请窗口”的入口,最终走到 WMS。
-
WindowManagerService (WMS) 系统侧统一管理所有 Window,并为每个 Window 创建一个在 SurfaceFlinger 那里的 Layer/Surface。
-
ViewRootImpl 连接 View 世界 ↔ Window/Surface 世界:
-
持有根 View(DecorView);
-
持有对应的 Surface(其实是 SurfaceFlinger 那个 Layer 的 Producer 句柄);
-
驱动 measure/layout/draw,把结果画到 Surface 的 buffer。
-
Canvas / Skia / OpenGL ES
-
Canvas View 的绘图接口。
-
Skia Canvas 背后的实现,把 drawXxx 转成 2D 绘制命令(软件 or 硬件)。
-
OpenGL ES 在硬件加速时,Skia / HWUI 会通过 OpenGL ES 调用 GPU,把图像画到 Surface buffer。
Choreographer / Handler
-
Choreographer 接收 VSync 信号,在每帧里统一触发:输入→动画→
ViewRootImpl.doTraversal()。 -
Handler 在 UI 线程上排队执行
doTraversal()(即 measure/layout/draw)。
View 框架+Skia+OpenGL ES 的职责,就是“在每帧 VSync 时,把 Activity 对应窗口的那张 Surface buffer 画好”。 它们只负责产生每个窗口自己的画面。
三、中场交接:Surface / BufferQueue 是如何把帧交给 SurfaceFlinger 的?
每个 Surface 对应一条 BufferQueue
每个 Window(或 SurfaceView/GLSurfaceView)被 WMS/SurfaceFlinger 注册后,会对应一个 Layer,其底层有一对:
-
BufferQueue Producer 生产端:给 App / ViewRootImpl / GL 使用;
-
BufferQueue Consumer 消费端:在 SurfaceFlinger 里。
App 进程内: ViewRootImpl / SurfaceView / GLSurfaceView └─ 持有 Surface(Producer 端) └─ dequeueBuffer() → 拿到一个空 buffer └─ 在 buffer 上绘制(Canvas or OpenGL ES) └─ queueBuffer() → 把绘制好的帧入队
System 进程内: SurfaceFlinger └─ 持有同一条 BufferQueue 的 Consumer 端 └─ acquireBuffer() → 在合成时刻取出最新帧 └─ releaseBuffer() → 用完后归还给队列
这就是上半场(App 绘制)和下半场(SurfaceFlinger 合成)精确的连接点。
一帧的交接时序(简化)
-
UI 线程 / RenderThread 在 VSyncN 周期内完成 View 渲染 → GPU 画到 Surface 当前 back buffer;
-
渲染结束后调用
eglSwapBuffers()或unlockCanvasAndPost():-
实际上就是对 BufferQueue 的
queueBuffer(); -
这块 buffer 现在变成 “已渲染、待消费”状态。
-
-
下一个 SurfaceFlinger VSync(一般与屏幕刷新同步)到来时:
-
SurfaceFlinger 从所有可见 Layer 的 BufferQueue 里 acquire 最新 buffer;
-
用这些 buffer 做合成,形成一张完整屏幕图像。
-
四、下半场:SurfaceFlinger 如何使用这些 Surface?
WMS 与 SurfaceFlinger 的关系
-
WMS 不负责画图,负责的是“窗口管理”:
-
哪些窗口可见;
-
它们的 Z 序(谁在上谁在下);
-
每个窗口的位置、大小、透明度等。
-
-
SurfaceFlinger 是系统唯一的“合成器(Compositor)”:
-
它维护一个 Layer 列表,每个 Layer 对应一个 Surface(即某个 Window / SurfaceView / Wallpaper 等);
-
从各 Layer 的 BufferQueue 中取帧;
-
根据 WMS 给出的 Layer 属性(位置、变换、Z序、透明度) 决定如何合成。
[ WMS ] └─ 管理 Window └─ 为每个 Window 创建 Layer/Surface,并设置: - 位置/大小 - Z序 - 可见性/透明度 - transform 等
[ SurfaceFlinger ] └─ 持有所有 Layer └─ 对每个 Layer: - 拿最新 buffer - 按 WMS 给的属性合成 └─ 输出一张整屏图像给显示系统
-
注意:SurfaceFlinger 不认识 View / Activity,它只看到一堆 Layer+buffer。
SurfaceFlinger 的合成过程
周期性(按 VSync)执行类似流程:
-
等待 VSync;
-
遍历所有可见 Layer:
-
对每个 Layer 的 BufferQueue 调用
acquireBuffer(),拿到最新帧; -
如果没有新帧,就沿用上一帧(静止画面)。
-
-
根据 Layer 属性,将这些 buffer 按顺序“叠加”:
-
有的 Layer 可以直接由 HWC 叠加(Overlay);
-
有的 Layer 需要由 GPU 渲染完成(Client Composition)。
-
-
合成完成后,把结果交给显示控制器,在下一次刷新中输出到屏幕。
五、SurfaceFlinger的上层概念
下面按你列的关键概念,逐个说明它们 如何影响 SurfaceFlinger / 显示结果。
Activity / Window / DecorView / View / ViewGroup
-
这些都只存在于 App 进程。
-
它们的全部工作结果就是: “在本窗口对应的 Surface buffer 上画出这一帧的内容是什么”。
-
对 SurfaceFlinger 来说,这些只是产生某个 Layer 的一张“bitmap - 位图”; 它完全不知道里面有多少 View、是什么布局。
总结:
这些概念决定“单个 Layer 的像素内容”,但不参与“多 Layer 合成”。
ViewRootImpl / WindowManager / WMS
-
ViewRootImpl
-
负责把 View 树的绘制结果写入到 Surface buffer;
-
它将
requestLayout()/invalidate()变成按 VSync 对齐的帧输出; -
每次输出的一帧就是 SurfaceFlinger 将来用于合成的一个 buffer。
-
-
WindowManager (App 侧) 负责向 WMS 申请 / 更新 / 删除 Window,从而影响 SurfaceFlinger “有哪些 Layer”。
-
WMS (系统侧)
-
决定:
-
哪些 Window/Surface 在屏幕上;
-
他们的 Z 序(如 Dialog 在上,Activity 在下);
-
-
把这些信息同步给 SurfaceFlinger(Layer 属性)。
-
总结:
-
ViewRootImpl 决定 这一 Layer 每帧的内容;
-
WMS 决定 这个 Layer 怎么摆在屏幕上,与其他 Layer 的关系;
-
SurfaceFlinger 根据这些决策完成合成。
Surface / SurfaceView
-
Surface 是连接 App 绘制 ↔ SurfaceFlinger 合成的 唯一通道。
-
App 通过 Surface(Producer)往 BufferQueue 里 queue帧;
-
SurfaceFlinger 从 BufferQueue(Consumer)里取帧。
-
-
SurfaceView
-
拥有独立的 Surface(即独立 Layer),直接被 SurfaceFlinger 看到;
-
主窗口的 View 树还是画在 Activity 的 Window Surface 上;
-
SurfaceView 的内容是另一个 Layer,常用于:
-
视频(MediaPlayer/MediaCodec 直接往 Surface 写帧);
-
游戏/相机预览(GL 或自定义渲染线程绘制)。
-
-
对 SurfaceFlinger 的意义:
-
一个普通 Activity 窗口:通常就是一个 Layer;
-
加上一个 SurfaceView:则是 两个 Layer:
-
背后是主窗口 Layer(UI 控件等);
-
前面/中间是 SurfaceView 的 Layer(视频/游戏等);
-
-
SurfaceFlinger 合成时会把这两个 Layer 按 Z 序叠加。
Canvas / Skia / OpenGL ES
-
Canvas、Skia、OpenGL ES 只负责在 Surface 的某个 buffer 上画出当前帧像素; 画完这一帧,就通过 queueBuffer 提交给 SurfaceFlinger 消费。
-
对 SurfaceFlinger 而言:
-
不关心你是用 Canvas/Skia 画的,还是直接用 GL 画的;
-
只关心:这个 Layer 在它合成时有没有一个最新的 buffer,以及这个 buffer 的格式/尺寸/变换。
-
Choreographer / Handler
-
Choreographer 收到的 VSync 实际来自 显示系统 / SurfaceFlinger / Display HAL,是显示管线统一的节奏信号。
-
App 侧用它来对齐自己的 UI 渲染帧;
-
SurfaceFlinger 侧也在 VSync 节奏下进行合成。
-
-
Handler 只是确保
doTraversal()这些工作运行在 UI 线程。
这样 App 侧和 SurfaceFlinger 侧都跟 同一个(或严格同步的)VSync 源同步:
-
App 在 VSyncN 时画完自己这一帧(输出到 Surface buffer);
-
SurfaceFlinger 在后续某个 VSync(通常是 N 或 N+1)用到这个 buffer 进行合成;
-
避免节奏错乱,减少撕裂和不规则卡顿。
六、一句话概括
Activity / View / Skia / OpenGL ES 只负责“在本窗口的 Surface 上按帧画图”;
WMS 决定每个 Surface 怎么摆;
SurfaceFlinger 在每个 VSync 周期,把所有 Surface 的最新帧按照 WMS 的布局规则合成为一张屏幕图像,再交给显示硬件显示。