Time duration blocked on dequeueBuffer for stuffing recovery

Start buffer stuffing recovery only when severely buffer stuffed.
Determined based on how long BBQ waits on buffer release. Waits
shorter than this may simply be false positives for buffer stuffing
recovery due to timing and should be ignored.

Bug: b/294922229
Test: Manually check perfetto traces, presubmit, SysUi performance tests
Flag: android.view.flags.buffer_stuffing_recovery
Change-Id: Ic8c01edaebd599724fc7a9a67630069c05b567c1
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 24d858c..0848fac 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -1221,16 +1221,12 @@
 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
     status_t waitForBufferRelease(std::unique_lock<std::mutex>& bufferQueueLock,
                                   nsecs_t timeout) const override {
+        const auto startTime = std::chrono::steady_clock::now();
         sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
         if (!bbq) {
             return OK;
         }
 
-        // Provide a callback for Choreographer to start buffer stuffing recovery when blocked
-        // on buffer release.
-        std::function<void()> callbackCopy = bbq->getWaitForBufferReleaseCallback();
-        if (callbackCopy) callbackCopy();
-
         // BufferQueue has already checked if we have a free buffer. If there's an unread interrupt,
         // we want to ignore it. This must be done before unlocking the BufferQueue lock to ensure
         // we don't miss an interrupt.
@@ -1252,6 +1248,14 @@
         }
 
         bbq->releaseBufferCallback(id, fence, maxAcquiredBufferCount);
+        const nsecs_t durationNanos = std::chrono::duration_cast<std::chrono::nanoseconds>(
+                                              std::chrono::steady_clock::now() - startTime)
+                                              .count();
+        // Provide a callback for Choreographer to start buffer stuffing recovery when blocked
+        // on buffer release.
+        std::function<void(const nsecs_t)> callbackCopy = bbq->getWaitForBufferReleaseCallback();
+        if (callbackCopy) callbackCopy(durationNanos);
+
         return OK;
     }
 #endif
@@ -1343,12 +1347,13 @@
     mApplyToken = std::move(applyToken);
 }
 
-void BLASTBufferQueue::setWaitForBufferReleaseCallback(std::function<void()> callback) {
+void BLASTBufferQueue::setWaitForBufferReleaseCallback(
+        std::function<void(const nsecs_t)> callback) {
     std::lock_guard _lock{mWaitForBufferReleaseMutex};
     mWaitForBufferReleaseCallback = std::move(callback);
 }
 
-std::function<void()> BLASTBufferQueue::getWaitForBufferReleaseCallback() const {
+std::function<void(const nsecs_t)> BLASTBufferQueue::getWaitForBufferReleaseCallback() const {
     std::lock_guard _lock{mWaitForBufferReleaseMutex};
     return mWaitForBufferReleaseCallback;
 }