AndroidQ SurfaceFlinger进程对Vsync的接收与分发(上)

前面两篇文章分析了应用层对Vsync的注册与接收,收到Vsync之后应用层便开始View的绘制

我们先来回顾一下大致的流程:

  1. 首先应用层想要绘制UI,则需要向native层注册接收下一个到来的Vsync,注册的过程是通过EventThreadConnection的Bp端最终调用到SurfaceFlinger进程的EventThread的requestNextVsync函数
  2. EventThread是用来专门处理各种事件的,除了Vsync,还有Hotplug和ConfigChanged,EventThread有两个,一个名字叫”app“,一个名字叫”sf“
  3. EventThreadConnection代表应用层到SurfaceFlinger进程的连接,每一个上层的ViewRootImpl都对应一个EventThreadConnection,因为每个View视图都需要Vsync来开启绘制工作
  4. EventThread并不是一个线程,它的内部有一个线程,这个线程就是用来处理底层Vsync的接收以及分发的,这个线程是一个死循环,当它没收到事件请求时会通过C++条件变量调用wait陷入等待状态
  5. 应用层请求Vsync的过程其实就是通过这个条件变量调用notify唤醒EventThread内部这个线程,然后从mPendingEvents中获取到Vsync信息分发给感兴趣的进程

我们前两篇文章大概就分析了这些,本篇文章就来探究mPendingEvents中的Vsync是哪来的,以及EventThread内部这个线程的工作原理

EventThread的创建是在SurfaceFlinger的init函数中

void SurfaceFlinger::init() {
	......
	    // start the EventThread
    mScheduler =
            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
                                         mRefreshRateConfigs);
	mAppConnectionHandle =
            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
                                         resyncCallback,
                                         impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
                                                       resyncCallback, [this](nsecs_t timestamp) {
                                                           mInterceptor->saveVSyncEvent(timestamp);
                                                       });
	......
}

这个函数中首先创建了Scheduler,接着通过Scheduler创建了两个Scheduler::ConnectionHandle,从名字能看出来,一个负责app处理,一个负责surfaceflinger处理,EventThread也会创建两个,刚好对应这两个ConnectionHandle

EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
      : mVSyncSource(src),
        mVSyncSourceUnique(std::move(uniqueSrc)),
        mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
        mThreadName(threadName) {
      ......
}

EventThread的构造函数里面先不忙分析,先来看看它构造函数中初始化的mVSyncSource,类型为VSyncSource,看它是如何创建的

回到前面创建Scheduler::ConnectionHandle的函数:

createConnection

sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
        const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    const int64_t id = sNextId++;
    std::unique_ptr<EventThread> eventThread =
            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
                            std::move(interceptCallback));
    ......
    return mConnections[id]->handle;
}

std::unique_ptr<EventThread> Scheduler::makeEventThread(
        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    std::unique_ptr<VSyncSource> eventThreadSource =
            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
    return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
                                               std::move(interceptCallback), connectionName);
}

上面两个函数就会创建VSyncSource并传递到EventThread中,

原来创建的是VSyncSource的子类DispSyncSourc,创建DispSyncSource时又需要一个DispSync,DispSync则是直接传递的mPrimaryDispSync.get()

那么现在就需要搞清楚mPrimaryDispSync是什么时候创建的

找到了,mPrimaryDispSync是在Scheduler的构造函数中创建的


Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
                     const scheduler::RefreshRateConfigs& refreshRateConfig)
      : mHasSyncFramework(running_without_sync_framework(true)),
        mDispSyncPresentTimeOffset(present_time_offset_from_vsync_ns(0)),
        mPrimaryHWVsyncEnabled(false),
        mHWVsyncAvailable(false),
        mRefreshRateConfigs(refreshRateConfig) {
    // Note: We create a local temporary with the real DispSync implementation
    // type temporarily so we can initialize it with the configured values,
    // before storing it for more generic use using the interface type.
    auto primaryDispSync = std::make_unique<impl::DispSync>("SchedulerDispSync");
    primaryDispSync->init(mHasSyncFramework, mDispSyncPresentTimeOffset);
    mPrimaryDispSync = std::move(primaryDispSync);
	......
}

创建DispSync之后调用了它的init函数,来看看DispSync的构造函数

DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0) {
    // This flag offers the ability to turn on systrace logging from the shell.
    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.dispsync_trace_detailed_info", value, "0");
    mTraceDetailedInfo = atoi(value);
    mThread = new DispSyncThread(name, mTraceDetailedInfo);
}

这里面创建了一个线程DispSyncThread,这个线程构造函数中只是对一些值做了初始化,这个线程重点是它的threadLoop函数,这个函数现在先不忙看,等下分析了EventThread之后在回头针对性看

好了EventThread的VSyncSource就创建好了,实际上是一个DispSyncSource对象,DispSyncSource内部有一个DispSync,DispSync内部有一个线程DispSyncThread,其实我们光看名字应该能够猜测,这几个类都是用来处理VSync的

接着回到EventThread的构造函数:

EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
      : mVSyncSource(src),
        mVSyncSourceUnique(std::move(uniqueSrc)),
        mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
        mThreadName(threadName) {
    ......
    mVSyncSource->setCallback(this);

    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
    });

     ......
}

这个函数有两个重点,1.给VSyncSource设置回调,2.创建一个线程,并调用threadMain函数

首先看设置回调:

class VSyncSource {
public:
    class Callback {
    public:
        virtual ~Callback() {}
        virtual void onVSyncEvent(nsecs_t when) = 0;
    };
	.....    
}

这个回调的类型是VSyncSource::Callback,它只有一个函数onVSyncEvent,这个函数被EventThread实现了,也就是说会有某些情况发生之后EventThread会调用onVSyncEvent函数,我们根据这个函数的名字可以猜测一下可能是收到来自硬件的VSync后会回调此函数

回调设置之后会创建一个线程调用threadMain函数,这是EventThread核心函数,这个函数代码很多,在看这个函数之前,我们先了解一下这个函数用到的重要变量的含义,主要有三个容器进行存取数据的操作,DisplayEventConsumers consumers,mPendingEvents,mDisplayEventConnections,它们都定义在EventThread.h中

//EventThread.h
using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;

std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);

std::vector<wp<EventThreadConnection>> mDisplayEventConnections GUARDED_BY(mMutex);

GUARDED_BY用来保证线程安全,类似java同步锁synchronized的用法

consumers类型为DisplayEventConsumers,这是一个vector,里面放的是EventThreadConnection

mPendingEvents是一个deque队列,里面放的是DisplayEventReceiver::Event

mDisplayEventConnections也是一个vector,里面放的也是EventThreadConnection

这里虽然consumers和mDisplayEventConnections都是存储EventThreadConnection,但是consumers存储的是请求了Vsync的connection,mDisplayEventConnections存储的是所有和surfaceFlinger进程建立连接的connection

这三个重要容器看了之后再来看看mState这个变量,这是用来描述EventThread的线程状态的,mState类型为State,定义在EventThread.h中

 enum class State {
        Idle,
        Quit,
        SyntheticVSync,
        VSync,
    };

    State mState GUARDED_BY(mMutex) = State::Idle;

一共有4种状态,Idle表示空闲,Quit表示退出,SyntheticVSync表示合成VSync(灭屏时会是这种状态),VSync表示请求VSync

EventThread线程状态看完之后再来看一个VSyncRequest

enum class VSyncRequest {
    None = -1,
    Single = 0,
    Periodic = 1,
    // Subsequent values are periods.
};

这个枚举类用来表示VSync的请求类型,有三种,None表示当前没有VSync请求,Single表示这是一次性VSync请求(请求一次,接收一次),Periodic表示这是周期性VSync请求(请求一次可以一直接收)

对threadMain函数中用到的重要变量有了基本了解之后,现在我们再来看这个函数:

void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    //存储EventThreadConnection的vector,consumers表示即将消费
    //事件的connection集合
    DisplayEventConsumers consumers;
    //只要不退出,就一直循环,相当于死循环
    while (mState != State::Quit) {
        //构造一个待分发的Event
        std::optional<DisplayEventReceiver::Event> event;

        // mPendingEvents是一个vector,存储即将处理的
        //DisplayEventReceiver::Event
        if (!mPendingEvents.empty()) {
            //获取头部Event
            event = mPendingEvents.front();
            //并将头部Event弹出
            mPendingEvents.pop_front();
            //根据Event的类型,做不同处理,我们只关心VSYNC类型
            switch (event->header.type) {
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                    ......
                    break;

                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
                    if (mInterceptVSyncsCallback) {
                        mInterceptVSyncsCallback(event->header.timestamp);
                    }
                    break;
            }
        }
        //是否有vsync请求,默认false
        bool vsyncRequested = false;

        // 从mDisplayEventConnections中查询应该接收Event的
        //EventThreadConnection,这是个vector遍历操作
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            //弱指针升级强指针,当对象已经销毁或者准备销毁则返回false
            if (const auto connection = it->promote()) {
                //如果有一个connection的vsyncRequest不为None则
                //vsyncRequested为true
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
                //如果event不为空并且shouldConsumeEvent返回true
                //则将connection加入到consumers,等待消费event,
                //shouldConsumeEvent的实现很简单,对于VSYNC类型的事件,
                //只要VSyncRequest的类型不是None就返回true
                if (event && shouldConsumeEvent(*event, connection)) {
                   //加入consumers
                    consumers.push_back(connection);
                }

                ++it;
            } else {
               //如果connections已经销毁则移除它
                it = mDisplayEventConnections.erase(it);
            }
        }
      
        if (!consumers.empty()) {
             //如果consumers不为空则调用dispatchEvent
             //为consumers中的每个connection分发事件
             //后面分析...
            dispatchEvent(*event, consumers);
            //分发之后清空consumers
            consumers.clear();
        }

        State nextState;
        //如果有vsync的请求
        if (mVSyncState && vsyncRequested) {
            //判断是SyntheticVSync还是VSync类型的VSync
            //mVSyncState->synthetic在灭屏时被赋值为true,亮屏
            //时为false
            nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            //没有vsync则状态为State::Idle
            nextState = State::Idle;
        }
        //两个状态不等说明有两种可能,1.从State::VSync变为其他
        //2.从其他变为State::VSync
        if (mState != nextState) {
            //情况1
            if (mState == State::VSync) {
                //后面分析...
                mVSyncSource->setVSyncEnabled(false);
                //情况2
            } else if (nextState == State::VSync) {
                mVSyncSource->setVSyncEnabled(true);
            }

            mState = nextState;
        }
        //如果有事件则继续循环
        if (event) {
            continue;
        }
        // 没有事件并且当前状态为State::Idle
        if (mState == State::Idle) {
            //则通过条件变量陷入等待
            mCondition.wait(lock);
        } else {
            //如果没有事件并且当前状态不为空闲,这种情况是硬件不知什么原因没
            //有发送VSync上来,需要伪造VSync信号,频率为灭屏时16ms,亮屏
            //1000ms
            const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms;
            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
                //将伪造的VSync放入mPendingEvents,准备分发
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId,
                                                   systemTime(SYSTEM_TIME_MONOTONIC),
                                                   ++mVSyncState->count));
            }
        }
    }
}

threadMain函数大概分析完了,代码是挺多的,仔细看看注释,结合前面单独对重要数据的分析,会发现逻辑是比较简单,总结一下:

  1. threadMain首先会开启一个死循环,这个循环会一直处理事件
  2. 从mPendingEvents头部获取VSYNC事件Event
  3. 遍历mDisplayEventConnections,找到其中所有vsyncRequest不为None的connection,并将这些connection放入consumers
  4. 调用dispatchEvent(*event, consumers)分发事件,事件会分发给consumers中的所有connection
  5. 根据mState和nextState的对比,选择setVSyncEnabled(false)还是(true),当从State::VSync变为其他状态时调用setVSyncEnabled(false),当从其他状态变为State::VSync时调用setVSyncEnabled(true),mState和nextState的对比其实是起到一个开关作用
  6. 如果没有事件并且线程状态为State::Idle,则通过条件变量mCondition让线程陷入等待,如果没有事件并且线程状态不为State::Idle时则需要伪造VSync发送给请求者

前面两篇文章分析了应用层想要进行UI绘制则需要向surfaceFlinger进程请求VSync,等待下一个VSync到来之后通知应用进行绘制,应用层请求VSync的过程就是通过条件变量的notify函数,唤醒threadMain中陷入等待的这个死循环,刚刚threadMain函数的分析又知道了这个死循环主要工作就是从mPendingEvents获取到事件,然后调用dispatchEvent函数分发给感兴趣的connection,何为感兴趣的connection?就是它的vsyncRequest不为None,dispatchEvent函数就会将

到这里还遗留了几个关键地方没有分析,1.mPendingEvents里的事件是怎么来的,2.setVSyncEnabled函数的具体作用

我们先来看setVSyncEnabled这个函数的具体作用,这个函数定义在DispSyncSource中,DispSyncSource我们前面分析过,是在创建EventThread的时候创建的,并且DispSyncSource内部还创建了一个DispSync,DispSync内部开启了一个线程DispSyncThread,这个线程有个重要的threadLoop函数我们还留着没分析
先看这个函数:

DispSyncSource.setVSyncEnabled

void DispSyncSource::setVSyncEnabled(bool enable) {
    std::lock_guard lock(mVsyncMutex);
    if (enable) {
        status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
                                                   static_cast<DispSync::Callback*>(this),
                                                   mLastCallbackTime);
        ......
    } else {
        status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this),
                                                      &mLastCallbackTime);
        ......
    }
    mEnabled = enable;
}

这个函数其实就是添加和移除监听器,那么这个监听器到底在监听什么?监听到了之后又调用它的哪个回调函数?
回调哪个函数这很简单,我们看看DispSync.h就知道了

class DispSync {
public:
    class Callback {
    public:
        Callback() = default;
        virtual ~Callback();
        virtual void onDispSyncEvent(nsecs_t when) = 0;
		......        
}

就是这个函数onDispSyncEvent,也就是说当通过setVSyncEnabled添加的监听器,监听到某件事发生之后就会回调DispSyncSource的onDispSyncEvent函数,那现在就需要找到添加的这个监听器在监听什么?

来看看DispSync添加监听器之后做了什么

mDispSync->addEventListener

status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback,
                              nsecs_t lastCallbackTime) {
 		...

        for (size_t i = 0; i < mEventListeners.size(); i++) {
            if (mEventListeners[i].mCallback == callback) {
                return BAD_VALUE;
            }
        }

        EventListener listener;
        listener.mName = name;
        listener.mPhase = phase;
        listener.mCallback = callback;
        .....
        mEventListeners.push_back(listener);

        mCond.signal();

        return NO_ERROR;
    }

我省略一大段EventListener time的计算,不想去分析了,剩下的代码无非就是根据添加的监听callback,name等构造一个EventListener,然后存储到mEventListeners这个Vector中,mCond.signal类似条件变量,也是一个唤醒/等待机制,那它是要唤醒什么呢?

前面DispSync创建时就开启了一个线程DispSyncThread,这个线程也类似EventThread内部的线程,是一个死循环,这个线程是真正分发Vsync信号的线程,所有应用程序以及surfaceFlinger注册的Vsync都是通过这个线程的死循环中分发出去的,限于篇幅,关于DispSyncThread的相关分析留到下一篇文章

发布了49 篇原创文章 · 获赞 72 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_34211365/article/details/105206088