android 的垂直同步模型(vsync)是隐藏在 view 系统后面的很重要的一块,它控制着 view 渲染的节奏;而且 vsync 还是比较复杂的,我们从下到上,先从最熟悉的 View.invalidate 讲起,看看简单的一个 invalidate 后面隐藏着多么复杂的工作

看左图,View.invalidate() 主要做了两件事:
ViewRootImpl.doTraversal() 加入到 Choreographer 的任务列表里,等待下一次 vsync 信号到来时执行;doTraversal 主要执行 view tree 的三个重要方法:measure、layout 和 draw;Choreographer 则是在一次 vsync 信号到来时,依次执行 INPUT,ANIMATION 和 TRAVERSAL 这三个类别的任务;也就是说 view tree 的渲染和 input 的处理都是从 vsync 到来时开始的,而且此时会开启同步栅栏,屏蔽非 ui 任务(用户任务),集中力量在下一次的 vsync 到来前完成一帧的渲染按照从下到上追踪法,下一步就是看看是谁在什么时候把 event 放到 mPendingEvents 里,但这里我选择掉转方向盘,先从 surfaceflinger 讲起
继续之前,我们得先了解几个跟硬件有关的概念
HAL,Hardware Abstract Layer,硬件抽象层
看名字就知道这是跟硬件、设备相关的东西,应该是最贴近硬件的那一层软件,我没有做过相关的开发,但是结合 google 和这两篇文章:Android图形系统系统篇之HWC,Android HIDL HAL 接口定义语言详解,我大概了解了它是干什么的,我说说我的理解:
HIDL,HAL Interface Definition Language,HAL 接口定义语言
看名字好像跟 AIDL 有点渊源啊,对的,它是 HAL 的代码生成器;具体怎么用我们了解下即可:Android图形系统系统篇之HWC,Android HIDL HAL 接口定义语言详解,Android HIDL 之 hal 进程启动及服务注册过程
总结下关键点:

HWC,硬件图层合成器
Android图形系统系统篇之HWC 这里也介绍了,它是一个合成多个图层的组件(原来状态栏、导航栏、壁纸、app 等不是一起渲染,而是独自渲染最后合成为屏幕内容的),这里只关心它会发出 vsync 信号
我们先理解这张图,屏幕(硬件)发出 vsync 信号(就是上图的 HW_VSYNC),经过软件的一系列的调整生成 SW_VSYNC,然后输出到两路:
SF_VSYNC,输出到 surfaceflingerAPP_VSYNC,输出到 app
HW_VSYNC - 硬件垂直同步信号
surfaceflinger 是一个很重要的服务进程,它跟图像和显示有关,源码在 /frameworks/native/services/surfaceflinger
目录下有个编译配置文件 Android.bp ,看下它的内容,它输出了可执行文件 surfaceflinger、共享库 libsurfaceflinger.so 和 libSurfaceFlingerProp.so
然后有个 surfaceflinger.rc,它是一个启动配置文件,意味着 surfaceflinger 会在系统启动后被 init 进程启动为服务进程,看下里面的内容,可执行文件是 /system/bin/surfaceflinger,main 函数入口在 main_surfaceflinger.cpp
从上图可以看到 surfaceflinger 进程启动后,会查找 HWC server 并注册 callback,当设备发出 hw_vsync 时,SurfaceFlinger.onVsyncReceived 被执行,看上面那张图,hw_vsync 不是直接被使用,而是被调整转换为 sw_vsync,也就是 DispSync.addResyncSample
SW_VSYNC - 软件垂直同步信号
DispSyncThread 和 DispSync 收集 HW_VSYNC,计算并输出 SW_VSYNC;主循环是 DispSyncThread.threadLoop(),但在分析 main loop 之前,我们需要先了解 DispSync 几个重要的属性(参考「Android SurfaceFlinger SW Vsync模型」)
mResyncSamples 数组 - 通过上面的分析我们知道 addResyncSample 把 HW_VSYNC 加入 DispSync,但 mResyncSamples 只会保留最新的 32 个以供后续计算;它是个首尾相连、环状的循环列表,容量为 32
mPeriod - 两个 HW_VSYNC 之间的时间间隔,相当于刷新率,我们看下它是怎么计算的