Android核心绘制流程

29 阅读4分钟

vsync app

  1. 由vsync app触发,主要在doFrame里面的Input(点击屏幕)、animation(计算滑动位置)、traversal(绘制、布局)
  2. UI线程执行完成之后,会转交给RenderThread线程工作
  3. RenderThread向SF申请一个buffer(DequeueBuffer),把绘制的指令交给GPU处理,执行queueBuffer给SF送帧

vsync sf

  1. 由vsync sf触发,sf遍历图层列表,获取更新图层的buffer
  2. 通过binder通信,到HWC,HWC根据硬件能力来判断是Device还是client的方式
  3. sf执行合成之后,释放用于上一帧画面的buffer
  4. Client合成: GPU合成,其合成过程由OpenGL完成,完成之后,再递交给HWC
  5. Device合成:硬件合成,由硬件合成器完成
  6. SF询问HWC合成方式 -> client/Device ->申请DequeueBuffer->queueBuffer->SF将client合成的结果存在FrameBuffer中交给HWC完成剩下的Device合成

image.png

image.png

HWC

  1. HWC根据硬件能力给出有效的合成方式反馈给SF,并通过DRM与显卡进行交互
  2. HWC通过iotcl调用到kernel,通知crtc_commit线程完成剩下的工作
  3. crtc_commit线程执行complete_commit函数完成画面合成之后,并且保存在FrameBuffer里面供屏幕显示

根据时间线来判断是否为卡顿

image.png

帧率

  • 60Hz 设备:每 16.67ms 刷新一次,每秒 60 帧
  • 90Hz 设备:每 11.11ms 刷新一次,每秒 90 帧
  • 120Hz 设备:每 8.33ms 刷新一次,每秒 120 帧

市场从 60Hz 到 90Hz,再到 120Hz 的演进有着明确的技术和用户体验驱动因素:

  1. 更高的流畅度:120Hz 比 60Hz 提供了两倍的视觉信息,使滑动、动画等交互感觉更加流畅自然。
  2. 减少延迟:输入事件到显示结果的延迟从 60Hz 的 16.67ms 减少到 120Hz 的 8.33ms,让用户操作反馈更及时。
  3. 硬件支持成熟:现代移动处理器(如高通骁龙 8 系列、联发科天玑系列)已经有足够性能支持 120Hz 的稳定运行。
  4. 电池技术进步:更高效的电池和电源管理技术缓解了高刷新率带来的功耗压力。
  5. 可变刷新率技术:LTPO 等自适应刷新率技术允许设备在不同场景下智能切换刷新率,平衡流畅度和功耗。

如今,120Hz 不仅是 Android 旗舰机型的标配,连 iOS 设备(iPhone 13 Pro 及以上)也已支持 120Hz 的 ProMotion 技术,标志着高刷新率已成为高端移动设备的基本特性。

image.png

在 120Hz 设备上,我们会看到:

  1. Vsync 间隔:VSYNC 信号每 8.33ms 触发一次
  2. 帧处理流程:每一帧的处理依然遵循 Input → Animation → Traversal 的顺序
  3. 时间压缩:所有处理步骤必须在更短的时间内完成,对系统和应用性能要求更高

上图中出现了两个 Buffer 相关的 Trace,这里做一个简单的说明:

  1. QueuedBuffer:(例如:QueuedBuffer - VRI[ImproveSnsTimelineUI]#748BLAST#748)
  • 这个 Trace Tag 是在 App 进程中打印的
  • 表示应用完成一帧渲染后,将渲染好的 Buffer 放入队列准备提交给 SurfaceFlinger
  • 在使用 BlastBufferQueue 的系统中,这个时刻标志着 RenderThread 完成渲染并准备将结果传输到系统服务
  1. BufferTX:(例如:BufferTX - com.tencent.mm/com.tencent.mm.plugin.sns.ui.improve.ImproveSnsTimelineUI#47974)
  • 这个 Trace Tag 是在 SurfaceFlinger 进程中打印的
  • 表示 SurfaceFlinger 接收到应用传来的 Buffer 并开始处理的时刻
  • TX 代表 “Transfer/Transmission”,即缓冲区的传输过程

正确的流程应该是:

  1. App 的 RenderThread 调用 queueBuffer,此时 App 认为自己已交出一个 Buffer,于是 QueuedBuffer  +1
  2. 该 Buffer 被传输给 SF,SF 接收(latch/acquire)后,BufferTX  +1
  3. SF 在未来的某个 Vsync 周期,使用这个 Buffer 完成合成并上屏。
  4. 当 SF 不再需要这个 Buffer 时(例如,它已经被新的帧替换,或者已稳定显示了足够长的时间),SF 会释放(release)这个 Buffer。
  5. SF 释放 Buffer 后,BufferTX -1。同时,App 会收到 Buffer 已被释放的回调,此时 App 端的 QueuedBuffer 才会 -1,表示这个 Buffer 已成功返回缓冲池,可被再次使用。
  6. surfaceFlinger的帧率(ofbFps)一般是120HZ
  7. app的帧率一般是60-90-60