gralloc: add IAllocator/IMapper 4.0 to codec2

Add support for gralloc 4.0 to codec2.

Bug: 136016160
Test: Compiles and boots

Change-Id: I5273a7f8d78afa7c94842f62a63cc52ae241df02
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index b6ddfab..60f9d20 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -51,9 +51,11 @@
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.allocator@3.0",
+        "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.bufferqueue@2.0",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
         "android.hardware.media.bufferpool@2.0",
         "libbase",
         "libbinder",
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index af97e61..3a715b1 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -22,6 +22,8 @@
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
 #include <cutils/native_handle.h>
 #include <hardware/gralloc.h>
 
@@ -66,6 +68,7 @@
 using ::android::hardware::graphics::common::V1_0::BufferUsage;
 using PixelFormat2 = ::android::hardware::graphics::common::V1_0::PixelFormat;
 using PixelFormat3 = ::android::hardware::graphics::common::V1_2::PixelFormat;
+using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
 
 using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
 using BufferDescriptor2 = ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
@@ -77,6 +80,11 @@
 using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
 using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
 
+using IAllocator4 = ::android::hardware::graphics::allocator::V4_0::IAllocator;
+using BufferDescriptor4 = ::android::hardware::graphics::mapper::V4_0::BufferDescriptor;
+using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
+using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
+
 namespace /* unnamed */ {
 
 struct BufferDescriptorInfo2 {
@@ -89,6 +97,11 @@
     uint32_t stride;
 };
 
+struct BufferDescriptorInfo4 {
+    IMapper4::BufferDescriptorInfo mapperInfo;
+    uint32_t stride;
+};
+
 /* ===================================== GRALLOC ALLOCATION ==================================== */
 c2_status_t maperr2error(Error2 maperr) {
     switch (maperr) {
@@ -114,6 +127,18 @@
     return C2_CORRUPTED;
 }
 
+c2_status_t maperr2error(Error4 maperr) {
+    switch (maperr) {
+        case Error4::NONE:           return C2_OK;
+        case Error4::BAD_DESCRIPTOR: return C2_BAD_VALUE;
+        case Error4::BAD_BUFFER:     return C2_BAD_VALUE;
+        case Error4::BAD_VALUE:      return C2_BAD_VALUE;
+        case Error4::NO_RESOURCES:   return C2_NO_MEMORY;
+        case Error4::UNSUPPORTED:    return C2_CANNOT_DO;
+    }
+    return C2_CORRUPTED;
+}
+
 bool native_handle_is_invalid(const native_handle_t *const handle) {
     // perform basic validation of a native handle
     if (handle == nullptr) {
@@ -321,6 +346,12 @@
               hidl_handle &hidlHandle,
               const C2HandleGralloc *const handle,
               C2Allocator::id_t allocatorId);
+    C2AllocationGralloc(
+              const BufferDescriptorInfo4 &info,
+              const sp<IMapper4> &mapper,
+              hidl_handle &hidlHandle,
+              const C2HandleGralloc *const handle,
+              C2Allocator::id_t allocatorId);
     int dup() const;
     c2_status_t status() const;
 
@@ -329,6 +360,8 @@
     const sp<IMapper2> mMapper2{nullptr};
     const BufferDescriptorInfo3 mInfo3{};
     const sp<IMapper3> mMapper3{nullptr};
+    const BufferDescriptorInfo4 mInfo4{};
+    const sp<IMapper4> mMapper4{nullptr};
     const hidl_handle mHidlHandle;
     const C2HandleGralloc *mHandle;
     buffer_handle_t mBuffer;
@@ -372,6 +405,23 @@
       mAllocatorId(allocatorId) {
 }
 
+C2AllocationGralloc::C2AllocationGralloc(
+          const BufferDescriptorInfo4 &info,
+          const sp<IMapper4> &mapper,
+          hidl_handle &hidlHandle,
+          const C2HandleGralloc *const handle,
+          C2Allocator::id_t allocatorId)
+    : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
+      mInfo4(info),
+      mMapper4(mapper),
+      mHidlHandle(std::move(hidlHandle)),
+      mHandle(handle),
+      mBuffer(nullptr),
+      mLockedHandle(nullptr),
+      mLocked(false),
+      mAllocatorId(allocatorId) {
+}
+
 C2AllocationGralloc::~C2AllocationGralloc() {
     if (mBuffer && mLocked) {
         // implementation ignores addresss and rect
@@ -384,12 +434,18 @@
                     mBuffer)).isOk()) {
                 ALOGE("failed transaction: freeBuffer");
             }
-        } else {
+        } else if (mMapper3) {
             if (!mMapper3->freeBuffer(const_cast<native_handle_t *>(
                     mBuffer)).isOk()) {
                 ALOGE("failed transaction: freeBuffer");
             }
+        } else {
+            if (!mMapper4->freeBuffer(const_cast<native_handle_t *>(
+                    mBuffer)).isOk()) {
+                ALOGE("failed transaction: freeBuffer");
+            }
         }
+
     }
     if (mHandle) {
         native_handle_delete(
@@ -435,7 +491,7 @@
                 ALOGE("failed transaction: importBuffer");
                 return C2_CORRUPTED;
             }
-        } else {
+        } else if (mMapper3) {
             if (!mMapper3->importBuffer(
                     mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
                         err = maperr2error(maperr);
@@ -446,6 +502,17 @@
                 ALOGE("failed transaction: importBuffer (@3.0)");
                 return C2_CORRUPTED;
             }
+        } else {
+            if (!mMapper4->importBuffer(
+                    mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
+                        err = maperr2error(maperr);
+                        if (err == C2_OK) {
+                            mBuffer = static_cast<buffer_handle_t>(buffer);
+                        }
+                    }).isOk()) {
+                ALOGE("failed transaction: importBuffer (@4.0)");
+                return C2_CORRUPTED;
+            }
         }
         if (err != C2_OK) {
             ALOGD("importBuffer failed: %d", err);
@@ -466,19 +533,29 @@
                     mBuffer, mInfo2.mapperInfo.width, mInfo2.mapperInfo.height,
                     (uint32_t)mInfo2.mapperInfo.format, mInfo2.mapperInfo.usage,
                     mInfo2.stride, generation, igbp_id, igbp_slot);
-        } else {
+        } else if (mMapper3) {
             mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
                     mBuffer, mInfo3.mapperInfo.width, mInfo3.mapperInfo.height,
                     (uint32_t)mInfo3.mapperInfo.format, mInfo3.mapperInfo.usage,
                     mInfo3.stride, generation, igbp_id, igbp_slot);
+        } else {
+            mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
+                    mBuffer, mInfo4.mapperInfo.width, mInfo4.mapperInfo.height,
+                    (uint32_t)mInfo4.mapperInfo.format, mInfo4.mapperInfo.usage,
+                    mInfo4.stride, generation, igbp_id, igbp_slot);
         }
     }
 
-    PixelFormat3 format = mMapper2 ?
-            PixelFormat3(mInfo2.mapperInfo.format) :
-            PixelFormat3(mInfo3.mapperInfo.format);
+    PixelFormat4 format;
+    if (mMapper2) {
+        format = PixelFormat4(mInfo2.mapperInfo.format);
+    } else if (mMapper3) {
+        format = PixelFormat4(mInfo3.mapperInfo.format);
+    } else {
+        format = PixelFormat4(mInfo4.mapperInfo.format);
+    }
     switch (format) {
-        case PixelFormat3::RGBA_1010102: {
+        case PixelFormat4::RGBA_1010102: {
             // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
             // Surface. In all other cases it is RGBA. We don't know which case it is here, so
             // default to YUV for now.
@@ -500,7 +577,7 @@
                     ALOGE("failed transaction: lock(RGBA_1010102)");
                     return C2_CORRUPTED;
                 }
-            } else {
+            } else if (mMapper3) {
                 if (!mMapper3->lock(
                         const_cast<native_handle_t *>(mBuffer),
                         grallocUsage,
@@ -520,6 +597,26 @@
                     ALOGE("failed transaction: lock(RGBA_1010102) (@3.0)");
                     return C2_CORRUPTED;
                 }
+            } else {
+                if (!mMapper4->lock(
+                        const_cast<native_handle_t *>(mBuffer),
+                        grallocUsage,
+                        { (int32_t)rect.left, (int32_t)rect.top,
+                          (int32_t)rect.width, (int32_t)rect.height },
+                        // TODO: fence
+                        hidl_handle(),
+                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
+                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
+                            err = maperr2error(maperr);
+                            if (err == C2_OK) {
+                                pointer = mapPointer;
+                            }
+                            (void)bytesPerPixel;
+                            (void)bytesPerStride;
+                        }).isOk()) {
+                    ALOGE("failed transaction: lock(RGBA_1010102) (@4.0)");
+                    return C2_CORRUPTED;
+                }
             }
             if (err != C2_OK) {
                 ALOGD("lock failed: %d", err);
@@ -533,9 +630,14 @@
             layout->type = C2PlanarLayout::TYPE_YUVA;
             layout->numPlanes = 4;
             layout->rootPlanes = 1;
-            int32_t stride = mMapper2 ?
-                    int32_t(mInfo2.stride) :
-                    int32_t(mInfo3.stride);
+            int32_t stride;
+            if (mMapper2) {
+                stride = int32_t(mInfo2.stride);
+            } if (mMapper3) {
+                stride = int32_t(mInfo3.stride);
+            } else {
+                stride = int32_t(mInfo4.stride);
+            }
             layout->planes[C2PlanarLayout::PLANE_Y] = {
                 C2PlaneInfo::CHANNEL_Y,         // channel
                 4,                              // colInc
@@ -591,10 +693,10 @@
             break;
         }
 
-        case PixelFormat3::RGBA_8888:
+        case PixelFormat4::RGBA_8888:
             // TODO: alpha channel
             // fall-through
-        case PixelFormat3::RGBX_8888: {
+        case PixelFormat4::RGBX_8888: {
             void *pointer = nullptr;
             if (mMapper2) {
                 if (!mMapper2->lock(
@@ -613,7 +715,7 @@
                     ALOGE("failed transaction: lock(RGBA_8888)");
                     return C2_CORRUPTED;
                 }
-            } else {
+            } else if (mMapper3) {
                 if (!mMapper3->lock(
                         const_cast<native_handle_t *>(mBuffer),
                         grallocUsage,
@@ -633,6 +735,26 @@
                     ALOGE("failed transaction: lock(RGBA_8888) (@3.0)");
                     return C2_CORRUPTED;
                 }
+            } else {
+                if (!mMapper4->lock(
+                        const_cast<native_handle_t *>(mBuffer),
+                        grallocUsage,
+                        { (int32_t)rect.left, (int32_t)rect.top,
+                          (int32_t)rect.width, (int32_t)rect.height },
+                        // TODO: fence
+                        hidl_handle(),
+                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
+                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
+                            err = maperr2error(maperr);
+                            if (err == C2_OK) {
+                                pointer = mapPointer;
+                            }
+                            (void)bytesPerPixel;
+                            (void)bytesPerStride;
+                        }).isOk()) {
+                    ALOGE("failed transaction: lock(RGBA_8888) (@4.0)");
+                    return C2_CORRUPTED;
+                }
             }
             if (err != C2_OK) {
                 ALOGD("lock failed: %d", err);
@@ -644,9 +766,14 @@
             layout->type = C2PlanarLayout::TYPE_RGB;
             layout->numPlanes = 3;
             layout->rootPlanes = 1;
-            int32_t stride = mMapper2 ?
-                    int32_t(mInfo2.stride) :
-                    int32_t(mInfo3.stride);
+            int32_t stride;
+            if (mMapper2) {
+                stride = int32_t(mInfo2.stride);
+            } if (mMapper3) {
+                stride = int32_t(mInfo3.stride);
+            } else {
+                stride = int32_t(mInfo4.stride);
+            }
             layout->planes[C2PlanarLayout::PLANE_R] = {
                 C2PlaneInfo::CHANNEL_R,         // channel
                 4,                              // colInc
@@ -689,9 +816,9 @@
             break;
         }
 
-        case PixelFormat3::YCBCR_420_888:
+        case PixelFormat4::YCBCR_420_888:
             // fall-through
-        case PixelFormat3::YV12:
+        case PixelFormat4::YV12:
             // fall-through
         default: {
             struct YCbCrLayout {
@@ -725,7 +852,7 @@
                     ALOGE("failed transaction: lockYCbCr");
                     return C2_CORRUPTED;
                 }
-            } else {
+            } else if (mMapper3) {
                 if (!mMapper3->lockYCbCr(
                         const_cast<native_handle_t *>(mBuffer), grallocUsage,
                         { (int32_t)rect.left, (int32_t)rect.top,
@@ -747,6 +874,28 @@
                     ALOGE("failed transaction: lockYCbCr (@3.0)");
                     return C2_CORRUPTED;
                 }
+            } else {
+                if (!mMapper4->lockYCbCr(
+                        const_cast<native_handle_t *>(mBuffer), grallocUsage,
+                        { (int32_t)rect.left, (int32_t)rect.top,
+                          (int32_t)rect.width, (int32_t)rect.height },
+                        // TODO: fence
+                        hidl_handle(),
+                        [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
+                            err = maperr2error(maperr);
+                            if (err == C2_OK) {
+                                ycbcrLayout = YCbCrLayout{
+                                        mapLayout.y,
+                                        mapLayout.cb,
+                                        mapLayout.cr,
+                                        mapLayout.yStride,
+                                        mapLayout.cStride,
+                                        mapLayout.chromaStep};
+                            }
+                        }).isOk()) {
+                    ALOGE("failed transaction: lockYCbCr (@4.0)");
+                    return C2_CORRUPTED;
+                }
             }
             if (err != C2_OK) {
                 ALOGD("lockYCbCr failed: %d", err);
@@ -839,7 +988,7 @@
             ALOGE("failed transaction: unlock");
             return C2_CORRUPTED;
         }
-    } else {
+    } else if (mMapper3) {
         if (!mMapper3->unlock(
                 const_cast<native_handle_t *>(mBuffer),
                 [&err, &fence](const auto &maperr, const auto &releaseFence) {
@@ -854,6 +1003,21 @@
             ALOGE("failed transaction: unlock (@3.0)");
             return C2_CORRUPTED;
         }
+    } else {
+        if (!mMapper4->unlock(
+                const_cast<native_handle_t *>(mBuffer),
+                [&err, &fence](const auto &maperr, const auto &releaseFence) {
+                    // TODO
+                    (void) fence;
+                    (void) releaseFence;
+                    err = maperr2error(maperr);
+                    if (err == C2_OK) {
+                        // TODO: fence
+                    }
+                }).isOk()) {
+            ALOGE("failed transaction: unlock (@4.0)");
+            return C2_CORRUPTED;
+        }
     }
     if (err == C2_OK) {
         mLocked = false;
@@ -899,6 +1063,8 @@
     sp<IMapper2> mMapper2;
     sp<IAllocator3> mAllocator3;
     sp<IMapper3> mMapper3;
+    sp<IAllocator4> mAllocator4;
+    sp<IMapper4> mMapper4;
     const bool mBufferQueue;
 };
 
@@ -918,17 +1084,23 @@
     mTraits = std::make_shared<C2Allocator::Traits>(traits);
 
     // gralloc allocator is a singleton, so all objects share a global service
-    mAllocator3 = IAllocator3::getService();
-    mMapper3 = IMapper3::getService();
-    if (!mAllocator3 || !mMapper3) {
-        mAllocator3 = nullptr;
-        mMapper3 = nullptr;
-        mAllocator2 = IAllocator2::getService();
-        mMapper2 = IMapper2::getService();
-        if (!mAllocator2 || !mMapper2) {
-            mAllocator2 = nullptr;
-            mMapper2 = nullptr;
-            mInit = C2_CORRUPTED;
+    mAllocator4 = IAllocator4::getService();
+    mMapper4 = IMapper4::getService();
+    if (!mAllocator4 || !mMapper4) {
+        mAllocator4 = nullptr;
+        mMapper4 = nullptr;
+        mAllocator3 = IAllocator3::getService();
+        mMapper3 = IMapper3::getService();
+        if (!mAllocator3 || !mMapper3) {
+            mAllocator3 = nullptr;
+            mMapper3 = nullptr;
+            mAllocator2 = IAllocator2::getService();
+            mMapper2 = IMapper2::getService();
+            if (!mAllocator2 || !mMapper2) {
+                mAllocator2 = nullptr;
+                mMapper2 = nullptr;
+                mInit = C2_CORRUPTED;
+            }
         }
     }
 }
@@ -1000,13 +1172,13 @@
                         0, 0, mBufferQueue ? ~0 : 0),
                 mTraits->id));
         return C2_OK;
-    } else {
+    } else if (mMapper3) {
         BufferDescriptorInfo3 info = {
             {
                 width,
                 height,
                 1u,  // layerCount
-                PixelFormat3(format),
+                PixelFormat4(format),
                 grallocUsage,
             },
             0u,  // stride placeholder
@@ -1057,6 +1229,63 @@
                         0, 0, mBufferQueue ? ~0 : 0),
                 mTraits->id));
         return C2_OK;
+    } else {
+        BufferDescriptorInfo4 info = {
+            {
+                width,
+                height,
+                1u,  // layerCount
+                PixelFormat4(format),
+                grallocUsage,
+            },
+            0u,  // stride placeholder
+        };
+        BufferDescriptor4 desc;
+        if (!mMapper4->createDescriptor(
+                info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
+                    err = maperr2error(maperr);
+                    if (err == C2_OK) {
+                        desc = descriptor;
+                    }
+                }).isOk()) {
+            ALOGE("failed transaction: createDescriptor");
+            return C2_CORRUPTED;
+        }
+        if (err != C2_OK) {
+            return err;
+        }
+
+        // IAllocator shares IMapper error codes.
+        if (!mAllocator4->allocate(
+                desc,
+                1u,
+                [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
+                    err = maperr2error(maperr);
+                    if (err != C2_OK) {
+                        return;
+                    }
+                    if (buffers.size() != 1u) {
+                        err = C2_CORRUPTED;
+                        return;
+                    }
+                    info.stride = stride;
+                    buffer = buffers[0];
+                }).isOk()) {
+            ALOGE("failed transaction: allocate");
+            return C2_CORRUPTED;
+        }
+        if (err != C2_OK) {
+            return err;
+        }
+        allocation->reset(new C2AllocationGralloc(
+                info, mMapper4, buffer,
+                C2HandleGralloc::WrapAndMoveNativeHandle(
+                        buffer.getNativeHandle(),
+                        width, height,
+                        format, grallocUsage, info.stride,
+                        0, 0, mBufferQueue ? ~0 : 0),
+                mTraits->id));
+        return C2_OK;
     }
 }
 
@@ -1086,7 +1315,7 @@
         allocation->reset(new C2AllocationGralloc(
                 info, mMapper2, hidlHandle, grallocHandle, mTraits->id));
         return C2_OK;
-    } else {
+    } else if (mMapper3) {
         BufferDescriptorInfo3 info;
         info.mapperInfo.layerCount = 1u;
         uint32_t generation;
@@ -1109,6 +1338,29 @@
         allocation->reset(new C2AllocationGralloc(
                 info, mMapper3, hidlHandle, grallocHandle, mTraits->id));
         return C2_OK;
+    } else {
+        BufferDescriptorInfo4 info;
+        info.mapperInfo.layerCount = 1u;
+        uint32_t generation;
+        uint64_t igbp_id;
+        uint32_t igbp_slot;
+        const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
+                handle,
+                &info.mapperInfo.width, &info.mapperInfo.height,
+                (uint32_t *)&info.mapperInfo.format,
+                (uint64_t *)&info.mapperInfo.usage,
+                &info.stride,
+                &generation, &igbp_id, &igbp_slot);
+        if (grallocHandle == nullptr) {
+            return C2_BAD_VALUE;
+        }
+
+        hidl_handle hidlHandle;
+        hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
+
+        allocation->reset(new C2AllocationGralloc(
+                info, mMapper4, hidlHandle, grallocHandle, mTraits->id));
+        return C2_OK;
     }
 }