Merge \\"Consider queue & dequeue times for should draw\\" into nyc-mr1-dev am: 3a465e7a12
am: 6354336493

Change-Id: Idbe85f08c27cc6f9433badd886a1fe7d9ba73c4f
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 0a48a0c..27a15e0 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -197,6 +197,45 @@
     return info && ((*info)[FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame);
 }
 
+bool CanvasContext::isSwapChainStuffed() {
+    if (mSwapHistory.size() != mSwapHistory.capacity()) {
+        // We want at least 3 frames of history before attempting to
+        // guess if the queue is stuffed
+        return false;
+    }
+    nsecs_t frameInterval = mRenderThread.timeLord().frameIntervalNanos();
+    auto& swapA = mSwapHistory[0];
+
+    // Was there a happy queue & dequeue time? If so, don't
+    // consider it stuffed
+    if (swapA.dequeueDuration < 3_ms
+            && swapA.queueDuration < 3_ms) {
+        return false;
+    }
+
+    for (size_t i = 1; i < mSwapHistory.size(); i++) {
+        auto& swapB = mSwapHistory[i];
+
+        // If there's a frameInterval gap we effectively already dropped a frame,
+        // so consider the queue healthy.
+        if (swapA.swapCompletedTime - swapB.swapCompletedTime > frameInterval) {
+            return false;
+        }
+
+        // Was there a happy queue & dequeue time? If so, don't
+        // consider it stuffed
+        if (swapB.dequeueDuration < 3_ms
+                && swapB.queueDuration < 3_ms) {
+            return false;
+        }
+
+        swapA = swapB;
+    }
+
+    // All signs point to a stuffed swap chain
+    return true;
+}
+
 void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
         int64_t syncQueued, RenderNode* target) {
     mRenderThread.removeFrameCallback(this);
@@ -242,7 +281,12 @@
 
     if (CC_LIKELY(mSwapHistory.size() && !Properties::forceDrawFrame)) {
         nsecs_t latestVsync = mRenderThread.timeLord().latestVsync();
-        const SwapHistory& lastSwap = mSwapHistory.back();
+        SwapHistory& lastSwap = mSwapHistory.back();
+        int durationUs;
+        mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs);
+        lastSwap.dequeueDuration = us2ns(durationUs);
+        mNativeSurface->query(NATIVE_WINDOW_LAST_QUEUE_DURATION, &durationUs);
+        lastSwap.queueDuration = us2ns(durationUs);
         nsecs_t vsyncDelta = std::abs(lastSwap.vsyncTime - latestVsync);
         // The slight fudge-factor is to deal with cases where
         // the vsync was estimated due to being slow handling the signal.
@@ -252,15 +296,12 @@
             // Already drew for this vsync pulse, UI draw request missed
             // the deadline for RT animations
             info.out.canDrawThisFrame = false;
-        } else if (lastSwap.swapTime < latestVsync) {
+        } else if (vsyncDelta >= mRenderThread.timeLord().frameIntervalNanos()) {
+            // It's been at least an entire frame interval, assume
+            // the buffer queue is fine
             info.out.canDrawThisFrame = true;
         } else {
-            // We're maybe behind? Find out for sure
-            int runningBehind = 0;
-            // TODO: Have this method be on Surface, too, not just ANativeWindow...
-            ANativeWindow* window = mNativeSurface.get();
-            window->query(window, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
-            info.out.canDrawThisFrame = !runningBehind;
+            info.out.canDrawThisFrame = !isSwapChainStuffed();
         }
     } else {
         info.out.canDrawThisFrame = true;
@@ -515,7 +556,7 @@
         }
         SwapHistory& swap = mSwapHistory.next();
         swap.damage = screenDirty;
-        swap.swapTime = systemTime(CLOCK_MONOTONIC);
+        swap.swapCompletedTime = systemTime(CLOCK_MONOTONIC);
         swap.vsyncTime = mRenderThread.timeLord().latestVsync();
         mHaveNewSurface = false;
         mFrameNumber = -1;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 528e29e..40e4118 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -178,6 +178,8 @@
 
     void waitOnFences();
 
+    bool isSwapChainStuffed();
+
     EGLint mLastFrameWidth = 0;
     EGLint mLastFrameHeight = 0;
 
@@ -196,7 +198,9 @@
     struct SwapHistory {
         SkRect damage;
         nsecs_t vsyncTime;
-        nsecs_t swapTime;
+        nsecs_t swapCompletedTime;
+        nsecs_t dequeueDuration;
+        nsecs_t queueDuration;
     };
 
     RingBuffer<SwapHistory, 3> mSwapHistory;