Merge changes If4126023,Iacda2386,I1eb691f7,Ib56139f8

* changes:
  Add support for sending VSYNC events to the framework
  BitTube::read now handles EAGAIN
  split ComposerService out of SurfaceComposerClient.h
  rewrite SF's message loop on top of Looper
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 10ceb7b..202abf6 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -126,7 +126,7 @@
     ASensorEvent event;
 
     res = queue->read(&event, 1);
-    if (res == -EAGAIN) {
+    if (res == 0) {
         res = queue->waitForEvent();
         if (res != NO_ERROR)
             return -1;
diff --git a/include/private/gui/ComposerService.h b/include/private/gui/ComposerService.h
new file mode 100644
index 0000000..d04491a
--- /dev/null
+++ b/include/private/gui/ComposerService.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_PRIVATE_GUI_COMPOSER_SERVICE_H
+#define ANDROID_PRIVATE_GUI_COMPOSER_SERVICE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Singleton.h>
+#include <utils/StrongPointer.h>
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class IMemoryHeap;
+class ISurfaceComposer;
+class surface_flinger_cblk_t;
+
+// ---------------------------------------------------------------------------
+
+class ComposerService : public Singleton<ComposerService>
+{
+    // these are constants
+    sp<ISurfaceComposer> mComposerService;
+    sp<IMemoryHeap> mServerCblkMemory;
+    surface_flinger_cblk_t volatile* mServerCblk;
+    ComposerService();
+    friend class Singleton<ComposerService>;
+public:
+    static sp<ISurfaceComposer> getComposerService();
+    static surface_flinger_cblk_t const volatile * getControlBlock();
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_PRIVATE_GUI_COMPOSER_SERVICE_H
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 5eb09c7..58fd89d 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -33,8 +33,9 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
-class IMemoryHeap;
 class ComposerState;
+class IDisplayEventConnection;
+class IMemoryHeap;
 
 class ISurfaceComposer : public IInterface
 {
@@ -124,13 +125,19 @@
             uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
 
+    /* triggers screen off animation */
     virtual status_t turnElectronBeamOff(int32_t mode) = 0;
+
+    /* triggers screen on animation */
     virtual status_t turnElectronBeamOn(int32_t mode) = 0;
 
     /* verify that an ISurfaceTexture was created by SurfaceFlinger.
      */
     virtual bool authenticateSurfaceTexture(
             const sp<ISurfaceTexture>& surface) const = 0;
+
+    /* return an IDisplayEventConnection */
+    virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -151,6 +158,7 @@
         TURN_ELECTRON_BEAM_OFF,
         TURN_ELECTRON_BEAM_ON,
         AUTHENTICATE_SURFACE,
+        CREATE_DISPLAY_EVENT_CONNECTION,
     };
 
     virtual status_t    onTransact( uint32_t code,
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 8226abe..99affda 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -28,7 +28,6 @@
 #include <utils/threads.h>
 
 #include <ui/PixelFormat.h>
-#include <ui/Region.h>
 
 #include <surfaceflinger/Surface.h>
 
@@ -39,30 +38,11 @@
 class DisplayInfo;
 class Composer;
 class IMemoryHeap;
-class ISurfaceComposer;
+class ISurfaceComposerClient;
 class Region;
-class surface_flinger_cblk_t;
-struct layer_state_t;
 
 // ---------------------------------------------------------------------------
 
-class ComposerService : public Singleton<ComposerService>
-{
-    // these are constants
-    sp<ISurfaceComposer> mComposerService;
-    sp<IMemoryHeap> mServerCblkMemory;
-    surface_flinger_cblk_t volatile* mServerCblk;
-    ComposerService();
-    friend class Singleton<ComposerService>;
-public:
-    static sp<ISurfaceComposer> getComposerService();
-    static surface_flinger_cblk_t const volatile * getControlBlock();
-};
-
-// ---------------------------------------------------------------------------
-
-class Composer;
-
 class SurfaceComposerClient : public RefBase
 {
     friend class Composer;
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index b7e3ee3..b8be67d 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -3,6 +3,8 @@
 
 LOCAL_SRC_FILES:= \
 	BitTube.cpp \
+	DisplayEventReceiver.cpp \
+	IDisplayEventConnection.cpp \
 	ISensorEventConnection.cpp \
 	ISensorServer.cpp \
 	ISurfaceTexture.cpp \
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index c632b43..fa8d0ea 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -97,6 +97,11 @@
         len = ::read(mReceiveFd, vaddr, size);
         err = len < 0 ? errno : 0;
     } while (err == EINTR);
+    if (err == EAGAIN || err == EWOULDBLOCK) {
+        // EAGAIN means that we have non-blocking I/O but there was
+        // no data to be read. Nothing the client should care about.
+        return 0;
+    }
     return err == 0 ? len : -err;
 }
 
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 86bc62a..db32827 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -29,6 +29,9 @@
 
 #include <surfaceflinger/ISurfaceComposer.h>
 
+#include <gui/BitTube.h>
+#include <gui/IDisplayEventConnection.h>
+
 #include <ui/DisplayInfo.h>
 
 #include <gui/ISurfaceTexture.h>
@@ -44,6 +47,8 @@
 
 namespace android {
 
+class IDisplayEventConnection;
+
 class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
 {
 public:
@@ -174,6 +179,27 @@
         }
         return result != 0;
     }
+
+    virtual sp<IDisplayEventConnection> createDisplayEventConnection()
+    {
+        Parcel data, reply;
+        sp<IDisplayEventConnection> result;
+        int err = data.writeInterfaceToken(
+                ISurfaceComposer::getInterfaceDescriptor());
+        if (err != NO_ERROR) {
+            return result;
+        }
+        err = remote()->transact(
+                BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
+                data, &reply);
+        if (err != NO_ERROR) {
+            LOGE("ISurfaceComposer::createDisplayEventConnection: error performing "
+                    "transaction: %s (%d)", strerror(-err), -err);
+            return result;
+        }
+        result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder());
+        return result;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
@@ -254,6 +280,12 @@
             int32_t result = authenticateSurfaceTexture(surfaceTexture) ? 1 : 0;
             reply->writeInt32(result);
         } break;
+        case CREATE_DISPLAY_EVENT_CONNECTION: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IDisplayEventConnection> connection(createDisplayEventConnection());
+            reply->writeStrongBinder(connection->asBinder());
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 4ad6c22..699438c 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -39,6 +39,7 @@
 #include <private/surfaceflinger/LayerState.h>
 #include <private/surfaceflinger/SharedBufferStack.h>
 
+#include <private/gui/ComposerService.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index b4d01a9..289726b 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -29,6 +29,8 @@
 
 #include <hardware/hardware.h>
 
+#include <private/gui/ComposerService.h>
+
 #include <surfaceflinger/ISurfaceComposer.h>
 #include <surfaceflinger/SurfaceComposerClient.h>
 #include <surfaceflinger/IGraphicBufferAlloc.h>
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 3d47f05..691b52d 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -23,6 +23,8 @@
 
 #include <utils/Log.h>
 
+#include <private/gui/ComposerService.h>
+
 namespace android {
 
 SurfaceTextureClient::SurfaceTextureClient(
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 693b7b8..ea52750 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -22,6 +22,8 @@
 #include <surfaceflinger/SurfaceComposerClient.h>
 #include <utils/String8.h>
 
+#include <private/gui/ComposerService.h>
+
 namespace android {
 
 class SurfaceTest : public ::testing::Test {
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 210635f..24e0d8c 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -32,6 +32,8 @@
 #include <utils/Log.h>
 #include <utils/String8.h>
 
+#include <private/gui/ComposerService.h>
+
 namespace android {
 
 SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) :
diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_PowerManagerService.cpp
index a389c11..08650e1 100644
--- a/services/jni/com_android_server_PowerManagerService.cpp
+++ b/services/jni/com_android_server_PowerManagerService.cpp
@@ -28,6 +28,8 @@
 #include <surfaceflinger/ISurfaceComposer.h>
 #include <surfaceflinger/SurfaceComposerClient.h>
 
+#include <private/gui/ComposerService.h>
+
 #include "com_android_server_PowerManagerService.h"
 
 namespace android {
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index f63c0c1..95d651a 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -2,19 +2,22 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    Layer.cpp 								\
-    LayerBase.cpp 							\
-    LayerDim.cpp 							\
-    LayerScreenshot.cpp						\
-    DdmConnection.cpp						\
-    DisplayHardware/DisplayHardware.cpp 	\
+    EventThread.cpp                         \
+    Layer.cpp                               \
+    LayerBase.cpp                           \
+    LayerDim.cpp                            \
+    LayerScreenshot.cpp                     \
+    DdmConnection.cpp                       \
+    DisplayHardware/DisplayHardware.cpp     \
     DisplayHardware/DisplayHardwareBase.cpp \
-    DisplayHardware/HWComposer.cpp 			\
-    GLExtensions.cpp 						\
-    MessageQueue.cpp 						\
-    SurfaceFlinger.cpp 						\
-    SurfaceTextureLayer.cpp 				\
-    Transform.cpp 							\
+    DisplayHardware/HWComposer.cpp          \
+    DisplayHardware/VSyncBarrier.cpp        \
+    DisplayEventConnection.cpp              \
+    GLExtensions.cpp                        \
+    MessageQueue.cpp                        \
+    SurfaceFlinger.cpp                      \
+    SurfaceTextureLayer.cpp                 \
+    Transform.cpp                           \
     
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f94d321..3bbc75e 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -140,6 +140,7 @@
     mDpiX = mNativeWindow->xdpi;
     mDpiY = mNativeWindow->ydpi;
     mRefreshRate = fbDev->fps;
+    mNextFakeVSync = 0;
 
 
 /* FIXME: this is a temporary HACK until we are able to report the refresh rate
@@ -152,6 +153,8 @@
 #warning "refresh rate set via makefile to REFRESH_RATE"
 #endif
 
+    mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
+
     EGLint w, h, dummy;
     EGLint numConfigs=0;
     EGLSurface surface;
@@ -346,6 +349,37 @@
     return mPageFlipCount;
 }
 
+// this needs to be thread safe
+nsecs_t DisplayHardware::waitForVSync() const {
+    nsecs_t timestamp;
+    if (mVSync.wait(&timestamp) < 0) {
+        // vsync not supported!
+        usleep( getDelayToNextVSyncUs(&timestamp) );
+    }
+    return timestamp;
+}
+
+int32_t DisplayHardware::getDelayToNextVSyncUs(nsecs_t* timestamp) const {
+    Mutex::Autolock _l(mFakeVSyncMutex);
+    const nsecs_t period = mRefreshPeriod;
+    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+    nsecs_t next_vsync = mNextFakeVSync;
+    nsecs_t sleep = next_vsync - now;
+    if (sleep < 0) {
+        // we missed, find where the next vsync should be
+        sleep = (period - ((now - next_vsync) % period));
+        next_vsync = now + sleep;
+    }
+    mNextFakeVSync = next_vsync + period;
+    timestamp[0] = next_vsync;
+
+    // round to next microsecond
+    int32_t sleep_us = (sleep + 999LL) / 1000LL;
+
+    // guaranteed to be > 0
+    return sleep_us;
+}
+
 status_t DisplayHardware::compositionComplete() const {
     return mNativeWindow->compositionComplete();
 }
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index f02c954..45d4b45 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -32,6 +32,7 @@
 #include "GLExtensions.h"
 
 #include "DisplayHardware/DisplayHardwareBase.h"
+#include "DisplayHardware/VSyncBarrier.h"
 
 namespace android {
 
@@ -74,6 +75,9 @@
     uint32_t    getMaxTextureSize() const;
     uint32_t    getMaxViewportDims() const;
 
+    // waits for the next vsync and returns the timestamp of when it happened
+    nsecs_t        waitForVSync() const;
+
     uint32_t getPageFlipCount() const;
     EGLDisplay getEGLDisplay() const { return mDisplay; }
 
@@ -95,6 +99,7 @@
 private:
     void init(uint32_t displayIndex) __attribute__((noinline));
     void fini() __attribute__((noinline));
+    int32_t getDelayToNextVSyncUs(nsecs_t* timestamp) const;
 
     sp<SurfaceFlinger> mFlinger;
     EGLDisplay      mDisplay;
@@ -112,7 +117,12 @@
     mutable uint32_t mPageFlipCount;
     GLint           mMaxViewportDims[2];
     GLint           mMaxTextureSize;
-    
+    VSyncBarrier    mVSync;
+
+    mutable Mutex   mFakeVSyncMutex;
+    mutable nsecs_t mNextFakeVSync;
+    nsecs_t         mRefreshPeriod;
+
     HWComposer*     mHwc;
 
     sp<FramebufferNativeWindow> mNativeWindow;
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index aebe1b8..1846ccb 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -29,169 +29,81 @@
 
 // ---------------------------------------------------------------------------
 
-void MessageList::insert(const sp<MessageBase>& node) 
-{
-    LIST::iterator cur(mList.begin());
-    LIST::iterator end(mList.end());
-    while (cur != end) {
-        if (*node < **cur) {
-            mList.insert(cur, node);
-            return;
-        }
-        ++cur;
-    }
-    mList.insert(++end, node);
+MessageBase::MessageBase()
+    : MessageHandler() {
 }
 
-void MessageList::remove(MessageList::LIST::iterator pos) 
-{
-    mList.erase(pos);
+MessageBase::~MessageBase() {
 }
 
+void MessageBase::handleMessage(const Message&) {
+    this->handler();
+    barrier.open();
+};
+
 // ---------------------------------------------------------------------------
 
 MessageQueue::MessageQueue()
-    : mInvalidate(false)
-{
-    mInvalidateMessage = new MessageBase(INVALIDATE);
-}
-
-MessageQueue::~MessageQueue()
+    : mLooper(new Looper(true)),
+      mInvalidatePending(0)
 {
 }
 
-sp<MessageBase> MessageQueue::waitMessage(nsecs_t timeout)
-{
-    sp<MessageBase> result;
+MessageQueue::~MessageQueue() {
+}
 
-    bool again;
+void MessageQueue::waitMessage() {
     do {
-        const nsecs_t timeoutTime = systemTime() + timeout;
-        while (true) {
-            Mutex::Autolock _l(mLock);
-            nsecs_t now = systemTime();
-            nsecs_t nextEventTime = -1;
-
-            LIST::iterator cur(mMessages.begin());
-            if (cur != mMessages.end()) {
-                result = *cur;
-            }
-            
-            if (result != 0) {
-                if (result->when <= now) {
-                    // there is a message to deliver
-                    mMessages.remove(cur);
-                    break;
-                }
-                nextEventTime = result->when;
-                result = 0;
-            }
-
-            // see if we have an invalidate message
-            if (mInvalidate) {
-                mInvalidate = false;
-                mInvalidateMessage->when = now;
-                result = mInvalidateMessage;
-                break;
-            }
-
-            if (timeout >= 0) {
-                if (timeoutTime < now) {
-                    // we timed-out, return a NULL message
-                    result = 0;
-                    break;
-                }
-                if (nextEventTime > 0) {
-                    if (nextEventTime > timeoutTime) {
-                        nextEventTime = timeoutTime;
-                    }
-                } else {
-                    nextEventTime = timeoutTime;
-                }
-            }
-
-            if (nextEventTime >= 0) {
-                //LOGD("nextEventTime = %lld ms", nextEventTime);
-                if (nextEventTime > 0) {
-                    // we're about to wait, flush the binder command buffer
-                    IPCThreadState::self()->flushCommands();
-                    const nsecs_t reltime = nextEventTime - systemTime();
-                    if (reltime > 0) {
-                        mCondition.waitRelative(mLock, reltime);
-                    }
-                }
-            } else {
-                //LOGD("going to wait");
-                // we're about to wait, flush the binder command buffer
-                IPCThreadState::self()->flushCommands();
-                mCondition.wait(mLock);
-            }
-        } 
-        // here we're not holding the lock anymore
-
-        if (result == 0)
+        // handle invalidate events first
+        if (android_atomic_and(0, &mInvalidatePending) != 0)
             break;
 
-        again = result->handler();
-        if (again) {
-            // the message has been processed. release our reference to it
-            // without holding the lock.
-            result->notify();
-            result = 0;
-        }
-        
-    } while (again);
+        IPCThreadState::self()->flushCommands();
 
-    return result;
+        int32_t ret = mLooper->pollOnce(-1);
+        switch (ret) {
+            case ALOOPER_POLL_WAKE:
+                // we got woken-up there is work to do in the main loop
+                continue;
+
+            case ALOOPER_POLL_CALLBACK:
+                // callback was handled, loop again
+                continue;
+
+            case ALOOPER_POLL_TIMEOUT:
+                // timeout (should not happen)
+                continue;
+
+            case ALOOPER_POLL_ERROR:
+                LOGE("ALOOPER_POLL_ERROR");
+                continue;
+
+            default:
+                // should not happen
+                LOGE("Looper::pollOnce() returned unknown status %d", ret);
+                continue;
+        }
+    } while (true);
 }
 
 status_t MessageQueue::postMessage(
-        const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
+        const sp<MessageBase>& messageHandler, nsecs_t relTime)
 {
-    return queueMessage(message, relTime, flags);
+    const Message dummyMessage;
+    if (relTime > 0) {
+        mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
+    } else {
+        mLooper->sendMessage(messageHandler, dummyMessage);
+    }
+    return NO_ERROR;
 }
 
 status_t MessageQueue::invalidate() {
-    Mutex::Autolock _l(mLock);
-    mInvalidate = true;
-    mCondition.signal();
+    android_atomic_or(1, &mInvalidatePending);
+    mLooper->wake();
     return NO_ERROR;
 }
 
-status_t MessageQueue::queueMessage(
-        const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
-{
-    Mutex::Autolock _l(mLock);
-    message->when = systemTime() + relTime;
-    mMessages.insert(message);
-    
-    //LOGD("MessageQueue::queueMessage time = %lld ms", message->when);
-    //dumpLocked(message);
-
-    mCondition.signal();
-    return NO_ERROR;
-}
-
-void MessageQueue::dump(const sp<MessageBase>& message)
-{
-    Mutex::Autolock _l(mLock);
-    dumpLocked(message);
-}
-
-void MessageQueue::dumpLocked(const sp<MessageBase>& message)
-{
-    LIST::const_iterator cur(mMessages.begin());
-    LIST::const_iterator end(mMessages.end());
-    int c = 0;
-    while (cur != end) {
-        const char tick = (*cur == message) ? '>' : ' ';
-        LOGD("%c %d: msg{.what=%08x, when=%lld}",
-                tick, c, (*cur)->what, (*cur)->when);
-        ++cur;
-        c++;
-    }
-}
-
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 890f809..25030a6 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -23,7 +23,7 @@
 
 #include <utils/threads.h>
 #include <utils/Timers.h>
-#include <utils/List.h>
+#include <utils/Looper.h>
 
 #include "Barrier.h"
 
@@ -31,92 +31,39 @@
 
 // ---------------------------------------------------------------------------
 
-class MessageBase;
-
-class MessageList 
-{
-    List< sp<MessageBase> > mList;
-    typedef List< sp<MessageBase> > LIST;
-public:
-    inline LIST::iterator begin()                { return mList.begin(); }
-    inline LIST::const_iterator begin() const    { return mList.begin(); }
-    inline LIST::iterator end()                  { return mList.end(); }
-    inline LIST::const_iterator end() const      { return mList.end(); }
-    inline bool isEmpty() const { return mList.empty(); }
-    void insert(const sp<MessageBase>& node);
-    void remove(LIST::iterator pos);
-};
-
-// ============================================================================
-
-class MessageBase : 
-    public LightRefBase<MessageBase>
+class MessageBase : public MessageHandler
 {
 public:
-    nsecs_t     when;
-    uint32_t    what;
-    int32_t     arg0;    
-
-    MessageBase() : when(0), what(0), arg0(0) { }
-    MessageBase(uint32_t what, int32_t arg0=0)
-        : when(0), what(what), arg0(arg0) { }
+    MessageBase();
     
     // return true if message has a handler
-    virtual bool handler() { return false; }
+    virtual bool handler() = 0;
 
     // waits for the handler to be processed
     void wait() const { barrier.wait(); }
-    
-    // releases all waiters. this is done automatically if
-    // handler returns true
-    void notify() const { barrier.open(); }
 
 protected:
-    virtual ~MessageBase() { }
+    virtual ~MessageBase();
 
 private:
-    mutable Barrier barrier;
-    friend class LightRefBase<MessageBase>;
-};
+    virtual void handleMessage(const Message& message);
 
-inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) {
-    return lhs.when < rhs.when;
-}
+    mutable Barrier barrier;
+};
 
 // ---------------------------------------------------------------------------
 
-class MessageQueue
-{
-    typedef List< sp<MessageBase> > LIST;
-public:
+class MessageQueue {
+    sp<Looper> mLooper;
+    volatile int32_t mInvalidatePending;
 
+public:
     MessageQueue();
     ~MessageQueue();
 
-    // pre-defined messages
-    enum {
-        INVALIDATE = '_upd'
-    };
-
-    sp<MessageBase> waitMessage(nsecs_t timeout = -1);
-    
-    status_t postMessage(const sp<MessageBase>& message,
-            nsecs_t reltime=0, uint32_t flags = 0);
-
+    void waitMessage();
+    status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
     status_t invalidate();
-    
-    void dump(const sp<MessageBase>& message);
-
-private:
-    status_t queueMessage(const sp<MessageBase>& message,
-            nsecs_t reltime, uint32_t flags);
-    void dumpLocked(const sp<MessageBase>& message);
-    
-    Mutex           mLock;
-    Condition       mCondition;
-    MessageList     mMessages;
-    bool            mInvalidate;
-    sp<MessageBase> mInvalidateMessage;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1b00e93..d5a8d08 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -34,6 +34,8 @@
 #include <binder/MemoryHeapBase.h>
 #include <binder/PermissionCache.h>
 
+#include <gui/IDisplayEventConnection.h>
+
 #include <utils/String8.h>
 #include <utils/String16.h>
 #include <utils/StopWatch.h>
@@ -46,6 +48,8 @@
 #include <GLES/gl.h>
 
 #include "clz.h"
+#include "DisplayEventConnection.h"
+#include "EventThread.h"
 #include "GLExtensions.h"
 #include "DdmConnection.h"
 #include "Layer.h"
@@ -293,12 +297,16 @@
     // put the origin in the left-bottom corner
     glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
 
-    mReadyToRunBarrier.open();
+
+    // start the EventThread
+    mEventThread = new EventThread(this);
 
     /*
      *  We're now ready to accept clients...
      */
 
+    mReadyToRunBarrier.open();
+
     // start boot animation
     property_set("ctl.start", "bootanim");
 
@@ -311,25 +319,30 @@
 #pragma mark Events Handler
 #endif
 
-void SurfaceFlinger::waitForEvent()
-{
-    while (true) {
-        nsecs_t timeout = -1;
-        sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
-        if (msg != 0) {
-            switch (msg->what) {
-                case MessageQueue::INVALIDATE:
-                    // invalidate message, just return to the main loop
-                    return;
-            }
-        }
-    }
+void SurfaceFlinger::waitForEvent() {
+    mEventQueue.waitMessage();
 }
 
 void SurfaceFlinger::signalEvent() {
     mEventQueue.invalidate();
 }
 
+status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
+        nsecs_t reltime, uint32_t flags) {
+    return mEventQueue.postMessage(msg, reltime);
+}
+
+status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
+        nsecs_t reltime, uint32_t flags) {
+    status_t res = mEventQueue.postMessage(msg, reltime);
+    if (res == NO_ERROR) {
+        msg->wait();
+    }
+    return res;
+}
+
+// ----------------------------------------------------------------------------
+
 bool SurfaceFlinger::authenticateSurfaceTexture(
         const sp<ISurfaceTexture>& surfaceTexture) const {
     Mutex::Autolock _l(mStateLock);
@@ -371,20 +384,17 @@
     return false;
 }
 
-status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
-        nsecs_t reltime, uint32_t flags)
-{
-    return mEventQueue.postMessage(msg, reltime, flags);
+// ----------------------------------------------------------------------------
+
+sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
+    sp<DisplayEventConnection> result(new DisplayEventConnection(this));
+    mEventThread->registerDisplayEventConnection(result);
+    return result;
 }
 
-status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
-        nsecs_t reltime, uint32_t flags)
-{
-    status_t res = mEventQueue.postMessage(msg, reltime, flags);
-    if (res == NO_ERROR) {
-        msg->wait();
-    }
-    return res;
+void SurfaceFlinger::cleanupDisplayEventConnection(
+        const wp<DisplayEventConnection>& connection) {
+    mEventThread->unregisterDisplayEventConnection(connection);
 }
 
 // ----------------------------------------------------------------------------
@@ -443,7 +453,7 @@
     } else {
         // pretend we did the post
         hw.compositionComplete();
-        usleep(16667); // 60 fps period
+        hw.waitForVSync();
     }
     return true;
 }
@@ -1583,9 +1593,16 @@
         }
 
         /*
+         * VSYNC state
+         */
+        mEventThread->dump(result, buffer, SIZE);
+
+        /*
          * Dump HWComposer state
          */
         HWComposer& hwc(hw.getHwComposer());
+        snprintf(buffer, SIZE, "h/w composer state:\n");
+        result.append(buffer);
         snprintf(buffer, SIZE, "  h/w composer %s and %s\n",
                 hwc.initCheck()==NO_ERROR ? "present" : "not present",
                 (mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 17028db..1039f47 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -46,6 +46,8 @@
 
 class Client;
 class DisplayHardware;
+class DisplayEventConnection;
+class EventThread;
 class Layer;
 class LayerDim;
 class LayerScreenshot;
@@ -171,6 +173,7 @@
                                                             int orientation, uint32_t flags);
     virtual int                         setOrientation(DisplayID dpy, int orientation, uint32_t flags);
     virtual bool                        authenticateSurfaceTexture(const sp<ISurfaceTexture>& surface) const;
+    virtual sp<IDisplayEventConnection> createDisplayEventConnection();
 
     virtual status_t captureScreen(DisplayID dpy,
             sp<IMemoryHeap>* heap,
@@ -222,6 +225,7 @@
 
 private:
     friend class Client;
+    friend class DisplayEventConnection;
     friend class LayerBase;
     friend class LayerBaseClient;
     friend class Layer;
@@ -331,6 +335,9 @@
             status_t electronBeamOffAnimationImplLocked();
             status_t electronBeamOnAnimationImplLocked();
 
+            void cleanupDisplayEventConnection(
+                    const wp<DisplayEventConnection>& connection);
+
             void        debugFlashRegions();
             void        debugShowFPS() const;
             void        drawWormhole() const;
@@ -361,6 +368,7 @@
                 GLuint                      mWormholeTexName;
                 GLuint                      mProtectedTexName;
                 nsecs_t                     mBootTime;
+                sp<EventThread>             mEventThread;
 
                 // Can only accessed from the main thread, these members
                 // don't need synchronization