Reapply "Codec2Client: use IProducerListener for Codec2 hidl1.2"

This reverts commit c7c9a060755459340d838e5622e97f388e6e7391.

Change-Id: Iaadc5dc47562b435d09b33ad675729beb76b62cb
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index 597852a..e8e7cb2 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -2372,7 +2372,7 @@
 
 void Codec2Client::Component::onBufferReleasedFromOutputSurface(
         uint32_t generation) {
-    (void) generation;
+    mOutputBufferQueue->onBufferReleased(generation);
 }
 
 c2_status_t Codec2Client::Component::connectToInputSurface(
diff --git a/media/codec2/hal/client/include/codec2/hidl/output.h b/media/codec2/hal/client/include/codec2/hidl/output.h
index 2e89c3b..fda34a8 100644
--- a/media/codec2/hal/client/include/codec2/hidl/output.h
+++ b/media/codec2/hal/client/include/codec2/hidl/output.h
@@ -65,6 +65,10 @@
             const BnGraphicBufferProducer::QueueBufferInput& input,
             BnGraphicBufferProducer::QueueBufferOutput* output);
 
+    // Nofify a buffer is released from the output surface. If HAL ver is 1.2
+    // update the number of dequeueable/allocatable buffers.
+    void onBufferReleased(uint32_t generation);
+
     // Retrieve frame event history from the output surface.
     void pollForRenderedFrames(FrameEventHistoryDelta* delta);
 
diff --git a/media/codec2/hal/client/output.cpp b/media/codec2/hal/client/output.cpp
index 7f4f86b..36322f5 100644
--- a/media/codec2/hal/client/output.cpp
+++ b/media/codec2/hal/client/output.cpp
@@ -441,9 +441,11 @@
             status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
                                          input, output);
             if (status == OK) {
-                syncVar->lock();
-                syncVar->notifyQueuedLocked();
-                syncVar->unlock();
+                if (output->bufferReplaced) {
+                    syncVar->lock();
+                    syncVar->notifyQueuedLocked();
+                    syncVar->unlock();
+                }
             }
         } else {
             status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
@@ -496,9 +498,11 @@
         status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
                                                   input, output);
         if (status == OK) {
-            syncVar->lock();
-            syncVar->notifyQueuedLocked();
-            syncVar->unlock();
+            if (output->bufferReplaced) {
+                syncVar->lock();
+                syncVar->notifyQueuedLocked();
+                syncVar->unlock();
+            }
         }
     } else {
         status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
@@ -514,6 +518,30 @@
     return OK;
 }
 
+void OutputBufferQueue::onBufferReleased(uint32_t generation) {
+    std::shared_ptr<C2SurfaceSyncMemory> syncMem;
+    sp<IGraphicBufferProducer> outputIgbp;
+    uint32_t outputGeneration = 0;
+    {
+        std::unique_lock<std::mutex> l(mMutex);
+        if (mStopped) {
+            return;
+        }
+        outputIgbp = mIgbp;
+        outputGeneration = mGeneration;
+        syncMem = mSyncMem;
+    }
+
+    if (outputIgbp && generation == outputGeneration) {
+        auto syncVar = syncMem ? syncMem->mem() : nullptr;
+        if (syncVar) {
+            syncVar->lock();
+            syncVar->notifyQueuedLocked();
+            syncVar->unlock();
+        }
+    }
+}
+
 void OutputBufferQueue::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
     if (mIgbp) {
         mIgbp->getFrameTimestamps(delta);
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 0db3eec..514d622 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1131,7 +1131,14 @@
 }
 
 void CCodecBufferChannel::onBufferReleasedFromOutputSurface(uint32_t generation) {
-    mComponent->onBufferReleasedFromOutputSurface(generation);
+    // Note: Since this is called asynchronously from IProducerListener not
+    // knowing the internal state of CCodec/CCodecBufferChannel,
+    // prevent mComponent from being destroyed by holding the shared reference
+    // during this interface being executed.
+    std::shared_ptr<Codec2Client::Component> comp = mComponent;
+    if (comp) {
+        comp->onBufferReleasedFromOutputSurface(generation);
+    }
 }
 
 status_t CCodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {