Fixing triple buffer bug

Bug: 141939236
Test: build, boot, libgui_test, manual
Change-Id: I2d7b2e70142fa04825f02580425e7899c7c56d45
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index b9cf9e1..a5e5693 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -17,10 +17,14 @@
 #undef LOG_TAG
 #define LOG_TAG "BLASTBufferQueue"
 
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
 #include <gui/BLASTBufferQueue.h>
 #include <gui/BufferItemConsumer.h>
 #include <gui/GLConsumer.h>
 
+#include <utils/Trace.h>
+
 #include <chrono>
 
 using namespace std::chrono_literals;
@@ -29,23 +33,29 @@
 
 BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)
       : mSurfaceControl(surface),
-        mPendingCallbacks(0),
         mWidth(width),
         mHeight(height),
         mNextTransaction(nullptr) {
     BufferQueue::createBufferQueue(&mProducer, &mConsumer);
     mConsumer->setMaxBufferCount(MAX_BUFFERS);
     mProducer->setMaxDequeuedBufferCount(MAX_BUFFERS - 1);
+    mConsumer->setMaxAcquiredBufferCount(MAX_ACQUIRED_BUFFERS);
     mBufferItemConsumer =
             new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
-    mBufferItemConsumer->setName(String8("BLAST Consumer"));
+    static int32_t id = 0;
+    auto name = std::string("BLAST Consumer") + std::to_string(id);
+    id++;
+    mBufferItemConsumer->setName(String8(name.c_str()));
     mBufferItemConsumer->setFrameAvailableListener(this);
     mBufferItemConsumer->setBufferFreedListener(this);
     mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
     mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888);
     mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint());
 
-    mAcquired = false;
+    mNumAcquired = 0;
+    mNumFrameAvailable = 0;
+    mPendingReleaseItem.item = BufferItem();
+    mPendingReleaseItem.releaseFence = nullptr;
 }
 
 void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) {
@@ -70,34 +80,46 @@
 void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
                                            const std::vector<SurfaceControlStats>& stats) {
     std::unique_lock _lock{mMutex};
+    ATRACE_CALL();
 
-    if (stats.size() > 0 && !mShadowQueue.empty()) {
-        mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem,
-                                           stats[0].previousReleaseFence
-                                                   ? stats[0].previousReleaseFence
+    if (mPendingReleaseItem.item.mGraphicBuffer != nullptr) {
+        if (stats.size() > 0) {
+            mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence;
+            mTransformHint = stats[0].transformHint;
+        } else {
+            ALOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback");
+            mPendingReleaseItem.releaseFence = nullptr;
+        }
+        mBufferItemConsumer->releaseBuffer(mPendingReleaseItem.item,
+                                           mPendingReleaseItem.releaseFence
+                                                   ? mPendingReleaseItem.releaseFence
                                                    : Fence::NO_FENCE);
-        mAcquired = false;
-        mNextCallbackBufferItem = BufferItem();
-        mBufferItemConsumer->setTransformHint(stats[0].transformHint);
+        mNumAcquired--;
+        mPendingReleaseItem.item = BufferItem();
+        mPendingReleaseItem.releaseFence = nullptr;
     }
-    mPendingCallbacks--;
+
+    if (mSubmitted.empty()) {
+        ALOGE("ERROR: callback with no corresponding submitted buffer item");
+    }
+    mPendingReleaseItem.item = std::move(mSubmitted.front());
+    mSubmitted.pop();
     processNextBufferLocked();
     mCallbackCV.notify_all();
     decStrong((void*)transactionCallbackThunk);
 }
 
 void BLASTBufferQueue::processNextBufferLocked() {
-    if (mShadowQueue.empty()) {
+    ATRACE_CALL();
+    if (mNumFrameAvailable == 0) {
         return;
     }
 
-    if (mAcquired) {
+    if (mSurfaceControl == nullptr) {
+        ALOGE("ERROR : surface control is null");
         return;
     }
 
-    BufferItem item = std::move(mShadowQueue.front());
-    mShadowQueue.pop();
-
     SurfaceComposerClient::Transaction localTransaction;
     bool applyTransaction = true;
     SurfaceComposerClient::Transaction* t = &localTransaction;
@@ -107,33 +129,34 @@
         applyTransaction = false;
     }
 
-    mNextCallbackBufferItem = mLastSubmittedBufferItem;
-    mLastSubmittedBufferItem = BufferItem();
+    BufferItem bufferItem;
 
-    status_t status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false);
-    mAcquired = true;
+    status_t status = mBufferItemConsumer->acquireBuffer(&bufferItem, -1, false);
     if (status != OK) {
-        ALOGE("Failed to acquire?");
-    }
-
-    auto buffer = mLastSubmittedBufferItem.mGraphicBuffer;
-
-    if (buffer == nullptr) {
-        ALOGE("Null buffer");
         return;
     }
+    auto buffer = bufferItem.mGraphicBuffer;
+    mNumFrameAvailable--;
+
+    if (buffer == nullptr) {
+        mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
+        return;
+    }
+
+    mNumAcquired++;
+    mSubmitted.push(bufferItem);
 
     // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
     incStrong((void*)transactionCallbackThunk);
 
     t->setBuffer(mSurfaceControl, buffer);
     t->setAcquireFence(mSurfaceControl,
-                       item.mFence ? new Fence(item.mFence->dup()) : Fence::NO_FENCE);
+                       bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE);
     t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
 
     t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
-    t->setCrop(mSurfaceControl, computeCrop(mLastSubmittedBufferItem));
-    t->setTransform(mSurfaceControl, mLastSubmittedBufferItem.mTransform);
+    t->setCrop(mSurfaceControl, computeCrop(bufferItem));
+    t->setTransform(mSurfaceControl, bufferItem.mTransform);
 
     if (applyTransaction) {
         t->apply();
@@ -147,13 +170,13 @@
     return item.mCrop;
 }
 
-void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
+void BLASTBufferQueue::onFrameAvailable(const BufferItem& /*item*/) {
+    ATRACE_CALL();
     std::lock_guard _lock{mMutex};
 
     // add to shadow queue
-    mShadowQueue.push(item);
+    mNumFrameAvailable++;
     processNextBufferLocked();
-    mPendingCallbacks++;
 }
 
 void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {