android15 vsync源码分析

一 概要

整个vsync可以分为4个角色:

APP:通过gui::DisplayEventReceiver与服务端建立连接,请求和接收vsync信号,用于驱动app侧绘制。

SurfaceFlinger:安卓重要角色之一,在这里有3个重要功能:(1)初始化和管理vsyn模块;(2)向app侧提供vsync接口;(3)获取自身上屏用的vsync信号

Scheduler:vsync管理模块对外的接口。负责vsync预测、分发等核心功能。

hardware vsync:硬件vysnc信号原始来源。

二 四角色一次拆解

2.1 APP

gui::DisplayEventReceiver创建和持有EventThreadConnection对象,通过该对象请求和接收vsync信号,APP侧如何基于gui::DisplayEventReceiver进行更多层次的封装,给上层提供更友好的接口,不在本文讨论范围。这里有个小技术点:BitTube,用于接受vsync事件的对象,BitTube是对socket的封装,为什么不用回调,或者广播的形式呢?socket更高效,不阻塞vsync事件分发。

2.2 SurfaceFlinger(简称sf)

在vysnc模块中,sf负责与Scheduler模块协作,初始化Vsync模块,注册sf和app vsync事件回调,向vsync模块添加present fence时间戳和硬件vsync原始时间戳,用于预测模块构建。

2.3 Scheduler

理解该模块,有几个核心概念。

预测模型计算:根据硬件vsync时间戳建立标准预测模型,通过present fence时间戳更新模型,并当误差大于一定值后,开启硬件vsync采样,重建标准预测模型。在采样时间戳时,有各种逻辑需要处理,如可变分辨率vrr,渲染率render rate,显示模式display mode等改变时,period如何管理。

schedule:当vsync请求发起时,如何调度。有多个请求者时,如何综合设置定时器。schedule()/update()/pendingWorkloadUpdate()三者在什么情况下使用?计算好的nextVsyncTime为什么还需要adjust?

回调注册和响应:通过MessageQueue和EventThread注册回调。关注初始化时机,使用场景。MessageQueue为什么可以直接被分发,EventThread为什么需要维护一个线程异步分发?

nextVsyncTime预测:两个核心问题:nextVsyncTime预测和修正。预测是很简单的,根据之前构建的预测模型Model(slope, intercept),直接计算next vsync timestamp。为什么需要修正呢?由于可变分辨率vrr,显示模型display mode切换等原因,需要对next vsync timestamp进行修正。

2.4 Hardware vsync

硬件vsync,吐出最原始的、标准的vsync信号,为什么不直接用vsync信号,非要搞出这么麻烦的vsync软件模块呢?核心原因是功耗和性能问题,硬件vsync信号频率太高,从内核态传到用户态,有大量的开销。另外也可能处于对vsync更好的管理和优化,减少上屏延迟。

至于SurfaceFlinger如何拿到Hardware vsync,有个专门的一个模块,叫HWComposer,不在本文讨论范围,简单的理解,通过一个callback事件,可以拿到硬件vsync事件。

三 细节拆解

3.1 三大流程

(1) 核心对象创建和callback绑定

重点看EventThread回调和MessageQueue回调注册时机

(2)sf申请vsync

重点看nextVsyncTime在什么时候计算,定时器如何设置,callback如何分发

一个技术点:epoll实现的Timer,为什么不直接用thread sleep?

(3)app申请vsync

重点看threadMain,为什么需要pendingEvents, connection建立时机,如何分发等。

需要关注的一个技术点:BitTube,socket建立双向连接,高效、高频收发数据。

3.2 timestamp管理

几个核心模块:

预测模型计算:简单线性回归计算斜率和截距,得到模型Model(slope, intercept),发生在VsyncPredictor。

PresentFence采样:把present fence上屏时间戳,用于模型调整,如果误差较大,则开启硬件采样。这里需要处理FenceTime还没及时唤醒的情况

onComposerHalVsync:标准硬件vsync时间戳,正常情况下,硬件时间戳直接收集并计算预测模型,但当display mode变化时,需要管理period,比较麻烦(这块本文没有细化,待补充)。

DisplayMode变化时period管理:待补充

VsyncModulator:待补充

3.3 schedule流程

三个重要逻辑:立即更新逻辑(workloadUpdate);schedule逻辑,update逻辑

大逻辑非常简单:如果now很大,则说明有负载瓶颈,依赖最近timer唤醒,本次无需改变定时器;否则预测当前请求者(callback→schedule()),update每一个callback(除当前请求者外),然后取最小唤醒时间,重新设定定时器

  • adjustVsyncIfNeeded()拆解

nextVsyncTime与mLastDispatchTime相比,上下波动mMinVsyncDistance(3ms),则说明已经分发过,则向mMinVsyncDistance后再预测一个

nextVsyncTime与mLastDispatchTime相比少于currentPeriod,则说明too close,则向+currentPeriod后,再预测一个

nextVsyncTime否则,直接使用

  • getExpectedCallbackTime()拆解

nextVsyncTime直接使用,不折腾

  • getArmedInfo(tracker, now, timing)拆解

now + timing.workDuration + timing.readDuration依此向后预测

  • mIntendedWakeupTime

初始化时,被设置为max()

timeCallback()被唤醒时,被重置为max()

cancel(CallbackToken)/cancelTimer()时,被重置为max()

setTimer(nsecs_t targetTime)时,被设置为有效值

  • mArmedInfo

schedule() / update()时,会赋有效值

timeCallback()满足唤醒条件时,被reset()

3.4 nextAnticaptedVsyncFrom下一个vsync计算和修正

根据预测模型Model(slope, intercept)计算vsync是非常简单的,由于vrr可变渲染率和多个渲染配置,导致vsync计算非常复杂,这里介绍主要流程和几个重要函数。

  • std::unordered_map<nsecs_t, Mode> mRateMap

存储ideal period对应的预测模型Model(slope, intercept),在addVsyncTimestamp()时赋值。

Map between ideal vsync period and the calculated model

  • snapToVsync(nsecs_t timePoint)拆解

根据计算好的预算模型Model(slope, intercept),计算timePoint对应的预测值

  • nextAnticipatedVSyncTimeFrom()拆解
  • 预测的vsync,相对于render state做适当修正:snapToVsyncAlignedWithRenderState()
  • 如果开启vrr(动态渲染率),则做适当修正
  • mTimelines拆解

render rate渲染率发生变化时,cache参数,用于修正预测值

  • purgeTimelines()拆解

清空过时的timelines

  • vrr模式下相关修正

onFrameBegin() / onFrameMissed()

ensureMinFrameDurationIsKept()

本质:vrr模式下,显示模式改变,则导致period变化,相关计算参数重置,需要重新计算

相关函数:setRenderState() / setDisplayModePtr(); onFrameBegin() / onFrameMissed()

ensureMinFrameDurationIsKept()

  • todo vrr/render rate修正细节逻辑
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui