前面两篇文章分析了应用层对Vsync的注册与接收,收到Vsync之后应用层便开始View的绘制
我们先来回顾一下大致的流程:
- 首先应用层想要绘制UI,则需要向native层注册接收下一个到来的Vsync,注册的过程是通过EventThreadConnection的Bp端最终调用到SurfaceFlinger进程的EventThread的requestNextVsync函数
- EventThread是用来专门处理各种事件的,除了Vsync,还有Hotplug和ConfigChanged,EventThread有两个,一个名字叫”app“,一个名字叫”sf“
- EventThreadConnection代表应用层到SurfaceFlinger进程的连接,每一个上层的ViewRootImpl都对应一个EventThreadConnection,因为每个View视图都需要Vsync来开启绘制工作
- EventThread并不是一个线程,它的内部有一个线程,这个线程就是用来处理底层Vsync的接收以及分发的,这个线程是一个死循环,当它没收到事件请求时会通过C++条件变量调用wait陷入等待状态
- 应用层请求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函数大概分析完了,代码是挺多的,仔细看看注释,结合前面单独对重要数据的分析,会发现逻辑是比较简单,总结一下:
- threadMain首先会开启一个死循环,这个循环会一直处理事件
- 从mPendingEvents头部获取VSYNC事件Event
- 遍历mDisplayEventConnections,找到其中所有vsyncRequest不为None的connection,并将这些connection放入consumers
- 调用dispatchEvent(*event, consumers)分发事件,事件会分发给consumers中的所有connection
- 根据mState和nextState的对比,选择setVSyncEnabled(false)还是(true),当从State::VSync变为其他状态时调用setVSyncEnabled(false),当从其他状态变为State::VSync时调用setVSyncEnabled(true),mState和nextState的对比其实是起到一个开关作用
- 如果没有事件并且线程状态为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的相关分析留到下一篇文章