media.c2 aidl: connect CCodec, Codec2Client and HAL

Test: m
Bug: 254050314
Change-Id: I63640f14416f8c3c3c4e1eb52ab85ae6bb04d421
diff --git a/media/codec2/vndk/C2Fence.cpp b/media/codec2/vndk/C2Fence.cpp
index 4c385f1..52ebe25 100644
--- a/media/codec2/vndk/C2Fence.cpp
+++ b/media/codec2/vndk/C2Fence.cpp
@@ -26,6 +26,8 @@
 #include <C2FenceFactory.h>
 #include <C2SurfaceSyncObj.h>
 
+#include <utility>
+
 #define MAX_FENCE_FDS 1
 
 class C2Fence::Impl {
@@ -485,17 +487,26 @@
         mValid = (mPipeFd.get() >= 0);
     }
 
+    PipeFenceImpl(::android::base::unique_fd &&ufd) : mPipeFd{std::move(ufd)} {
+        mValid = (mPipeFd.get() >= 0);
+    }
+
 private:
     friend struct _C2FenceFactory;
     static constexpr int kPipeFenceWaitLimitSecs = 5;
 
     mutable std::atomic<bool> mValid;
-    ::android::base::unique_fd mPipeFd;
+    const ::android::base::unique_fd mPipeFd;
 };
 
 C2Fence _C2FenceFactory::CreatePipeFence(int fd) {
+    ::android::base::unique_fd ufd{fd};
+    return CreatePipeFence(std::move(ufd));
+}
+
+C2Fence _C2FenceFactory::CreatePipeFence(::android::base::unique_fd &&ufd) {
     std::shared_ptr<_C2FenceFactory::PipeFenceImpl> impl =
-        std::make_shared<_C2FenceFactory::PipeFenceImpl>(fd);
+        std::make_shared<_C2FenceFactory::PipeFenceImpl>(std::move(ufd));
     std::shared_ptr<C2Fence::Impl> p = std::static_pointer_cast<C2Fence::Impl>(impl);
     if (!p) {
         ALOGE("PipeFence creation failure");
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 76c378d..e7fd14f 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -26,12 +26,15 @@
 #include <C2BqBufferPriv.h>
 #include <C2Component.h>
 #include <C2Config.h>
+#include <C2IgbaBufferPriv.h>
 #include <C2PlatformStorePluginLoader.h>
 #include <C2PlatformSupport.h>
 #include <codec2/common/HalSelection.h>
 #include <cutils/properties.h>
 #include <util/C2InterfaceHelper.h>
 
+#include <aidl/android/hardware/media/c2/IGraphicBufferAllocator.h>
+
 #include <dlfcn.h>
 #include <unistd.h> // getpagesize
 
@@ -92,6 +95,9 @@
     /// returns a shared-singleton bufferqueue supporting gralloc allocator
     std::shared_ptr<C2Allocator> fetchBufferQueueAllocator();
 
+    /// returns a shared-singleton IGBA supporting AHardwareBuffer/gralloc allocator
+    std::shared_ptr<C2Allocator> fetchIgbaAllocator();
+
     /// component store to use
     std::mutex _mComponentStoreSetLock; // protects the entire updating _mComponentStore and its
                                         // dependencies
@@ -158,6 +164,10 @@
         *allocator = fetchBlobAllocator();
         break;
 
+    case C2PlatformAllocatorStore::IGBA:
+        *allocator = fetchIgbaAllocator();
+        break;
+
     default:
         // Try to create allocator from platform store plugins.
         c2_status_t res =
@@ -389,6 +399,18 @@
     return allocator;
 }
 
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIgbaAllocator() {
+    static std::mutex mutex;
+    static std::weak_ptr<C2Allocator> ahwbAllocator;
+    std::lock_guard<std::mutex> lock(mutex);
+    std::shared_ptr<C2Allocator> allocator = ahwbAllocator.lock();
+    if (allocator == nullptr) {
+        allocator = std::make_shared<C2AllocatorAhwb>(C2PlatformAllocatorStore::IGBA);
+        ahwbAllocator = allocator;
+    }
+    return allocator;
+}
+
 namespace {
     std::mutex gPreferredComponentStoreMutex;
     std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
@@ -460,12 +482,13 @@
 
 private:
     c2_status_t _createBlockPool(
-            C2PlatformAllocatorStore::id_t allocatorId,
+            C2PlatformAllocatorDesc &allocatorParam,
             std::vector<std::shared_ptr<const C2Component>> components,
             C2BlockPool::local_id_t poolId,
             std::shared_ptr<C2BlockPool> *pool) {
         std::shared_ptr<C2AllocatorStore> allocatorStore =
                 GetCodec2PlatformAllocatorStore();
+        C2PlatformAllocatorStore::id_t allocatorId = allocatorParam.allocatorId;
         std::shared_ptr<C2Allocator> allocator;
         c2_status_t res = C2_NOT_FOUND;
 
@@ -532,6 +555,22 @@
                            components.begin(), components.end());
                 }
                 break;
+            case C2PlatformAllocatorStore::IGBA:
+                res = allocatorStore->fetchAllocator(
+                        C2PlatformAllocatorStore::IGBA, &allocator);
+                if (res == C2_OK) {
+                    std::shared_ptr<C2BlockPool> ptr(
+                            new C2IgbaBlockPool(allocator,
+                                                allocatorParam.igba,
+                                                std::move(allocatorParam.waitableFd),
+                                                poolId), deleter);
+                    *pool = ptr;
+                    mBlockPools[poolId] = ptr;
+                    mComponents[poolId].insert(
+                           mComponents[poolId].end(),
+                           components.begin(), components.end());
+                }
+                break;
             default:
                 // Try to create block pool from platform store plugins.
                 std::shared_ptr<C2BlockPool> ptr;
@@ -554,10 +593,20 @@
             C2PlatformAllocatorStore::id_t allocatorId,
             std::vector<std::shared_ptr<const C2Component>> components,
             std::shared_ptr<C2BlockPool> *pool) {
-        std::unique_lock lock(mMutex);
-        return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
+        C2PlatformAllocatorDesc allocator;
+        allocator.allocatorId = allocatorId;
+        return createBlockPool(allocator, components, pool);
     }
 
+    c2_status_t createBlockPool(
+            C2PlatformAllocatorDesc &allocator,
+            std::vector<std::shared_ptr<const C2Component>> components,
+            std::shared_ptr<C2BlockPool> *pool) {
+        std::unique_lock lock(mMutex);
+        return _createBlockPool(allocator, components, mBlockPoolSeqId++, pool);
+    }
+
+
     c2_status_t getBlockPool(
             C2BlockPool::local_id_t blockPoolId,
             std::shared_ptr<const C2Component> component,
@@ -586,8 +635,10 @@
         }
         // TODO: remove this. this is temporary
         if (blockPoolId == C2BlockPool::PLATFORM_START) {
+            C2PlatformAllocatorDesc allocator;
+            allocator.allocatorId = C2PlatformAllocatorStore::BUFFERQUEUE;
             return _createBlockPool(
-                    C2PlatformAllocatorStore::BUFFERQUEUE, {component}, blockPoolId, pool);
+                    allocator, {component}, blockPoolId, pool);
         }
         return C2_NOT_FOUND;
     }
@@ -644,7 +695,9 @@
         std::shared_ptr<C2BlockPool> *pool) {
     pool->reset();
 
-    return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
+    C2PlatformAllocatorDesc allocator;
+    allocator.allocatorId = allocatorId;
+    return sBlockPoolCache->createBlockPool(allocator, components, pool);
 }
 
 c2_status_t CreateCodec2BlockPool(
@@ -653,7 +706,27 @@
         std::shared_ptr<C2BlockPool> *pool) {
     pool->reset();
 
-    return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
+    C2PlatformAllocatorDesc allocator;
+    allocator.allocatorId = allocatorId;
+    return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
+}
+
+c2_status_t CreateCodec2BlockPool(
+        C2PlatformAllocatorDesc &allocator,
+        const std::vector<std::shared_ptr<const C2Component>> &components,
+        std::shared_ptr<C2BlockPool> *pool) {
+    pool->reset();
+
+    return sBlockPoolCache->createBlockPool(allocator, components, pool);
+}
+
+c2_status_t CreateCodec2BlockPool(
+        C2PlatformAllocatorDesc &allocator,
+        std::shared_ptr<const C2Component> component,
+        std::shared_ptr<C2BlockPool> *pool) {
+    pool->reset();
+
+    return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
 }
 
 class C2PlatformComponentStore : public C2ComponentStore {
diff --git a/media/codec2/vndk/include/C2FenceFactory.h b/media/codec2/vndk/include/C2FenceFactory.h
index 9b09980..4f974ca 100644
--- a/media/codec2/vndk/include/C2FenceFactory.h
+++ b/media/codec2/vndk/include/C2FenceFactory.h
@@ -20,6 +20,8 @@
 
 #include <C2Buffer.h>
 
+#include <android-base/unique_fd.h>
+
 /*
  * Create a list of fds from fence
  *
@@ -69,6 +71,7 @@
 
     /*
      * Create C2Fence from an fd created by pipe()/pipe2() syscall.
+     * The ownership of \p fd is transterred to the returned C2Fence.
      *
      * \param fd                An fd representing the write end from a pair of
      *                          file descriptors which are created by
@@ -76,6 +79,15 @@
      */
     static C2Fence CreatePipeFence(int fd);
 
+    /*
+     * Create C2Fence from a unique_fd created by pipe()/pipe2() syscall.
+     *
+     * \param ufd               A unique_fd representing the write end from a pair
+     *                          of file descriptors which are created by
+     *                          pipe()/pipe2() syscall.
+     */
+    static C2Fence CreatePipeFence(::android::base::unique_fd &&ufd);
+
     /**
      * Create a native handle from fence for marshalling
      *
diff --git a/media/codec2/vndk/include/C2IgbaBufferPriv.h b/media/codec2/vndk/include/C2IgbaBufferPriv.h
index a5676b7..5879263 100644
--- a/media/codec2/vndk/include/C2IgbaBufferPriv.h
+++ b/media/codec2/vndk/include/C2IgbaBufferPriv.h
@@ -17,6 +17,8 @@
 
 #include <C2Buffer.h>
 
+#include <android-base/unique_fd.h>
+
 #include <memory>
 
 namespace aidl::android::hardware::media::c2 {
@@ -32,8 +34,9 @@
 public:
     explicit C2IgbaBlockPool(
             const std::shared_ptr<C2Allocator> &allocator,
-            const std::shared_ptr<
-                    ::aidl::android::hardware::media::c2::IGraphicBufferAllocator> &igba,
+            const std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator>
+                    &igba,
+            ::android::base::unique_fd &&ufd,
             const local_id_t localId);
 
     virtual ~C2IgbaBlockPool() = default;
@@ -89,8 +92,7 @@
 
     C2IgbaBlockPoolData(
             const AHardwareBuffer *buffer,
-            const std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator>
-                &igba);
+            std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> &igba);
 
     virtual ~C2IgbaBlockPoolData() override;
 
@@ -103,7 +105,10 @@
 
     void disown();
 
+    void registerIgba(std::shared_ptr<
+            ::aidl::android::hardware::media::c2::IGraphicBufferAllocator> &igba);
+
     bool mOwned;
     const AHardwareBuffer *mBuffer;
-    const std::weak_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> mIgba;
+    std::weak_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> mIgba;
 };
diff --git a/media/codec2/vndk/include/C2PlatformSupport.h b/media/codec2/vndk/include/C2PlatformSupport.h
index 221a799..6fa155a 100644
--- a/media/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/codec2/vndk/include/C2PlatformSupport.h
@@ -22,6 +22,12 @@
 
 #include <memory>
 
+#include <android-base/unique_fd.h>
+
+namespace aidl::android::hardware::media::c2 {
+class IGraphicBufferAllocator;
+}
+
 namespace android {
 
 /**
@@ -164,6 +170,53 @@
         std::shared_ptr<C2BlockPool> *pool);
 
 /**
+ * BlockPool creation parameters regarding allocator.
+ *
+ * igba, waitableFd are required only when allocatorId is
+ * C2PlatformAllocatorStore::IGBA.
+ */
+struct C2PlatformAllocatorDesc {
+    C2PlatformAllocatorStore::id_t allocatorId;
+    std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> igba;
+    ::android::base::unique_fd waitableFd; // This will be passed and moved to C2Fence
+                                           // implementation.
+};
+
+/**
+ * Creates a block pool.
+ * \param allocator     allocator ID and parameters which are used to allocate blocks
+ * \param component     the component using the block pool (must be non-null)
+ * \param pool          pointer to where the created block pool shall be store on success.
+ *                      nullptr will be stored here on failure
+ *
+ * \retval C2_OK        the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the allocator does not exist
+ * \retval C2_NO_MEMORY not enough memory to create a block pool
+ */
+c2_status_t CreateCodec2BlockPool(
+        C2PlatformAllocatorDesc &allocator,
+        std::shared_ptr<const C2Component> component,
+        std::shared_ptr<C2BlockPool> *pool);
+
+/**
+ * Creates a block pool.
+ * \param allocator     allocator ID and parameters which are used to allocate blocks
+ * \param components    the components using the block pool
+ * \param pool          pointer to where the created block pool shall be store on success.
+ *                      nullptr will be stored here on failure
+ *
+ * \retval C2_OK        the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the allocator does not exist
+ * \retval C2_NO_MEMORY not enough memory to create a block pool
+ */
+c2_status_t CreateCodec2BlockPool(
+        C2PlatformAllocatorDesc &allocator,
+        const std::vector<std::shared_ptr<const C2Component>> &components,
+        std::shared_ptr<C2BlockPool> *pool);
+
+/**
  * Returns the platform component store.
  * \retval nullptr if the platform component store could not be obtained
  */
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index 8198ee1..4baf2db 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -39,6 +39,12 @@
 
 }
 
+namespace aidl::android::hardware::media::c2 {
+
+// IGraphicBufferAllocator for media.c2 aidl
+class IGraphicBufferAllocator;
+}
+
 typedef struct AHardwareBuffer AHardwareBuffer;
 
 using bufferpool_BufferPoolData = android::hardware::media::bufferpool::BufferPoolData;
@@ -472,6 +478,16 @@
      */
     static void DisownIgbaBlock(
             const std::shared_ptr<_C2BlockPoolData>& poolData);
+
+    /**
+     * When the client receives a block from HAL, the client needs to store
+     * IGraphicBufferAllocator from which the block was originally allocated.
+     * The stored \p igba will be used in the dtor to deallocate the buffer.
+     * (calling IGraphicBufferAllocator::deallocate to reclaim.)
+     */
+    static void RegisterIgba(
+            const std::shared_ptr<_C2BlockPoolData>& poolData,
+            std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> &igba);
 };
 
 #endif // ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
diff --git a/media/codec2/vndk/platform/C2IgbaBuffer.cpp b/media/codec2/vndk/platform/C2IgbaBuffer.cpp
index 853d5a3..2051e8f 100644
--- a/media/codec2/vndk/platform/C2IgbaBuffer.cpp
+++ b/media/codec2/vndk/platform/C2IgbaBuffer.cpp
@@ -67,7 +67,8 @@
             return err;
         }
         std::shared_ptr<C2IgbaBlockPoolData> poolData =
-                std::make_shared<C2IgbaBlockPoolData>(ahwb, igba);
+                std::make_shared<C2IgbaBlockPoolData>(
+                        ahwb, const_cast<std::shared_ptr<C2IGBA>&>(igba));
         *block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
         return C2_OK;
     } else {
@@ -79,7 +80,7 @@
 
 C2IgbaBlockPoolData::C2IgbaBlockPoolData(
         const AHardwareBuffer *buffer,
-        const std::shared_ptr<C2IGBA> &igba) : mOwned(true), mBuffer(buffer), mIgba(igba) {
+        std::shared_ptr<C2IGBA> &igba) : mOwned(true), mBuffer(buffer), mIgba(igba) {
     CHECK(mBuffer);
     AHardwareBuffer_acquire(const_cast<AHardwareBuffer *>(mBuffer));
 }
@@ -115,6 +116,10 @@
     mOwned = false;
 }
 
+void C2IgbaBlockPoolData::registerIgba(std::shared_ptr<C2IGBA> &igba) {
+    mIgba = igba;
+}
+
 std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(AHardwareBuffer *ahwb) {
     // TODO: get proper allocator? and synchronization? or allocator-less?
     static std::shared_ptr<C2AllocatorAhwb> sAllocator = std::make_shared<C2AllocatorAhwb>(0);
@@ -148,22 +153,30 @@
     }
 }
 
+void _C2BlockFactory::RegisterIgba(
+        const std::shared_ptr<_C2BlockPoolData>& data,
+        std::shared_ptr<C2IGBA> &igba) {
+    if (data && data->getType() == _C2BlockPoolData::TYPE_AHWBUFFER) {
+        const std::shared_ptr<C2IgbaBlockPoolData> poolData =
+                std::static_pointer_cast<C2IgbaBlockPoolData>(data);
+        poolData->registerIgba(igba);
+    }
+}
+
 C2IgbaBlockPool::C2IgbaBlockPool(
         const std::shared_ptr<C2Allocator> &allocator,
         const std::shared_ptr<C2IGBA> &igba,
+        ::android::base::unique_fd &&ufd,
         const local_id_t localId) : mAllocator(allocator), mIgba(igba), mLocalId(localId) {
     if (!mIgba) {
         mValid = false;
         return;
     }
-    // TODO: Remove IPC (This is a nested IPC call during c2aidl creatBlockPool().
-    ::ndk::ScopedFileDescriptor fd;
-    ::ndk::ScopedAStatus status = mIgba->getWaitableFd(&fd);
-    if (!status.isOk()) {
+    if (ufd.get() < 0) {
         mValid = false;
         return;
     }
-    mWaitFence = _C2FenceFactory::CreatePipeFence(fd.release());
+    mWaitFence = _C2FenceFactory::CreatePipeFence(std::move(ufd));
     if (!mWaitFence.valid()) {
         mValid = false;
         return;