merge in klp-release history after reset to klp-dev
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index bd89bd5..c3daa64 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -5,6 +5,7 @@
     Client.cpp \
     DisplayDevice.cpp \
     DispSync.cpp \
+    EventControlThread.cpp \
     EventThread.cpp \
     FrameTracker.cpp \
     Layer.cpp \
@@ -65,6 +66,13 @@
     LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=0
 endif
 
+# See build/target/board/generic/BoardConfig.mk for a description of this setting.
+ifneq ($(SF_VSYNC_EVENT_PHASE_OFFSET_NS),)
+    LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=$(SF_VSYNC_EVENT_PHASE_OFFSET_NS)
+else
+    LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=0
+endif
+
 ifneq ($(PRESENT_TIME_OFFSET_FROM_VSYNC_NS),)
     LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=$(PRESENT_TIME_OFFSET_FROM_VSYNC_NS)
 else
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
new file mode 100644
index 0000000..6504091
--- /dev/null
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include "EventControlThread.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+EventControlThread::EventControlThread(const sp<SurfaceFlinger>& flinger):
+        mFlinger(flinger),
+        mVsyncEnabled(false) {
+}
+
+void EventControlThread::setVsyncEnabled(bool enabled) {
+    Mutex::Autolock lock(mMutex);
+    mVsyncEnabled = enabled;
+    mCond.signal();
+}
+
+bool EventControlThread::threadLoop() {
+    Mutex::Autolock lock(mMutex);
+
+    bool vsyncEnabled = mVsyncEnabled;
+
+    mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,
+            mVsyncEnabled);
+
+    while (true) {
+        status_t err = mCond.wait(mMutex);
+        if (err != NO_ERROR) {
+            ALOGE("error waiting for new events: %s (%d)",
+                strerror(-err), err);
+            return false;
+        }
+
+        if (vsyncEnabled != mVsyncEnabled) {
+            mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
+                    SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);
+            vsyncEnabled = mVsyncEnabled;
+        }
+    }
+
+    return false;
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/EventControlThread.h b/services/surfaceflinger/EventControlThread.h
new file mode 100644
index 0000000..be6c53a
--- /dev/null
+++ b/services/surfaceflinger/EventControlThread.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 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_EVENTCONTROLTHREAD_H
+#define ANDROID_EVENTCONTROLTHREAD_H
+
+#include <stddef.h>
+
+#include <utils/Mutex.h>
+#include <utils/Thread.h>
+
+namespace android {
+
+class SurfaceFlinger;
+
+class EventControlThread: public Thread {
+public:
+
+    EventControlThread(const sp<SurfaceFlinger>& flinger);
+    virtual ~EventControlThread() {}
+
+    void setVsyncEnabled(bool enabled);
+    virtual bool threadLoop();
+
+private:
+    sp<SurfaceFlinger> mFlinger;
+    bool mVsyncEnabled;
+
+    Mutex mMutex;
+    Condition mCond;
+};
+
+}
+
+#endif // ANDROID_DISPSYNC_H
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bc8cfb8..9d94c87 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -60,6 +60,7 @@
 #include "DdmConnection.h"
 #include "DisplayDevice.h"
 #include "DispSync.h"
+#include "EventControlThread.h"
 #include "EventThread.h"
 #include "Layer.h"
 #include "LayerDim.h"
@@ -116,6 +117,9 @@
 // conservatively (or at least with awareness of the trade-off being made).
 static const int64_t vsyncPhaseOffsetNs = VSYNC_EVENT_PHASE_OFFSET_NS;
 
+// This is the phase offset at which SurfaceFlinger's composition runs.
+static const int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS;
+
 // ---------------------------------------------------------------------------
 
 const String16 sHardwareTest("android.permission.HARDWARE_TEST");
@@ -438,7 +442,11 @@
 
 class DispSyncSource : public VSyncSource, private DispSync::Callback {
 public:
-    DispSyncSource(DispSync* dispSync) : mValue(0), mDispSync(dispSync) {}
+    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) :
+            mValue(0),
+            mPhaseOffset(phaseOffset),
+            mTraceVsync(traceVsync),
+            mDispSync(dispSync) {}
 
     virtual ~DispSyncSource() {}
 
@@ -446,7 +454,7 @@
         // Do NOT lock the mutex here so as to avoid any mutex ordering issues
         // with locking it in the onDispSyncEvent callback.
         if (enable) {
-            status_t err = mDispSync->addEventListener(vsyncPhaseOffsetNs,
+            status_t err = mDispSync->addEventListener(mPhaseOffset,
                     static_cast<DispSync::Callback*>(this));
             if (err != NO_ERROR) {
                 ALOGE("error registering vsync callback: %s (%d)",
@@ -476,8 +484,10 @@
             Mutex::Autolock lock(mMutex);
             callback = mCallback;
 
-            mValue = (mValue + 1) % 2;
-            ATRACE_INT("VSYNC", mValue);
+            if (mTraceVsync) {
+                mValue = (mValue + 1) % 2;
+                ATRACE_INT("VSYNC", mValue);
+            }
         }
 
         if (callback != NULL) {
@@ -487,6 +497,9 @@
 
     int mValue;
 
+    const nsecs_t mPhaseOffset;
+    const bool mTraceVsync;
+
     DispSync* mDispSync;
     sp<VSyncSource::Callback> mCallback;
     Mutex mMutex;
@@ -588,9 +601,16 @@
     getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
 
     // start the EventThread
-    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync);
+    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+            vsyncPhaseOffsetNs, true);
     mEventThread = new EventThread(vsyncSrc);
-    mEventQueue.setEventThread(mEventThread);
+    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+            sfVsyncPhaseOffsetNs, false);
+    mSFEventThread = new EventThread(sfVsyncSrc);
+    mEventQueue.setEventThread(mSFEventThread);
+
+    mEventControlThread = new EventControlThread(this);
+    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
 
     // set a fake vsync period if there is no HWComposer
     if (mHwc->initCheck() != NO_ERROR) {
@@ -755,7 +775,8 @@
     Mutex::Autolock _l(mHWVsyncLock);
     if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
         mPrimaryDispSync.beginResync();
-        eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
+        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
+        mEventControlThread->setVsyncEnabled(true);
         mPrimaryHWVsyncEnabled = true;
     }
 }
@@ -778,7 +799,8 @@
 
     if (!mPrimaryHWVsyncEnabled) {
         mPrimaryDispSync.beginResync();
-        eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
+        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
+        mEventControlThread->setVsyncEnabled(true);
         mPrimaryHWVsyncEnabled = true;
     }
 }
@@ -786,7 +808,8 @@
 void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
     Mutex::Autolock _l(mHWVsyncLock);
     if (mPrimaryHWVsyncEnabled) {
-        eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
+        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
+        mEventControlThread->setVsyncEnabled(false);
         mPrimaryDispSync.endResync();
         mPrimaryHWVsyncEnabled = false;
     }
@@ -796,15 +819,20 @@
 }
 
 void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
-    if (type == 0) {
-        bool needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
+    bool needsHwVsync = false;
 
-        if (needsHwVsync) {
-            enableHardwareVsync();
-        } else {
-            disableHardwareVsync(false);
+    { // Scope for the lock
+        Mutex::Autolock _l(mHWVsyncLock);
+        if (type == 0 && mPrimaryHWVsyncEnabled) {
+            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
         }
     }
+
+    if (needsHwVsync) {
+        enableHardwareVsync();
+    } else {
+        disableHardwareVsync(false);
+    }
 }
 
 void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 353e7ba..f08e66a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -67,6 +67,7 @@
 class LayerDim;
 class Surface;
 class RenderEngine;
+class EventControlThread;
 
 // ---------------------------------------------------------------------------
 
@@ -427,6 +428,8 @@
     nsecs_t mBootTime;
     bool mGpuToCpuSupported;
     sp<EventThread> mEventThread;
+    sp<EventThread> mSFEventThread;
+    sp<EventControlThread> mEventControlThread;
     EGLContext mEGLContext;
     EGLConfig mEGLConfig;
     EGLDisplay mEGLDisplay;
@@ -477,7 +480,6 @@
     bool mDaltonize;
 };
 
-// ---------------------------------------------------------------------------
 }; // namespace android
 
 #endif // ANDROID_SURFACE_FLINGER_H