media.c2 aidl: Implement IGBA/AHwB based blockpool

Implement IGBA/AHwB based BlockPool(C2IgbaBlockPool).
Also implement IGBA/AHwB based GraphicBlock transfer between HAL and the
client.

Test: m
Bug: 254050314
Change-Id: Ie27a36d071440d807adda00fe1fa9f78ec413834
diff --git a/media/codec2/hal/aidl/BufferTypes.cpp b/media/codec2/hal/aidl/BufferTypes.cpp
index 1cd3555..b1af579 100644
--- a/media/codec2/hal/aidl/BufferTypes.cpp
+++ b/media/codec2/hal/aidl/BufferTypes.cpp
@@ -54,8 +54,10 @@
 using ::aidl::android::hardware::media::c2::utils::BufferPoolTypes;
 
 using AidlNativeHandle = ::aidl::android::hardware::common::NativeHandle;
+using AidlHardwareBuffer = ::aidl::android::hardware::HardwareBuffer;
 
 constexpr BaseBlock::Tag NATIVE_BLOCK = BaseBlock::nativeBlock;
+constexpr BaseBlock::Tag HWB_BLOCK = BaseBlock::hwbBlock;
 constexpr BaseBlock::Tag POOLED_BLOCK = BaseBlock::pooledBlock;
 
 // BaseBlock -> C2BaseBlock
@@ -97,6 +99,21 @@
             }
             return false;
         }
+    case HWB_BLOCK: {
+            AHardwareBuffer *pBuf =
+                    const_cast<AidlHardwareBuffer&>(
+                            s.get<HWB_BLOCK>()).release();
+            d->graphic = _C2BlockFactory::CreateGraphicBlock(pBuf);
+            if (pBuf) {
+                AHardwareBuffer_release(pBuf);
+            }
+            if (d->graphic) {
+                d->type = ::android::C2BaseBlock::GRAPHIC;
+                return true;
+            }
+            LOG(ERROR) << "Improper ahwb in BaseBlock::hwbBlock.";
+            return false;
+        }
     case POOLED_BLOCK: {
             const BufferStatusMessage &bpMessage = s.get<POOLED_BLOCK>();
             std::shared_ptr<ClientManager> bp = ClientManager::getInstance();
@@ -188,6 +205,13 @@
 }
 
 template<>
+void SetAHardwareBuffer(BaseBlock *block, AHardwareBuffer *ahwb) {
+    AHardwareBuffer_acquire(ahwb);
+    block->set<HWB_BLOCK>(AidlHardwareBuffer());
+    (block->get<HWB_BLOCK>()).reset(ahwb);
+}
+
+template<>
 void SetPooledBlock<BufferPoolTypes>(
         BaseBlock *baseBlock,
         const typename BufferPoolTypes::BufferStatusMessage &pooledBlock) {
@@ -326,6 +350,28 @@
     return ::android::objcpy(d, s);
 }
 
+void ReturnOutputBlocksToClientIfNeeded(
+        const std::list<std::unique_ptr<C2Work>>& workList) {
+    for (const std::unique_ptr<C2Work>& work : workList) {
+        if (!work) {
+            continue;
+        }
+        for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
+            if (worklet) {
+                for (const std::shared_ptr<C2Buffer>& buffer : worklet->output.buffers) {
+                    if (buffer) {
+                        for (const C2ConstGraphicBlock& block : buffer->data().graphicBlocks()) {
+                            std::shared_ptr<_C2BlockPoolData> poolData =
+                                  _C2BlockFactory::GetGraphicBlockPoolData(block);
+                            _C2BlockFactory::DisownIgbaBlock(poolData);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
 }  // namespace utils
 }  // namespace c2
 }  // namespace media
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
index 9c21a5b..2e0859b 100644
--- a/media/codec2/hal/aidl/Component.cpp
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -113,26 +113,22 @@
             WorkBundle workBundle;
 
             std::shared_ptr<Component> strongComponent = mComponent.lock();
-            // TODO
-            // beginTransferBufferQueueBlocks(c2workItems, true);
             if (!ToAidl(&workBundle, c2workItems, strongComponent ?
                     &strongComponent->mBufferPoolSender : nullptr)) {
                 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
                            << "received corrupted work items.";
-                // TODO
-                // endTransferBufferQueueBlocks(c2workItems, false, true);
                 return;
             }
             ScopedAStatus transStatus = listener->onWorkDone(workBundle);
             if (!transStatus.isOk()) {
                 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
                            << "transaction failed.";
-                // TODO
-                // endTransferBufferQueueBlocks(c2workItems, false, true);
                 return;
             }
-            // TODO
-            // endTransferBufferQueueBlocks(c2workItems, true, true);
+            // If output blocks are originally owned by the client(not by HAL),
+            // return the ownership to the client. (Since the blocks are
+            // transferred to the client here.)
+            ReturnOutputBlocksToClientIfNeeded(c2workItems);
         }
     }
 
@@ -210,15 +206,15 @@
         }
     }
 
-    // TODO
-    // beginTransferBufferQueueBlocks(c2flushedWorks, true);
     if (c2res == C2_OK) {
         if (!ToAidl(flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
             c2res = C2_CORRUPTED;
         }
     }
-    // TODO
-    // endTransferBufferQueueBlocks(c2flushedWorks, true, true);
+    // If output blocks are originally owned by the client(not by HAL),
+    // return the ownership to the client. (Since the blocks are
+    // transferred to the client here.)
+    ReturnOutputBlocksToClientIfNeeded(c2flushedWorks);
     if (c2res == C2_OK) {
         return ScopedAStatus::ok();
     }
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h b/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h
index 470863c..87fb855 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h
@@ -115,6 +115,12 @@
         std::list<std::unique_ptr<C2Work>>* d,
         const WorkBundle& s);
 
+// Return the ownership of output blocks to the client if it is originally
+// created from the client, after C2Work is returned to the client.
+// (e.g. C2BqPool / C2IgbaBlockPool)
+void ReturnOutputBlocksToClientIfNeeded(
+        const std::list<std::unique_ptr<C2Work>>& workList);
+
 /**
  * Converts a BufferPool status value to c2_status_t.
  * \param BufferPool status
diff --git a/media/codec2/hal/client/GraphicsTracker.cpp b/media/codec2/hal/client/GraphicsTracker.cpp
index 2424f7b..573ded8 100644
--- a/media/codec2/hal/client/GraphicsTracker.cpp
+++ b/media/codec2/hal/client/GraphicsTracker.cpp
@@ -20,6 +20,7 @@
 #include <private/android/AHardwareBufferHelpers.h>
 #include <vndk/hardware_buffer.h>
 
+#include <C2BlockInternal.h>
 #include <codec2/aidl/GraphicsTracker.h>
 
 namespace aidl::android::hardware::media::c2::implementation {
@@ -30,10 +31,23 @@
 static constexpr int kMaxDequeueMax = ::android::BufferQueueDefs::NUM_BUFFER_SLOTS - 2;
 
 c2_status_t retrieveAHardwareBufferId(const C2ConstGraphicBlock &blk, uint64_t *bid) {
-    // TODO
-    (void)blk;
-    (void)bid;
-    return C2_OK;
+    std::shared_ptr<const _C2BlockPoolData> bpData = _C2BlockFactory::GetGraphicBlockPoolData(blk);
+    if (bpData->getType() != _C2BlockPoolData::TYPE_AHWBUFFER) {
+        return C2_BAD_VALUE;
+    }
+    if (__builtin_available(android __ANDROID_API_T__, *)) {
+        AHardwareBuffer *pBuf;
+        if (!_C2BlockFactory::GetAHardwareBuffer(bpData, &pBuf)) {
+            return C2_CORRUPTED;
+        }
+        int ret = AHardwareBuffer_getId(pBuf, bid);
+        if (ret != ::android::OK) {
+            return C2_CORRUPTED;
+        }
+        return C2_OK;
+    } else {
+        return C2_OMITTED;
+    }
 }
 
 } // anonymous namespace
@@ -44,16 +58,18 @@
     if (!buf) {
         return;
     }
-    AHardwareBuffer *pBuf = AHardwareBuffer_from_GraphicBuffer(buf.get());
-    int ret = AHardwareBuffer_getId(pBuf, &mId);
-    if (ret != ::android::OK) {
-        return;
+    if (__builtin_available(android __ANDROID_API_T__, *)) {
+        AHardwareBuffer *pBuf = AHardwareBuffer_from_GraphicBuffer(buf.get());
+        int ret = AHardwareBuffer_getId(pBuf, &mId);
+        if (ret != ::android::OK) {
+            return;
+        }
+        mUsage = buf->getUsage();
+        AHardwareBuffer_acquire(pBuf);
+        mBuf = pBuf;
+        mFence = fence;
+        mInit = true;
     }
-    mUsage = buf->getUsage();
-    AHardwareBuffer_acquire(pBuf);
-    mBuf = pBuf;
-    mFence = fence;
-    mInit = true;
 }
 
 GraphicsTracker::BufferItem::BufferItem(
diff --git a/media/codec2/hal/common/include/codec2/common/BufferTypes.h b/media/codec2/hal/common/include/codec2/common/BufferTypes.h
index 8998a6d..afd2db0 100644
--- a/media/codec2/hal/common/include/codec2/common/BufferTypes.h
+++ b/media/codec2/hal/common/include/codec2/common/BufferTypes.h
@@ -63,6 +63,9 @@
 template <typename BaseBlock>
 void SetHandle(BaseBlock *baseBlock, const C2Handle *handle);
 
+template <typename BaseBlock>
+void SetAHardwareBuffer(BaseBlock *baseBlock, AHardwareBuffer *pBuf);
+
 template <typename BufferPoolTypes, typename BaseBlock>
 void SetPooledBlock(
         BaseBlock *baseBlock,
@@ -100,6 +103,31 @@
     return true;
 }
 
+// Find or add a HAL BaseBlock object from a given AHardwareBuffer* to a list and an
+// associated map.
+template <typename BaseBlock>
+bool _addBaseBlock(
+        uint32_t* index,
+        AHardwareBuffer* pBuf,
+        std::list<BaseBlock>* baseBlocks,
+        std::map<const void*, uint32_t>* baseBlockIndices) {
+    if (!pBuf) {
+        LOG(ERROR) << "addBaseBlock called on a null AHardwareBuffer.";
+    }
+    auto it = baseBlockIndices->find(pBuf);
+    if (it != baseBlockIndices->end()) {
+        *index = it->second;
+    } else {
+        *index = baseBlocks->size();
+        baseBlockIndices->emplace(pBuf, *index);
+        baseBlocks->emplace_back();
+
+        BaseBlock &dBaseBlock = baseBlocks->back();
+        SetAHardwareBuffer(&dBaseBlock, pBuf);
+    }
+    return true;
+}
+
 // Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
 // an associated map.
 template <typename BufferPoolTypes, typename BaseBlock>
@@ -179,6 +207,15 @@
         return _addBaseBlock(
                 index, handle,
                 baseBlocks, baseBlockIndices);
+    case _C2BlockPoolData::TYPE_AHWBUFFER:
+        AHardwareBuffer *pBuf;
+        if (!_C2BlockFactory::GetAHardwareBuffer(blockPoolData, &pBuf)) {
+            LOG(ERROR) << "AHardwareBuffer unavailable in a block.";
+            return false;
+        }
+        return _addBaseBlock(
+                index, pBuf,
+                baseBlocks, baseBlockIndices);
     default:
         LOG(ERROR) << "Unknown C2BlockPoolData type.";
         return false;
diff --git a/media/codec2/hal/hidl/1.0/utils/types.cpp b/media/codec2/hal/hidl/1.0/utils/types.cpp
index abe5494..69f664b 100644
--- a/media/codec2/hal/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/types.cpp
@@ -210,6 +210,13 @@
 }
 
 template<>
+void SetAHardwareBuffer(BaseBlock *block, AHardwareBuffer *pBuf) {
+    (void) block;
+    (void) pBuf;
+    LOG(FATAL) << "This is not used";
+}
+
+template<>
 void SetPooledBlock<BufferPoolTypes>(
         BaseBlock *baseBlock,
         const typename BufferPoolTypes::BufferStatusMessage &pooledBlock) {