DispSync: workaround HH hardware vsync issue

The HWC of HH seems to have a bug where it fails to generate vsync events upon
the first eventControl call to turn on HWC_EVENT_VSYNC.

The workaround is for DispSync to detect when it has received no resync samples
after many presents, and return false so that SF will disable HW vsync and
re-enable it in the next present. This gets the HWC of HH out of the bad state.

Bug:25845510
TEST=reboot HH then immediately capture systrace while scrolling all apps

Change-Id: Ie034c113d94ea53068eef75b8eac39a32788666a
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 5ba387d..e0d7339 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -322,6 +322,7 @@
     mNumResyncSamples = 0;
     mFirstResyncSample = 0;
     mNumResyncSamplesSincePresent = 0;
+    mNumPresentWithoutResyncSamples = 0;
     resetErrorLocked();
 }
 
@@ -346,6 +347,15 @@
 
     updateErrorLocked();
 
+    // This is a workaround for b/25845510.
+    // If we have no resync samples after many presents, something is wrong with
+    // HW vsync. Tell SF to disable HW vsync now and re-enable it next time.
+    if (mNumResyncSamples == 0 &&
+        mNumPresentWithoutResyncSamples++ > MAX_PRESENT_WITHOUT_RESYNC_SAMPLES) {
+        mNumPresentWithoutResyncSamples = 0;
+        return false;
+    }
+
     return !mModelUpdated || mError > kErrorThreshold;
 }
 
@@ -354,6 +364,7 @@
 
     mModelUpdated = false;
     mNumResyncSamples = 0;
+    mNumPresentWithoutResyncSamples = 0;
 }
 
 bool DispSync::addResyncSample(nsecs_t timestamp) {
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index a8524b9..1ee0865 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -140,6 +140,7 @@
     enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 3 };
     enum { NUM_PRESENT_SAMPLES = 8 };
     enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
+    enum { MAX_PRESENT_WITHOUT_RESYNC_SAMPLES = 8 };
 
     // mPeriod is the computed period of the modeled vsync events in
     // nanoseconds.
@@ -168,6 +169,7 @@
     size_t mFirstResyncSample;
     size_t mNumResyncSamples;
     int mNumResyncSamplesSincePresent;
+    int mNumPresentWithoutResyncSamples;
 
     // These member variables store information about the present fences used
     // to validate the currently computed model.