[Android禅修之路] 解读Vsync(一)

本文详细解读了Android系统中Vsync的初始化过程,包括SurfaceFlinger的初始化、EventThread的创建和MessageQueue的处理机制。Vsync在Android图形刷新中的作用是同步应用渲染和屏幕合成,确保流畅性。文章通过分析SurfaceFlinger的创建、EventThread的线程逻辑和MessageQueue的事件处理,揭示了Vsync信号如何产生和分发。同时,概述了Vsync信号如何从硬件转换为SurfaceFlinger的事件,涉及DispSync、EventThread、BitTube和MessageQueue等关键组件的工作原理。
摘要由CSDN通过智能技术生成

一 概述

说到 Vsync,大家首先想到的肯定是游戏中的垂直同步。可能会有人疑惑,游戏的垂直同步和 Android 的图形系统的关系。其实在 Android 中,同样有着 Vsync 机制。

在 Android 的刷新过程中,Vsync 的作用就是同步的唤醒应用以开始渲染、唤醒 SurfaceFlinger 开始屏幕的合成以及屏幕刷新周期。

在 SurfaceFlinger 渲染的过程中,画面的显示会经过应用程序的绘制,SurfaceFlinger 的合成,以及硬件的显示。这些过程分别处于三个不同的进程中,系统一般采用三缓冲的策略。

也就是当屏幕开始显示第N帧的时候,SurfaceFlinger 会开始为第N+1帧进行合成。而应用则准备的生成第N+2帧。这个具体的流程,就发生在我们之前介绍的 BufferQueue 的生产者和消费者模型中。

Vsync 机制是 SurfaceFlinger 中重要的机制之一,它用于通知在 SurfaceFlinger 的刷新时机。 Vsync 主要的工作过程就是产生 Vsync 信号和分发信号。所以解读 Vsync 机制,就是弄清楚最关键的两个问题:

  1. Vsync 信号是如何产生的
  2. Vsync 信号是如何分发到 SurfaceFlinger 的(是如何传递的)

接下来我们就从三个方面一步一步了解 Vsync 机制

  • Vsync 的初始化 [节一]
  • Vsync 的分发线程的工作原理(部分)[节二]
  • Vsync 消息的传递逻辑 [节三]

一 Vsync 的初始化

首先,在 SurfaceFlinger 启动的时候,会做一个初始化的过程,调用 init 函数,在这个函数中,创建一个 EventThread 和一个 MessageQueue,用来处理 Vsync 信号。

[frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::init() {
    ...
    //1 启动 EventThread,EventThread有两个,分别是App EventThread和SF EventThread
    // getFactory()拿到的是SurfaceFlingerFactory, 然后创建一个 Scheduler 调度器
    mScheduler =getFactory().createScheduler([this](bool enabled) {
        setPrimaryVsyncEnabled(enabled); 
    },mRefreshRateConfigs);
    // 通过 mScheduler 创建回调,具体的回调函数是 SurfaceFlinger 的 getVsyncPeriod
    auto resyncCallback = mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
  	// 1.1 App EventThread,传入了创建的回调函数 resyncCallback
    mAppConnectionHandle =
            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
                                         resyncCallback,
                                         impl::EventThread::InterceptVSyncsCallback());
    // 1.2 SF EventThread,同样传入了刚才创建的回调函数,拿到的是一个 Handle
    mSfConnectionHandle = mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
        mPhaseOffsets->getOffsetThresholdForNextVsync(),resyncCallback, [this](nsecs_t timestamp) {
        mInterceptor->saveVSyncEvent(timestamp);
    });
    // 将 Handle(也就是mSfConnectionHandle) 对应的 EventThreadConnection 注入 mEventQueue,这个 mEventQueue 是一个 MessageQueue 消息队列
    // 这里很重要
    // Handle 对应一个 EventThreadConnection,这个 EventThreadConnection 是一个连接器,它保存着回调函数和Vsync事件源
    mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
} 

这里的 init 函数,通过 Scheduler 创建了两个 EventThread,一个是 App 的 EventThread ,一个是 SurfaceFlinger 的 EventThread。

因为 Vsync 是通知 SurfaceFlinger 刷新的信号,如果 App 信号和 SF 信号是同步的话,那么就会造成系统工作的拥挤,按照正常的思路,我们应该是希望处理 App 事务和处理 SF 事务是错开的,所以这里用了两个线程来分开处理。并且这两个线程还采用了不同的时间偏移量。

创建完 EventThread 之后,就将 SurfaceFlinger 的 EventConnection 设置进了 EventQueue。

这里出现了几个对象,我们分别来看,首先是 EventQueue。

1.1 MessageQueue

EventQueue 是定义在 SurfaceFlinger 中的一个成员变量,它其实就是一个 MessageQueue ,定义如下

[frameworks/native/services/surfaceflinger/SurfaceFlinger.h]
std::unique_ptr<MessageQueue> mEventQueue; 

MessageQueue 是 Android 中比较常见的一个机制,这里的 mEventQueue 会在创建 SurfaceFlinger 的强指针的时候初始化。

[frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::onFirstRef() {
    mEventQueue->init(this);
} 
1.1.1 MessageQueue::init
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
} 

初始化就是创建对应的 Looper 和 Handler。Handler 是 MessageQueue 的内部类

1.1.2 MessageQueue::Handler
class MessageQueue final : public android::MessageQueue {
    class Handler : public MessageHandler {
      ... 

这里就是 Android 中经常用的 Handler 和 MessageQueue 机制

接下来再看 EventConnection 这个对象,它是通过 Scheduler::createConnection 创建的

1.2 Scheduler::createConnection

createConnection 其实就是建立连接,它会创建一个 EventThread 对象,并将它与 SurfaceFlinger 建立相应的关联。这里传递进来的参数很多

  • connectionName:连接名,传入的分别是 app 和 sf,也就是 app 和 sf 都会建立连接
  • phaseOffsetNs:相位差,传入的分别是 mVsyncModulator.getOffsets().app和 mVsyncModulator.getOffsets().sf。之前已经说过了,我们希望系统在分发 App 信号和 SF 信号时是错开的,这样就能避免系统工作的拥挤,这个错开的方式就是通过相位差实现的
  • offsetThresholdForNextVsync:下个Vsync的偏移阈值,传入的是mPhaseOffsets->getOffsetThresholdForNextVsync(),mPhaseOffsets 在 SurfaceFlinger 创建的时候是0,是在获取硬件信息后重新设置的值
  • resyncCallback:Vsync 信号的回调
  • interceptCallback:Vsync 信号拦截的回调
[frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
        const char* connectionName, 
        nsecs_t phaseOffsetNs, 
        nsecs_t offsetThresholdForNextVsync,
        ResyncCallback resyncCallback,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    const int64_t id = sNextId++;

    // 创建一个管理 Vsync 的 EventThread
    // mPrimaryDispSync.get()是一个 DispSync,这个 DispSync 是合成延时的 Vsync 源
    // 关于 DispSync 的介绍见[四 DispSync]
    // 然后通过这个 Vsync 源创建一个 EventThread 关联,这样这个 EventThread 就可以产生 Vsync 信号的通知事件了
    std::unique_ptr<EventThread> eventThread =
            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
                            offsetThresholdForNextVsync, std::move(interceptCallback));

    // 创建 EventThread 的 Connection 连接 EventThreadConnection
    auto eventThreadConnection =
            createConnectionInternal(eventThread.get(), std::move(resyncCallback),
                                     ISurfaceComposer::eConfigChangedSuppress);
    // mConnections是一个Connection的集合 
    // 将创建的 EventThreadConnection 保存到这个 Connection 的集合中
    mConnections.emplace(id,
                         std::make_unique<Connection>(new ConnectionHandle(id),
                                                      eventThreadConnection,
                                                      std::move(eventThread)));
    // Connection 的 handle 是一个 BBinder
    return mConnections[id]->handle;
} 

Scheduler 中有一个 DispSync,这个 DispSync 是在 Scheduler 的构造函数中创建的,它其实就是 Vsync 的信号源,mPrimaryDispSync.get()拿到的就是 DispSync

通过 makeEventThread 创建完 EventThread 之后,会将 EventThread和 SF 的 Vsync 回调进行绑定,创建出一个 EventThreadConnection,这样这个 EventThreadConnection 就既有 Vsync 事件的信号源,又有对应的回调。 然后就将这个 EventThreadConnection 保存到一个名为 mConnections 的 Connection 集合,这个 Connection 其实就是 Scheduler 的内部类,它包含三个成员变量,分别是

  • ConnectionHandle 指针,它是 BBinder 的子类
  • EventThreadConnection 指针,这个 EventThreadConnection 它有包含 EventThread 和对应的 SF 回调
  • EventThread 指针
class Connection {
public:
    Connection(sp<ConnectionHandle> handle, sp<EventThreadConnec
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值