Merge Android 14 QPR2 to AOSP main

Bug: 319669529
Merged-In: Id57ac546595fde736a32d17f61039b44107f413e
Change-Id: I2f803594c587ed291e5f86f82779cadc5c1a77e4
diff --git a/common/include/v4l2_codec2/common/V4L2Device.h b/common/include/v4l2_codec2/common/V4L2Device.h
index 77d7ddb..9824221 100644
--- a/common/include/v4l2_codec2/common/V4L2Device.h
+++ b/common/include/v4l2_codec2/common/V4L2Device.h
@@ -105,7 +105,7 @@
     // Do the actual queue operation once the v4l2_buffer structure is properly filled.
     bool doQueue() &&;
 
-    V4L2WritableBufferRef(const struct v4l2_buffer& v4l2Buffer, base::WeakPtr<V4L2Queue> queue);
+    V4L2WritableBufferRef(const struct v4l2_buffer& v4l2Buffer, ::base::WeakPtr<V4L2Queue> queue);
 
     V4L2WritableBufferRef(const V4L2WritableBufferRef&) = delete;
     V4L2WritableBufferRef& operator=(const V4L2WritableBufferRef&) = delete;
@@ -124,7 +124,7 @@
 // buffers they originate from. This flexibility is required because V4L2ReadableBufferRefs can be
 // embedded into VideoFrames, which are then passed to other threads and not necessarily destroyed
 // before the V4L2Queue buffers are freed.
-class V4L2ReadableBuffer : public base::RefCountedThreadSafe<V4L2ReadableBuffer> {
+class V4L2ReadableBuffer : public ::base::RefCountedThreadSafe<V4L2ReadableBuffer> {
 public:
     // Returns whether the V4L2_BUF_FLAG_LAST flag is set for this buffer.
     bool isLast() const;
@@ -148,11 +148,11 @@
 
 private:
     friend class V4L2BufferRefFactory;
-    friend class base::RefCountedThreadSafe<V4L2ReadableBuffer>;
+    friend class ::base::RefCountedThreadSafe<V4L2ReadableBuffer>;
 
     ~V4L2ReadableBuffer();
 
-    V4L2ReadableBuffer(const struct v4l2_buffer& v4l2Buffer, base::WeakPtr<V4L2Queue> queue);
+    V4L2ReadableBuffer(const struct v4l2_buffer& v4l2Buffer, ::base::WeakPtr<V4L2Queue> queue);
 
     V4L2ReadableBuffer(const V4L2ReadableBuffer&) = delete;
     V4L2ReadableBuffer& operator=(const V4L2ReadableBuffer&) = delete;
@@ -183,7 +183,7 @@
 //    metadata, as well as making other references to it. The buffer will not be reused until all
 //    the references are dropped. Once this happens, the buffer goes back to the free list described
 //    in 1).
-class V4L2Queue : public base::RefCountedThreadSafe<V4L2Queue> {
+class V4L2Queue : public ::base::RefCountedThreadSafe<V4L2Queue> {
 public:
     // Set |fourcc| as the current format on this queue. |size| corresponds to the desired buffer's
     // dimensions (i.e. width and height members of v4l2_pix_format_mplane (if not applicable, pass
@@ -206,10 +206,10 @@
                                                 size_t bufferSize) WARN_UNUSED_RESULT;
 
     // Returns the currently set format on the queue. The result is returned as a std::pair where
-    // the first member is the format, or base::nullopt if the format could not be obtained due to
-    // an ioctl error. The second member is only used in case of an error and contains the |errno|
-    // set by the failing ioctl. If the first member is not base::nullopt, the second member will
-    // always be zero.
+    // the first member is the format, or ::base::nullopt if the format could not be obtained due
+    // to an ioctl error. The second member is only used in case of an error and contains the
+    // |errno| set by the failing ioctl. If the first member is not ::base::nullopt, the second
+    // member will always be zero.
     //
     // If the second member is 0, then the first member is guaranteed to have a valid value. So
     // clients that are not interested in the precise error message can just check that the first
@@ -304,19 +304,20 @@
 
     scoped_refptr<V4L2Device> mDevice;
     // Callback to call in this queue's destructor.
-    base::OnceClosure mDestroyCb;
+    ::base::OnceClosure mDestroyCb;
 
-    V4L2Queue(scoped_refptr<V4L2Device> dev, enum v4l2_buf_type type, base::OnceClosure destroyCb);
+    V4L2Queue(scoped_refptr<V4L2Device> dev, enum v4l2_buf_type type,
+              ::base::OnceClosure destroyCb);
     friend class V4L2QueueFactory;
     friend class V4L2BufferRefBase;
-    friend class base::RefCountedThreadSafe<V4L2Queue>;
+    friend class ::base::RefCountedThreadSafe<V4L2Queue>;
 
     SEQUENCE_CHECKER(mSequenceChecker);
 
-    base::WeakPtrFactory<V4L2Queue> mWeakThisFactory{this};
+    ::base::WeakPtrFactory<V4L2Queue> mWeakThisFactory{this};
 };
 
-class V4L2Device : public base::RefCountedThreadSafe<V4L2Device> {
+class V4L2Device : public ::base::RefCountedThreadSafe<V4L2Device> {
 public:
     // Specification of an encoding profile supported by an encoder.
     struct SupportedEncodeProfile {
@@ -364,7 +365,7 @@
     // Composes human readable string of v4l2_buffer.
     static std::string v4L2BufferToString(const struct v4l2_buffer& buffer);
 
-    // Composes VideoFrameLayout based on v4l2_format. If error occurs, it returns base::nullopt.
+    // Composes VideoFrameLayout based on v4l2_format. If error occurs, it returns ::base::nullopt.
     static std::optional<VideoFrameLayout> v4L2FormatToVideoFrameLayout(
             const struct v4l2_format& format);
 
@@ -411,8 +412,8 @@
     // Return a vector of dmabuf file descriptors, exported for V4L2 buffer with |index|, assuming
     // the buffer contains |numPlanes| V4L2 planes and is of |bufType|. Return an empty vector on
     // failure. The caller is responsible for closing the file descriptors after use.
-    std::vector<base::ScopedFD> getDmabufsForV4L2Buffer(int index, size_t numPlanes,
-                                                        enum v4l2_buf_type bufType);
+    std::vector<::base::ScopedFD> getDmabufsForV4L2Buffer(int index, size_t numPlanes,
+                                                          enum v4l2_buf_type bufType);
 
     // Returns the preferred V4L2 input formats for |type| or empty if none.
     std::vector<uint32_t> preferredInputFormat(Type type);
@@ -440,7 +441,7 @@
     // be posted to the client's
     // sequence if a polling error has occurred.
     bool startPolling(android::V4L2DevicePoller::EventCallback eventCallback,
-                      base::RepeatingClosure errorCallback);
+                      ::base::RepeatingClosure errorCallback);
     // Stop polling this V4L2Device if polling was active. No new events will be posted after this
     // method has returned.
     bool stopPolling();
@@ -463,7 +464,7 @@
     // Vector of video device node paths and corresponding pixelformats supported by each device node.
     using Devices = std::vector<std::pair<std::string, std::vector<uint32_t>>>;
 
-    friend class base::RefCountedThreadSafe<V4L2Device>;
+    friend class ::base::RefCountedThreadSafe<V4L2Device>;
     V4L2Device();
     ~V4L2Device();
 
@@ -500,13 +501,13 @@
     std::map<V4L2Device::Type, Devices> mDevicesByType;
 
     // The actual device fd.
-    base::ScopedFD mDeviceFd;
+    ::base::ScopedFD mDeviceFd;
 
     // eventfd fd to signal device poll thread when its poll() should be interrupted.
-    base::ScopedFD mDevicePollInterruptFd;
+    ::base::ScopedFD mDevicePollInterruptFd;
 
     // Associates a v4l2_buf_type to its queue.
-    base::flat_map<enum v4l2_buf_type, V4L2Queue*> mQueues;
+    ::base::flat_map<enum v4l2_buf_type, V4L2Queue*> mQueues;
 
     // Used if EnablePolling() is called to signal the user that an event happened or a buffer is
     // ready to be dequeued.
diff --git a/common/include/v4l2_codec2/common/V4L2DevicePoller.h b/common/include/v4l2_codec2/common/V4L2DevicePoller.h
index ad256be..53b4b3f 100644
--- a/common/include/v4l2_codec2/common/V4L2DevicePoller.h
+++ b/common/include/v4l2_codec2/common/V4L2DevicePoller.h
@@ -32,7 +32,7 @@
 public:
     // Callback to be called when buffer ready/V4L2 event has potentially been polled. |event| is
     // set if a V4L2 event has been detected.
-    using EventCallback = base::RepeatingCallback<void(bool event)>;
+    using EventCallback = ::base::RepeatingCallback<void(bool event)>;
 
     // Create a poller for |device|, using a thread named |threadName|. Notification won't start
     // until |startPolling()| is called.
@@ -45,7 +45,7 @@
     // again in order to be notified for them.
     //
     // If an error occurs during polling, |mErrorCallback| will be posted on the caller's sequence.
-    bool startPolling(EventCallback eventCallback, base::RepeatingClosure errorCallback);
+    bool startPolling(EventCallback eventCallback, ::base::RepeatingClosure errorCallback);
     // Stop polling and stop the thread. The poller won't post any new event to the caller's
     // sequence after this method has returned.
     bool stopPolling();
@@ -66,19 +66,19 @@
     // V4L2 device we are polling.
     V4L2Device* const mDevice;
     // Thread on which polling is done.
-    base::Thread mPollThread;
+    ::base::Thread mPollThread;
     // Callback to post to the client's sequence when an event occurs.
     EventCallback mEventCallback;
     // Closure to post to the client's sequence when an error occurs.
-    base::RepeatingClosure mErrorCallback;
+    ::base::RepeatingClosure mErrorCallback;
     // Client sequence's task runner, where closures are posted.
-    scoped_refptr<base::SequencedTaskRunner> mClientTaskTunner;
+    scoped_refptr<::base::SequencedTaskRunner> mClientTaskTunner;
 
     // Since poll() returns immediately if no buffers have been queued, we cannot rely on it to
     // pause the polling thread until an event occurs. Instead,
     // the polling thread will wait on this WaitableEvent (signaled by |schedulePoll| before calling
     // poll(), so we only call it when we are actually waiting for an event.
-    base::WaitableEvent mTriggerPoll;
+    ::base::WaitableEvent mTriggerPoll;
     // Set to true when we wish to stop polling, instructing the poller thread to break its loop.
     std::atomic_bool mStopPolling;
 };
diff --git a/components/V4L2DecodeComponent.cpp b/components/V4L2DecodeComponent.cpp
index 456f3c4..2770b1e 100644
--- a/components/V4L2DecodeComponent.cpp
+++ b/components/V4L2DecodeComponent.cpp
@@ -30,7 +30,6 @@
 #include <v4l2_codec2/components/BitstreamBuffer.h>
 #include <v4l2_codec2/components/V4L2Decoder.h>
 #include <v4l2_codec2/components/VideoFramePool.h>
-#include <v4l2_codec2/plugin_store/C2VdaBqBlockPool.h>
 
 namespace android {
 namespace {
diff --git a/components/V4L2DecodeInterface.cpp b/components/V4L2DecodeInterface.cpp
index d22f77b..32483be 100644
--- a/components/V4L2DecodeInterface.cpp
+++ b/components/V4L2DecodeInterface.cpp
@@ -267,9 +267,9 @@
     const C2Allocator::id_t inputAllocators[] = {secureMode ? V4L2AllocatorId::SECURE_LINEAR
                                                             : C2AllocatorStore::DEFAULT_LINEAR};
 
-    const C2Allocator::id_t outputAllocators[] = {V4L2AllocatorId::V4L2_BUFFERPOOL};
+    const C2Allocator::id_t outputAllocators[] = {C2PlatformAllocatorStore::GRALLOC};
     const C2Allocator::id_t surfaceAllocator =
-            secureMode ? V4L2AllocatorId::SECURE_GRAPHIC : V4L2AllocatorId::V4L2_BUFFERQUEUE;
+            secureMode ? V4L2AllocatorId::SECURE_GRAPHIC : C2PlatformAllocatorStore::BUFFERQUEUE;
     const C2BlockPool::local_id_t outputBlockPools[] = {C2BlockPool::BASIC_GRAPHIC};
 
     addParameter(
diff --git a/components/V4L2EncodeComponent.cpp b/components/V4L2EncodeComponent.cpp
index f9d735d..b266a6e 100644
--- a/components/V4L2EncodeComponent.cpp
+++ b/components/V4L2EncodeComponent.cpp
@@ -517,6 +517,32 @@
                 reportError(status);
                 return;
             }
+        } else {
+            // Android encoder framework reuses the same gpu buffers as
+            // inputs and doesn't call lock/unlock explicitly between writes.
+            // If there is format conversion, this is fine since we will
+            // read back what we've written first and then put it in another
+            // buffer. Whenever there is no format conversion, this causes
+            // sync issue on ARCVM since host side buffers never get updated.
+            // Fix this by explicitly calling lock/unlock before sending buffer
+            // to encoder.
+            const C2Handle* handle = inputBlock.handle();
+            uint32_t width, height, format, stride, generation, igbpSlot;
+            uint64_t usage, igbpId;
+            _UnwrapNativeCodec2GrallocMetadata(handle, &width, &height, &format, &usage, &stride,
+                                               &generation, &igbpId, &igbpSlot);
+            do {
+                if (!(usage & GRALLOC_USAGE_SW_WRITE_MASK)) break;
+                native_handle_t* gralloc_handle = UnwrapNativeCodec2GrallocHandle(handle);
+                if (nullptr == gralloc_handle) break;
+                sp<GraphicBuffer> buffer =
+                        new GraphicBuffer(gralloc_handle, GraphicBuffer::CLONE_HANDLE, width,
+                                          height, format, 1, usage, stride);
+                native_handle_delete(gralloc_handle);
+                void* pixels;
+                if (buffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &pixels)) break;
+                buffer->unlock();
+            } while (0);
         }
         if (!encode(inputBlock, index, timestamp)) {
             return;
diff --git a/components/VideoFramePool.cpp b/components/VideoFramePool.cpp
index 665ff73..4bf45f3 100644
--- a/components/VideoFramePool.cpp
+++ b/components/VideoFramePool.cpp
@@ -10,6 +10,9 @@
 #include <stdint.h>
 #include <memory>
 
+#include <C2BlockInternal.h>
+#include <bufferpool/BufferPoolTypes.h>
+
 #include <android/hardware/graphics/common/1.0/types.h>
 #include <base/bind.h>
 #include <base/memory/ptr_util.h>
@@ -17,11 +20,11 @@
 #include <log/log.h>
 
 #include <v4l2_codec2/common/VideoTypes.h>
-#include <v4l2_codec2/plugin_store/C2VdaBqBlockPool.h>
-#include <v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h>
+#include <v4l2_codec2/plugin_store/DmabufHelpers.h>
 #include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::media::bufferpool::BufferPoolData;
 
 namespace android {
 
@@ -30,11 +33,32 @@
                                                                     const C2Block2D& block) {
     ALOGV("%s() blockPool.getAllocatorId() = %u", __func__, blockPool.getAllocatorId());
 
-    if (blockPool.getAllocatorId() == android::V4L2AllocatorId::V4L2_BUFFERPOOL) {
-        return C2VdaPooledBlockPool::getBufferIdFromGraphicBlock(block);
-    } else if (blockPool.getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
-        C2VdaBqBlockPool* bqPool = static_cast<C2VdaBqBlockPool*>(&blockPool);
-        return bqPool->getBufferIdFromGraphicBlock(block);
+    switch (blockPool.getAllocatorId()) {
+    case V4L2AllocatorId::SECURE_GRAPHIC:
+        FALLTHROUGH;
+    case C2PlatformAllocatorStore::BUFFERQUEUE: {
+        auto dmabufId = android::getDmabufId(block.handle()->data[0]);
+        if (!dmabufId) {
+            return std::nullopt;
+        }
+        return dmabufId.value();
+    }
+    case C2PlatformAllocatorStore::GRALLOC:
+        FALLTHROUGH;
+    case V4L2AllocatorId::SECURE_LINEAR: {
+        std::shared_ptr<_C2BlockPoolData> blockPoolData =
+                _C2BlockFactory::GetGraphicBlockPoolData(block);
+        if (blockPoolData->getType() != _C2BlockPoolData::TYPE_BUFFERPOOL) {
+            ALOGE("Obtained C2GraphicBlock is not bufferpool-backed.");
+            return std::nullopt;
+        }
+        std::shared_ptr<BufferPoolData> bpData;
+        if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData) || !bpData) {
+            ALOGE("BufferPoolData unavailable in block.");
+            return std::nullopt;
+        }
+        return bpData->mId;
+    }
     }
 
     ALOGE("%s(): unknown allocator ID: %u", __func__, blockPool.getAllocatorId());
@@ -42,35 +66,6 @@
 }
 
 // static
-c2_status_t VideoFramePool::requestNewBufferSet(C2BlockPool& blockPool, int32_t bufferCount,
-                                                const ui::Size& size, uint32_t format,
-                                                C2MemoryUsage usage) {
-    ALOGV("%s() blockPool.getAllocatorId() = %u", __func__, blockPool.getAllocatorId());
-
-    if (blockPool.getAllocatorId() == android::V4L2AllocatorId::V4L2_BUFFERPOOL) {
-        C2VdaPooledBlockPool* bpPool = static_cast<C2VdaPooledBlockPool*>(&blockPool);
-        return bpPool->requestNewBufferSet(bufferCount);
-    } else if (blockPool.getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
-        C2VdaBqBlockPool* bqPool = static_cast<C2VdaBqBlockPool*>(&blockPool);
-        return bqPool->requestNewBufferSet(bufferCount, size.width, size.height, format, usage);
-    }
-
-    ALOGE("%s(): unknown allocator ID: %u", __func__, blockPool.getAllocatorId());
-    return C2_BAD_VALUE;
-}
-
-// static
-bool VideoFramePool::setNotifyBlockAvailableCb(C2BlockPool& blockPool, ::base::OnceClosure cb) {
-    ALOGV("%s() blockPool.getAllocatorId() = %u", __func__, blockPool.getAllocatorId());
-
-    if (blockPool.getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
-        C2VdaBqBlockPool* bqPool = static_cast<C2VdaBqBlockPool*>(&blockPool);
-        return bqPool->setNotifyBlockAvailableCb(std::move(cb));
-    }
-    return false;
-}
-
-// static
 std::unique_ptr<VideoFramePool> VideoFramePool::Create(
         std::shared_ptr<C2BlockPool> blockPool, const size_t numBuffers, const ui::Size& size,
         HalPixelFormat pixelFormat, bool isSecure,
@@ -80,27 +75,25 @@
     uint64_t usage = static_cast<uint64_t>(BufferUsage::VIDEO_DECODER);
     if (isSecure) {
         usage |= C2MemoryUsage::READ_PROTECTED;
-    } else if (blockPool->getAllocatorId() == android::V4L2AllocatorId::V4L2_BUFFERPOOL) {
+    } else if (blockPool->getAllocatorId() == C2PlatformAllocatorStore::GRALLOC) {
         // CPU access to buffers is only required in byte buffer mode.
         usage |= C2MemoryUsage::CPU_READ;
     }
     const C2MemoryUsage memoryUsage(usage);
 
-    if (requestNewBufferSet(*blockPool, numBuffers, size, static_cast<uint32_t>(pixelFormat),
-                            memoryUsage) != C2_OK) {
-        return nullptr;
-    }
-
-    std::unique_ptr<VideoFramePool> pool = ::base::WrapUnique(new VideoFramePool(
-            std::move(blockPool), size, pixelFormat, memoryUsage, std::move(taskRunner)));
+    std::unique_ptr<VideoFramePool> pool =
+            ::base::WrapUnique(new VideoFramePool(std::move(blockPool), numBuffers, size,
+                                                  pixelFormat, memoryUsage, std::move(taskRunner)));
     if (!pool->initialize()) return nullptr;
     return pool;
 }
 
-VideoFramePool::VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const ui::Size& size,
-                               HalPixelFormat pixelFormat, C2MemoryUsage memoryUsage,
+VideoFramePool::VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const size_t maxBufferCount,
+                               const ui::Size& size, HalPixelFormat pixelFormat,
+                               C2MemoryUsage memoryUsage,
                                scoped_refptr<::base::SequencedTaskRunner> taskRunner)
       : mBlockPool(std::move(blockPool)),
+        mMaxBufferCount(maxBufferCount),
         mSize(size),
         mPixelFormat(pixelFormat),
         mMemoryUsage(memoryUsage),
@@ -144,6 +137,18 @@
     mFetchWeakThisFactory.InvalidateWeakPtrs();
 }
 
+bool VideoFramePool::shouldDropBuffer(uint32_t bufferId) {
+    if (mBuffers.size() < mMaxBufferCount) {
+        return false;
+    }
+
+    if (mBuffers.find(bufferId) != mBuffers.end()) {
+        return false;
+    }
+
+    return true;
+}
+
 bool VideoFramePool::getVideoFrame(GetVideoFrameCB cb) {
     ALOGV("%s()", __func__);
     ALOG_ASSERT(mClientTaskRunner->RunsTasksInCurrentSequence());
@@ -176,28 +181,58 @@
     // Variables used to exponential backoff retry when buffer fetching times out.
     constexpr size_t kFetchRetryDelayInit = 64;    // Initial delay: 64us
     constexpr size_t kFetchRetryDelayMax = 16384;  // Max delay: 16ms (1 frame at 60fps)
+    constexpr size_t kFenceWaitTimeoutNs = 16000000;  // 16ms (1 frame at 60fps)
     static size_t sNumRetries = 0;
     static size_t sDelay = kFetchRetryDelayInit;
 
+    C2Fence fence;
     std::shared_ptr<C2GraphicBlock> block;
-    c2_status_t err = mBlockPool->fetchGraphicBlock(
-            mSize.width, mSize.height, static_cast<uint32_t>(mPixelFormat), mMemoryUsage, &block);
-    if (err == C2_TIMED_OUT || err == C2_BLOCKING) {
-        if (setNotifyBlockAvailableCb(*mBlockPool,
-                                      ::base::BindOnce(&VideoFramePool::getVideoFrameTaskThunk,
-                                                       mFetchTaskRunner, mFetchWeakThis))) {
-            ALOGV("%s(): fetchGraphicBlock() timeout, waiting for block available.", __func__);
-        } else {
-            ALOGV("%s(): fetchGraphicBlock() timeout, waiting %zuus (%zu retry)", __func__, sDelay,
-                  sNumRetries + 1);
-            mFetchTaskRunner->PostDelayedTask(
-                    FROM_HERE, ::base::BindOnce(&VideoFramePool::getVideoFrameTask, mFetchWeakThis),
-                    ::base::TimeDelta::FromMicroseconds(sDelay));
-
-            sDelay = std::min(sDelay * 2, kFetchRetryDelayMax);  // Exponential backoff
-            sNumRetries++;
+    c2_status_t err = mBlockPool->fetchGraphicBlock(mSize.width, mSize.height,
+                                                    static_cast<uint32_t>(mPixelFormat),
+                                                    mMemoryUsage, &block, &fence);
+    if (err == C2_BLOCKING) {
+        err = fence.wait(kFenceWaitTimeoutNs);
+        if (err == C2_OK) {
+            ALOGV("%s(): fence wait succeded, retrying now", __func__);
+            mFetchTaskRunner->PostTask(
+                    FROM_HERE,
+                    ::base::BindOnce(&VideoFramePool::getVideoFrameTask, mFetchWeakThis));
+            return;
         }
+        ALOGV("%s(): fence wait unsucessful err=%d", __func__, err);
+    } else if (err == C2_OMITTED) {
+        // Fenced version is not supported, try legacy version.
+        err = mBlockPool->fetchGraphicBlock(mSize.width, mSize.height,
+                                            static_cast<uint32_t>(mPixelFormat), mMemoryUsage,
+                                            &block);
+    }
 
+    std::optional<uint32_t> bufferId;
+    if (err == C2_OK) {
+        bufferId = getBufferIdFromGraphicBlock(*mBlockPool, *block);
+
+        if (bufferId) {
+            ALOGV("%s(): Got buffer with id = %u", __func__, *bufferId);
+
+            if (shouldDropBuffer(*bufferId)) {
+                // We drop buffer, since we got more then needed.
+                ALOGV("%s(): Dropping allocated buffer with id = %u", __func__, *bufferId);
+                bufferId = std::nullopt;
+                block.reset();
+                err = C2_TIMED_OUT;
+            }
+        }
+    }
+
+    if (err == C2_TIMED_OUT || err == C2_BLOCKING) {
+        ALOGV("%s(): fetchGraphicBlock() timeout, waiting %zuus (%zu retry)", __func__, sDelay,
+              sNumRetries + 1);
+        mFetchTaskRunner->PostDelayedTask(
+                FROM_HERE, ::base::BindOnce(&VideoFramePool::getVideoFrameTask, mFetchWeakThis),
+                ::base::TimeDelta::FromMicroseconds(sDelay));
+
+        sDelay = std::min(sDelay * 2, kFetchRetryDelayMax);  // Exponential backoff
+        sNumRetries++;
         return;
     }
 
@@ -205,20 +240,22 @@
     sNumRetries = 0;
     sDelay = kFetchRetryDelayInit;
 
+    if (err != C2_OK) {
+        ALOGE("%s(): Failed to fetch block, err=%d", __func__, err);
+        return;
+    }
+
+    ALOG_ASSERT(block != nullptr);
+    std::unique_ptr<VideoFrame> frame = VideoFrame::Create(std::move(block));
     std::optional<FrameWithBlockId> frameWithBlockId;
-    if (err == C2_OK) {
-        ALOG_ASSERT(block != nullptr);
-        std::optional<uint32_t> bufferId = getBufferIdFromGraphicBlock(*mBlockPool, *block);
-        std::unique_ptr<VideoFrame> frame = VideoFrame::Create(std::move(block));
+
+    if (bufferId && frame) {
         // Only pass the frame + id pair if both have successfully been obtained.
         // Otherwise exit the loop so a nullopt is passed to the client.
-        if (bufferId && frame) {
-            frameWithBlockId = std::make_pair(std::move(frame), *bufferId);
-        } else {
-            ALOGE("%s(): Failed to generate VideoFrame or get the buffer id.", __func__);
-        }
+        frameWithBlockId = std::make_pair(std::move(frame), *bufferId);
+        mBuffers.insert(*bufferId);
     } else {
-        ALOGE("%s(): Failed to fetch block, err=%d", __func__, err);
+        ALOGE("%s(): Failed to generate VideoFrame or get the buffer id.", __func__);
     }
 
     mClientTaskRunner->PostTask(
diff --git a/components/include/v4l2_codec2/components/VideoDecoder.h b/components/include/v4l2_codec2/components/VideoDecoder.h
index 5b2da41..3e3fec4 100644
--- a/components/include/v4l2_codec2/components/VideoDecoder.h
+++ b/components/include/v4l2_codec2/components/VideoDecoder.h
@@ -26,11 +26,11 @@
     };
     static const char* DecodeStatusToString(DecodeStatus status);
 
-    using GetPoolCB = base::RepeatingCallback<std::unique_ptr<VideoFramePool>(
+    using GetPoolCB = ::base::RepeatingCallback<std::unique_ptr<VideoFramePool>(
             const ui::Size& size, HalPixelFormat pixelFormat, size_t numOutputBuffers)>;
-    using DecodeCB = base::OnceCallback<void(DecodeStatus)>;
-    using OutputCB = base::RepeatingCallback<void(std::unique_ptr<VideoFrame>)>;
-    using ErrorCB = base::RepeatingCallback<void()>;
+    using DecodeCB = ::base::OnceCallback<void(DecodeStatus)>;
+    using OutputCB = ::base::RepeatingCallback<void(std::unique_ptr<VideoFrame>)>;
+    using ErrorCB = ::base::RepeatingCallback<void()>;
 
     virtual ~VideoDecoder();
 
diff --git a/components/include/v4l2_codec2/components/VideoEncoder.h b/components/include/v4l2_codec2/components/VideoEncoder.h
index 5f23541..7e5a3c2 100644
--- a/components/include/v4l2_codec2/components/VideoEncoder.h
+++ b/components/include/v4l2_codec2/components/VideoEncoder.h
@@ -47,13 +47,13 @@
     };
 
     using FetchOutputBufferCB =
-            base::RepeatingCallback<void(uint32_t, std::unique_ptr<BitstreamBuffer>* buffer)>;
+            ::base::RepeatingCallback<void(uint32_t, std::unique_ptr<BitstreamBuffer>* buffer)>;
     // TODO(dstaessens): Change callbacks to OnceCallback provided when requesting encode/drain.
-    using InputBufferDoneCB = base::RepeatingCallback<void(uint64_t)>;
-    using OutputBufferDoneCB = base::RepeatingCallback<void(
+    using InputBufferDoneCB = ::base::RepeatingCallback<void(uint64_t)>;
+    using OutputBufferDoneCB = ::base::RepeatingCallback<void(
             size_t, int64_t, bool, std::unique_ptr<BitstreamBuffer> buffer)>;
-    using DrainDoneCB = base::RepeatingCallback<void(bool)>;
-    using ErrorCB = base::RepeatingCallback<void()>;
+    using DrainDoneCB = ::base::RepeatingCallback<void(bool)>;
+    using ErrorCB = ::base::RepeatingCallback<void()>;
 
     virtual ~VideoEncoder() = default;
 
diff --git a/components/include/v4l2_codec2/components/VideoFramePool.h b/components/include/v4l2_codec2/components/VideoFramePool.h
index 2978eed..6bebc37 100644
--- a/components/include/v4l2_codec2/components/VideoFramePool.h
+++ b/components/include/v4l2_codec2/components/VideoFramePool.h
@@ -44,12 +44,13 @@
 
 private:
     // |blockPool| is the C2BlockPool that we fetch graphic blocks from.
+    // |maxBufferCount| maximum number of buffer that should should provide to client
     // |size| is the resolution size of the required graphic blocks.
     // |pixelFormat| is the pixel format of the required graphic blocks.
     // |isSecure| indicates the video stream is encrypted or not.
     // All public methods and the callbacks should be run on |taskRunner|.
-    VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const ui::Size& size,
-                   HalPixelFormat pixelFormat, C2MemoryUsage memoryUsage,
+    VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const size_t maxBufferCount,
+                   const ui::Size& size, HalPixelFormat pixelFormat, C2MemoryUsage memoryUsage,
                    scoped_refptr<::base::SequencedTaskRunner> taskRunner);
     bool initialize();
     void destroyTask();
@@ -59,20 +60,20 @@
     void getVideoFrameTask();
     void onVideoFrameReady(std::optional<FrameWithBlockId> frameWithBlockId);
 
-    // Ask |blockPool| to allocate the specified number of buffers.
-    // |bufferCount| is the number of requested buffers.
-    static c2_status_t requestNewBufferSet(C2BlockPool& blockPool, int32_t bufferCount,
-                                           const ui::Size& size, uint32_t format,
-                                           C2MemoryUsage usage);
+    // Returns true if a buffer shall not be handed to client.
+    bool shouldDropBuffer(uint32_t bufferId);
 
     static std::optional<uint32_t> getBufferIdFromGraphicBlock(C2BlockPool& blockPool,
                                                                const C2Block2D& block);
 
-    // Ask |blockPool| to notify when a block is available via |cb|.
-    // Return true if |blockPool| supports notifying buffer available.
-    static bool setNotifyBlockAvailableCb(C2BlockPool& blockPool, ::base::OnceClosure cb);
-
     std::shared_ptr<C2BlockPool> mBlockPool;
+
+    // Holds the number of maximum amount of buffers that VideoFramePool
+    // should provide to client.
+    size_t mMaxBufferCount;
+    // Contains known buffer ids that are valid for the pool.
+    std::set<uint32_t> mBuffers;
+
     const ui::Size mSize;
     const HalPixelFormat mPixelFormat;
     const C2MemoryUsage mMemoryUsage;
diff --git a/plugin_store/Android.bp b/plugin_store/Android.bp
index 621cbfc..6427512 100644
--- a/plugin_store/Android.bp
+++ b/plugin_store/Android.bp
@@ -16,10 +16,7 @@
     ],
 
     srcs: [
-        "C2VdaBqBlockPool.cpp",
-        "C2VdaPooledBlockPool.cpp",
         "DmabufHelpers.cpp",
-        "H2BGraphicBufferProducer.cpp",
         "V4L2PluginStore.cpp",
         "VendorAllocatorLoader.cpp",
     ],
diff --git a/plugin_store/C2VdaBqBlockPool.cpp b/plugin_store/C2VdaBqBlockPool.cpp
deleted file mode 100644
index d53f4a0..0000000
--- a/plugin_store/C2VdaBqBlockPool.cpp
+++ /dev/null
@@ -1,957 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "C2VdaBqBlockPool"
-
-#include <v4l2_codec2/plugin_store/C2VdaBqBlockPool.h>
-
-#include <errno.h>
-#include <string.h>
-
-#include <chrono>
-#include <mutex>
-#include <set>
-#include <sstream>
-#include <thread>
-
-#include <C2AllocatorGralloc.h>
-#include <C2BlockInternal.h>
-#include <C2SurfaceSyncObj.h>
-#include <android/hardware/graphics/bufferqueue/2.0/IProducerListener.h>
-#include <base/callback.h>
-#include <log/log.h>
-#include <ui/BufferQueueDefs.h>
-
-#include <v4l2_codec2/plugin_store/DmabufHelpers.h>
-#include <v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h>
-#include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
-
-namespace android {
-namespace {
-
-// The wait time for acquire fence in milliseconds. The normal display is 60Hz,
-// which period is 16ms. We choose 2x period as timeout.
-constexpr int kFenceWaitTimeMs = 32;
-
-// The default maximum dequeued buffer count of IGBP. Currently we don't use
-// this value to restrict the count of allocated buffers, so we choose a huge
-// enough value here.
-constexpr int kMaxDequeuedBufferCount = 32u;
-
-}  // namespace
-
-using namespace std::chrono_literals;
-
-// Type for IGBP slot index.
-using slot_t = int32_t;
-
-using ::android::BufferQueueDefs::BUFFER_NEEDS_REALLOCATION;
-using ::android::BufferQueueDefs::NUM_BUFFER_SLOTS;
-using ::android::hardware::Return;
-using HProducerListener = ::android::hardware::graphics::bufferqueue::V2_0::IProducerListener;
-
-static c2_status_t asC2Error(status_t err) {
-    switch (err) {
-    case OK:
-        return C2_OK;
-    case NO_INIT:
-        return C2_NO_INIT;
-    case BAD_VALUE:
-        return C2_BAD_VALUE;
-    case TIMED_OUT:
-        return C2_TIMED_OUT;
-    case WOULD_BLOCK:
-        return C2_BLOCKING;
-    case NO_MEMORY:
-        return C2_NO_MEMORY;
-    }
-    return C2_CORRUPTED;
-}
-
-// Convert GraphicBuffer to C2GraphicAllocation and wrap producer id and slot index.
-std::shared_ptr<C2GraphicAllocation> ConvertGraphicBuffer2C2Allocation(
-        sp<GraphicBuffer> graphicBuffer, const uint64_t igbpId, const slot_t slot,
-        C2Allocator* const allocator) {
-    ALOGV("%s(idbpId=0x%" PRIx64 ", slot=%d)", __func__, igbpId, slot);
-
-    C2Handle* c2Handle = WrapNativeCodec2GrallocHandle(
-            graphicBuffer->handle, graphicBuffer->width, graphicBuffer->height,
-            graphicBuffer->format, graphicBuffer->usage, graphicBuffer->stride,
-            graphicBuffer->getGenerationNumber(), igbpId, slot);
-    if (!c2Handle) {
-        ALOGE("WrapNativeCodec2GrallocHandle() failed");
-        return nullptr;
-    }
-
-    std::shared_ptr<C2GraphicAllocation> allocation;
-    const auto err = allocator->priorGraphicAllocation(c2Handle, &allocation);
-    if (err != C2_OK) {
-        ALOGE("C2Allocator::priorGraphicAllocation() failed: %d", err);
-        native_handle_close(c2Handle);
-        native_handle_delete(c2Handle);
-        return nullptr;
-    }
-
-    return allocation;
-}
-
-// This class is used to notify the listener when a certain event happens.
-class EventNotifier : public virtual android::RefBase {
-public:
-    class Listener {
-    public:
-        virtual ~Listener() = default;
-
-        // Called by EventNotifier when a certain event happens.
-        virtual void onEventNotified() = 0;
-    };
-
-    explicit EventNotifier(std::weak_ptr<Listener> listener) : mListener(std::move(listener)) {}
-    virtual ~EventNotifier() = default;
-
-protected:
-    void notify() {
-        ALOGV("%s()", __func__);
-        std::shared_ptr<Listener> listener = mListener.lock();
-        if (listener) {
-            listener->onEventNotified();
-        }
-    }
-
-    std::weak_ptr<Listener> mListener;
-};
-
-// Notifies the listener when the connected IGBP releases buffers.
-class BufferReleasedNotifier : public EventNotifier, public HProducerListener {
-public:
-    using EventNotifier::EventNotifier;
-    ~BufferReleasedNotifier() override = default;
-
-    // HProducerListener implementation
-    Return<void> onBuffersReleased(uint32_t count) override {
-        ALOGV("%s(%u)", __func__, count);
-        if (count > 0) {
-            notify();
-        }
-        return {};
-    }
-};
-
-// IGBP expects its user (e.g. C2VdaBqBlockPool) to keep the mapping from dequeued slot index to
-// graphic buffers. Also, C2VdaBqBlockPool guaratees to fetch N fixed set of buffers with buffer
-// identifier. So this class stores the mapping from slot index to buffers and the mapping from
-// buffer unique ID to buffers.
-// This class also implements functionalities for buffer migration when surface switching. Buffers
-// are owned by either component (i.e. local buffers) or CCodec framework (i.e. remote buffers).
-// When switching surface, the ccodec framework migrates remote buffers to the new surfaces. Then
-// C2VdaBqBlockPool migrates local buffers. However, some buffers might be lost during migration.
-// We assume that there are enough buffers migrated to the new surface to continue the playback.
-// After |NUM_BUFFER_SLOTS| amount of buffers are dequeued from new surface, all buffers should
-// be dequeued at least once. Then we treat the missing buffer as lost, and attach these bufers to
-// the new surface.
-class TrackedGraphicBuffers {
-public:
-    using value_type = std::tuple<slot_t, unique_id_t, std::shared_ptr<C2GraphicAllocation>>;
-
-    TrackedGraphicBuffers() = default;
-    ~TrackedGraphicBuffers() = default;
-
-    void reset() {
-        mSlotId2GraphicBuffer.clear();
-        mSlotId2PoolData.clear();
-        mAllocationsRegistered.clear();
-        mAllocationsToBeMigrated.clear();
-        mMigrateLostBufferCounter = 0;
-        mGenerationToBeMigrated = 0;
-    }
-
-    void registerUniqueId(unique_id_t uniqueId, std::shared_ptr<C2GraphicAllocation> allocation) {
-        ALOGV("%s(uniqueId=%u)", __func__, uniqueId);
-        ALOG_ASSERT(allocation != nullptr);
-
-        mAllocationsRegistered[uniqueId] = std::move(allocation);
-    }
-
-    std::shared_ptr<C2GraphicAllocation> getRegisteredAllocation(unique_id_t uniqueId) {
-        const auto iter = mAllocationsRegistered.find(uniqueId);
-        ALOG_ASSERT(iter != mAllocationsRegistered.end());
-
-        return iter->second;
-    }
-
-    bool hasUniqueId(unique_id_t uniqueId) const {
-        return mAllocationsRegistered.find(uniqueId) != mAllocationsRegistered.end() ||
-               mAllocationsToBeMigrated.find(uniqueId) != mAllocationsToBeMigrated.end();
-    }
-
-    void updateSlotBuffer(slot_t slotId, unique_id_t uniqueId, sp<GraphicBuffer> slotBuffer) {
-        ALOGV("%s(slotId=%d)", __func__, slotId);
-        ALOG_ASSERT(slotBuffer != nullptr);
-
-        mSlotId2GraphicBuffer[slotId] = std::make_pair(uniqueId, std::move(slotBuffer));
-    }
-
-    std::pair<unique_id_t, sp<GraphicBuffer>> getSlotBuffer(slot_t slotId) const {
-        const auto iter = mSlotId2GraphicBuffer.find(slotId);
-        ALOG_ASSERT(iter != mSlotId2GraphicBuffer.end());
-
-        return iter->second;
-    }
-
-    bool hasSlotId(slot_t slotId) const {
-        return mSlotId2GraphicBuffer.find(slotId) != mSlotId2GraphicBuffer.end();
-    }
-
-    void updatePoolData(slot_t slotId, std::weak_ptr<C2BufferQueueBlockPoolData> poolData) {
-        ALOGV("%s(slotId=%d)", __func__, slotId);
-        ALOG_ASSERT(hasSlotId(slotId));
-
-        mSlotId2PoolData[slotId] = std::move(poolData);
-    }
-
-    bool migrateLocalBuffers(H2BGraphicBufferProducer* const producer, uint64_t producerId,
-                             uint32_t generation, uint64_t usage) {
-        ALOGV("%s(producerId=%" PRIx64 ", generation=%u, usage=%" PRIx64 ")", __func__, producerId,
-              generation, usage);
-
-        mGenerationToBeMigrated = generation;
-        mUsageToBeMigrated = usage;
-
-        // Move all buffers to mAllocationsToBeMigrated.
-        for (auto& pair : mAllocationsRegistered) {
-            if (!mAllocationsToBeMigrated.insert(pair).second) {
-                ALOGE("%s() duplicated uniqueId=%u", __func__, pair.first);
-                return false;
-            }
-        }
-        mAllocationsRegistered.clear();
-
-        ALOGV("%s(producerId=%" PRIx64 ", generation=%u, usage=%" PRIx64 ") before %s", __func__,
-              producerId, generation, usage, debugString().c_str());
-
-        // Migrate local buffers.
-        std::map<slot_t, std::pair<unique_id_t, sp<GraphicBuffer>>> newSlotId2GraphicBuffer;
-        std::map<slot_t, std::weak_ptr<C2BufferQueueBlockPoolData>> newSlotId2PoolData;
-        for (const auto& pair : mSlotId2PoolData) {
-            auto oldSlot = pair.first;
-            auto poolData = pair.second.lock();
-            if (!poolData) {
-                continue;
-            }
-
-            unique_id_t uniqueId;
-            sp<GraphicBuffer> slotBuffer;
-            std::shared_ptr<C2SurfaceSyncMemory> syncMem;
-            std::tie(uniqueId, slotBuffer) = getSlotBuffer(oldSlot);
-            slot_t newSlot = poolData->migrate(producer->getBase(), mGenerationToBeMigrated,
-                                               mUsageToBeMigrated, producerId, slotBuffer,
-                                               slotBuffer->getGenerationNumber(),
-                                               syncMem);
-            if (newSlot < 0) {
-                ALOGW("%s() Failed to migrate local buffer: uniqueId=%u, oldSlot=%d", __func__,
-                      uniqueId, oldSlot);
-                continue;
-            }
-
-            ALOGV("%s() migrated buffer: uniqueId=%u, oldSlot=%d, newSlot=%d", __func__, uniqueId,
-                  oldSlot, newSlot);
-            newSlotId2GraphicBuffer[newSlot] = std::make_pair(uniqueId, std::move(slotBuffer));
-            newSlotId2PoolData[newSlot] = std::move(poolData);
-
-            if (!moveBufferToRegistered(uniqueId)) {
-                ALOGE("%s() failed to move buffer to registered, uniqueId=%u", __func__, uniqueId);
-                return false;
-            }
-        }
-        mSlotId2GraphicBuffer = std::move(newSlotId2GraphicBuffer);
-        mSlotId2PoolData = std::move(newSlotId2PoolData);
-
-        // Choose a big enough number to ensure all buffer should be dequeued at least once.
-        mMigrateLostBufferCounter = NUM_BUFFER_SLOTS;
-        ALOGD("%s() migrated %zu local buffers", __func__, mAllocationsRegistered.size());
-        return true;
-    }
-
-    bool needMigrateLostBuffers() const {
-        return mMigrateLostBufferCounter == 0 && !mAllocationsToBeMigrated.empty();
-    }
-
-    status_t migrateLostBuffer(C2Allocator* const allocator,
-                               H2BGraphicBufferProducer* const producer, const uint64_t producerId,
-                               slot_t* newSlot) {
-        ALOGV("%s() %s", __func__, debugString().c_str());
-
-        if (!needMigrateLostBuffers()) {
-            return NO_INIT;
-        }
-
-        auto iter = mAllocationsToBeMigrated.begin();
-        const unique_id_t uniqueId = iter->first;
-        const C2Handle* c2Handle = iter->second->handle();
-
-        // Convert C2GraphicAllocation to GraphicBuffer, and update generation and usage.
-        uint32_t width, height, format, stride, igbpSlot, generation;
-        uint64_t usage, igbpId;
-        _UnwrapNativeCodec2GrallocMetadata(c2Handle, &width, &height, &format, &usage, &stride,
-                                           &generation, &igbpId, &igbpSlot);
-        native_handle_t* grallocHandle = UnwrapNativeCodec2GrallocHandle(c2Handle);
-        sp<GraphicBuffer> graphicBuffer =
-                new GraphicBuffer(grallocHandle, GraphicBuffer::CLONE_HANDLE, width, height, format,
-                                  1, mUsageToBeMigrated, stride);
-        native_handle_delete(grallocHandle);
-        if (graphicBuffer->initCheck() != android::NO_ERROR) {
-            ALOGE("Failed to create GraphicBuffer: %d", graphicBuffer->initCheck());
-            return false;
-        }
-        graphicBuffer->setGenerationNumber(mGenerationToBeMigrated);
-
-        // Attach GraphicBuffer to producer.
-        const auto attachStatus = producer->attachBuffer(graphicBuffer, newSlot);
-        if (attachStatus == TIMED_OUT || attachStatus == INVALID_OPERATION) {
-            ALOGV("%s(): No free slot yet.", __func__);
-            return TIMED_OUT;
-        }
-        if (attachStatus != OK) {
-            ALOGE("%s(): Failed to attach buffer to new producer: %d", __func__, attachStatus);
-            return attachStatus;
-        }
-        ALOGD("%s(), migrated lost buffer uniqueId=%u to slot=%d", __func__, uniqueId, *newSlot);
-        updateSlotBuffer(*newSlot, uniqueId, graphicBuffer);
-
-        // Wrap the new GraphicBuffer to C2GraphicAllocation and register it.
-        std::shared_ptr<C2GraphicAllocation> allocation =
-                ConvertGraphicBuffer2C2Allocation(graphicBuffer, producerId, *newSlot, allocator);
-        if (!allocation) {
-            return UNKNOWN_ERROR;
-        }
-        registerUniqueId(uniqueId, std::move(allocation));
-
-        // Note: C2ArcProtectedGraphicAllocator releases the protected buffers if all the
-        // corrresponding C2GraphicAllocations are released. To prevent the protected buffer is
-        // released and then allocated again, we release the old C2GraphicAllocation after the new
-        // one has been created.
-        mAllocationsToBeMigrated.erase(iter);
-
-        return OK;
-    }
-
-    void onBufferDequeued(slot_t slotId) {
-        ALOGV("%s(slotId=%d)", __func__, slotId);
-        unique_id_t uniqueId;
-        std::tie(uniqueId, std::ignore) = getSlotBuffer(slotId);
-
-        moveBufferToRegistered(uniqueId);
-        if (mMigrateLostBufferCounter > 0) {
-            --mMigrateLostBufferCounter;
-        }
-    }
-
-    size_t size() const { return mAllocationsRegistered.size() + mAllocationsToBeMigrated.size(); }
-
-    std::string debugString() const {
-        std::stringstream ss;
-        ss << "tracked size: " << size() << std::endl;
-        ss << "  registered uniqueIds: ";
-        for (const auto& pair : mAllocationsRegistered) {
-            ss << pair.first << ", ";
-        }
-        ss << std::endl;
-        ss << "  to-be-migrated uniqueIds: ";
-        for (const auto& pair : mAllocationsToBeMigrated) {
-            ss << pair.first << ", ";
-        }
-        ss << std::endl;
-        ss << "  Count down for lost buffer migration: " << mMigrateLostBufferCounter;
-        return ss.str();
-    }
-
-private:
-    bool moveBufferToRegistered(unique_id_t uniqueId) {
-        ALOGV("%s(uniqueId=%u)", __func__, uniqueId);
-        auto iter = mAllocationsToBeMigrated.find(uniqueId);
-        if (iter == mAllocationsToBeMigrated.end()) {
-            return false;
-        }
-        if (!mAllocationsRegistered.insert(*iter).second) {
-            ALOGE("%s() duplicated uniqueId=%u", __func__, uniqueId);
-            return false;
-        }
-        mAllocationsToBeMigrated.erase(iter);
-
-        return true;
-    }
-
-    // Mapping from IGBP slots to the corresponding graphic buffers.
-    std::map<slot_t, std::pair<unique_id_t, sp<GraphicBuffer>>> mSlotId2GraphicBuffer;
-
-    // Mapping from IGBP slots to the corresponding pool data.
-    std::map<slot_t, std::weak_ptr<C2BufferQueueBlockPoolData>> mSlotId2PoolData;
-
-    // Track the buffers registered at the current producer.
-    std::map<unique_id_t, std::shared_ptr<C2GraphicAllocation>> mAllocationsRegistered;
-
-    // Track the buffers that should be migrated to the current producer.
-    std::map<unique_id_t, std::shared_ptr<C2GraphicAllocation>> mAllocationsToBeMigrated;
-
-    // The counter for migrating lost buffers. Count down when a buffer is
-    // dequeued from IGBP. When it goes to 0, then we treat the remaining
-    // buffers at |mAllocationsToBeMigrated| lost, and migrate them to
-    // current IGBP.
-    size_t mMigrateLostBufferCounter = 0;
-
-    // The generation and usage of the current IGBP, used to migrate buffers.
-    uint32_t mGenerationToBeMigrated = 0;
-    uint64_t mUsageToBeMigrated = 0;
-};
-
-class C2VdaBqBlockPool::Impl : public std::enable_shared_from_this<C2VdaBqBlockPool::Impl>,
-                               public EventNotifier::Listener {
-public:
-    using HGraphicBufferProducer = C2VdaBqBlockPool::HGraphicBufferProducer;
-
-    explicit Impl(const std::shared_ptr<C2Allocator>& allocator);
-    // TODO: should we detach buffers on producer if any on destructor?
-    ~Impl() = default;
-
-    // EventNotifier::Listener implementation.
-    void onEventNotified() override;
-
-    c2_status_t fetchGraphicBlock(uint32_t width, uint32_t height, uint32_t format,
-                                  C2MemoryUsage usage,
-                                  std::shared_ptr<C2GraphicBlock>* block /* nonnull */);
-    void setRenderCallback(const C2BufferQueueBlockPool::OnRenderCallback& renderCallback);
-    void configureProducer(const sp<HGraphicBufferProducer>& producer);
-    c2_status_t requestNewBufferSet(int32_t bufferCount, uint32_t width, uint32_t height,
-                                    uint32_t format, C2MemoryUsage usage);
-    bool setNotifyBlockAvailableCb(::base::OnceClosure cb);
-    std::optional<unique_id_t> getBufferIdFromGraphicBlock(const C2Block2D& block);
-
-private:
-    // Requested buffer formats.
-    struct BufferFormat {
-        BufferFormat(uint32_t width, uint32_t height, uint32_t pixelFormat,
-                     C2AndroidMemoryUsage androidUsage)
-              : mWidth(width), mHeight(height), mPixelFormat(pixelFormat), mUsage(androidUsage) {}
-        BufferFormat() = default;
-
-        uint32_t mWidth = 0;
-        uint32_t mHeight = 0;
-        uint32_t mPixelFormat = 0;
-        C2AndroidMemoryUsage mUsage = C2MemoryUsage(0);
-    };
-
-    status_t getFreeSlotLocked(uint32_t width, uint32_t height, uint32_t format,
-                               C2MemoryUsage usage, slot_t* slot, sp<Fence>* fence);
-
-    // Queries the generation and usage flags from the given producer by dequeuing and requesting a
-    // buffer (the buffer is then detached and freed).
-    status_t queryGenerationAndUsageLocked(uint32_t width, uint32_t height, uint32_t pixelFormat,
-                                           C2AndroidMemoryUsage androidUsage, uint32_t* generation,
-                                           uint64_t* usage);
-
-    // Wait the fence. If any error occurs, cancel the buffer back to the producer.
-    status_t waitFence(slot_t slot, sp<Fence> fence);
-
-    // Call mProducer's allowAllocation if needed.
-    status_t allowAllocation(bool allow);
-
-    const std::shared_ptr<C2Allocator> mAllocator;
-
-    std::unique_ptr<H2BGraphicBufferProducer> mProducer;
-    uint64_t mProducerId = 0;
-    bool mAllowAllocation = false;
-
-    C2BufferQueueBlockPool::OnRenderCallback mRenderCallback;
-
-    // Function mutex to lock at the start of each API function call for protecting the
-    // synchronization of all member variables.
-    std::mutex mMutex;
-
-    TrackedGraphicBuffers mTrackedGraphicBuffers;
-
-    // Number of buffers requested on requestNewBufferSet() call.
-    size_t mBuffersRequested = 0u;
-    // Currently requested buffer formats.
-    BufferFormat mBufferFormat;
-
-    // Listener for buffer release events.
-    sp<EventNotifier> mFetchBufferNotifier;
-
-    std::mutex mBufferReleaseMutex;
-    // Set to true when the buffer release event is triggered after dequeueing buffer from IGBP
-    // times out. Reset when fetching new slot times out, or |mNotifyBlockAvailableCb| is executed.
-    bool mBufferReleasedAfterTimedOut GUARDED_BY(mBufferReleaseMutex) = false;
-    // The callback to notify the caller the buffer is available.
-    ::base::OnceClosure mNotifyBlockAvailableCb GUARDED_BY(mBufferReleaseMutex);
-
-    // Set to true if any error occurs at previous configureProducer().
-    bool mConfigureProducerError = false;
-};
-
-C2VdaBqBlockPool::Impl::Impl(const std::shared_ptr<C2Allocator>& allocator)
-      : mAllocator(allocator) {}
-
-c2_status_t C2VdaBqBlockPool::Impl::fetchGraphicBlock(
-        uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
-        std::shared_ptr<C2GraphicBlock>* block /* nonnull */) {
-    ALOGV("%s(%ux%u)", __func__, width, height);
-    std::lock_guard<std::mutex> lock(mMutex);
-
-    if (width != mBufferFormat.mWidth || height != mBufferFormat.mHeight ||
-        format != mBufferFormat.mPixelFormat || usage.expected != mBufferFormat.mUsage.expected) {
-        ALOGE("%s(): buffer format (%ux%u, format=%u, usage=%" PRIx64
-              ") is different from requested format (%ux%u, format=%u, usage=%" PRIx64 ")",
-              __func__, width, height, format, usage.expected, mBufferFormat.mWidth,
-              mBufferFormat.mHeight, mBufferFormat.mPixelFormat, mBufferFormat.mUsage.expected);
-        return C2_BAD_VALUE;
-    }
-    if (mConfigureProducerError || !mProducer) {
-        ALOGE("%s(): error occurred at previous configureProducer()", __func__);
-        return C2_CORRUPTED;
-    }
-
-    slot_t slot;
-    sp<Fence> fence = new Fence();
-    const auto status = getFreeSlotLocked(width, height, format, usage, &slot, &fence);
-    if (status != OK) {
-        return asC2Error(status);
-    }
-
-    unique_id_t uniqueId;
-    sp<GraphicBuffer> slotBuffer;
-    std::tie(uniqueId, slotBuffer) = mTrackedGraphicBuffers.getSlotBuffer(slot);
-    ALOGV("%s(): dequeued slot=%d uniqueId=%u", __func__, slot, uniqueId);
-
-    if (!mTrackedGraphicBuffers.hasUniqueId(uniqueId)) {
-        if (mTrackedGraphicBuffers.size() >= mBuffersRequested) {
-            // The dequeued slot has a pre-allocated buffer whose size and format is as same as
-            // currently requested (but was not dequeued during allocation cycle). Just detach it to
-            // free this slot. And try dequeueBuffer again.
-            ALOGD("dequeued a new slot %d but already allocated enough buffers. Detach it.", slot);
-
-            if (mProducer->detachBuffer(slot) != OK) {
-                return C2_CORRUPTED;
-            }
-
-            const auto allocationStatus = allowAllocation(false);
-            if (allocationStatus != OK) {
-                return asC2Error(allocationStatus);
-            }
-            return C2_TIMED_OUT;
-        }
-
-        std::shared_ptr<C2GraphicAllocation> allocation =
-                ConvertGraphicBuffer2C2Allocation(slotBuffer, mProducerId, slot, mAllocator.get());
-        if (!allocation) {
-            return C2_CORRUPTED;
-        }
-        mTrackedGraphicBuffers.registerUniqueId(uniqueId, std::move(allocation));
-
-        ALOGV("%s(): mTrackedGraphicBuffers.size=%zu", __func__, mTrackedGraphicBuffers.size());
-        if (mTrackedGraphicBuffers.size() == mBuffersRequested) {
-            ALOGV("Tracked IGBP slots: %s", mTrackedGraphicBuffers.debugString().c_str());
-            // Already allocated enough buffers, set allowAllocation to false to restrict the
-            // eligible slots to allocated ones for future dequeue.
-            const auto allocationStatus = allowAllocation(false);
-            if (allocationStatus != OK) {
-                return asC2Error(allocationStatus);
-            }
-        }
-    }
-
-    std::shared_ptr<C2SurfaceSyncMemory> syncMem;
-    // TODO: the |owner| argument should be set correctly.
-    std::shared_ptr<C2GraphicAllocation> allocation =
-            mTrackedGraphicBuffers.getRegisteredAllocation(uniqueId);
-    auto poolData = std::make_shared<C2BufferQueueBlockPoolData>(
-            slotBuffer->getGenerationNumber(), mProducerId, slot, std::make_shared<int>(0),
-            mProducer->getBase(), syncMem);
-    mTrackedGraphicBuffers.updatePoolData(slot, poolData);
-    *block = _C2BlockFactory::CreateGraphicBlock(std::move(allocation), std::move(poolData));
-    if (*block == nullptr) {
-        ALOGE("failed to create GraphicBlock: no memory");
-        return C2_NO_MEMORY;
-    }
-
-    // Wait for acquire fence at the last point of returning buffer.
-    if (fence) {
-        const auto fenceStatus = waitFence(slot, fence);
-        if (fenceStatus != OK) {
-            return asC2Error(fenceStatus);
-        }
-
-        if (mRenderCallback) {
-            nsecs_t signalTime = fence->getSignalTime();
-            if (signalTime >= 0 && signalTime < INT64_MAX) {
-                mRenderCallback(mProducerId, slot, signalTime);
-            } else {
-                ALOGV("got fence signal time of %" PRId64 " nsec", signalTime);
-            }
-        }
-    }
-
-    return C2_OK;
-}
-
-status_t C2VdaBqBlockPool::Impl::getFreeSlotLocked(uint32_t width, uint32_t height, uint32_t format,
-                                                   C2MemoryUsage usage, slot_t* slot,
-                                                   sp<Fence>* fence) {
-    if (mTrackedGraphicBuffers.needMigrateLostBuffers()) {
-        slot_t newSlot;
-        if (mTrackedGraphicBuffers.migrateLostBuffer(mAllocator.get(), mProducer.get(), mProducerId,
-                                                     &newSlot) == OK) {
-            ALOGV("%s(): migrated buffer: slot=%d", __func__, newSlot);
-            *slot = newSlot;
-            return OK;
-        }
-    }
-
-    // Dequeue a free slot from IGBP.
-    ALOGV("%s(): try to dequeue free slot from IGBP.", __func__);
-    const auto dequeueStatus = mProducer->dequeueBuffer(width, height, format, usage, slot, fence);
-    if (dequeueStatus == TIMED_OUT) {
-        std::lock_guard<std::mutex> lock(mBufferReleaseMutex);
-        mBufferReleasedAfterTimedOut = false;
-    }
-    if (dequeueStatus != OK && dequeueStatus != BUFFER_NEEDS_REALLOCATION) {
-        return dequeueStatus;
-    }
-
-    // Call requestBuffer to update GraphicBuffer for the slot and obtain the reference.
-    if (!mTrackedGraphicBuffers.hasSlotId(*slot) || dequeueStatus == BUFFER_NEEDS_REALLOCATION) {
-        sp<GraphicBuffer> slotBuffer = new GraphicBuffer();
-        const auto requestStatus = mProducer->requestBuffer(*slot, &slotBuffer);
-        if (requestStatus != OK) {
-            mProducer->cancelBuffer(*slot, *fence);
-            return requestStatus;
-        }
-
-        const auto uniqueId = getDmabufId(slotBuffer->handle->data[0]);
-        if (!uniqueId) {
-            ALOGE("%s(): failed to get uniqueId of GraphicBuffer from slot=%d", __func__, *slot);
-            return UNKNOWN_ERROR;
-        }
-        mTrackedGraphicBuffers.updateSlotBuffer(*slot, *uniqueId, std::move(slotBuffer));
-    }
-
-    ALOGV("%s(%ux%u): dequeued slot=%d", __func__, mBufferFormat.mWidth, mBufferFormat.mHeight,
-          *slot);
-    mTrackedGraphicBuffers.onBufferDequeued(*slot);
-    return OK;
-}
-
-void C2VdaBqBlockPool::Impl::onEventNotified() {
-    ALOGV("%s()", __func__);
-    ::base::OnceClosure outputCb;
-    {
-        std::lock_guard<std::mutex> lock(mBufferReleaseMutex);
-
-        mBufferReleasedAfterTimedOut = true;
-        if (mNotifyBlockAvailableCb) {
-            mBufferReleasedAfterTimedOut = false;
-            outputCb = std::move(mNotifyBlockAvailableCb);
-        }
-    }
-
-    // Calling the callback outside the lock to avoid the deadlock.
-    if (outputCb) {
-        std::move(outputCb).Run();
-    }
-}
-
-status_t C2VdaBqBlockPool::Impl::queryGenerationAndUsageLocked(uint32_t width, uint32_t height,
-                                                               uint32_t pixelFormat,
-                                                               C2AndroidMemoryUsage androidUsage,
-                                                               uint32_t* generation,
-                                                               uint64_t* usage) {
-    ALOGV("%s()", __func__);
-
-    sp<Fence> fence = new Fence();
-    slot_t slot;
-    const auto dequeueStatus =
-            mProducer->dequeueBuffer(width, height, pixelFormat, androidUsage, &slot, &fence);
-    if (dequeueStatus != OK && dequeueStatus != BUFFER_NEEDS_REALLOCATION) {
-        return dequeueStatus;
-    }
-
-    // Call requestBuffer to allocate buffer for the slot and obtain the reference.
-    // Get generation number here.
-    sp<GraphicBuffer> slotBuffer = new GraphicBuffer();
-    const auto requestStatus = mProducer->requestBuffer(slot, &slotBuffer);
-
-    // Detach and delete the temporary buffer.
-    const auto detachStatus = mProducer->detachBuffer(slot);
-    if (detachStatus != OK) {
-        return detachStatus;
-    }
-
-    // Check requestBuffer return flag.
-    if (requestStatus != OK) {
-        return requestStatus;
-    }
-
-    // Get generation number and usage from the slot buffer.
-    *usage = slotBuffer->getUsage();
-    *generation = slotBuffer->getGenerationNumber();
-    ALOGV("Obtained from temp buffer: generation = %u, usage = %" PRIu64 "", *generation, *usage);
-    return OK;
-}
-
-status_t C2VdaBqBlockPool::Impl::waitFence(slot_t slot, sp<Fence> fence) {
-    const auto fenceStatus = fence->wait(kFenceWaitTimeMs);
-    if (fenceStatus == OK) {
-        return OK;
-    }
-
-    const auto cancelStatus = mProducer->cancelBuffer(slot, fence);
-    if (cancelStatus != OK) {
-        ALOGE("%s(): failed to cancelBuffer(slot=%d)", __func__, slot);
-        return cancelStatus;
-    }
-
-    if (fenceStatus == -ETIME) {  // fence wait timed out
-        ALOGV("%s(): buffer (slot=%d) fence wait timed out", __func__, slot);
-        return TIMED_OUT;
-    }
-    ALOGE("buffer fence wait error: %d", fenceStatus);
-    return fenceStatus;
-}
-
-void C2VdaBqBlockPool::Impl::setRenderCallback(
-        const C2BufferQueueBlockPool::OnRenderCallback& renderCallback) {
-    ALOGV("setRenderCallback");
-    std::lock_guard<std::mutex> lock(mMutex);
-    mRenderCallback = renderCallback;
-}
-
-c2_status_t C2VdaBqBlockPool::Impl::requestNewBufferSet(int32_t bufferCount, uint32_t width,
-                                                        uint32_t height, uint32_t format,
-                                                        C2MemoryUsage usage) {
-    ALOGV("%s(bufferCount=%d, size=%ux%u, format=0x%x, usage=%" PRIu64 ")", __func__, bufferCount,
-          width, height, format, usage.expected);
-
-    if (bufferCount <= 0) {
-        ALOGE("Invalid requested buffer count = %d", bufferCount);
-        return C2_BAD_VALUE;
-    }
-
-    std::lock_guard<std::mutex> lock(mMutex);
-    if (!mProducer) {
-        ALOGD("No HGraphicBufferProducer is configured...");
-        return C2_NO_INIT;
-    }
-    if (mBuffersRequested == static_cast<size_t>(bufferCount) && mBufferFormat.mWidth == width &&
-        mBufferFormat.mHeight == height && mBufferFormat.mPixelFormat == format &&
-        mBufferFormat.mUsage.expected == usage.expected) {
-        ALOGD("%s() Request the same format and amount of buffers, skip", __func__);
-        return C2_OK;
-    }
-
-    const auto status = allowAllocation(true);
-    if (status != OK) {
-        return asC2Error(status);
-    }
-
-    // Release all remained slot buffer references here. CCodec should either cancel or queue its
-    // owned buffers from this set before the next resolution change.
-    mTrackedGraphicBuffers.reset();
-
-    mBuffersRequested = static_cast<size_t>(bufferCount);
-
-    // Store buffer formats for future usage.
-    mBufferFormat = BufferFormat(width, height, format, C2AndroidMemoryUsage(usage));
-
-    return C2_OK;
-}
-
-void C2VdaBqBlockPool::Impl::configureProducer(const sp<HGraphicBufferProducer>& producer) {
-    ALOGV("%s(producer=%p)", __func__, producer.get());
-
-    std::lock_guard<std::mutex> lock(mMutex);
-    if (producer == nullptr) {
-        ALOGI("input producer is nullptr...");
-
-        mProducer = nullptr;
-        mProducerId = 0;
-        mTrackedGraphicBuffers.reset();
-        return;
-    }
-
-    auto newProducer = std::make_unique<H2BGraphicBufferProducer>(producer);
-    uint64_t newProducerId;
-    if (newProducer->getUniqueId(&newProducerId) != OK) {
-        ALOGE("%s(): failed to get IGBP ID", __func__);
-        mConfigureProducerError = true;
-        return;
-    }
-    if (newProducerId == mProducerId) {
-        ALOGI("%s(): configure the same producer, ignore", __func__);
-        return;
-    }
-
-    ALOGI("Producer (Surface) is going to switch... ( 0x%" PRIx64 " -> 0x%" PRIx64 " )",
-          mProducerId, newProducerId);
-    mProducer = std::move(newProducer);
-    mProducerId = newProducerId;
-    mConfigureProducerError = false;
-    mAllowAllocation = false;
-
-    // Set allowAllocation to new producer.
-    if (allowAllocation(true) != OK) {
-        ALOGE("%s(): failed to allowAllocation(true)", __func__);
-        mConfigureProducerError = true;
-        return;
-    }
-    if (mProducer->setDequeueTimeout(0) != OK) {
-        ALOGE("%s(): failed to setDequeueTimeout(0)", __func__);
-        mConfigureProducerError = true;
-        return;
-    }
-    if (mProducer->setMaxDequeuedBufferCount(kMaxDequeuedBufferCount) != OK) {
-        ALOGE("%s(): failed to setMaxDequeuedBufferCount(%d)", __func__, kMaxDequeuedBufferCount);
-        mConfigureProducerError = true;
-        return;
-    }
-
-    // Migrate existing buffers to the new producer.
-    if (mTrackedGraphicBuffers.size() > 0) {
-        uint32_t newGeneration = 0;
-        uint64_t newUsage = 0;
-        const status_t err = queryGenerationAndUsageLocked(
-                mBufferFormat.mWidth, mBufferFormat.mHeight, mBufferFormat.mPixelFormat,
-                mBufferFormat.mUsage, &newGeneration, &newUsage);
-        if (err != OK) {
-            ALOGE("failed to query generation and usage: %d", err);
-            mConfigureProducerError = true;
-            return;
-        }
-
-        if (!mTrackedGraphicBuffers.migrateLocalBuffers(mProducer.get(), mProducerId, newGeneration,
-                                                        newUsage)) {
-            ALOGE("%s(): failed to migrateLocalBuffers()", __func__);
-            mConfigureProducerError = true;
-            return;
-        }
-
-        if (mTrackedGraphicBuffers.size() == mBuffersRequested) {
-            if (allowAllocation(false) != OK) {
-                ALOGE("%s(): failed to allowAllocation(false)", __func__);
-                mConfigureProducerError = true;
-                return;
-            }
-        }
-    }
-
-    // hack(b/146409777): Try to connect ARC-specific listener first.
-    sp<BufferReleasedNotifier> listener = new BufferReleasedNotifier(weak_from_this());
-    if (mProducer->connect(listener, 'ARC\0', false) == OK) {
-        ALOGI("connected to ARC-specific IGBP listener.");
-        mFetchBufferNotifier = listener;
-    }
-
-    // There might be free buffers at the new producer, notify the client if needed.
-    onEventNotified();
-}
-
-bool C2VdaBqBlockPool::Impl::setNotifyBlockAvailableCb(::base::OnceClosure cb) {
-    ALOGV("%s()", __func__);
-    if (mFetchBufferNotifier == nullptr) {
-        return false;
-    }
-
-    ::base::OnceClosure outputCb;
-    {
-        std::lock_guard<std::mutex> lock(mBufferReleaseMutex);
-
-        // If there is any buffer released after dequeueBuffer() timed out, then we could notify the
-        // caller directly.
-        if (mBufferReleasedAfterTimedOut) {
-            mBufferReleasedAfterTimedOut = false;
-            outputCb = std::move(cb);
-        } else {
-            mNotifyBlockAvailableCb = std::move(cb);
-        }
-    }
-
-    // Calling the callback outside the lock to avoid the deadlock.
-    if (outputCb) {
-        std::move(outputCb).Run();
-    }
-    return true;
-}
-
-std::optional<unique_id_t> C2VdaBqBlockPool::Impl::getBufferIdFromGraphicBlock(
-        const C2Block2D& block) {
-    return getDmabufId(block.handle()->data[0]);
-}
-
-status_t C2VdaBqBlockPool::Impl::allowAllocation(bool allow) {
-    ALOGV("%s(%d)", __func__, allow);
-
-    if (!mProducer) {
-        ALOGW("%s() mProducer is not initiailzed", __func__);
-        return NO_INIT;
-    }
-    if (mAllowAllocation == allow) {
-        return OK;
-    }
-
-    const auto status = mProducer->allowAllocation(allow);
-    if (status == OK) {
-        mAllowAllocation = allow;
-    }
-    return status;
-}
-
-C2VdaBqBlockPool::C2VdaBqBlockPool(const std::shared_ptr<C2Allocator>& allocator,
-                                   const local_id_t localId)
-      : C2BufferQueueBlockPool(allocator, localId), mLocalId(localId), mImpl(new Impl(allocator)) {}
-
-c2_status_t C2VdaBqBlockPool::fetchGraphicBlock(
-        uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
-        std::shared_ptr<C2GraphicBlock>* block /* nonnull */) {
-    if (mImpl) {
-        return mImpl->fetchGraphicBlock(width, height, format, usage, block);
-    }
-    return C2_NO_INIT;
-}
-
-void C2VdaBqBlockPool::setRenderCallback(
-        const C2BufferQueueBlockPool::OnRenderCallback& renderCallback) {
-    if (mImpl) {
-        mImpl->setRenderCallback(renderCallback);
-    }
-}
-
-c2_status_t C2VdaBqBlockPool::requestNewBufferSet(int32_t bufferCount, uint32_t width,
-                                                  uint32_t height, uint32_t format,
-                                                  C2MemoryUsage usage) {
-    if (mImpl) {
-        return mImpl->requestNewBufferSet(bufferCount, width, height, format, usage);
-    }
-    return C2_NO_INIT;
-}
-
-void C2VdaBqBlockPool::configureProducer(const sp<HGraphicBufferProducer>& producer) {
-    if (mImpl) {
-        mImpl->configureProducer(producer);
-    }
-}
-
-bool C2VdaBqBlockPool::setNotifyBlockAvailableCb(::base::OnceClosure cb) {
-    if (mImpl) {
-        return mImpl->setNotifyBlockAvailableCb(std::move(cb));
-    }
-    return false;
-}
-
-std::optional<unique_id_t> C2VdaBqBlockPool::getBufferIdFromGraphicBlock(const C2Block2D& block) {
-    if (mImpl) {
-        return mImpl->getBufferIdFromGraphicBlock(block);
-    }
-    return std::nullopt;
-}
-
-}  // namespace android
diff --git a/plugin_store/C2VdaPooledBlockPool.cpp b/plugin_store/C2VdaPooledBlockPool.cpp
deleted file mode 100644
index 2b9104b..0000000
--- a/plugin_store/C2VdaPooledBlockPool.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "C2VdaPooledBlockPool"
-
-#include <v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h>
-
-#include <time.h>
-
-#include <C2BlockInternal.h>
-#include <bufferpool/BufferPoolTypes.h>
-#include <log/log.h>
-
-namespace android {
-
-using android::hardware::media::bufferpool::BufferPoolData;
-
-// static
-std::optional<uint32_t> C2VdaPooledBlockPool::getBufferIdFromGraphicBlock(const C2Block2D& block) {
-    std::shared_ptr<_C2BlockPoolData> blockPoolData =
-            _C2BlockFactory::GetGraphicBlockPoolData(block);
-    if (blockPoolData->getType() != _C2BlockPoolData::TYPE_BUFFERPOOL) {
-        ALOGE("Obtained C2GraphicBlock is not bufferpool-backed.");
-        return std::nullopt;
-    }
-    std::shared_ptr<BufferPoolData> bpData;
-    if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData) || !bpData) {
-        ALOGE("BufferPoolData unavailable in block.");
-        return std::nullopt;
-    }
-    return bpData->mId;
-}
-
-// Tries to fetch a buffer from bufferpool. When the size of |mBufferIds| is smaller than
-// |mBufferCount|, pass the obtained buffer to caller and record its ID in BufferPoolData to
-// |mBufferIds|. When the size of |mBufferIds| is equal to |mBufferCount|, pass the obtained
-// buffer only if its ID is included in |mBufferIds|. Otherwise, discard the buffer and
-// return C2_TIMED_OUT.
-c2_status_t C2VdaPooledBlockPool::fetchGraphicBlock(uint32_t width, uint32_t height,
-                                                    uint32_t format, C2MemoryUsage usage,
-                                                    std::shared_ptr<C2GraphicBlock>* block) {
-    ALOG_ASSERT(block != nullptr);
-    std::lock_guard<std::mutex> lock(mMutex);
-
-    std::shared_ptr<C2GraphicBlock> fetchBlock;
-    c2_status_t err =
-            C2PooledBlockPool::fetchGraphicBlock(width, height, format, usage, &fetchBlock);
-    if (err != C2_OK) {
-        ALOGE("Failed at C2PooledBlockPool::fetchGraphicBlock: %d", err);
-        return err;
-    }
-
-    std::optional<uint32_t> bufferId = getBufferIdFromGraphicBlock(*fetchBlock);
-    if (!bufferId) {
-        ALOGE("Failed to getBufferIdFromGraphicBlock");
-        return C2_CORRUPTED;
-    }
-
-    if (mBufferIds.size() < mBufferCount) {
-        mBufferIds.insert(*bufferId);
-    }
-
-    if (mBufferIds.find(*bufferId) != mBufferIds.end()) {
-        ALOGV("Returned buffer id = %u", *bufferId);
-        *block = std::move(fetchBlock);
-        return C2_OK;
-    }
-    ALOGV("No buffer could be recycled now, wait for another try...");
-    return C2_TIMED_OUT;
-}
-
-c2_status_t C2VdaPooledBlockPool::requestNewBufferSet(int32_t bufferCount) {
-    if (bufferCount <= 0) {
-        ALOGE("Invalid requested buffer count = %d", bufferCount);
-        return C2_BAD_VALUE;
-    }
-
-    std::lock_guard<std::mutex> lock(mMutex);
-    mBufferIds.clear();
-    mBufferCount = bufferCount;
-    return C2_OK;
-}
-
-}  // namespace android
diff --git a/plugin_store/H2BGraphicBufferProducer.cpp b/plugin_store/H2BGraphicBufferProducer.cpp
deleted file mode 100644
index 95251de..0000000
--- a/plugin_store/H2BGraphicBufferProducer.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "H2BGraphicBuferProducer"
-
-#include <v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h>
-
-#include <log/log.h>
-#include <types.h>
-#include <ui/BufferQueueDefs.h>
-
-namespace android {
-
-using ::android::BufferQueueDefs::BUFFER_NEEDS_REALLOCATION;
-using ::android::BufferQueueDefs::RELEASE_ALL_BUFFERS;
-using ::android::hardware::Return;
-
-using HBuffer = ::android::hardware::graphics::common::V1_2::HardwareBuffer;
-using HStatus = ::android::hardware::graphics::bufferqueue::V2_0::Status;
-using HConnectionType = hardware::graphics::bufferqueue::V2_0::ConnectionType;
-using HQueueBufferOutput =
-        ::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer::QueueBufferOutput;
-
-using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
-using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
-using ::android::hardware::graphics::bufferqueue::V2_0::utils::HFenceWrapper;
-
-H2BGraphicBufferProducer::H2BGraphicBufferProducer(sp<HGraphicBufferProducer> base) : mBase(base) {}
-
-status_t H2BGraphicBufferProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
-    bool converted = false;
-    status_t status = UNKNOWN_ERROR;
-    Return<void> transResult = mBase->requestBuffer(
-            slot, [&converted, &status, buf](HStatus hStatus, HBuffer const& hBuffer,
-                                             uint32_t generationNumber) {
-                converted = h2b(hStatus, &status) && h2b(hBuffer, buf);
-                if (*buf) {
-                    (*buf)->setGenerationNumber(generationNumber);
-                }
-            });
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    if (!converted) {
-        ALOGE("%s(): corrupted transaction.", __func__);
-        return FAILED_TRANSACTION;
-    }
-    if (status != OK) {
-        ALOGD("%s() failed: %d", __func__, status);
-    }
-    return status;
-}
-
-status_t H2BGraphicBufferProducer::setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
-    status_t status = UNKNOWN_ERROR;
-    Return<HStatus> transResult =
-            mBase->setMaxDequeuedBufferCount(static_cast<int32_t>(maxDequeuedBuffers));
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    if (!h2b(static_cast<HStatus>(transResult), &status)) {
-        ALOGE("%s(): corrupted transaction.", __func__);
-        return FAILED_TRANSACTION;
-    }
-    if (status != OK) {
-        ALOGD("%s() failed: %d", __func__, status);
-    }
-    return status;
-}
-
-status_t H2BGraphicBufferProducer::dequeueBuffer(uint32_t width, uint32_t height,
-                                                 uint32_t pixelFormat,
-                                                 C2AndroidMemoryUsage androidUsage, int* slot,
-                                                 sp<Fence>* fence) {
-    using Input = HGraphicBufferProducer::DequeueBufferInput;
-    using Output = HGraphicBufferProducer::DequeueBufferOutput;
-    Input input{width, height, pixelFormat, androidUsage.asGrallocUsage()};
-
-    bool converted = false;
-    status_t status = UNKNOWN_ERROR;
-    Return<void> transResult = mBase->dequeueBuffer(
-            input, [&converted, &status, &slot, &fence](HStatus hStatus, int32_t hSlot,
-                                                        Output const& hOutput) {
-                converted = h2b(hStatus, &status);
-                if (!converted || status != OK) {
-                    return;
-                }
-
-                *slot = hSlot;
-                if (hOutput.bufferNeedsReallocation) {
-                    status = BUFFER_NEEDS_REALLOCATION;
-                }
-                converted = h2b(hOutput.fence, fence);
-            });
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    if (!converted) {
-        ALOGE("%s(): corrupted transaction.", __func__);
-        return FAILED_TRANSACTION;
-    }
-    // The C2VdaBqBlockPool does not fully own the bufferqueue. After buffers are dequeued here,
-    // they are passed into the codec2 framework, processed, and eventually queued into the
-    // bufferqueue. The C2VdaBqBlockPool cannot determine exactly when a buffer gets queued.
-    // However, if every buffer is being processed by the codec2 framework, then dequeueBuffer()
-    // will return INVALID_OPERATION because of an attempt to dequeue too many buffers.
-    // The C2VdaBqBlockPool cannot prevent this from happening, so just map it to TIMED_OUT
-    // and let the C2VdaBqBlockPool's caller's timeout retry logic handle the failure.
-    if (status == INVALID_OPERATION) {
-        status = TIMED_OUT;
-    }
-    if (status != OK && status != BUFFER_NEEDS_REALLOCATION && status != TIMED_OUT) {
-        ALOGD("%s() failed: %d", __func__, status);
-    }
-    return status;
-}
-
-status_t H2BGraphicBufferProducer::detachBuffer(int slot) {
-    status_t status = UNKNOWN_ERROR;
-    Return<HStatus> transResult = mBase->detachBuffer(static_cast<int32_t>(slot));
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    if (!h2b(static_cast<HStatus>(transResult), &status)) {
-        ALOGE("%s(): corrupted transaction.", __func__);
-        return FAILED_TRANSACTION;
-    }
-    if (status != OK) {
-        ALOGD("%s() failed: %d", __func__, status);
-    }
-    return status;
-}
-
-status_t H2BGraphicBufferProducer::attachBuffer(const sp<GraphicBuffer>& buffer, int* outSlot) {
-    HBuffer hBuffer;
-    uint32_t hGenerationNumber;
-    if (!b2h(buffer, &hBuffer, &hGenerationNumber)) {
-        ALOGE("%s: invalid input buffer.", __func__);
-        return BAD_VALUE;
-    }
-
-    bool converted = false;
-    status_t status = UNKNOWN_ERROR;
-    Return<void> transResult = mBase->attachBuffer(
-            hBuffer, hGenerationNumber,
-            [&converted, &status, outSlot](HStatus hStatus, int32_t hSlot, bool releaseAllBuffers) {
-                converted = h2b(hStatus, &status);
-                *outSlot = static_cast<int>(hSlot);
-                if (converted && releaseAllBuffers && status == OK) {
-                    status = RELEASE_ALL_BUFFERS;
-                }
-            });
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    if (!converted) {
-        ALOGE("%s(): corrupted transaction.", __func__);
-        return FAILED_TRANSACTION;
-    }
-    if (status != OK) {
-        ALOGD("%s() failed: %d", __func__, status);
-    }
-    return status;
-}
-
-status_t H2BGraphicBufferProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
-    HFenceWrapper hFenceWrapper;
-    if (!b2h(fence, &hFenceWrapper)) {
-        ALOGE("%s(): corrupted input fence.", __func__);
-        return UNKNOWN_ERROR;
-    }
-
-    status_t status = UNKNOWN_ERROR;
-    Return<HStatus> transResult =
-            mBase->cancelBuffer(static_cast<int32_t>(slot), hFenceWrapper.getHandle());
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    if (!h2b(static_cast<HStatus>(transResult), &status)) {
-        ALOGE("%s(): corrupted transaction.", __func__);
-        return FAILED_TRANSACTION;
-    }
-    if (status != OK) {
-        ALOGD("%s() failed: %d", __func__, status);
-    }
-    return status;
-}
-
-int H2BGraphicBufferProducer::query(int what, int* value) {
-    int result = 0;
-    Return<void> transResult =
-            mBase->query(static_cast<int32_t>(what), [&result, value](int32_t r, int32_t v) {
-                result = static_cast<int>(r);
-                *value = static_cast<int>(v);
-            });
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    return result;
-}
-
-status_t H2BGraphicBufferProducer::allowAllocation(bool allow) {
-    status_t status = UNKNOWN_ERROR;
-    Return<HStatus> transResult = mBase->allowAllocation(allow);
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    if (!h2b(static_cast<HStatus>(transResult), &status)) {
-        ALOGE("%s(): corrupted transaction.", __func__);
-        return FAILED_TRANSACTION;
-    }
-    if (status != OK) {
-        ALOGD("%s() failed: %d", __func__, status);
-    }
-    return status;
-}
-
-status_t H2BGraphicBufferProducer::getUniqueId(uint64_t* outId) const {
-    Return<uint64_t> transResult = mBase->getUniqueId();
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-
-    *outId = static_cast<uint64_t>(transResult);
-    return OK;
-}
-
-// android::IProducerListener cannot be depended by vendor library, so we use HProducerListener
-// directly.
-status_t H2BGraphicBufferProducer::connect(sp<HProducerListener> const& hListener, int32_t api,
-                                           bool producerControlledByApp) {
-    bool converted = false;
-    status_t status = UNKNOWN_ERROR;
-    // hack(b/146409777): We pass self-defined api, so we don't use b2h() here.
-    Return<void> transResult = mBase->connect(
-            hListener, static_cast<HConnectionType>(api), producerControlledByApp,
-            [&converted, &status](HStatus hStatus, HQueueBufferOutput const& /* hOutput */) {
-                converted = h2b(hStatus, &status);
-            });
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    if (!converted) {
-        ALOGE("%s(): corrupted transaction.", __func__);
-        return FAILED_TRANSACTION;
-    }
-    return status;
-}
-
-status_t H2BGraphicBufferProducer::setDequeueTimeout(nsecs_t timeout) {
-    status_t status = UNKNOWN_ERROR;
-    Return<HStatus> transResult = mBase->setDequeueTimeout(static_cast<int64_t>(timeout));
-
-    if (!transResult.isOk()) {
-        ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    if (!h2b(static_cast<HStatus>(transResult), &status)) {
-        ALOGE("%s(): corrupted transaction.", __func__);
-        return FAILED_TRANSACTION;
-    }
-    return status;
-}
-
-}  // namespace android
diff --git a/plugin_store/V4L2PluginStore.cpp b/plugin_store/V4L2PluginStore.cpp
index 2d53c5f..9f9f262 100644
--- a/plugin_store/V4L2PluginStore.cpp
+++ b/plugin_store/V4L2PluginStore.cpp
@@ -12,11 +12,10 @@
 #include <mutex>
 
 #include <C2AllocatorGralloc.h>
+#include <C2BqBufferPriv.h>
 #include <C2BufferPriv.h>
 #include <log/log.h>
 
-#include <v4l2_codec2/plugin_store/C2VdaBqBlockPool.h>
-#include <v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h>
 #include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
 #include <v4l2_codec2/plugin_store/VendorAllocatorLoader.h>
 
@@ -67,17 +66,11 @@
     }
 
     switch (allocatorId) {
-    case V4L2AllocatorId::V4L2_BUFFERPOOL:
-        return new C2VdaPooledBlockPool(allocator, poolId);
-
-    case V4L2AllocatorId::V4L2_BUFFERQUEUE:
-        return new C2VdaBqBlockPool(allocator, poolId);
-
     case V4L2AllocatorId::SECURE_LINEAR:
         return new C2PooledBlockPool(allocator, poolId);
 
     case V4L2AllocatorId::SECURE_GRAPHIC:
-        return new C2VdaBqBlockPool(allocator, poolId);
+        return new C2BufferQueueBlockPool(allocator, poolId);
 
     default:
         ALOGE("%s(): Unknown allocator id=%u", __func__, allocatorId);
diff --git a/plugin_store/include/v4l2_codec2/plugin_store/C2VdaBqBlockPool.h b/plugin_store/include/v4l2_codec2/plugin_store/C2VdaBqBlockPool.h
deleted file mode 100644
index fde6299..0000000
--- a/plugin_store/include/v4l2_codec2/plugin_store/C2VdaBqBlockPool.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_BQ_BLOCK_POOL_H
-#define ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_BQ_BLOCK_POOL_H
-
-#include <functional>
-#include <map>
-#include <optional>
-
-#include <C2BqBufferPriv.h>
-#include <C2Buffer.h>
-#include <C2PlatformSupport.h>
-#include <base/callback_forward.h>
-
-namespace android {
-
-/**
- * The BufferQueue-backed block pool design which supports to request arbitrary count of graphic
- * buffers from IGBP, and use this buffer set among codec component and client.
- *
- * The block pool should restore the mapping table between slot indices and GraphicBuffer (or
- * C2GraphicAllocation). When component requests a new buffer, the block pool calls dequeueBuffer
- * to IGBP to obtain a valid slot index, and returns the corresponding buffer from map.
- */
-class C2VdaBqBlockPool : public C2BufferQueueBlockPool {
-public:
-    C2VdaBqBlockPool(const std::shared_ptr<C2Allocator>& allocator, const local_id_t localId);
-
-    ~C2VdaBqBlockPool() override = default;
-
-    /**
-     * It's a trick here. Return C2PlatformAllocatorStore::BUFFERQUEUE instead of the ID of backing
-     * allocator for client's query. It's because in platform side this ID is recognized as
-     * BufferQueue-backed block pool which is only allowed to set surface.
-     */
-    C2Allocator::id_t getAllocatorId() const override {
-        return android::C2PlatformAllocatorStore::BUFFERQUEUE;
-    };
-
-    local_id_t getLocalId() const override { return mLocalId; };
-
-    /**
-     * Tries to dequeue a buffer from producer. If the producer is allowed allocation now, call
-     * requestBuffer of dequeued slot for allocating new buffer and storing the reference into
-     * |mSlotAllocations|.
-     *
-     * When the size of |mSlotAllocations| reaches the requested buffer count, set disallow
-     * allocation to producer. After that buffer set is started to be recycled by dequeue.
-     *
-     * \retval C2_BAD_STATE informs the caller producer is switched.
-     */
-    c2_status_t fetchGraphicBlock(uint32_t width, uint32_t height, uint32_t format,
-                                  C2MemoryUsage usage,
-                                  std::shared_ptr<C2GraphicBlock>* block /* nonnull */) override;
-
-    void setRenderCallback(const C2BufferQueueBlockPool::OnRenderCallback& renderCallback =
-                                   C2BufferQueueBlockPool::OnRenderCallback()) override;
-    void configureProducer(const android::sp<HGraphicBufferProducer>& producer) override;
-
-    /**
-     * Sends the request of arbitrary number of graphic buffers allocation. If producer is given,
-     * it will set maxDequeuedBufferCount with regard to the requested buffer count and allow
-     * allocation to producer.
-     *
-     * \note C2VdaBqBlockPool-specific function
-     * \note caller should release all buffer references obtained from fetchGraphicBlock() before
-     *       calling this function.
-     *
-     * \param bufferCount  the number of requested buffers
-     *
-     * \retval C2_OK        the operation was successful.
-     * \retval C2_NO_INIT   this class is not initialized, or producer is not assigned.
-     * \retval C2_BAD_VALUE |bufferCount| is not greater than zero.
-     * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected).
-     */
-    c2_status_t requestNewBufferSet(int32_t bufferCount, uint32_t width, uint32_t height,
-                                    uint32_t format, C2MemoryUsage usage);
-
-    /**
-     * Set the callback that will be triggered when there is block available.
-     *
-     * \note C2VdaBqBlockPool-specific function
-     *
-     * \param cb  the callback function that will be triggered when there is block available.
-     *
-     * Return false if we don't support to notify the caller when a buffer is available.
-     *
-     */
-    bool setNotifyBlockAvailableCb(base::OnceClosure cb);
-
-    std::optional<uint32_t> getBufferIdFromGraphicBlock(const C2Block2D& block);
-
-private:
-    friend struct C2VdaBqBlockPoolData;
-    class Impl;
-
-    const local_id_t mLocalId;
-    std::shared_ptr<Impl> mImpl;
-};
-
-}  // namespace android
-#endif  // ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_BQ_BLOCK_POOL_H
diff --git a/plugin_store/include/v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h b/plugin_store/include/v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h
deleted file mode 100644
index 749ff47..0000000
--- a/plugin_store/include/v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_POOLED_BLOCK_POOL_H
-#define ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_POOLED_BLOCK_POOL_H
-
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <set>
-
-#include <C2Buffer.h>
-#include <C2BufferPriv.h>
-#include <C2PlatformSupport.h>
-#include <android-base/thread_annotations.h>
-
-namespace android {
-
-class C2VdaPooledBlockPool : public C2PooledBlockPool {
-public:
-    using C2PooledBlockPool::C2PooledBlockPool;
-    ~C2VdaPooledBlockPool() override = default;
-
-    // Extracts the buffer ID from BufferPoolData of the graphic block.
-    // |block| is the graphic block allocated by bufferpool block pool.
-    static std::optional<uint32_t> getBufferIdFromGraphicBlock(const C2Block2D& block);
-
-    // Allocate the specified number of buffers.
-    // |bufferCount| is the number of requested buffers.
-    c2_status_t requestNewBufferSet(int32_t bufferCount);
-
-    // Return C2_OK and store a buffer in |block| if a buffer is successfully fetched.
-    // Return C2_TIMED_OUT if the pool already allocated |mBufferCount| buffers but they are all in
-    // use.
-    // Return C2_NO_MEMORY if the pool fails to allocate a new buffer.
-    c2_status_t fetchGraphicBlock(uint32_t width, uint32_t height, uint32_t format,
-                                  C2MemoryUsage usage,
-                                  std::shared_ptr<C2GraphicBlock>* block /* nonnull */) override;
-
-private:
-    // Function mutex to lock at the start of each API function call for protecting the
-    // synchronization of all member variables.
-    std::mutex mMutex;
-
-    // The ids of all allocated buffers.
-    std::set<uint32_t> mBufferIds GUARDED_BY(mMutex);
-    // The maximum count of allocated buffers.
-    size_t mBufferCount GUARDED_BY(mMutex){0};
-};
-
-}  // namespace android
-#endif  // ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_POOLED_BLOCK_POOL_H
diff --git a/plugin_store/include/v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h b/plugin_store/include/v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h
deleted file mode 100644
index 11185bb..0000000
--- a/plugin_store/include/v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_V4L2_CODEC2_PLUGIN_STORE_H2B_GRAPHIC_BUFFER_PRODUCER_H
-#define ANDROID_V4L2_CODEC2_PLUGIN_STORE_H2B_GRAPHIC_BUFFER_PRODUCER_H
-
-#include <C2Buffer.h>
-#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
-#include <android/hardware/graphics/bufferqueue/2.0/IProducerListener.h>
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-class H2BGraphicBufferProducer {
-public:
-    using HGraphicBufferProducer =
-            ::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer;
-    using HProducerListener = ::android::hardware::graphics::bufferqueue::V2_0::IProducerListener;
-
-    explicit H2BGraphicBufferProducer(sp<HGraphicBufferProducer> base);
-    ~H2BGraphicBufferProducer() = default;
-
-    // Convert HIDL interface of IGraphicBufferProducer.
-    status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
-    status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
-    status_t dequeueBuffer(uint32_t width, uint32_t height, uint32_t pixelFormat,
-                           C2AndroidMemoryUsage androidUsage, int* slot, sp<Fence>* fence);
-    status_t detachBuffer(int slot);
-    status_t attachBuffer(const sp<GraphicBuffer>& buffer, int* outSlot);
-    status_t cancelBuffer(int slot, const sp<Fence>& fence);
-    int query(int what, int* value);
-    status_t allowAllocation(bool allow);
-    status_t getUniqueId(uint64_t* outId) const;
-    status_t connect(sp<HProducerListener> const& hListener, int32_t api,
-                     bool producerControlledByApp);
-    status_t setDequeueTimeout(nsecs_t timeout);
-
-    sp<HGraphicBufferProducer> getBase() { return mBase; }
-
-private:
-    const sp<HGraphicBufferProducer> mBase;
-};
-
-}  // namespace android
-#endif  // ANDROID_V4L2_CODEC2_PLUGIN_STORE_H2B_GRAPHIC_BUFFER_PRODUCER_H
diff --git a/plugin_store/include/v4l2_codec2/plugin_store/V4L2AllocatorId.h b/plugin_store/include/v4l2_codec2/plugin_store/V4L2AllocatorId.h
index 0808963..2353076 100644
--- a/plugin_store/include/v4l2_codec2/plugin_store/V4L2AllocatorId.h
+++ b/plugin_store/include/v4l2_codec2/plugin_store/V4L2AllocatorId.h
@@ -12,9 +12,7 @@
 
 // The allocator ids used for V4L2DecodeComponent.
 enum : C2AllocatorStore::id_t {
-    V4L2_BUFFERQUEUE = C2PlatformAllocatorStore::PLATFORM_END,
-    V4L2_BUFFERPOOL,
-    SECURE_LINEAR,
+    SECURE_LINEAR = C2PlatformAllocatorStore::PLATFORM_END,
     SECURE_GRAPHIC,
 };
 
diff --git a/service/Android.bp b/service/Android.bp
index eaf5d3f..d2d70c7 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -8,7 +8,7 @@
 }
 
 cc_binary {
-    name: "android.hardware.media.c2@1.0-service-v4l2",
+    name: "android.hardware.media.c2@1.2-service-v4l2",
 
     defaults: [
         "hidl_defaults",
@@ -37,11 +37,11 @@
     multilib: {
         lib32: {
             suffix: "-32",
-            init_rc: ["android.hardware.media.c2@1.0-service-v4l2-32.rc"],
+            init_rc: ["android.hardware.media.c2@1.2-service-v4l2-32.rc"],
         },
         lib64: {
             suffix: "-64",
-            init_rc: ["android.hardware.media.c2@1.0-service-v4l2-64.rc"],
+            init_rc: ["android.hardware.media.c2@1.2-service-v4l2-64.rc"],
         },
     },
     vintf_fragments: ["android.hardware.media.c2@1.2-service-v4l2.xml"],
diff --git a/service/android.hardware.media.c2@1.0-service-v4l2-32.rc b/service/android.hardware.media.c2@1.0-service-v4l2-32.rc
deleted file mode 100644
index e4ddbc3..0000000
--- a/service/android.hardware.media.c2@1.0-service-v4l2-32.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service android-hardware-media-c2-v4l2-hal-1-0 /vendor/bin/hw/android.hardware.media.c2@1.0-service-v4l2-32
-    class hal
-    user media
-    group mediadrm drmrpc
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh
-    setenv MESA_GLSL_CACHE_DISABLE 1
diff --git a/service/android.hardware.media.c2@1.0-service-v4l2-64.rc b/service/android.hardware.media.c2@1.0-service-v4l2-64.rc
deleted file mode 100644
index 454953b..0000000
--- a/service/android.hardware.media.c2@1.0-service-v4l2-64.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service android-hardware-media-c2-v4l2-hal-1-0 /vendor/bin/hw/android.hardware.media.c2@1.0-service-v4l2-64
-    class hal
-    user media
-    group mediadrm drmrpc
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh
-    setenv MESA_GLSL_CACHE_DISABLE 1
diff --git a/service/android.hardware.media.c2@1.2-service-v4l2-32.rc b/service/android.hardware.media.c2@1.2-service-v4l2-32.rc
new file mode 100644
index 0000000..4fe0ccb
--- /dev/null
+++ b/service/android.hardware.media.c2@1.2-service-v4l2-32.rc
@@ -0,0 +1,7 @@
+service android-hardware-media-c2-v4l2-hal-1-2 /vendor/bin/hw/android.hardware.media.c2@1.2-service-v4l2-32
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh
+    setenv MESA_GLSL_CACHE_DISABLE 1
diff --git a/service/android.hardware.media.c2@1.2-service-v4l2-64.rc b/service/android.hardware.media.c2@1.2-service-v4l2-64.rc
new file mode 100644
index 0000000..9869c6b
--- /dev/null
+++ b/service/android.hardware.media.c2@1.2-service-v4l2-64.rc
@@ -0,0 +1,7 @@
+service android-hardware-media-c2-v4l2-hal-1-2 /vendor/bin/hw/android.hardware.media.c2@1.2-service-v4l2-64
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh
+    setenv MESA_GLSL_CACHE_DISABLE 1
diff --git a/service/service.cpp b/service/service.cpp
index 1fa9aae..bde1521 100644
--- a/service/service.cpp
+++ b/service/service.cpp
@@ -5,9 +5,9 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "android.hardware.media.c2@1.0-service-v4l2"
 
-#include <base/logging.h>
 #include <C2Component.h>
-#include <codec2/hidl/1.0/ComponentStore.h>
+#include <base/logging.h>
+#include <codec2/hidl/1.2/ComponentStore.h>
 #include <hidl/HidlTransportSupport.h>
 #include <log/log.h>
 #include <minijail.h>
@@ -43,7 +43,7 @@
 
     // Create IComponentStore service.
     {
-        using namespace ::android::hardware::media::c2::V1_0;
+        using namespace ::android::hardware::media::c2::V1_2;
 
         ALOGD("Instantiating Codec2's V4L2 IComponentStore service...");
         android::sp<IComponentStore> store(