Added vsync debugging information in dumpsys log

Change-Id: I20ef05a73d89caaf6a70dc9ca25ada6e6a1f6ff9
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 4e13377..6ae03c9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -32,6 +32,7 @@
 #include <hardware/hwcomposer.h>
 
 #include <cutils/log.h>
+#include <cutils/properties.h>
 
 #include <EGL/egl.h>
 
@@ -51,8 +52,13 @@
       mNumOVLayers(0), mNumFBLayers(0),
       mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE),
       mEventHandler(handler),
-      mRefreshPeriod(refreshPeriod), mVSyncCount(0)
+      mRefreshPeriod(refreshPeriod),
+      mVSyncCount(0), mDebugForceFakeVSync(false)
 {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.sf.no_hw_vsync", value, "0");
+    mDebugForceFakeVSync = atoi(value);
+
     bool needVSyncThread = false;
     int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
     ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
@@ -68,7 +74,12 @@
                 mHwc->registerProcs(mHwc, &mCBContext.procs);
                 memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero));
             }
-            if (mHwc->common.version < HWC_DEVICE_API_VERSION_0_3) {
+            if (mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
+                if (mDebugForceFakeVSync) {
+                    // make sure to turn h/w vsync off in "fake vsync" mode
+                    mHwc->methods->eventControl(mHwc, HWC_EVENT_VSYNC, 0);
+                }
+            } else {
                 needVSyncThread = true;
             }
         }
@@ -83,6 +94,7 @@
 }
 
 HWComposer::~HWComposer() {
+    eventControl(EVENT_VSYNC, 0);
     free(mList);
     if (mVSyncThread != NULL) {
         mVSyncThread->requestExitAndWait();
@@ -116,7 +128,9 @@
 status_t HWComposer::eventControl(int event, int enabled) {
     status_t err = NO_ERROR;
     if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
-        err = mHwc->methods->eventControl(mHwc, event, enabled);
+        if (!mDebugForceFakeVSync) {
+            err = mHwc->methods->eventControl(mHwc, event, enabled);
+        }
     }
 
     if (err == NO_ERROR && mVSyncThread != NULL) {
@@ -219,10 +233,10 @@
         const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
     if (mHwc && mList) {
         result.append("Hardware Composer state:\n");
-
-        snprintf(buffer, SIZE, "  numHwLayers=%u, flags=%08x\n",
+        result.appendFormat("  mDebugForceFakeVSync=%d\n",
+                mDebugForceFakeVSync);
+        result.appendFormat("  numHwLayers=%u, flags=%08x\n",
                 mList->numHwLayers, mList->flags);
-        result.append(buffer);
         result.append(
                 "   type   |  handle  |   hints  |   flags  | tr | blend |  format  |       source crop         |           frame           name \n"
                 "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
@@ -237,17 +251,16 @@
                     format = buffer->getPixelFormat();
                 }
             }
-            snprintf(buffer, SIZE,
+            result.appendFormat(
                     " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
                     l.compositionType ? "OVERLAY" : "FB",
                     intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
                     l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
                     l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
                     layer->getName().string());
-            result.append(buffer);
         }
     }
-    if (mHwc && mHwc->common.version >= 1 && mHwc->dump) {
+    if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_1 && mHwc->dump) {
         mHwc->dump(mHwc, buffer, SIZE);
         result.append(buffer);
     }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 7814594..76aadf8 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -144,6 +144,7 @@
     nsecs_t                 mRefreshPeriod;
     size_t                  mVSyncCount;
     sp<VSyncThread>         mVSyncThread;
+    bool                    mDebugForceFakeVSync;
 };
 
 
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index cc44186..5813eefb 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -41,7 +41,8 @@
       mHw(flinger->graphicPlane(0).editDisplayHardware()),
       mLastVSyncTimestamp(0),
       mVSyncTimestamp(0),
-      mDeliveredEvents(0)
+      mDeliveredEvents(0),
+      mDebugVsyncEnabled(false)
 {
 }
 
@@ -144,8 +145,7 @@
                 if (!waitForNextVsync) {
                     // we received a VSYNC but we have no clients
                     // don't report it, and disable VSYNC events
-                    mHw.getHwComposer().eventControl(
-                            HWComposer::EVENT_VSYNC, false);
+                    disableVSync();
                 } else {
                     // report VSYNC event
                     break;
@@ -157,8 +157,7 @@
                 // disable VSYNC events then.
                 if (waitForNextVsync) {
                     // enable
-                    mHw.getHwComposer().eventControl(
-                            HWComposer::EVENT_VSYNC, true);
+                    enableVSync();
                 }
             }
 
@@ -234,6 +233,16 @@
     return true;
 }
 
+void EventThread::enableVSync() {
+    mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, true);
+    mDebugVsyncEnabled = true;
+}
+
+void EventThread::disableVSync() {
+    mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, false);
+    mDebugVsyncEnabled = false;
+}
+
 status_t EventThread::readyToRun() {
     ALOGI("EventThread ready to run.");
     return NO_ERROR;
@@ -241,10 +250,16 @@
 
 void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {
     Mutex::Autolock _l(mLock);
-    result.append("VSYNC state:\n");
-    snprintf(buffer, SIZE, "  numListeners=%u, events-delivered: %u\n",
+    result.appendFormat("VSYNC state: %s\n",
+            mDebugVsyncEnabled?"enabled":"disabled");
+    result.appendFormat("  numListeners=%u,\n  events-delivered: %u\n",
             mDisplayEventConnections.size(), mDeliveredEvents);
-    result.append(buffer);
+    for (size_t i=0 ; i<mDisplayEventConnections.size() ; i++) {
+        sp<Connection> connection =
+                mDisplayEventConnections.itemAt(i).promote();
+        result.appendFormat("    %p: count=%d\n",
+                connection.get(), connection!=NULL ? connection->count : 0);
+    }
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 3f9d452..2e237dd 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -81,9 +81,11 @@
     virtual bool        threadLoop();
     virtual status_t    readyToRun();
     virtual void        onFirstRef();
-    virtual void onVSyncReceived(int, nsecs_t timestamp);
+    virtual void        onVSyncReceived(int, nsecs_t timestamp);
 
     void removeDisplayEventConnection(const wp<Connection>& connection);
+    void enableVSync();
+    void disableVSync();
 
     // constants
     sp<SurfaceFlinger> mFlinger;
@@ -99,6 +101,9 @@
 
     // main thread only
     size_t mDeliveredEvents;
+
+    // for debugging
+    bool mDebugVsyncEnabled;
 };
 
 // ---------------------------------------------------------------------------