surfaceflinger: add getDisplayStats() method

This is used by media service to schedule video frames at the
proper time, based on precise vsync timings.

Bug: 14659809
Change-Id: I1a90603f3dc09dca9aa4f90a3aa845fab56e0a5e
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 12da9a5..3738a55 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -408,6 +408,12 @@
     mThread->updateModel(mPeriod, mPhase);
 }
 
+nsecs_t DispSync::getPeriod() {
+    // lock mutex as mPeriod changes multiple times in updateModelLocked
+    Mutex::Autolock lock(mMutex);
+    return mPeriod;
+}
+
 void DispSync::updateModelLocked() {
     if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
         nsecs_t durationSum = 0;
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 7a26df3..96efc34 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -101,6 +101,9 @@
     // turned on.  It should NOT be used after that.
     void setPeriod(nsecs_t period);
 
+    // The getPeriod method returns the current vsync period.
+    nsecs_t getPeriod();
+
     // setRefreshSkipCount specifies an additional number of refresh
     // cycles to skip.  For example, on a 60Hz display, a skip count of 1
     // will result in events happening at 30Hz.  Default is zero.  The idea
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 043b075..12f22a7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -35,6 +35,7 @@
 #include <binder/PermissionCache.h>
 
 #include <ui/DisplayInfo.h>
+#include <ui/DisplayStatInfo.h>
 
 #include <gui/BitTube.h>
 #include <gui/BufferQueue.h>
@@ -603,6 +604,19 @@
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& display,
+        DisplayStatInfo* stats) {
+    if (stats == NULL) {
+        return BAD_VALUE;
+    }
+
+    // FIXME for now we always return stats for the primary display
+    memset(stats, 0, sizeof(*stats));
+    stats->vsyncTime   = mPrimaryDispSync.computeNextRefresh(0);
+    stats->vsyncPeriod = mPrimaryDispSync.getPeriod();
+    return NO_ERROR;
+}
+
 int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
     return getDisplayDevice(display)->getActiveConfig();
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 26f0acf..2cc522b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -206,6 +206,8 @@
             Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool useIdentityTransform, ISurfaceComposer::Rotation rotation);
+    virtual status_t getDisplayStats(const sp<IBinder>& display,
+            DisplayStatInfo* stats);
     virtual status_t getDisplayConfigs(const sp<IBinder>& display,
             Vector<DisplayInfo>* configs);
     virtual int getActiveConfig(const sp<IBinder>& display);