From a72d0db29213c407278a1d0257baa60db28c8471 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 9 Jan 2012 18:19:18 -0800 Subject: [PATCH] Fix an issue with VSYNC one-shot VSYNC listeners could miss a VSYNC event if scheduled while in waitForVsync(). Change-Id: I720485784aecfea6cc7a23c77081d7af3c9c71db --- services/surfaceflinger/EventThread.cpp | 69 +++++++++++-------------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index 92457811e..035836ed2 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -107,27 +107,17 @@ bool EventThread::threadLoop() { { // scope for the lock Mutex::Autolock _l(mLock); do { - // wait for listeners + // see if we need to wait for the VSYNC at all do { bool waitForNextVsync = false; size_t count = mDisplayEventConnections.size(); for (size_t i=0 ; i= 1) { - // continuous mode + if (info.count >= 0) { + // at least one continuous mode or active one-shot event waitForNextVsync = true; - } else { - // one-shot event - if (info.count >= -1) { - ConnectionInfo& info( - mDisplayEventConnections.editValueAt(i)); - info.count--; - if (info.count == -1) { - // fired this time around - waitForNextVsync = true; - } - } + break; } } @@ -137,14 +127,38 @@ bool EventThread::threadLoop() { mCondition.wait(mLock); } while(true); - // wait for vsync + // at least one listener requested VSYNC mLock.unlock(); timestamp = mHw.waitForVSync(); mLock.lock(); mDeliveredEvents++; - // make sure we still have some listeners - } while (!mDisplayEventConnections.size()); + // now see if we still need to report this VSYNC event + bool reportVsync = false; + size_t count = mDisplayEventConnections.size(); + for (size_t i=0 ; i= 1) { + if (info.count==1 || (mDeliveredEvents % info.count) == 0) { + // continuous event, and time to report it + reportVsync = true; + } + } else if (info.count >= -1) { + ConnectionInfo& info( + mDisplayEventConnections.editValueAt(i)); + if (info.count == 0) { + // fired this time around + reportVsync = true; + } + info.count--; + } + } + + if (reportVsync) { + break; + } + } while (true); // dispatch vsync events to listeners... vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; @@ -161,27 +175,6 @@ bool EventThread::threadLoop() { sp conn(displayEventConnections.keyAt(i).promote()); // make sure the connection didn't die if (conn != NULL) { - - const ConnectionInfo& info( - displayEventConnections.valueAt(i)); - - if ((info.count > 1) && (mDeliveredEvents % info.count)) { - // continuous event, but not time to send this event yet - continue; - } else if (info.count < -1) { - // disabled event - continue; - } else if (info.count == 0) { - // impossible by construction. but we prefer to be safe. - continue; - } - - // here, either: - // count = -1 : one-shot scheduled this time around - // count = 1 : continuous not rate-limited - // count > 1 : continuous, rate-limited - // Note: count == 0 is not possible by construction - status_t err = conn->postEvent(vsync); if (err == -EAGAIN || err == -EWOULDBLOCK) { // The destination doesn't accept events anymore, it's probably