Block on BufferReleaseChannel when out of buffers

Bug: 294133380
Flag: com.android.graphics.libgui.flags.buffer_release_channel
Test: BLASTBufferQueueTest
Change-Id: I4ffec81ffb9c26546cc50176f3c44ffe6eb90b75
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index da74e9c..e58233c 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -202,7 +202,11 @@
         if (delta < 0) {
             listener = mCore->mConsumerListener;
         }
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+        mCore->notifyBufferReleased();
+#else
         mCore->mDequeueCondition.notify_all();
+#endif
     } // Autolock scope
 
     // Call back without lock held
@@ -254,7 +258,12 @@
         }
         mCore->mAsyncMode = async;
         VALIDATE_CONSISTENCY();
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+        mCore->notifyBufferReleased();
+#else
         mCore->mDequeueCondition.notify_all();
+#endif
+
         if (delta < 0) {
             listener = mCore->mConsumerListener;
         }
@@ -376,6 +385,12 @@
                     (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
                 return WOULD_BLOCK;
             }
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+            if (status_t status = waitForBufferRelease(lock, mDequeueTimeout);
+                status == TIMED_OUT) {
+                return TIMED_OUT;
+            }
+#else
             if (mDequeueTimeout >= 0) {
                 std::cv_status result = mCore->mDequeueCondition.wait_for(lock,
                         std::chrono::nanoseconds(mDequeueTimeout));
@@ -385,12 +400,29 @@
             } else {
                 mCore->mDequeueCondition.wait(lock);
             }
+#endif
         }
     } // while (tryAgain)
 
     return NO_ERROR;
 }
 
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+status_t BufferQueueProducer::waitForBufferRelease(std::unique_lock<std::mutex>& lock,
+                                                   nsecs_t timeout) const {
+    if (mDequeueTimeout >= 0) {
+        std::cv_status result =
+                mCore->mDequeueCondition.wait_for(lock, std::chrono::nanoseconds(timeout));
+        if (result == std::cv_status::timeout) {
+            return TIMED_OUT;
+        }
+    } else {
+        mCore->mDequeueCondition.wait(lock);
+    }
+    return OK;
+}
+#endif
+
 status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
                                             uint32_t width, uint32_t height, PixelFormat format,
                                             uint64_t usage, uint64_t* outBufferAge,
@@ -741,7 +773,11 @@
         mCore->mActiveBuffers.erase(slot);
         mCore->mFreeSlots.insert(slot);
         mCore->clearBufferSlotLocked(slot);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+        mCore->notifyBufferReleased();
+#else
         mCore->mDequeueCondition.notify_all();
+#endif
         VALIDATE_CONSISTENCY();
     }
 
@@ -1082,7 +1118,11 @@
         }
 
         mCore->mBufferHasBeenQueued = true;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+        mCore->notifyBufferReleased();
+#else
         mCore->mDequeueCondition.notify_all();
+#endif
         mCore->mLastQueuedSlot = slot;
 
         output->width = mCore->mDefaultWidth;
@@ -1218,7 +1258,11 @@
             bufferId = gb->getId();
         }
         mSlots[slot].mFence = fence;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+        mCore->notifyBufferReleased();
+#else
         mCore->mDequeueCondition.notify_all();
+#endif
         listener = mCore->mConsumerListener;
         VALIDATE_CONSISTENCY();
     }
@@ -1457,7 +1501,11 @@
                     mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
                     mCore->mConnectedPid = -1;
                     mCore->mSidebandStream.clear();
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+                    mCore->notifyBufferReleased();
+#else
                     mCore->mDequeueCondition.notify_all();
+#endif
                     mCore->mAutoPrerotation = false;
 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
                     mCore->mAdditionalOptions.clear();