http://blog.csdn.net/lewif/article/details/50573397
- android44中的实现
- 整体流程
- HWComposer对象的建立
- EventControlThread闸刀的建立
- DispSync和DispSyncThread
- DispSyncSource和EventThread
- 完整走一遍
Android 4.1一个很大的更新是Project Butter,黄油计划,为了解决用户交互体验差的问题(Jelly Bean iscrazy fast)。
主要包括两部分:Vsync和Triple Buffering。(以下surfaceflinger简写为SF)
Vsync,垂直同步,HWC利用硬件或者软件产生的持续Vsync信号去触发SF和UI去做绘图相关的工作,让绘图工作充分利用每个Vsync信号间隔的时间;
Triple Buffering,虽然有Vsync,细想肯定还是无法避免Jank,三缓冲会将Jank几率降到最小,当然如果出现第一次Jack肯定避免不了。
DispSync maintainsa model of the periodic hardware-based vsync events of a
display and usesthat model to execute period callbacks at specific phase
offsets from thehardware vsync events. The model isconstructed by
feedingconsecutive hardware event timestamps to the DispSync object via
the addResyncSamplemethod.
在4.4中,新加了个DispSync,从上面的解释,DispSync根据特定屏幕硬件的vsync信号创建一个模型,利用这个模型去做定期的回调工作,回调的时间比vsync信号的到来稍晚一点,有个偏移量。为何要有个偏移量呢?因为这个模型会驱动多个事件,例如SF去合成图形,如果多个事件一起工作就会出现抢占cpu。所以对每个事件的偏移量设置为不同的,就能减缓这种问题的存在。
目前只是看代码的实现流程,还没对参数在真实机器上调试过,效果待观察。
上面图形是Vsync信号从产生到驱动SF去工作的一个过程,其中绿色部分是HWC中的Vsync信号软件模拟进程,其他都是SF中的:
其中包含4个线程,EventControlThread,就像是Vsync信号产生的闸刀,当然闸刀肯定需要人去打开和关闭,这个人就是SF;
VsyncThread,下面的代码只介绍软件模拟的Vsync信号,这个线程主要工作就是循环定期产生信号,然后调用SF中的函数,这就相当于触发了;
DispSyncThread,是Vsync信号的模型,VsyncThread首先触发DispSyncThread,然后DispSyncThread再去驱动其他事件,它就是Vsync在SF中的代表;
EventThread,具体的事件线程,由DispSyncThread去驱动。
主要步骤可以分为8步,下面的展开也基本是基于这个步骤。
在SF的init()中,
mHwc = new HWComposer(this,
*static_cast<HWComposer::EventHandler*>(this));
由于SF也继承了HWComposer::EventHandler,所以上面的构造函数的输入都是SF对象。
class SurfaceFlinger : publicBnSurfaceComposer,
private IBinder::DeathRecipient,
private HWComposer::EventHandler{
}
在构造函数中,对mFlinger和mEventHandler赋值,这里不涉及Vsync的硬件实现和Gralloc,其实硬件实现最终调用的SF中的函数和软件是一样的。只关注最后一行软件实现,新建了一个VSyncThread对象,VSyncThread继承了Thread,是个线程。
HWComposer::HWComposer(
constsp<SurfaceFlinger>& flinger,
EventHandler& handler)
:mFlinger(flinger),
mFbDev(0), mHwc(0), mNumDisplays(1),
mCBContext(new cb_context),
mEventHandler(handler),
mDebugForceFakeVSync(false)
{
//Vsync软件实现
if(needVSyncThread) {
// we don't have VSYNC support, we needto fake it
mVSyncThread = new VSyncThread(*this);
}
}
构造函数中,设置了mRefreshPeriod,从HWC_DISPLAY_PRIMARY,从主屏幕获取。
HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
: mHwc(hwc), mEnabled(false),
mNextFakeVSync(0),
mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY))
{
}
注意,由于sp<VSyncThread>mVSyncThread;,是个sp指针,第一次引用的时候回去调用onFirstRef() ,一贯的伎俩,启动了这个线程。
void HWComposer::VSyncThread::onFirstRef() {
run("VSyncThread", PRIORITY_URGENT_DISPLAY+PRIORITY_MORE_FAVORABLE);
}
那么我们需要看下线程函数的实现,
boolHWComposer::VSyncThread::threadLoop() {
{ // scope for lock
Mutex::Autolock _l(mLock);
//①
//初始为false,阻塞
while (!mEnabled) {
mCondition.wait(mLock);
}
}
const nsecs_t period= mRefreshPeriod;
const nsecs_t now =systemTime(CLOCK_MONOTONIC);
nsecs_tnext_vsync = mNextFakeVSync;
nsecs_t sleep =next_vsync - now;
if (sleep < 0) {
// we missed, find where the next vsyncshould be
sleep =(period - ((now - next_vsync) % period));
next_vsync= now + sleep;
}
mNextFakeVSync= next_vsync + period;
struct timespec spec;
spec.tv_sec = next_vsync / 1000000000;
spec.tv_nsec = next_vsync % 1000000000;
int err;
do {
err =clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
} while (err<0 &&errno == EINTR);
if (err == 0) {
//②
//去驱动SF
mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
}
returntrue;
}
上面的代码,我们需要注意两个地方:
1. mEnabled默认为false,mCondition在这里阻塞,直到有人调用了signal(),同时mEnabled为true。
2. 如果阻塞解开,则会定期休眠,然后去驱动SF,这就相当于产生了持续的Vsync信号。
到目前为止,HWC中新建了一个线程VSyncThread,阻塞中,下面我们看下打开Vsync开关的闸刀是如何建立的,以及何处去开闸刀。
在SF的init()中,有下面的代码,
mEventControlThread= newEventControlThread(this);
mEventControlThread->run("EventControl",PRIORITY_URGENT_DISPLAY);
新建了一个EventControlThread对象,同时启动这个线程,构造函数很简单,mVsyncEnabled默认为false,闸刀默认是关闭的。
EventControlThread::EventControlThread(constsp<SurfaceFlinger>& flinger):
mFlinger(flinger),
mVsyncEnabled(false) {
}
下面看下线程函数,
bool EventControlThread::threadLoop() {
Mutex::Autolock lock(mMutex);
boolvsyncEnabled = mVsyncEnabled;
mFlinger->eventControl(HWC_DISPLAY_PRIMARY,SurfaceFlinger::EVENT_VSYNC,
mVsyncEnabled);
while (true) {
//①
//mCond阻塞,
status_terr = mCond.wait(mMutex);
if (err != NO_ERROR) {
ALOGE("error waiting for new events: %s(%d)",
strerror(-err), err);
returnfalse;
}
//②
//vsyncEnabled 开始和mVsyncEnabled都为false,如果有其他地方改变了mVsyncEnabled
//会去调用SF的eventControl函数
if (vsyncEnabled != mVsyncEnabled){
mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);
vsyncEnabled = mVsyncEnabled;
}
}
returnfalse;
}
其中,
1. 在mCond阻塞,可以看到外面是个死循环,while(true),所以如果有其他地方对这个mCond调用了signal,执行完下面的代码又会阻塞
2. 解除阻塞后,如果vsyncEnabled !=mVsyncEnabled,也就是开关状态不同,由开到关和由关到开,都回去调用mFlinger->eventControl,调用完成后把这次的开关状态保存,vsyncEnabled =mVsyncEnabled;,与下次做比较。
从上面我们能明显认识到EventControlThread线程,其实就起到了个闸刀的作用,等待着别人去开、关。
下面研究下开关函数,
voidSurfaceFlinger::eventControl(int disp, intevent, int enabled) {
ATRACE_CALL();
getHwComposer().eventControl(disp, event, enabled);
}
前面在SF的init()中已经建立了一个HWC,这里就是mHwc,
voidHWComposer::eventControl(int disp, intevent, int enabled) {
....
//只看最后一句,mVSyncThread就是HWC中的软件模拟Vsync线程
if (err ==NO_ERROR && mVSyncThread != NULL) {
mVSyncThread->setEnabled(enabled);
}
}
将软件模拟线程VSyncThread的mCondition释放,这时候VSyncThread就会定期产生“信号”,去驱动SF了。
void HWComposer::VSyncThread::setEnabled(bool enabled) {
Mutex::Autolock _l(mLock);
//mEnabled和enabled不同,即从开到关和从关到开
if (mEnabled != enabled) {
mEnabled = enabled;
//释放mCondition
mCondition.signal();
}
}
那么EventControlThread这个闸刀到底在哪被SF打开的呢?
在SF的init()中调用了initializeDisplays();
voidSurfaceFlinger::initializeDisplays() {
classMessageScreenInitialized : public MessageBase {
SurfaceFlinger* flinger;
public:
MessageScreenInitialized(SurfaceFlinger*flinger) : flinger(flinger) { }
virtualbool handler() {
flinger->onInitializeDisplays();
returntrue;
}
};
sp<MessageBase> msg = new MessageScreenInitialized(this);
postMessageAsync(msg); // we may be called from main thread,use async message
}
发送异步消息,前面一节已经分析过处理流程了,即会执行handler(),flinger->onInitializeDisplays();,
void SurfaceFlinger::onInitializeDisplays() {
//主要看这个
onScreenAcquired(getDefaultDisplayDevice());
}
void SurfaceFlinger::onScreenAcquired(const sp<const DisplayDevice>& hw) {
if (type< DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
// built-in display, tell the HWC
getHwComposer().acquire(type);
//主屏幕,Primary,回去调用
if (type== DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: eventthread only knows aboutthe main display right now
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true);
}
}
mVisibleRegionsDirty =true;
repaintEverything();
}
接着调用resyncToHardwareVsync(true),从字面意思就是能看出,是去和HardwareVsync去同步,参数为true。
void SurfaceFlinger::resyncToHardwareVsync(boolmakeAvailable) {
Mutex::Autolock_l(mHWVsyncLock);
if (makeAvailable){
mHWVsyncAvailable =true;
} elseif (!mHWVsyncAvailable) {
ALOGE("resyncToHardwareVsync called whenHW vsync unavailable");
return;
}
const nsecs_tperiod =
getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
mPrimaryDispSync.reset();
mPrimaryDispSync.setPeriod(period);
if (!mPrimaryHWVsyncEnabled) {
mPrimaryDispSync.beginResync();
//eventControl(HWC_DISPLAY_PRIMARY,SurfaceFlinger::EVENT_VSYNC, true);
//打开闸刀,
mEventControlThread->setVsyncEnabled(true);
mPrimaryHWVsyncEnabled =true;
}
}
很明显,代码中调用了mEventControlThread->setVsyncEnabled(true);,
voidEventControlThread::setVsyncEnabled(bool enabled) {
Mutex::Autolocklock(mMutex);
mVsyncEnabled =enabled;
//释放mCond
mCond.signal();
}
可以看到,在这里释放了前面的mCond,让EventControlThread去调用mFlinger->eventControl()函数,从而去HWC中打开Vsync开关。
上面分析的这些对应了最开始图的步骤①。
下面开始分析,android 4.4中对hardware Vsync模型的建立,在SF类中有一个field为DispSyncmPrimaryDispSync;,因此在SF类建立的时候,会去在栈上生成这个对象,首先看下构造函数,
DispSync::DispSync() {
//①
//创建DispSyncThread线程,并运行
mThread =newDispSyncThread();
mThread->run("DispSync",PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
//线程自己运行去了,SF主线程继续
....
}
在DispSync的构造函数中,创建DispSyncThread线程,并运行,DispSyncThread的构造函数将mStop设置为false,mPeriod设置为0,
DispSyncThread():
mStop(false),
mPeriod(0),
mPhase(0),
mWakeupLatency(0) {
}
线程函数,
virtualbool threadLoop() {
status_terr;
nsecs_t now= systemTime(SYSTEM_TIME_MONOTONIC);
nsecs_tnextEventTime = 0;
while (true) {
Vector<CallbackInvocation> callbackInvocations;
nsecs_ttargetTime = 0;
{ // Scope for lock
Mutex::Autolock lock(mMutex);
if (mStop) {
returnfalse;
}
//①
//mCond阻塞,当signal,同时mPeriod 不为0时,继续往下执行,
if (mPeriod == 0) {
err = mCond.wait(mMutex);
if (err !=NO_ERROR) {
ALOGE("errorwaiting for new events: %s (%d)",
strerror(-err), err);
returnfalse;
}
continue;
}
nextEventTime = computeNextEventTimeLocked(now);
targetTime = nextEventTime;
bool isWakeup = false;
if (now <targetTime) {
err = mCond.waitRelative(mMutex, targetTime - now);
if (err ==TIMED_OUT) {
isWakeup = true;
} elseif (err !=NO_ERROR) {
ALOGE("errorwaiting for next event: %s (%d)",
strerror(-err),err);
returnfalse;
}
}
now = systemTime(SYSTEM_TIME_MONOTONIC);
if (isWakeup) {
mWakeupLatency = ((mWakeupLatency * 63) +
(now - targetTime))/ 64;
if (mWakeupLatency> 500000) {
// Don't correct by more than 500 us
mWakeupLatency = 500000;
}
if(traceDetailedInfo) {
ATRACE_INT64("DispSync:WakeupLat", now -nextEventTime);
ATRACE_INT64("DispSync:AvgWakeupLat",mWakeupLatency);
}
}
//②
//很重要,这是模型线程去驱动SF做事的关键
callbackInvocations = gatherCallbackInvocationsLocked(now);
}
if(callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations);
}
}
returnfalse;
}
主要2点:
1. 模型线程DispSyncThread阻塞在mCond,等待别人给mPeriod 赋值和signal;
2. gatherCallbackInvocationsLocked()和fireCallbackInvocations()函数是模型线程DispSyncThread驱动SF去做事的关键,这里先不介绍,对应开始图形中的④。
3.
新建的DispSyncThread线程,目前被阻塞,先不管,我们先看模型DispSync和要驱动的事件(DispSyncSource,EventThread等)是如何联系起来的。
到这里我们先打住,思考个问题:
如果自己写代码,在同一进程中,我们如何实现这种多个事件之间驱动?我认为多线程就是最好的方式,然后再加上同步机制和回调。而android Vsync的实现我认为也是用了这种实现方式,模型DispSync和DispSyncThread线程相结合,而驱动事件由DispSyncSource和EventThread线程相结合。
在SF的init函数中,有如下代码,涉及到了DispSync,DispSyncSource,EventThread和mEventQueue的纠缠关系。我们可以看到在驱动事件DispSyncSource的构造中,我们输入了模型DispSync,这样就为回调创造了机会,下面看具体如何实现的。
//把模型mPrimaryDispSync(DispSync)保存在DispSyncSource中
sp<VSyncSource> sfVsyncSrc = newDispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, false);
mSFEventThread= newEventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
先看下DispSyncSource对象的建立,其实这个对象从名字上看就是模型所驱动的事件,构造函数中主要设置了模型mDispSync(dispSync),以及触发时间的偏移量mPhaseOffset(phaseOffset)。
DispSyncSource(DispSync*dispSync, nsecs_t phaseOffset, bool traceVsync) :
mValue(0),
mPhaseOffset(phaseOffset),
mTraceVsync(traceVsync),
mDispSync(dispSync) {}
继续mSFEventThread =new EventThread(sfVsyncSrc);,
EventThread::EventThread(constsp<VSyncSource>& src)
:mVSyncSource(src),
mUseSoftwareVSync(false),
mVsyncEnabled(false),
mDebugVsyncEnabled(false) {
//DisplayEventReceiver::EventmVSyncEvent[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
//i<2
for (int32_t i=0;i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[i].header.id = 0;
mVSyncEvent[i].header.timestamp = 0;
mVSyncEvent[i].vsync.count = 0;
}
}
在EventThread的构造中,输入了与之对应的DispSyncSource,同时把mUseSoftwareVSync和mVsyncEnabled, mDebugVsyncEnabled都设置为false,同时初始化了一个DisplayEventReceiver类型的数组,从名字上看这是display event,也就是Vsync信号,接收到的Vsync信号相关的一个数组。把type设置为DISPLAY_EVENT_VSYNC。
注意,又是小伎俩,把EventThread线程启动起来,
//在onFirstRef中启动线程,相当于mEventThread.run();,把这个线程启动起来
void EventThread::onFirstRef() {
run("EventThread",PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}
那么我们需要看下线程函数,
boolEventThread::threadLoop() {
DisplayEventReceiver::Event event;
Vector< sp<EventThread::Connection>> signalConnections;
//①
//等待事件
signalConnections = waitForEvent(&event);
// ②
// 把事件分发给listener
// dispatch events to listeners...
const size_t count =signalConnections.size();
for (size_t i=0 ; i<count ;i++) {
constsp<Connection>& conn(signalConnections[i]);
// now see if we still need to reportthis event
// ③
// 调用postEvent
status_terr = conn->postEvent(event);
if (err == -EAGAIN|| err == -EWOULDBLOCK) {
// The destination doesn't accept eventsanymore, it's probably
// full. For now, we just drop theevents on the floor.
// FIXME: Note that some events cannotbe dropped and would have
// to be re-sent later.
// Right-now we don't have the abilityto do this.
ALOGW("EventThread: dropping event (%08x)for connection %p",
event.header.type,conn.get());
} elseif (err < 0) {
// handle any other error on the pipe as fatal. the only
// reasonable thing to do is to clean-upthis connection.
// The most common error we'll get hereis -EPIPE.
removeDisplayEventConnection(signalConnections[i]);
}
}
returntrue;
}
上面重点主要有:
1. 等待事件到来
2. 把事件分发给listener
3. 调用conn->postEvent(event)
2和3后面再看,先看1,难道EventThread线程上来直接也休眠了?
Vector< sp<EventThread::Connection> >EventThread::waitForEvent(
DisplayEventReceiver::Event* event)
{
Mutex::Autolock_l(mLock);
Vector<sp<EventThread::Connection> > signalConnections;
do {
booleventPending = false;
boolwaitForVSync = false;
size_tvsyncCount = 0;
nsecs_ttimestamp = 0;
//上面初始化EventThread时候,都是0
for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; i++) {
timestamp = mVSyncEvent[i].header.timestamp;
if (timestamp) {
// we have a vsync event to dispatch
*event = mVSyncEvent[i];
mVSyncEvent[i].header.timestamp = 0;
vsyncCount = mVSyncEvent[i].vsync.count;
break;
}
}
if (!timestamp) {
// no vsync event, see if there are someother event
eventPending = !mPendingEvents.isEmpty();
//初始为假
if (eventPending){
// we have some other event to dispatch
*event = mPendingEvents[0];
mPendingEvents.removeAt(0);
}
}
// SortedVector< wp<Connection>> mDisplayEventConnections;
// 初始也是空的
// find out connections waiting forevents
size_t count =mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
sp<Connection> connection(mDisplayEventConnections[i].promote());
if (connection !=NULL) {
bool added = false;
if(connection->count >= 0) {
// we need vsyncevents because at least
// oneconnection is waiting for it
waitForVSync = true;
if (timestamp) {
// we consumethe event only if it's time
// (ie: wereceived a vsync event)
if (connection->count == 0) {
// fired this time around
connection->count = -1;
signalConnections.add(connection);
added = true;
} elseif(connection->count == 1 ||
(vsyncCount %connection->count) == 0) {
// continuous event, and time to reportit
signalConnections.add(connection);
added = true;
}
}
}
if (eventPending&& !timestamp && !added) {
// we don't havea 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 toenable or disable vsyncs
if (timestamp&& !waitForVSync) {
// we received a VSYNC but we have noclients
// don't report it, and disable VSYNCevents
disableVSyncLocked();
} elseif (!timestamp&& waitForVSync) {
// we have at least one client, so wewant vsync enabled
// (TODO: this function is called rightafter we finish
// notifying clients of a vsync, so thiscall will be made
// at the vsync rate, e.g. 60fps. If we can accurately
// track the current state we couldavoid making this call
// so often.)
enableVSyncLocked();
}
// note: !timestamp impliessignalConnections.isEmpty(), because we
// don't populate signalConnections ifthere's no vsync pending
if (!timestamp&& !eventPending) {
// wait for something to happen
if (waitForVSync){
// This is where we spend most of ourtime, waiting
// for vsync events and new clientregistrations.
//
// If the screen is off, we can't useh/w vsync, so we
// use a 16ms timeout instead. It doesn't need to be
// precise, we just need to keep feedingour clients.
//
// We don't want to stall if there's adriver bug, so we
// use a (long) timeout when waiting forh/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 outwaiting for hw vsync; faking it");
}
// FIXME: how do we decide which display idthe fake
// vsync camefrom ?
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 wejust want to sleep.
// h/w vsync should be disabled, so thiswill wait until we
// get a new connection, or an existingconnection becomes
// interested in receiving vsync again.
// ①
// 所以EventThread初始的时候会在这阻塞
mCondition.wait(mLock);
}
}
//②
} while(signalConnections.isEmpty());
//因为mCondition有可能异常返回,所以要看下这个while,就知道何时mCondition被正常的signal
//如果signalConnections不为空了,这时候就会从while中退出来
//也就是上面的mDisplayEventConnections有东西了
// here we're guaranteed to have atimestamp and some connections to signal
// (The connections might have droppedout of mDisplayEventConnections
// while we were asleep, but we'll stillhave strong references to them.)
returnsignalConnections;
}
上面的代码主要关注2点:
1. 初始的时候,mCondition会阻塞
2. 因为mCondition有可能异常返回,所以要看下外围的while循环,就知道何时mCondition会被signal。即使mCondition异常返回,也会再去判断signalConnections是否为空。空的话继续阻塞,如果signalConnections不为空了,这时候就会从while中退出来,也就是上面的mDisplayEventConnections有东西了。所以mDisplayEventConnections需要留意何时赋值啦。
至此,创建了一个mSFEventThread =new EventThread(sfVsyncSrc);,也阻塞着了。。
下面继续看mEventQueue.setEventThread(mSFEventThread);,会不会柳暗花明又一村呢?
这里EventThread和SF主线程的MessageQueue又纠缠到了一起。
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
mEventThread = eventThread;
//①
mEvents = eventThread->createEventConnection();
//②
mEventTube = mEvents->getDataChannel();
//③
mLooper->addFd(mEventTube->getFd(), 0,ALOOPER_EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
}
上面代码主要看三点:
首先, eventThread->createEventConnection(),新建了一个Connection对象,
sp<EventThread::Connection>EventThread::createEventConnection() const {
returnnew Connection(const_cast<EventThread*>(this));
}
新建的 Connection 对象如下图所示,Connection中保存了了一个EventThread对象,和一个生成的BitTube对象mChannel,下面看下Connection的构造函数,
EventThread::Connection::Connection(
constsp<EventThread>& eventThread)
: count(-1), mEventThread(eventThread), mChannel(newBitTube())
{
}
调用了BitTube的无参构造函数,
BitTube::BitTube()
: mSendFd(-1), mReceiveFd(-1)
{
init(DEFAULT_SOCKET_BUFFER_SIZE,DEFAULT_SOCKET_BUFFER_SIZE);
}
//就是建立一个域套接字对,一个读,一个写,mSendFd和mReceiveFd ,
void BitTube::init(size_trcvbuf, size_t sndbuf) {
int sockets[2];
if(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
size_t size= DEFAULT_SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
setsockopt(sockets[1], SOL_SOCKET,SO_SNDBUF, &sndbuf, sizeof(sndbuf));
// sine we don't use the "returnchannel", we keep it small...
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(sockets[0], F_SETFL, O_NONBLOCK);
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
mReceiveFd= sockets[0];
mSendFd =sockets[1];
} else {
mReceiveFd= -errno;
ALOGE("BitTube: pipe creation failed(%s)", strerror(-mReceiveFd));
}
}
继续回到MessageQueue::setEventThread中,mEvents =eventThread->createEventConnection();,又是sp赋值,得小心onFirstRef(),这里的处理非常关键。
void EventThread::Connection::onFirstRef() {
// NOTE: mEventThread doesn't hold astrong reference on us
mEventThread->registerDisplayEventConnection(this);
}
前面提到,EventThread一直阻塞在waitForEvent中,正是这个mCondition,这里也对mDisplayEventConnections添加了东西,不为空了。
status_t EventThread::registerDisplayEventConnection(
const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock);
//把connection添加到mDisplayEventConnections
mDisplayEventConnections.add(connection);
//mCondition解除
mCondition.broadcast();
return NO_ERROR;
}
为了方便,这里再把waitForEvent()函数列出来,
Vector< sp<EventThread::Connection> >EventThread::waitForEvent(
DisplayEventReceiver::Event* event)
{
Mutex::Autolock_l(mLock);
Vector<sp<EventThread::Connection> > signalConnections;
do {
booleventPending = false;
boolwaitForVSync = false;
size_tvsyncCount = 0;
nsecs_t timestamp = 0;
for (int32_t i=0 ;i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
timestamp = mVSyncEvent[i].header.timestamp;
if (timestamp) {
// we have a vsync event to dispatch
*event = mVSyncEvent[i];
mVSyncEvent[i].header.timestamp = 0;
vsyncCount = mVSyncEvent[i].vsync.count;
break;
}
}
//②
//这里timestamp 还是0
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);
}
}
//③
//有东西了,就是保存的Connection
// find out connections waiting forevents
size_t count =mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
sp<Connection> connection(mDisplayEventConnections[i].promote());
if (connection !=NULL) {
bool added = false;
if(connection->count >= 0) {
// we need vsyncevents because at least
// oneconnection is waiting for it
waitForVSync = true;
if (timestamp) {
// we consumethe event only if it's time
// (ie: wereceived a vsync event)
if(connection->count == 0) {
// fired this time around
connection->count = -1;
signalConnections.add(connection);
added = true;
} elseif(connection->count == 1 ||
(vsyncCount %connection->count) == 0) {
// continuous event, and time to reportit
signalConnections.add(connection);
added = true;
}
}
}
if (eventPending&& !timestamp && !added) {
// we don't havea 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 toenable or disable vsyncs
if (timestamp&& !waitForVSync) {
// we received a VSYNC but we have noclients
// don't report it, and disable VSYNC events
disableVSyncLocked();
} elseif (!timestamp&& waitForVSync) {
// we have at least one client, so wewant vsync enabled
// (TODO: this function is called rightafter we finish
// notifying clients of a vsync, so thiscall will be made
// at the vsync rate, e.g. 60fps. If we can accurately
// track the current state we couldavoid making this call
// so often.)
//④
//这次执行到这里了
enableVSyncLocked();
}
// note: !timestamp impliessignalConnections.isEmpty(), because we
// don't populate signalConnections ifthere's no vsync pending
if (!timestamp&& !eventPending) {
// wait for something to happen
if (waitForVSync){
// This is where we spend most of ourtime, waiting
// for vsync events and new clientregistrations.
//
// If the screen is off, we can't useh/w vsync, so we
// use a 16ms timeout instead. It doesn't need to be
// precise, we just need to keep feedingour clients.
//
// We don't want to stall if there's adriver bug, so we
// use a (long) timeout when waiting forh/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 outwaiting for hw vsync; faking it");
}
// FIXME: how do we decide which display id the fake
// vsync camefrom ?
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 wejust want to sleep.
// h/w vsync should be disabled, so thiswill wait until we
// get a new connection, or an existingconnection becomes
// interested in receiving vsync again.
// ①
// mCondition这次解开了
mCondition.wait(mLock);
}
}
} while(signalConnections.isEmpty());
// here we're guaranteed to have atimestamp and some connections to signal
// (The connections might have droppedout of mDisplayEventConnections
// while we were asleep, but we'll stillhave strong references to them.)
returnsignalConnections;
}
上面代码,主要看4点:
1. 建立Connection后,mCondition返回了;
2. 这里timestamp 还是0
3. mDisplayEventConnections非空了,将waitForVSync = true;
4. 所以会执行到enableVSyncLocked();。
继续看,enableVSyncLocked(),
voidEventThread::enableVSyncLocked() {
//初始为false
if(!mUseSoftwareVSync) {
// never enable h/w VSYNC when screen isoff
//初始为false
if(!mVsyncEnabled) {
//①
mVsyncEnabled = true;
mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));
//②
mVSyncSource->setVSyncEnabled(true);
mPowerHAL.vsyncHint(true);
}
}
mDebugVsyncEnabled = true;
}
主要看两点:
1. 将mVsyncEnabled 设为true,调用mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));,this为EventThread,既是调用DispSyncSource的setCallback,把mCallback设置为EventThread,
virtualvoid setCallback(constsp<VSyncSource::Callback>& callback) {
Mutex::Autolock lock(mMutex);
mCallback =callback;
}
2.调用mVSyncSource->setVSyncEnabled(true);,既是调用DispSyncSource的setVSyncEnabled,
,这里的this为DispSyncSource
virtualvoidsetVSyncEnabled(bool enable) {
// Do NOT lock the mutex here so as toavoid any mutex ordering issues
// with locking it in theonDispSyncEvent callback.
if (enable) {
//在硬件modelmDispSync中添加addEventListener,一个参数为偏移量,一个为DispSyncSource
status_t err = mDispSync->addEventListener(mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err !=NO_ERROR) {
ALOGE("errorregistering vsync callback: %s (%d)",
strerror(-err), err);
}
ATRACE_INT("VsyncOn", 1);
} else {
status_t err = mDispSync->removeEventListener(
static_cast<DispSync::Callback*>(this));
if (err !=NO_ERROR) {
ALOGE("errorunregistering vsync callback: %s (%d)",
strerror(-err), err);
}
ATRACE_INT("VsyncOn", 0);
}
}
从上面的代码可以看出,这里是将驱动事件DispSyncSource和硬件模型mDispSync建立起关系,继续,
status_t DispSync::addEventListener(nsecs_t phase,
const sp<Callback>& callback) {
Mutex::Autolock lock(mMutex);
return mThread->addEventListener(phase,callback);
}
status_taddEventListener(nsecs_t phase, const sp<DispSync::Callback>& callback) {
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i <mEventListeners.size(); i++) {
if(mEventListeners[i].mCallback == callback) {
return BAD_VALUE;
}
}
EventListener listener;
listener.mPhase = phase;
listener.mCallback = callback;
// We want to allow the firstmost futureevent to fire without
// allowing any past events tofire. Because
// computeListenerNextEventTimeLockedfilters out events within a half
// a period of the last event time, weneed to initialize the last
// event time to a half a period in thepast.
listener.mLastEventTime = systemTime(SYSTEM_TIME_MONOTONIC) - mPeriod / 2;
//把listener放到mEventListeners中,
mEventListeners.push(listener);
//释放mCond
mCond.signal();
return NO_ERROR;
}
这里可以看出,驱动事件DispSyncSource是硬件模型DispSync的“listener”,监听者,把两者联系了起来。并把DispSyncThread线程中的阻塞mCond解除,但是,前面我们分析过,还要mPeriod 非0,
if (mPeriod == 0) {
err = mCond.wait(mMutex);
if (err !=NO_ERROR) {
ALOGE("errorwaiting for new events: %s (%d)",
strerror(-err),err);
return false;
}
continue;
}
那么哪里给mPeriod 赋值呢?在SF的init中initializeDisplays()会调用resyncToHardwareVsync()函数,又调用
mPrimaryDispSync.setPeriod(period);
mPeriod 赋值后,已经不为0,
void DispSync::setPeriod(nsecs_t period){
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase =0;
//调用线程的更新模型函数
mThread->updateModel(mPeriod,mPhase);
}
Cond解除阻塞,
voidupdateModel(nsecs_t period, nsecs_t phase) {
Mutex::Autolock lock(mMutex);
mPeriod =period;
mPhase =phase;
//mCond阻塞解除
mCond.signal();
}
至此,DispSync中设置了监听者DispSyncSource,mPeriod 也不为0,硬件模型线程不再阻塞,不阻塞了干什么先不分析,继续回到前面的MessageQueue::setEventThread()函数,经过调用mEvents =eventThread->createEventConnection();完成了,
1. MessageQueue中保存了一个Connection,mEvents ;
2. EventThread中保存了这个Connection,mDisplayEventConnections.add(connection);
3. mVSyncSource->setCallback 把mCallback = callback 设置为EventThread
4. 在mDispSync中注册listener,放到DispSyncthread的mEventListeners中,这个listener的callback就是mVSyncSource,
listener.mPhase = phase;
listener.mCallback = callback;
接着继续MessageQueue::setEventThread()函数,调用,
mEventTube = mEvents->getDataChannel();
binder传数据,bp侧
virtual sp<BitTube>getDataChannel() const
{
Parceldata, reply;
data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
remote()->transact(GET_DATA_CHANNEL, data, &reply);
//返回的是一个包含接收描述符的parcel,在这里调用带参的BitTube构造函数,所以mEventTube只负责读
return new BitTube(reply);
}
bn侧
caseGET_DATA_CHANNEL: {
CHECK_INTERFACE(IDisplayEventConnection, data, reply);
sp<BitTube>channel(getDataChannel());
channel->writeToParcel(reply);
return NO_ERROR;
} break;
这样 mEventTube 中只包含了读 fd ,而 mEvents 这个 connection 中的 mChannel 只剩下写 fd ,两个依然是一对读写,,但是分开了,如下图所示继续调用,这里就是把mEventTube这个读tube注册到SF主线程的Looper中去,回调函数为MessageQueue::cb_eventReceiver,
mLooper->addFd(mEventTube->getFd(), 0,ALOOPER_EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
int Looper::addFd(int fd, int ident, int events,ALooper_callbackFunc callback, void* data) {
return addFd(fd,ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);
}
int Looper::addFd(int fd, int ident, int events, constsp<LooperCallback>& callback, void* data) {
#ifDEBUG_CALLBACKS
ALOGD("%p ~ addFd - fd=%d, ident=%d,events=0x%x, callback=%p, data=%p", this, fd, ident,
events,callback.get(), data);
#endif
if (!callback.get()) {
if (!mAllowNonCallbacks) {
ALOGE("Invalid attempt to set NULLcallback but not allowed for this looper.");
return -1;
}
if (ident < 0) {
ALOGE("Invalid attempt to set NULLcallback with ident < 0.");
return -1;
}
} else {
ident =ALOOPER_POLL_CALLBACK;
}
int epollEvents = 0;
if (events &ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
if (events &ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
{ // acquire lock
AutoMutex_l(mLock);
//封装一个request,callback其实就是MessageQueue::cb_eventReceiver
Requestrequest;
request.fd= fd;
request.ident = ident;
request.callback = callback;
request.data = data;
struct epoll_eventeventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data fieldunion
eventItem.events = epollEvents;
eventItem.data.fd = fd;
ssize_trequestIndex = mRequests.indexOfKey(fd);
if (requestIndex< 0) {
//epoll监听读bittube
int epollResult =epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
if (epollResult< 0) {
ALOGE("Erroradding epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
//把fd和request的键值对放到全局的mRequests中,
mRequests.add(fd, request);
} else {
int epollResult =epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
if (epollResult < 0) {
ALOGE("Errormodifying epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
mRequests.replaceValueAt(requestIndex, request);
}
} // release lock
return1;
}
分析了这么多,从头来一遍,
1.首先HWC发送Vsync信号,
mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
2.SF处理onVSyncReceived
那么来一次信号,就会调用一次硬件模型mPrimaryDispSync的addResyncSample(timestamp)函数,输入为时间戳,
voidSurfaceFlinger::onVSyncReceived(int type, nsecs_ttimestamp) {
boolneedsHwVsync = false;
{ // Scope for the lock
Mutex::Autolock _l(mHWVsyncLock);
//启动,mPrimaryHWVsyncEnabled前面已经赋值为true了
if (type == 0 && mPrimaryHWVsyncEnabled) {
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
}
if (needsHwVsync){
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
}
boolDispSync::addResyncSample(nsecs_t timestamp) {
Mutex::Autolocklock(mMutex);
size_t idx =(mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
mResyncSamples[idx] = timestamp;
if(mNumResyncSamples < MAX_RESYNC_SAMPLES) {
mNumResyncSamples++;
} else {
mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;
}
updateModelLocked();
if(mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {
resetErrorLocked();
}
if(runningWithoutSyncFramework) {
// If we don't have the sync frameworkwe will never have
// addPresentFence called. This means we have no way to know whether
// or not we're synchronized with the HWvsyncs, so we just request
// that the HW vsync events be turned onwhenever we need to generate
// SW vsync events.
returnmThread->hasAnyEventListeners();
}
return mPeriod == 0 || mError >errorThreshold;
}
mNumResyncSamples大于3次以后都会调用 mThread->updateModel(mPeriod, mPhase);,那意思就是前三个周期不通知SF工作。
oid DispSync::updateModelLocked() {
//mNumResyncSamples 大于3次以后
if(mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
nsecs_tdurationSum = 0;
for (size_t i = 1; i <mNumResyncSamples; i++) {
size_tidx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) %MAX_RESYNC_SAMPLES;
durationSum += mResyncSamples[idx] - mResyncSamples[prev];
}
mPeriod =durationSum / (mNumResyncSamples - 1);
double sampleAvgX = 0;
double sampleAvgY = 0;
double scale = 2.0 * M_PI / double(mPeriod);
for (size_t i = 0; i <mNumResyncSamples; i++) {
size_tidx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
nsecs_tsample = mResyncSamples[idx];
double samplePhase = double(sample %mPeriod) * scale;
sampleAvgX += cos(samplePhase);
sampleAvgY += sin(samplePhase);
}
sampleAvgX/= double(mNumResyncSamples);
sampleAvgY/= double(mNumResyncSamples);
mPhase =nsecs_t(atan2(sampleAvgY,sampleAvgX) / scale);
if (mPhase < 0) {
mPhase+= mPeriod;
}
if(traceDetailedInfo) {
ATRACE_INT64("DispSync:Period", mPeriod);
ATRACE_INT64("DispSync:Phase", mPhase);
}
mThread->updateModel(mPeriod, mPhase);
}
}
voidupdateModel(nsecs_t period, nsecs_t phase) {
Mutex::Autolock lock(mMutex);
mPeriod =period;
mPhase =phase;
mCond.signal();
}
mPeriod 不为0,也有signal,DispSyncThread线程不阻塞了,执行gatherCallbackInvocationsLocked(now)和fireCallbackInvocations(callbackInvocations)
virtualbool threadLoop() {
status_terr;
nsecs_t now= systemTime(SYSTEM_TIME_MONOTONIC);
nsecs_tnextEventTime = 0;
while (true) {
Vector<CallbackInvocation> callbackInvocations;
nsecs_ttargetTime = 0;
{ // Scope for lock
Mutex::Autolock lock(mMutex);
if (mStop) {
returnfalse;
}
if (mPeriod == 0) {
err = mCond.wait(mMutex);
if (err !=NO_ERROR) {
ALOGE("errorwaiting for new events: %s (%d)",
strerror(-err), err);
returnfalse;
}
continue;
}
nextEventTime = computeNextEventTimeLocked(now);
targetTime = nextEventTime;
bool isWakeup = false;
if (now <targetTime) {
err = mCond.waitRelative(mMutex, targetTime - now);
if (err ==TIMED_OUT) {
isWakeup = true;
} elseif (err !=NO_ERROR) {
ALOGE("errorwaiting for next event: %s (%d)",
strerror(-err),err);
returnfalse;
}
}
now= systemTime(SYSTEM_TIME_MONOTONIC);
if (isWakeup) {
mWakeupLatency = ((mWakeupLatency * 63) +
(now - targetTime))/ 64;
if (mWakeupLatency> 500000) {
// Don't correct by more than 500 us
mWakeupLatency = 500000;
}
if(traceDetailedInfo) {
ATRACE_INT64("DispSync:WakeupLat", now -nextEventTime);
ATRACE_INT64("DispSync:AvgWakeupLat",mWakeupLatency);
}
}
callbackInvocations = gatherCallbackInvocationsLocked(now);
}
if(callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations);
}
}
returnfalse;
}
这里的mEventListeners[i].mCallback都是驱动的事件DispSyncSource,
Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_tnow) {
Vector<CallbackInvocation> callbackInvocations;
nsecs_t ref = now -mPeriod;
for (size_t i = 0; i <mEventListeners.size(); i++) {
nsecs_tt = computeListenerNextEventTimeLocked(mEventListeners[i],
ref);
if (t < now) {
CallbackInvocation ci;
ci.mCallback = mEventListeners[i].mCallback;
ci.mEventTime = t;
callbackInvocations.push(ci);
mEventListeners.editItemAt(i).mLastEventTime = t;
}
}
returncallbackInvocations;
}
这里的callbacks[i].mCallback,就是驱动的事件DispSyncSource,
voidfireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
for (size_t i = 0; i <callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}
virtual voidonDispSyncEvent(nsecs_t when) {
sp<VSyncSource::Callback> callback;
{
Mutex::Autolock lock(mMutex);
callback = mCallback;
if (mTraceVsync) {
mValue = (mValue +1) %2;
ATRACE_INT("VSYNC", mValue);
}
}
//这里的callback为EventThread
if (callback !=NULL) {
callback->onVSyncEvent(when);
}
}
继续调用,这里已经从驱动事件,转化到驱动事件的线程EventThread中,填充EventThread的mVSyncEvent,
void EventThread::onVSyncEvent(nsecs_t timestamp) {
Mutex::Autolock_l(mLock);
mVSyncEvent[0].header.type =DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[0].header.id = 0;
mVSyncEvent[0].header.timestamp = timestamp;
mVSyncEvent[0].vsync.count++;
mCondition.broadcast();
}
EventThread的waitForEvent(),返回signalConnections,就是开始建立的Connection,这个Connection里面有个BitTube的写fd,另外的读fd在MessageQueue中,
Vector< sp<EventThread::Connection> >EventThread::waitForEvent(
DisplayEventReceiver::Event* event)
{
Mutex::Autolock_l(mLock);
Vector<sp<EventThread::Connection> > signalConnections;
do {
booleventPending = false;
bool waitForVSync= false;
size_tvsyncCount = 0;
nsecs_ttimestamp = 0;
for (int32_t i=0 ;i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
timestamp = mVSyncEvent[i].header.timestamp;
if (timestamp) {
// we have a vsync event to dispatch
*event = mVSyncEvent[i];
mVSyncEvent[i].header.timestamp = 0;
vsyncCount = mVSyncEvent[i].vsync.count;
break;
}
}
if (!timestamp) {
// no vsync event, see if there are someother event
eventPending = !mPendingEvents.isEmpty();
if (eventPending){
// we have some other event to dispatch
*event = mPendingEvents[0];
mPendingEvents.removeAt(0);
}
}
// find out connections waiting forevents
size_t count =mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
sp<Connection> connection(mDisplayEventConnections[i].promote());
if (connection !=NULL) {
bool added = false;
if(connection->count >= 0) {
// we need vsyncevents because at least
// oneconnection is waiting for it
waitForVSync = true;
if (timestamp) {
// we consumethe event only if it's time
// (ie: wereceived a vsync event)
if (connection->count == 0) {
// fired this time around
connection->count = -1;
signalConnections.add(connection);
added = true;
} elseif(connection->count == 1 ||
(vsyncCount %connection->count) == 0) {
// continuous event, and time to reportit
signalConnections.add(connection);
added = true;
}
}
}
if (eventPending&& !timestamp && !added) {
// we don't havea 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 toenable or disable vsyncs
if (timestamp&& !waitForVSync) {
// we received a VSYNC but we have noclients
// don't report it, and disable VSYNCevents
disableVSyncLocked();
} elseif (!timestamp&& waitForVSync) {
// we have at least one client, so wewant vsync enabled
// (TODO: this function is called rightafter we finish
// notifying clients of a vsync, so thiscall will be made
// at the vsync rate, e.g. 60fps. If we can accurately
// track the current state we couldavoid making this call
// so often.)
enableVSyncLocked();
}
// note: !timestamp impliessignalConnections.isEmpty(), because we
// don't populate signalConnections ifthere's no vsync pending
if (!timestamp&& !eventPending) {
// wait for something to happen
if (waitForVSync){
// This is where we spend most of ourtime, waiting
// for vsync events and new clientregistrations.
//
// If the screen is off, we can't use h/wvsync, so we
// use a 16ms timeout instead. It doesn't need to be
// precise, we just need to keep feedingour clients.
//
// We don't want to stall if there's adriver bug, so we
// use a (long) timeout when waiting forh/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 outwaiting for hw vsync; faking it");
}
// FIXME: how dowe decide which display id the fake
// vsync camefrom ?
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 wejust want to sleep.
// h/w vsync should be disabled, so thiswill wait until we
// get a new connection, or an existingconnection becomes
// interested in receiving vsync again.
mCondition.wait(mLock);
}
}
} while(signalConnections.isEmpty());
// here we're guaranteed to have atimestamp and some connections to signal
// (The connections might have droppedout of mDisplayEventConnections
// while we were asleep, but we'll stillhave strong references to them.)
returnsignalConnections;
}
waitForEvent返回,调用conn->postEvent(event),
boolEventThread::threadLoop() {
DisplayEventReceiver::Event event;
Vector<sp<EventThread::Connection> > signalConnections;
signalConnections = waitForEvent(&event);
// dispatch events to listeners...
const size_t count =signalConnections.size();
for (size_t i=0 ; i<count ;i++) {
constsp<Connection>& conn(signalConnections[i]);
// now see if we still need to report this event
status_terr = conn->postEvent(event);
if (err == -EAGAIN|| err == -EWOULDBLOCK) {
// The destination doesn't accept eventsanymore, it's probably
// full. For now, we just drop theevents on the floor.
// FIXME: Note that some events cannotbe dropped and would have
// to be re-sent later.
// Right-now we don't have the abilityto do this.
ALOGW("EventThread: dropping event (%08x)for connection %p",
event.header.type,conn.get());
} elseif (err < 0) {
// handle any other error on the pipe asfatal. the only
// reasonable thing to do is to clean-upthis connection.
// The most common error we'll get here is-EPIPE.
removeDisplayEventConnection(signalConnections[i]);
}
}
returntrue;
}
也就是通过Connection的写fd将event发送给MessageQueue,
status_t EventThread::Connection::postEvent(
constDisplayEventReceiver::Event& event) {
ssize_t size =DisplayEventReceiver::sendEvents(mChannel, &event, 1);
returnsize < 0 ? status_t(size) :status_t(NO_ERROR);
}
这时候MessageQueue的looper epoll返回,最终会去调用response.request.callback->handleEvent,
intLooper::pollInner(int timeoutMillis){
// Release lock.
mLock.unlock();
// Invoke all response callbacks.
for (size_t i = 0; i <mResponses.size(); i++) {
Response& response = mResponses.editItemAt(i);
if (response.request.ident== ALOOPER_POLL_CALLBACK) {
int fd =response.request.fd;
int events =response.events;
void* data =response.request.data;
#ifDEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
ALOGD("%p ~ pollOnce - invoking fd eventcallback %p: fd=%d, events=0x%x, data=%p",
this,response.request.callback.get(), fd, events, data);
#endif
int callbackResult= response.request.callback->handleEvent(fd, events, data);
if (callbackResult== 0) {
removeFd(fd);
}
// Clear the callback reference in theresponse structure promptly because we
// will not clear the response vectoritself until the next poll.
response.request.callback.clear();
result= ALOOPER_POLL_CALLBACK;
}
}
return result;
}
最终调用的是mCallback(fd,events, data);
intSimpleLooperCallback::handleEvent(int fd, int events, void* data) {
return mCallback(fd,events, data);
}
而这个mCallback,既是MessageQueue::cb_eventReceiver,
intMessageQueue::cb_eventReceiver(int fd, int events, void* data) {
MessageQueue* queue = reinterpret_cast<MessageQueue*>(data);
returnqueue->eventReceiver(fd,events);
}
这里会从MessageQueue的读BitTube中读出event,然后调用mHandler->dispatchInvalidate();
intMessageQueue::eventReceiver(int fd, int events) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n =DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
for (int i=0 ; i<n ; i++){
if(buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
#ifINVALIDATE_ON_VSYNC
mHandler->dispatchInvalidate();
#else
mHandler->dispatchRefresh();
#endif
break;
}
}
}
return1;
}
void MessageQueue::Handler::dispatchInvalidate() {
if((android_atomic_or(eventMaskInvalidate, &mEventMask) &eventMaskInvalidate) ==0) {
mQueue.mLooper->sendMessage(this,Message(MessageQueue::INVALIDATE));
}
}
void MessageQueue::Handler::handleMessage(constMessage& message) {
switch (message.what) {
caseINVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
caseREFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
caseTRANSACTION:
android_atomic_and(~eventMaskTransaction, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
进而去调用SF的onMessageReceived函数,最终每次Vsync信号来了,SF都会去执行handleMessageTransaction()等函数。
voidSurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
caseMessageQueue::TRANSACTION:
handleMessageTransaction();
break;
caseMessageQueue::INVALIDATE:
handleMessageTransaction();
handleMessageInvalidate();
signalRefresh();
break;
caseMessageQueue::REFRESH:
handleMessageRefresh();
break;
}
}