2. Android系统架构与渲染机制
要理解卡顿与ANR,必须先看清Android图形栈中“谁在什么时候做什么”。一次用户滑动,从触摸事件到像素上屏,中间横跨应用进程、SystemServer、SurfaceFlinger与硬件合成器,并由VSYNC信号统一节拍。任何一环超时,都会表现为掉帧甚至ANR。
一、核心角色与职责
Android渲染链路上有四个关键角色,它们分工明确、通过Binder与共享内存协作:
- 应用进程(App Process):运行主线程(UI线程),负责测量、布局、绘制(measure/layout/draw),把绘制指令写入RenderThread,最终提交为图形缓冲区(GraphicBuffer)。
- SystemServer:系统服务大本营,其中ActivityManagerService负责进程与ANR判定,WindowManagerService负责窗口层级、输入分发与窗口动画,InputManagerService负责触摸事件派发。
- SurfaceFlinger:系统合成服务,接收各应用提交的图层(Layer),按Z序与可见区域进行合成,输出到显示设备。
- Choreographer:应用侧的“节拍器”,接收VSYNC回调,统一调度输入、动画、遍历(Traversal)三类回调,保证UI工作与屏幕刷新对齐。
二、VSYNC与帧生命周期
VSYNC(Vertical Synchronization)是显示器的垂直同步信号,通常以60Hz、90Hz或120Hz周期到达。Android采用“双缓冲+预测式VSYNC”机制:Choreographer在VSYNC到来时触发doFrame,应用完成一帧的输入处理、动画计算与View树遍历,随后通过RenderThread提交GPU命令,最终由SurfaceFlinger在下一个VSYNC周期合成上屏。
一帧的完整生命周期可概括为:
- VSYNC到达,Choreographer回调doFrame。
- 执行输入事件、动画、Traversal(measure/layout/draw)。
- RenderThread将绘制指令转为GPU命令并渲染到GraphicBuffer。
- 应用通过BufferQueue将缓冲区dequeue/queue给SurfaceFlinger。
- SurfaceFlinger在下一VSYNC进行合成(HWC或GPU)。
- 合成结果送显示控制器扫描上屏。
三、掉帧判定标准
掉帧(Jank)的本质是“某一帧未能在其VSYNC周期内完成提交”。判定标准通常包括:
| 指标 | 含义 | 典型阈值 |
|---|---|---|
| Frame Duration | 单帧从doFrame到queueBuffer的耗时 | >16.67ms(60Hz) |
| Jank Count | 单位时间内掉帧次数 | >5次/秒需关注 |
| Missed VSYNC | 错过VSYNC提交窗口 | 连续≥2次即明显卡顿 |
| Input Latency | 触摸到上屏的延迟 | >100ms用户可感知 |
| ANR Timeout | 主线程阻塞超时 | 输入5s、广播10s、服务20s |
实际分析中,常用以下命令抓取帧数据:
adb shell dumpsys gfxinfo com.example.app framestats
adb shell dumpsys SurfaceFlinger --latency
adb shell atrace -t 5 gfx view wm am
四、典型场景与误区复盘
场景:列表滑动掉帧。某应用在RecyclerView滑动时出现周期性卡顿。通过Systrace发现,主线程在onBindViewHolder中执行了数据库查询,单帧耗时达到40ms,直接错过两个VSYNC。修复方式是将查询移至子线程并预取,主线程仅做绑定。
误区一:只盯主线程。RenderThread同样可能成为瓶颈,例如复杂阴影、过度绘制导致GPU命令堆积,此时主线程看似空闲,但帧仍无法按时提交。
误区二:把掉帧等同于ANR。掉帧是帧未按时上屏,ANR是主线程被阻塞超过系统阈值。掉帧可能由GPU或SurfaceFlinger引起,而ANR几乎总是主线程问题。
误区三:忽略VSYNC对齐。即使单帧工作只需10ms,若提交时机错过VSYNC窗口,仍要再等一个周期,表现为“明明很快却卡”。