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周期合成上屏。

一帧的完整生命周期可概括为:

  1. VSYNC到达,Choreographer回调doFrame。
  2. 执行输入事件、动画、Traversal(measure/layout/draw)。
  3. RenderThread将绘制指令转为GPU命令并渲染到GraphicBuffer。
  4. 应用通过BufferQueue将缓冲区dequeue/queue给SurfaceFlinger。
  5. SurfaceFlinger在下一VSYNC进行合成(HWC或GPU)。
  6. 合成结果送显示控制器扫描上屏。
帧预算(Frame Budget)= 1000ms / 刷新率。60Hz下每帧仅16.67ms,120Hz下仅8.33ms。主线程与RenderThread必须在预算内完成各自工作,否则该帧无法按时提交。

三、掉帧判定标准

掉帧(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窗口,仍要再等一个周期,表现为“明明很快却卡”。

排查卡顿的推荐顺序:先用gfxinfo确认掉帧比例,再用Systrace/Perfetto定位是主线程、RenderThread还是SurfaceFlinger超时,最后结合代码与日志验证根因。
Android渲染链路与帧生命周期 VSYNC 0ms 16.7ms 33.3ms 50ms 66.7ms 应用进程 主线程:measure/layout/draw RenderThread:GPU命令 Choreographer:doFrame BufferQueue:dequeue/queue SystemServer AMS:ANR判定 WMS:窗口层级/输入 IMS:触摸派发 InputDispatcher SurfaceFlinger Layer合成 HWC/GPU合成 VSYNC调度 送显示控制器 Binder BufferQueue 帧时间线(60Hz,每帧16.7ms) Frame 1 正常 12ms Frame 2 超时 28ms → 掉帧 Frame 3 正常 14ms Frame 4 超时 22ms → 掉帧 错过VSYNC窗口 错过VSYNC窗口 掉帧判定要点 • 帧预算 = 1000ms / 刷新率(60Hz→16.67ms,120Hz→8.33ms) • 主线程或RenderThread任一超时,均导致帧无法按时提交 • 连续错过≥2个VSYNC,用户可明显感知卡顿;ANR阈值:输入5s/广播10s/服务20s