DO NOT MERGE Add "dumpsys SurfaceFlinger --dispsync"

Dumps the current DispSync state.

Bug 14651879

(this is a near-cherrypick of Ide4e6dbd58b117bc1a6b97b57d10cd92ec86dc84)

Change-Id: I6e6c8452ede5c2d5098db1b884d28226e77d9a03
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index ce07ab5..c51d207 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -20,6 +20,7 @@
 #define __STDC_LIMIT_MACROS
 
 #include <math.h>
+#include <inttypes.h>
 
 #include <cutils/log.h>
 
@@ -487,4 +488,49 @@
     }
 }
 
+void DispSync::dump(String8& result) const {
+    Mutex::Autolock lock(mMutex);
+    result.appendFormat("mPeriod: %"PRId64" ns\n", mPeriod);
+    result.appendFormat("mPhase: %"PRId64" ns\n", mPhase);
+    result.appendFormat("mError: %"PRId64" ns (sqrt: %.1f)\n",
+            mError, sqrt(mError));
+    result.appendFormat("mNumResyncSamplesSincePresent: %d (max %d)\n",
+            mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT);
+    result.appendFormat("mNumResyncSamples: %d (max %d)\n",
+            mNumResyncSamples, MAX_RESYNC_SAMPLES);
+
+    result.appendFormat("mResyncSamples:\n");
+    nsecs_t previous = -1;
+    for (size_t i = 0; i < mNumResyncSamples; i++) {
+        size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
+        nsecs_t sampleTime = mResyncSamples[idx];
+        if (i == 0) {
+            result.appendFormat("  %"PRId64"\n", sampleTime);
+        } else {
+            result.appendFormat("  %"PRId64" (+%"PRId64")\n",
+                    sampleTime, sampleTime - previous);
+        }
+        previous = sampleTime;
+    }
+
+    result.appendFormat("mPresentFences / mPresentTimes [%d]:\n",
+            NUM_PRESENT_SAMPLES);
+    previous = 0;
+    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
+        size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES;
+        bool signaled = mPresentFences[idx] == NULL;
+        nsecs_t presentTime = mPresentTimes[idx];
+        if (!signaled) {
+            result.appendFormat("  [unsignaled fence]\n");
+        } else if (previous == 0) {
+            result.appendFormat("  %"PRId64"\n", presentTime);
+        } else {
+            result.appendFormat("  %"PRId64" (+%"PRId64" / %.3f)\n",
+                    presentTime, presentTime - previous,
+                    (presentTime - previous) / (double) mPeriod);
+        }
+        previous = presentTime;
+    }
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index c4280aa..19eb3e5 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -99,6 +99,9 @@
     // DispSync object.
     status_t removeEventListener(const sp<Callback>& callback);
 
+    // dump appends human-readable debug info to the result string.
+    void dump(String8& result) const;
+
 private:
 
     void updateModelLocked();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1a9a694..b1db870 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2201,6 +2201,13 @@
                 clearStatsLocked(args, index, result);
                 dumpAll = false;
             }
+
+            if ((index < numArgs) &&
+                    (args[index] == String16("--dispsync"))) {
+                index++;
+                mPrimaryDispSync.dump(result);
+                dumpAll = false;
+            }
         }
 
         if (dumpAll) {
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index b161480..90e3f7d 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -27,7 +27,7 @@
 
 using namespace android;
 
-int main(int argc, char** argv) {
+int main(int, char**) {
     // When SF is launched in its own process, limit the number of
     // binder threads to 4.
     ProcessState::self()->setThreadPoolMaxThreadCount(4);