Add support for sending VSYNC events to the framework

use gui/DisplayEvent to receive the events. Events are
dispatched through a unix pipe, so the API is compatible
with utils/Looper. see gui/DisplayEvent.h for more info.

Bug: 1475048
Change-Id: Ia720f64d1b950328b47b22c6a86042e481d35f09
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();
 }