SurfaceFlinger在收到来自硬件层的Vsync事件之后,不是每次都会调用SurfaceFlinger::handleMessageInvalidate()
的。而SurfaceFlinger中处理Vsync事件涉及到的类有:DispSyncThread
, DispSync
, SurfaceFlinger::DispSyncSource
, EventThread
, EventThread::Connection
, MessageQueue
.
本文首先研究这些类之间的关系,以及自Vysnc事件发生后这些类的处理流程。最终,通过修改EventThread::Connection中的成员count实现了每个Vsync事件都会调用SurfaceFlinger::handleMessageInvalidate()的功能。
在SurfaceFlinger.cpp的init()
方法中,通过如下的代码初始化了DispSyncSource和EventThread,并将mSFEventThread关联到成员变量MessageQueue mEventQueue
中:
sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc, *this, false);
sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
在EventThread.cpp中可以看到当EventThread的实例创建时,在其onFirstRef()中会开启线程:
void EventThread::onFirstRef() {
run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}
而在MessageQueue::setEventThread()
中,会创建EventThread::Connection
:
void MessageQueue::setEventThread(const sp& eventThread)
{
if (mEventThread == eventThread) {
return;
}
if (mEventTube.getFd() >= 0) {
mLooper->removeFd(mEventTube.getFd());
}
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
}
sp EventThread::createEventConnection() const {
return new Connection(const_cast(this));
}
EventThread::Connection::Connection(
const sp& eventThread)
: count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}
注意 count的初始值是-1。
在EventThread::Connection
的onFirstConnection
中,会将Connection
的实例传给EventThread
,并加到其成员变量mDisplayEventConnections
:
void EventThread::Connection::onFirstRef() {
mEventThread->registerDisplayEventConnection(this);
}
status_t EventThread::registerDisplayEventConnection(
const sp& connection) {
Mutex::Autolock _l(mLock);
mDisplayEventConnections.add(connection);
if (!mFirstConnectionInited) {
// additional external displays can't be enumerated by default,
// need to report additional hotplug to listeners
for (int32_t type = DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES;
type < (int32_t)mHotplugEvent.size(); type++) {
if (mHotplugEvent[type].hotplug.connected) {
connection->postEvent(mHotplugEvent[type]);
}
}
mFirstConnectionInited = true;
}
mCondition.broadcast();
return NO_ERROR;
}
当EventThread::threadLoop()
运行起来后,首先会执行EventThread::waitForEvent()
方法:
Vector< sp > EventThread::waitForEvent(
DisplayEventReceiver::Event* event)
{
Mutex::Autolock _l(mLock);
Vector< sp > signalConnections;
do {
bool eventPending = false;
bool waitForVSync = false;
size_t vsyncCount = 0;
nsecs_t timestamp = 0;
for (int32_t i=0 ; i<(int32_t)mVSyncEvent.size(); i++) {
timestamp = mVSyncEvent[i].header.timestamp;
if (timestamp) {
// we have a vsync event to dispatch
if (mInterceptVSyncs) {
mFlinger.mInterceptor.saveVSyncEvent(timestamp);
}
*event = mVSyncEvent[i];
mVSyncEvent[i].header.timestamp = 0;
vsyncCount = mVSyncEvent[i].vsync.count;
break;
}
}
if (!timestamp) {
// no vsync event, see if there are some other event
eventPending = !mPendingEvents.isEmpty();
if (eventPending) {
// we have some other event to dispatch
*event = mPendingEvents[0];
mPendingEvents.removeAt(0);
}
}
// find out connections waiting for events
size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i connection(mDisplayEventConnections[i].promote());
if (connection != NULL) {
bool added = false;
if (connection->count >= 0) {
// we need vsync events because at least
// one connection is waiting for it
waitForVSync = true;
if (timestamp) {
// we consume the event only if it's time
// (ie: we received a vsync event)
if (connection->count == 0) {
// fired this time around
connection->count = -1;
signalConnections.add(connection);
added = true;
} else if (connection->count == 1 ||
(vsyncCount % connection->count) == 0) {
// continuous event, and time to report it
signalConnections.add(connection);
added = true;
}
}
}
if (eventPending && !timestamp && !added) {
// we don't have a vsync event to process
// (timestamp==0), but we have some pending
// messages.
signalConnections.add(connection);
}
} else {
// we couldn't promote this reference, the connection has
// died, so clean-up!
mDisplayEventConnections.removeAt(i);
--i; --count;
}
}
// Here we figure out if we need to enable or disable vsyncs
if (timestamp && !waitForVSync) {
// we received a VSYNC but we have no clients
// don't report it, and disable VSYNC events
disableVSyncLocked();
} else if (!timestamp && waitForVSync) {
// we have at least one client, so we want vsync enabled
// (TODO: this function is called right after we finish
// notifying clients of a vsync, so this call will be made
// at the vsync rate, e.g. 60fps. If we can accurately
// track the current state we could avoid making this call
// so often.)
enableVSyncLocked();
}
// note: !timestamp implies signalConnections.isEmpty(), because we
// don't populate signalConnections if there's no vsync pending
if (!timestamp && !eventPending) {
// wait for something to happen
if (waitForVSync) {
// This is where we spend most of our time, waiting
// for vsync events and new client registrations.
//
// If the screen is off, we can't use h/w vsync, so we
// use a 16ms timeout instead. It doesn't need to be
// precise, we just need to keep feeding our clients.
//
// We don't want to stall if there's a driver bug, so we
// use a (long) timeout when waiting for h/w vsync, and
// generate fake events when necessary.
bool softwareSync = mUseSoftwareVSync;
nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
if (!softwareSync) {
ALOGW("Timed out waiting for hw vsync; faking it");
}
// FIXME: how do we decide which display id the fake
// vsync came from ?
mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
mVSyncEvent[0].vsync.count++;
}
} else {
// Nobody is interested in vsync, so we just want to sleep.
// h/w vsync should be disabled, so this will wait until we
// get a new connection, or an existing connection becomes
// interested in receiving vsync again.
mCondition.wait(mLock);
}
}
} while (signalConnections.isEmpty());
// here we're guaranteed to have a timestamp and some connections to signal
// (The connections might have dropped out of mDisplayEventConnections
// while we were asleep, but we'll still have strong references to them.)
return signalConnections;
}
初次运行waitForEvent()
时,由于EventThread::onVSyncEvent()
和EventThread::onHotplugReceived()
方法都没有被调用。因此经过循环:
for (int32_t i=0 ; i<(int32_t)mVSyncEvent.size(); i++) {
之后,timestamp的值还是0。同样地,mPendingEvents
为空,因此eventPending=false
.
前面提到,在Connection
的onFirstRef()
方法中,会将自己加到mDisplayEventConnections
中。因此在这里,mDisplayEventConnections.size()=1
。而EventThread::Connection的构造方法中,其成员count的初始值为-1。因此代码块:
if (connection->count >= 0) {
...
}
不会执行到,进而waitForVSync=false
.
于是执行代码:
if (!timestamp && !eventPending) {
if (waitForVSync) {
} else {
mCondition.wait(mLock);
}
EventThread线程会一直等待下去(这里没有Timeout).
ventThread::Connection类是BnDisplayEventConnection的服务端,其客户端IDisplayEventConnection开放出来的接口只有三个:
class IDisplayEventConnection : public IInterface {
public:
DECLARE_META_INTERFACE(DisplayEventConnection)
/*
* stealReceiveChannel() returns a BitTube to receive events from. Only the receive file
* descriptor of outChannel will be initialized, and this effectively "steals" the receive
* channel from the remote end (such that the remote end can only use its send channel).
*/
virtual status_t stealReceiveChannel(gui::BitTube* outChannel) = 0;
/*
* setVsyncRate() sets the vsync event delivery rate. A value of 1 returns every vsync event.
* A value of 2 returns every other event, etc. A value of 0 returns no event unless
* requestNextVsync() has been called.
*/
virtual status_t setVsyncRate(uint32_t count) = 0;
/*
* requestNextVsync() schedules the next vsync event. It has no effect if the vsync rate is > 0.
*/
virtual void requestNextVsync() = 0; // Asynchronous
};
其中用于控制EventThread的接口是setVsyncRate()
和requestNextVsync()
. 需要注意这里的注释:
再来看EventThread::Connection中这两个接口的实现:
void EventThread::setVsyncRate(uint32_t count,
const sp& connection) {
if (int32_t(count) >= 0) { // server must protect against bad params
Mutex::Autolock _l(mLock);
const int32_t new_count = (count == 0) ? -1 : count;
if (connection->count != new_count) {
connection->count = new_count;
mCondition.broadcast();
}
}
}
void EventThread::requestNextVsync(
const sp& connection) {
Mutex::Autolock _l(mLock);
mFlinger.resyncWithRateLimit();
if (connection->count < 0) {
connection->count = 0;
mCondition.broadcast();
}
}
这两个方法都会设置Connection类中的count成员变量(即vsync rate). 接下来先研究requestNextVsync()被调用后waitForEvent()的情况.
EventThread::requestNextVsync()
会把EventThread::Connection
的count
的值赋为0并唤醒EventThread
线程。由于waitForEvent()
方法的主体是一个do...while (signalConnections.isEmpty())
循环,而signalConnections
依然为空,所以当线程被唤醒之后,还是从waitForEvent()
继续.
此时timestamp依然为0,eventPending也依然为false。但由于connection->count的值变成了0,因此会执行如下的代码块
if (connection->count >= 0) {
// we need vsync events because at least
// one connection is waiting for it
waitForVSync = true;
if (timestamp) {
// we consume the event only if it's time
// (ie: we received a vsync event)
if (connection->count == 0) {
// fired this time around
connection->count = -1;
signalConnections.add(connection);
added = true;
} else if (connection->count == 1 ||
(vsyncCount % connection->count) == 0) {
// continuous event, and time to report it
signalConnections.add(connection);
added = true;
}
}
}
可以看到此时waitForVSync=true
. 由于timestamp=0
而waitForVSync=true
,因此满足条件
else if (!timestamp && waitForVSync) {
从而会执行EventThread::enableVSyncLocked()
. 且满足如下条件:
if (!timestamp && !eventPending) {
if (waitForVSync) {
bool softwareSync = mUseSoftwareVSync;
nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
mVSyncEvent[0].vsync.count++;
}
}
}
由于mUseSoftwareVSync
的值为false,因此这里设置timeout为1秒钟并执行:
mCondition.waitRelative(mLock, timeout)
这里有三种情况:
EventThread::requestNextVsync()
被调用,从EventThread::requestNextVsync()
的实现可以看到,由于此时EventThread::Connection
的count
成员的值依然为0,那么该方法是不能唤醒EventThread线程的.do...while
循环. 然后回到EventThread::threadLoop(),执行Connection::postEvent()方法,向Connection的成员变量发送消息:status_t EventThread::Connection::postEvent(
const DisplayEventReceiver::Event& event) {
...
ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
由于EventThread继承自system/core中的Thread类,因此当postEvent()方法执行完,然后threadLoop()方法返回true之后,会继续执行threadLoop()方法。此时waitForEvent()
方法中,timestamp的值为0,count的值为-1,进而waitForVSync的值为false,那么会执行到
mCondition.wait(mLock);
EventThread会一直等待下去。直到下一个requestNextVsync()发生.
当setVSyncEnable()
方法执行后,Vsync事件就可以从DispSyncThread
起,顺序执行:
在EventThread::onVSyncEvent()
中,设置了mVSyncEvent
并唤醒了EventThread
线程。此时再执行waitForEvent()
时,timestamp有值,而Connection的count值不确定:
count的值为-1。说明在onVSyncEvent()被调用之前已经发生了TIMEOUT,EventThread处于一直等待的状态。此时满足条件timestamp && !waitForVSync
因此会执行disableVSyncLocked():
void EventThread::disableVSyncLocked() {
if (mVsyncEnabled) {
mVsyncEnabled = false;
mVSyncSource->setVSyncEnabled(false);
mDebugVsyncEnabled = false;
}
}
该方法调用了DispSyncSource的setVSyncEnabled(false)
方法,最终会执行DispSyncThread的removeEventListener()
方法,从mEventListeners中移除了DispSyncSource这个Callback,那么DispSyncThread::fireCallbackInvocations()
方法是不会传给EventThread了。
继续执行waitForEvent()
,由于signalConnections
内容还是为空,因此还是在do…while()的循环里面。再次开始循环时,timestamp的值已经是0。这是因为上一个循环中,当给timestamp赋值之后,会设置mVSyncEvent[i].header.timestamp
的值为0.
此时waitForEvent()最终会走到:
mCondition.wait(mLock);
从而EventThread线程一直等待下去.
count的值为0。说明waitForEvent()此时的状态是停留在:
mCondition.waitRelative(mLock, timeout)
并且还没有超时。当本线程被唤醒之后,会重新执行do…while()循环。此时timestamp的值非0,而count的值为0,此时会把waitForVSync赋为true,count的值赋为-1,并把当前Connection的实例添加到signalConnections中。这样signalConnections非空,走出do…while()循环。然后EventThread::threadLoop()调用postEvent()方法。接下来再次执行waitForEvent(),最终会执行:
mCondition.wait(mLock);
EventThread会一直等待下去。直到下一个requestNextVsync()发生.
第一次执行waitForEvent()时,会执行enableVSyncLocked()。而无须等待requestNextVsync()的发生。然后waitForEvent()会执行到mCondition.waitRelative()。接下来有3种情况:
onVSyncEvent()
比超时先发生:waitForEvent()
会从do…while()中跳出来,并执行EventThread::postEvent()方法。再次执行waitForEvent()
时,会执行到mCondition.waitRelative()
.onVSyncEvent()
比超时晚发生:当超时发生时,waitForEvent()
会从do...while()
中跳出来,并执行EventThread::postEvent()
方法。再次执行waitForEvent()
时,会执行到mCondition.waitRelative()
,而非mCondition.wait()
。接下来onVSyncEvent()
发生时,情况与2同。可以看到,当count的值为1时,产生的效果是消除了对requestNextVsync()方法的依赖.
于是可以看到每次VSYNC事件到来之后,都能最终调用到SurfaceFlinger::handleMessageInvalidate()
EventThread.setVsyncRate(1)
可以使EventThread不再依赖requestNextVsync()
. 进而每次VSYNC事件到来之后,都能最终调用到SurfaceFlinger::handleMessageInvalidate()
.