Migrate buffers during surface change

Migrate graphic buffers during surface change in order to avoid
BufferQueue handling complexity later on.

Test: Manually using Chrome and google photo app
Bug: 132302078
Bug: 130862880
Change-Id: Ifb348b5d6a8f5a89dcc10a9f0be075057a5d3a6d
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 6aca4a3..2b417a6 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -1080,15 +1080,7 @@
 void Codec2Client::Component::handleOnWorkDone(
         const std::list<std::unique_ptr<C2Work>> &workItems) {
     // Output bufferqueue-based blocks' lifetime management
-    mOutputBufferQueueMutex.lock();
-    sp<IGraphicBufferProducer> igbp = mOutputIgbp;
-    uint64_t bqId = mOutputBqId;
-    uint32_t generation = mOutputGeneration;
-    mOutputBufferQueueMutex.unlock();
-
-    if (igbp) {
-        holdBufferQueueBlocks(workItems, igbp, bqId, generation);
-    }
+    mOutputBufferQueue.holdBufferQueueBlocks(workItems);
 }
 
 c2_status_t Codec2Client::Component::queue(
@@ -1151,15 +1143,7 @@
     }
 
     // Output bufferqueue-based blocks' lifetime management
-    mOutputBufferQueueMutex.lock();
-    sp<IGraphicBufferProducer> igbp = mOutputIgbp;
-    uint64_t bqId = mOutputBqId;
-    uint32_t generation = mOutputGeneration;
-    mOutputBufferQueueMutex.unlock();
-
-    if (igbp) {
-        holdBufferQueueBlocks(*flushedWork, igbp, bqId, generation);
-    }
+    mOutputBufferQueue.holdBufferQueueBlocks(*flushedWork);
 
     return status;
 }
@@ -1239,15 +1223,31 @@
         C2BlockPool::local_id_t blockPoolId,
         const sp<IGraphicBufferProducer>& surface,
         uint32_t generation) {
-    sp<HGraphicBufferProducer2> igbp =
-            surface->getHalInterface<HGraphicBufferProducer2>();
+    uint64_t bqId = 0;
+    sp<IGraphicBufferProducer> nullIgbp;
+    sp<HGraphicBufferProducer2> nullHgbp;
 
-    if (!igbp) {
+    sp<HGraphicBufferProducer2> igbp = surface ?
+            surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
+    if (surface && !igbp) {
         igbp = new B2HGraphicBufferProducer2(surface);
     }
 
+    if (!surface) {
+        mOutputBufferQueue.configure(nullIgbp, generation, 0);
+    } else if (surface->getUniqueId(&bqId) != OK) {
+        LOG(ERROR) << "setOutputSurface -- "
+                   "cannot obtain bufferqueue id.";
+        bqId = 0;
+        mOutputBufferQueue.configure(nullIgbp, generation, 0);
+    } else {
+        mOutputBufferQueue.configure(surface, generation, bqId);
+    }
+    ALOGD("generation remote change %u", generation);
+
     Return<Status> transStatus = mBase->setOutputSurface(
-            static_cast<uint64_t>(blockPoolId), igbp);
+            static_cast<uint64_t>(blockPoolId),
+            bqId == 0 ? nullHgbp : igbp);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "setOutputSurface -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1256,18 +1256,6 @@
             static_cast<c2_status_t>(static_cast<Status>(transStatus));
     if (status != C2_OK) {
         LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
-    } else {
-        std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
-        if (mOutputIgbp != surface) {
-            mOutputIgbp = surface;
-            if (!surface) {
-                mOutputBqId = 0;
-            } else if (surface->getUniqueId(&mOutputBqId) != OK) {
-                LOG(ERROR) << "setOutputSurface -- "
-                              "cannot obtain bufferqueue id.";
-            }
-        }
-        mOutputGeneration = generation;
     }
     return status;
 }
@@ -1276,74 +1264,7 @@
         const C2ConstGraphicBlock& block,
         const QueueBufferInput& input,
         QueueBufferOutput* output) {
-    uint32_t generation;
-    uint64_t bqId;
-    int32_t bqSlot;
-    if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
-            bqId == 0) {
-        // Block not from bufferqueue -- it must be attached before queuing.
-
-        mOutputBufferQueueMutex.lock();
-        sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
-        uint32_t outputGeneration = mOutputGeneration;
-        mOutputBufferQueueMutex.unlock();
-
-        status_t status = attachToBufferQueue(block,
-                                               outputIgbp,
-                                               outputGeneration,
-                                               &bqSlot);
-        if (status != OK) {
-            LOG(WARNING) << "queueToOutputSurface -- attaching failed.";
-            return INVALID_OPERATION;
-        }
-
-        status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
-                                         input, output);
-        if (status != OK) {
-            LOG(ERROR) << "queueToOutputSurface -- queueBuffer() failed "
-                          "on non-bufferqueue-based block. "
-                          "Error = " << status << ".";
-            return status;
-        }
-        return OK;
-    }
-
-    mOutputBufferQueueMutex.lock();
-    sp<IGraphicBufferProducer> outputIgbp = mOutputIgbp;
-    uint64_t outputBqId = mOutputBqId;
-    uint32_t outputGeneration = mOutputGeneration;
-    mOutputBufferQueueMutex.unlock();
-
-    if (!outputIgbp) {
-        LOG(VERBOSE) << "queueToOutputSurface -- output surface is null.";
-        return NO_INIT;
-    }
-
-    if (bqId != outputBqId || generation != outputGeneration) {
-        if (!holdBufferQueueBlock(block, mOutputIgbp, mOutputBqId, mOutputGeneration)) {
-            LOG(ERROR) << "queueToOutputSurface -- migration failed.";
-            return DEAD_OBJECT;
-        }
-        if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot)) {
-            LOG(ERROR) << "queueToOutputSurface -- corrupted bufferqueue assignment.";
-            return UNKNOWN_ERROR;
-        }
-    }
-
-    status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
-                                              input, output);
-    if (status != OK) {
-        LOG(DEBUG) << "queueToOutputSurface -- queueBuffer() failed "
-                      "on bufferqueue-based block. "
-                      "Error = " << status << ".";
-        return status;
-    }
-    if (!yieldBufferQueueBlock(block)) {
-        LOG(DEBUG) << "queueToOutputSurface -- cannot yield "
-                      "bufferqueue-based block to the bufferqueue.";
-        return UNKNOWN_ERROR;
-    }
-    return OK;
+    return mOutputBufferQueue.outputBuffer(block, input, output);
 }
 
 c2_status_t Codec2Client::Component::connectToInputSurface(