/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <string.h>
#include <pthread.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>

#include <set>
#include <map>
#include <vector>
#include <string>
#include <algorithm>

#include <log/log.h>
#include <sys/mman.h>

#include <hardware/hardware.h>
#include <hardware/gralloc.h>

#include <gralloc_cb_bp.h>
#include "gralloc_common.h"
#include "goldfish_address_space.h"
#include "HostConnection.h"
#include "FormatConversions.h"
#include <qemu_pipe_bp.h>

#define CRASH(MSG) \
    do { \
        ALOGE("%s:%d crashed with '%s'", __func__, __LINE__, MSG); \
        ::abort(); \
    } while (false)

#define CRASH_IF(COND, MSG) \
    do { \
        if ((COND)) { \
            ALOGE("%s:%d crashed on '%s' with '%s'", __func__, __LINE__, #COND, MSG); \
            ::abort(); \
        } \
    } while (false)

#define RETURN_ERROR_CODE(X) \
    do { \
        ALOGE("%s:%d failed with '%s' (%d)", \
              __func__, __LINE__, strerror(-(X)), -(X)); \
        return (X); \
    } while (false)

#define RETURN_ERROR(X) \
    do { \
        ALOGE("%s:%d failed with '%s'", __func__, __LINE__, #X); \
        return (X); \
    } while (false)

#define OMX_COLOR_FormatYUV420Planar 19

namespace {

const char GOLDFISH_GRALLOC_MODULE_NAME[] = "Graphics Memory Allocator Module";

hw_device_t make_hw_device(hw_module_t* module, int (*close)(hw_device_t*)) {
    hw_device_t result = {};

    result.tag = HARDWARE_DEVICE_TAG;
    result.version = 0;
    result.module = module;
    result.close = close;

    return result;
}

size_t align(const size_t v, const size_t a) { return (v + a - 1) & ~(a - 1); }

class HostConnectionSession {
public:
    explicit HostConnectionSession(HostConnection* hc) : conn(hc) {
        hc->lock();
    }

    ~HostConnectionSession() {
        if (conn) {
            conn->unlock();
        }
     }

    HostConnectionSession(HostConnectionSession&& rhs) : conn(rhs.conn) {
        rhs.conn = nullptr;
    }

    HostConnectionSession& operator=(HostConnectionSession&& rhs) {
        if (this != &rhs) {
            std::swap(conn, rhs.conn);
        }
        return *this;
    }

    HostConnectionSession(const HostConnectionSession&) = delete;
    HostConnectionSession& operator=(const HostConnectionSession&) = delete;

    ExtendedRCEncoderContext* getRcEncoder() const {
        return conn->rcEncoder();
    }

private:
    HostConnection* conn;
};

class goldfish_gralloc30_module_t;
class goldfish_gralloc30_device_t;
class goldfish_fb30_device_t;

class buffer_manager_t {
public:
    buffer_manager_t() = default;
    buffer_manager_t(const buffer_manager_t&) = delete;
    buffer_manager_t& operator=(const buffer_manager_t&) = delete;
    buffer_manager_t(buffer_manager_t&&) = delete;
    buffer_manager_t& operator=(buffer_manager_t&&) = delete;
    virtual ~buffer_manager_t() {}

    virtual uint64_t getMmapedPhysAddr(uint64_t offset) const = 0;

    virtual int alloc_buffer(int usage,
                             int width, int height, int format,
                             EmulatorFrameworkFormat emulatorFrameworkFormat,
                             int glFormat, int glType,
                             size_t bufferSize,
                             buffer_handle_t* pHandle) = 0;
    virtual int free_buffer(buffer_handle_t h) = 0;
    virtual int register_buffer(buffer_handle_t h) = 0;
    virtual int unregister_buffer(buffer_handle_t h) = 0;
};

std::unique_ptr<buffer_manager_t> create_buffer_manager(goldfish_gralloc30_module_t*);

class goldfish_gralloc30_module_t {
public:
    // TODO(b/142677230): Use unique pointers instead.
    goldfish_gralloc30_module_t()
        : m_hostConn(HostConnection::createUnique().release()) {
        CRASH_IF(!m_hostConn, "m_hostConn cannot be nullptr");
        m_bufferManager = create_buffer_manager(this);
        CRASH_IF(!m_bufferManager, "m_bufferManager cannot be nullptr");
    }

    HostConnectionSession getHostConnectionSession() const {
        return HostConnectionSession(m_hostConn /*.get()*/);
    }

    int alloc_buffer(int usage,
                     int width, int height, int format,
                     EmulatorFrameworkFormat emulatorFrameworkFormat,
                     int glFormat, int glType,
                     size_t bufferSize,
                     buffer_handle_t* pHandle) {
        return m_bufferManager->alloc_buffer(usage,
                                             width, height, format,
                                             emulatorFrameworkFormat,
                                             glFormat, glType,
                                             bufferSize,
                                             pHandle);
    }

    int free_buffer(buffer_handle_t h) {
        return m_bufferManager->free_buffer(h);
    }

    int register_buffer(buffer_handle_t h) {
        return m_bufferManager->register_buffer(h);
    }

    int unregister_buffer(buffer_handle_t h) {
        return m_bufferManager->unregister_buffer(h);
    }

    int lock(cb_handle_t& handle,
             const int usage,
             const int left, const int top, const int width, const int height,
             void** vaddr) {
        if (!handle.bufferSize) { RETURN_ERROR_CODE(-EINVAL); }
        char* const bufferBits = static_cast<char*>(handle.getBufferPtr());
        if (!bufferBits) { RETURN_ERROR_CODE(-EINVAL); }

        if (handle.hostHandle) {
            const int res = lock_impl(handle,
                                      usage,
                                      left, top, width, height,
                                      bufferBits);
            if (res) { return res; }
        }

        *vaddr = bufferBits;
        return 0;
    }

    int unlock(cb_handle_t& handle) {
        if (!handle.bufferSize) { RETURN_ERROR_CODE(-EINVAL); }

        char* const bufferBits = static_cast<char*>(handle.getBufferPtr());
        if (!bufferBits) { RETURN_ERROR_CODE(-EINVAL); }

        if (handle.hostHandle) {
            unlock_impl(handle, bufferBits);
        }

        return 0;
    }

    int lock_ycbcr(cb_handle_t& handle,
                   const int usage,
                   const int left, const int top, const int width, const int height,
                   android_ycbcr* ycbcr) {
        if (!ycbcr) { RETURN_ERROR_CODE(-EINVAL); }
        if (!handle.bufferSize) { RETURN_ERROR_CODE(-EINVAL); }
        char* const bufferBits = static_cast<char*>(handle.getBufferPtr());
        if (!bufferBits) { RETURN_ERROR_CODE(-EINVAL); }

        size_t uOffset;
        size_t vOffset;
        size_t yStride;
        size_t cStride;
        size_t cStep;

        switch (handle.format) {
        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
            yStride = handle.width;
            cStride = yStride;
            vOffset = yStride * handle.height;
            uOffset = vOffset + 1;
            cStep = 2;
            break;

        case HAL_PIXEL_FORMAT_YV12:
            // https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12
            yStride = align(handle.width, 16);
            cStride = align(yStride / 2, 16);
            vOffset = yStride * handle.height;
            uOffset = vOffset + (cStride * handle.height / 2);
            cStep = 1;
            break;

        case HAL_PIXEL_FORMAT_YCbCr_420_888:
            yStride = handle.width;
            cStride = yStride / 2;
            uOffset = handle.height * yStride;
            vOffset = uOffset + cStride * handle.height / 2;
            cStep = 1;
            break;

        default:
            ALOGE("%s:%d unexpected format (%d)", __func__, __LINE__, handle.format);
            RETURN_ERROR_CODE(-EINVAL);
        }

        if (handle.hostHandle) {
            const int res = lock_impl(handle,
                                      usage,
                                      left, top, width, height,
                                      bufferBits);
            if (res) { return res; }
        }

        memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
        char* const vaddr1 = static_cast<char*>(bufferBits);
        ycbcr->y = vaddr1;
        ycbcr->cb = vaddr1 + uOffset;
        ycbcr->cr = vaddr1 + vOffset;
        ycbcr->ystride = yStride;
        ycbcr->cstride = cStride;
        ycbcr->chroma_step = cStep;
        return 0;
    }

private:
    int lock_impl(cb_handle_t& handle,
                  const int usage,
                  const int left, const int top, const int width, const int height,
                  char* const bufferBits) {
        const bool usageSwRead = usage & GRALLOC_USAGE_SW_READ_MASK;
        const bool usageSwWrite = usage & GRALLOC_USAGE_SW_WRITE_MASK;
        const bool usageHwCamera = usage & GRALLOC_USAGE_HW_CAMERA_MASK;
        const bool usageHwCameraWrite = usage & GRALLOC_USAGE_HW_CAMERA_WRITE;

        const HostConnectionSession conn = getHostConnectionSession();
        ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();

        const int res = rcEnc->rcColorBufferCacheFlush(
            rcEnc, handle.hostHandle, 0, usageSwRead);
        if (res < 0) {
            RETURN_ERROR_CODE(-EBUSY);
        }

        // camera delivers bits to the buffer directly and does not require
        // an explicit read.
        if (usageSwRead && !usageHwCamera) {
            if (gralloc_is_yuv_format(handle.format)) {
                if (rcEnc->hasYUVCache()) {
                    uint32_t bufferSize;

                    switch (handle.format) {
                    case HAL_PIXEL_FORMAT_YV12:
                        get_yv12_offsets(handle.width, handle.height,
                                         nullptr, nullptr, &bufferSize);
                        break;
                    case HAL_PIXEL_FORMAT_YCbCr_420_888:
                        get_yuv420p_offsets(handle.width, handle.height,
                                            nullptr, nullptr, &bufferSize);
                        break;
                    default:
                        CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
                        break;
                    }

                    rcEnc->rcReadColorBufferYUV(rcEnc, handle.hostHandle,
                        0, 0, handle.width, handle.height,
                        bufferBits, bufferSize);
                } else {
                    // We are using RGB888
                    std::vector<char> tmpBuf(handle.width * handle.height * 3);
                    rcEnc->rcReadColorBuffer(rcEnc, handle.hostHandle,
                                             0, 0, handle.width, handle.height,
                                             handle.glFormat, handle.glType,
                                             tmpBuf.data());

                    switch (handle.format) {
                    case HAL_PIXEL_FORMAT_YV12:
                        rgb888_to_yv12(bufferBits, tmpBuf.data(),
                                       handle.width, handle.height,
                                       left, top,
                                       left + width - 1, top + height - 1);
                        break;
                    case HAL_PIXEL_FORMAT_YCbCr_420_888:
                        rgb888_to_yuv420p(bufferBits, tmpBuf.data(),
                                          handle.width, handle.height,
                                          left, top,
                                          left + width - 1, top + height - 1);
                        break;
                    default:
                        CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
                        break;
                    }
                }
            } else {
                rcEnc->rcReadColorBuffer(rcEnc,
                                         handle.hostHandle,
                                         0, 0, handle.width, handle.height,
                                         handle.glFormat, handle.glType,
                                         bufferBits);
            }
        }

        if (usageSwWrite || usageHwCameraWrite) {
            handle.lockedLeft = left;
            handle.lockedTop = top;
            handle.lockedWidth = width;
            handle.lockedHeight = height;
        } else {
            handle.lockedLeft = 0;
            handle.lockedTop = 0;
            handle.lockedWidth = handle.width;
            handle.lockedHeight = handle.height;
        }

        return 0;
    }

    void unlock_impl(cb_handle_t& handle, char* const bufferBits) {
        const int bpp = glUtilsPixelBitSize(handle.glFormat, handle.glType) >> 3;
        const int left = handle.lockedLeft;
        const int top = handle.lockedTop;
        const int width = handle.lockedWidth;
        const int height = handle.lockedHeight;
        const uint32_t rgbSize = width * height * bpp;

        std::vector<char> convertedBuf;
        const char* bitsToSend;
        uint32_t sizeToSend;
        if (gralloc_is_yuv_format(handle.format)) {
            bitsToSend = bufferBits;
            switch (handle.format) {
            case HAL_PIXEL_FORMAT_YV12:
                get_yv12_offsets(width, height, nullptr, nullptr, &sizeToSend);
                break;

            case HAL_PIXEL_FORMAT_YCbCr_420_888:
                get_yuv420p_offsets(width, height, nullptr, nullptr, &sizeToSend);
                break;

            default:
                CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
                break;
            }
        } else {
            convertedBuf.resize(rgbSize);
            copy_rgb_buffer_from_unlocked(
                convertedBuf.data(), bufferBits,
                handle.width,
                width, height, top, left, bpp);
            bitsToSend = convertedBuf.data();
            sizeToSend = rgbSize;
        }

        {
            const HostConnectionSession conn = getHostConnectionSession();
            ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();

            rcEnc->bindDmaDirectly(bufferBits,
                                   m_bufferManager->getMmapedPhysAddr(handle.getMmapedOffset()));
            rcEnc->rcUpdateColorBufferDMA(rcEnc, handle.hostHandle,
                    left, top, width, height,
                    handle.glFormat, handle.glType,
                    const_cast<char*>(bitsToSend), sizeToSend);
        }

        handle.lockedLeft = 0;
        handle.lockedTop = 0;
        handle.lockedWidth = 0;
        handle.lockedHeight = 0;
    }

    //std::unique_ptr<HostConnection> m_hostConn;  // b/142677230
    HostConnection* m_hostConn;
    std::unique_ptr<buffer_manager_t> m_bufferManager;
};

// no ctor/dctor here
struct private_module_t {
    goldfish_gralloc30_module_t* impl() {
        return &gralloc30;
    }

    hw_module_t* to_hw_module() { return &base.common; }

    static private_module_t* from_hw_module(const hw_module_t* m) {
        if (!m) {
            RETURN_ERROR(nullptr);
        }

        if ((m->id == GRALLOC_HARDWARE_MODULE_ID) && (m->name == GOLDFISH_GRALLOC_MODULE_NAME)) {
            return reinterpret_cast<private_module_t*>(const_cast<hw_module_t*>(m));
        } else {
            RETURN_ERROR(nullptr);
        }
    }

    static private_module_t* from_gralloc_module(const gralloc_module_t* m) {
        if (!m) {
            RETURN_ERROR(nullptr);
        }

        return from_hw_module(&m->common);
    }

    gralloc_module_t base;
    goldfish_gralloc30_module_t gralloc30;
};

class goldfish_gralloc30_device_t {
    alloc_device_t device;
    goldfish_gralloc30_module_t* gralloc_module;

public:
    goldfish_gralloc30_device_t(private_module_t* module)
            : gralloc_module(module->impl()) {
        memset(&device, 0, sizeof(device));
        device.common = make_hw_device(module->to_hw_module(),
                                       &s_goldfish_gralloc30_device_close);
        device.alloc = &s_gralloc_alloc;
        device.free  = &s_gralloc_free;
    }

    hw_device_t* get_hw_device_ptr() { return &device.common; }

private:
    static int get_buffer_format(const int frameworkFormat, const int usage) {
        if (frameworkFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
            if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
                if (usage & GRALLOC_USAGE_HW_TEXTURE) {
                    // Camera-to-display is RGBA
                    return HAL_PIXEL_FORMAT_RGBA_8888;
                } else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
                    // Camera-to-encoder is NV21
                    return HAL_PIXEL_FORMAT_YCrCb_420_SP;
                }
            }

            RETURN_ERROR_CODE(-EINVAL);
        } else if (frameworkFormat == OMX_COLOR_FormatYUV420Planar &&
               (usage & GOLDFISH_GRALLOC_USAGE_GPU_DATA_BUFFER)) {
            ALOGW("gralloc_alloc: Requested OMX_COLOR_FormatYUV420Planar, given "
              "YCbCr_420_888, taking experimental path. "
              "usage=%x", usage);
            return HAL_PIXEL_FORMAT_YCbCr_420_888;
        }
        else  {
            return frameworkFormat;
        }
    }

    int gralloc_alloc(const int width, const int height,
                      const int frameworkFormat,
                      const int usage,
                      buffer_handle_t* pHandle,
                      int* pStride) {
        const bool usageSwWrite = usage & GRALLOC_USAGE_SW_WRITE_MASK;
        const bool usageSwRead = usage & GRALLOC_USAGE_SW_READ_MASK;
        const bool usageHwTexture = usage & GRALLOC_USAGE_HW_TEXTURE;
        const bool usageHwRender = usage & GRALLOC_USAGE_HW_RENDER;
        const bool usageHw2d = usage & GRALLOC_USAGE_HW_2D;
        const bool usageHwComposer = usage & GRALLOC_USAGE_HW_COMPOSER;
        const bool usageHwFb = usage & GRALLOC_USAGE_HW_FB;
        const bool usageHwCamWrite = usage & GRALLOC_USAGE_HW_CAMERA_WRITE;
        const bool usageHwCamRead = usage & GRALLOC_USAGE_HW_CAMERA_READ;
        const bool usageRGB888Unsupported = usageHwTexture
            || usageHwRender ||usageHw2d || usageHwComposer || usageHwFb;

        int bpp = 1;
        int glFormat = 0;
        int glType = 0;
        int align = 1;
        bool yuv_format = false;
        EmulatorFrameworkFormat emulatorFrameworkFormat = FRAMEWORK_FORMAT_GL_COMPATIBLE;

        const int format = get_buffer_format(frameworkFormat, usage);
        if (format < 0) {
            ALOGE("%s:%d Unsupported format: frameworkFormat=%d, usage=%x",
                  __func__, __LINE__, frameworkFormat, usage);
            return format;
        }

        switch (format) {
        case HAL_PIXEL_FORMAT_RGBA_8888:
        case HAL_PIXEL_FORMAT_RGBX_8888:
        case HAL_PIXEL_FORMAT_BGRA_8888:
            bpp = 4;
            glFormat = GL_RGBA;
            glType = GL_UNSIGNED_BYTE;
            break;

        case HAL_PIXEL_FORMAT_RGB_888:
            if (usageRGB888Unsupported) {
                RETURN_ERROR_CODE(-EINVAL);  // we dont support RGB_888 for HW usage
            } else {
                bpp = 3;
                glFormat = GL_RGB;
                glType = GL_UNSIGNED_BYTE;
            }
            break;

        case HAL_PIXEL_FORMAT_RGB_565:
            bpp = 2;
            glFormat = GL_RGB565;
            glType = GL_UNSIGNED_SHORT_5_6_5;
            break;

        case HAL_PIXEL_FORMAT_RGBA_FP16:
            bpp = 8;
            glFormat = GL_RGBA16F;
            glType = GL_HALF_FLOAT;
            break;

        case HAL_PIXEL_FORMAT_RGBA_1010102:
            bpp = 4;
            glFormat = GL_RGB10_A2;
            glType = GL_UNSIGNED_INT_2_10_10_10_REV;
            break;

        case HAL_PIXEL_FORMAT_RAW16:
        case HAL_PIXEL_FORMAT_Y16:
            bpp = 2;
            align = 16 * bpp;
            if (!((usageSwRead || usageHwCamRead) && (usageSwWrite || usageHwCamWrite))) {
                // Raw sensor data or Y16 only goes between camera and CPU
                RETURN_ERROR_CODE(-EINVAL);
            }
            // Not expecting to actually create any GL surfaces for this
            glFormat = GL_LUMINANCE;
            glType = GL_UNSIGNED_SHORT;
            break;

        case HAL_PIXEL_FORMAT_BLOB:
            if (!usageSwRead) {
                // Blob data cannot be used by HW other than camera emulator
                // But there is a CTS test trying to have access to it
                // BUG: https://buganizer.corp.google.com/issues/37719518
                RETURN_ERROR_CODE(-EINVAL);
            }
            // Not expecting to actually create any GL surfaces for this
            glFormat = GL_LUMINANCE;
            glType = GL_UNSIGNED_BYTE;
            break;

        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
            yuv_format = true;
            // Not expecting to actually create any GL surfaces for this
            break;

        case HAL_PIXEL_FORMAT_YV12:
            align = 16;
            yuv_format = true;
            // We are going to use RGB8888 on the host for Vulkan
            glFormat = GL_RGBA;
            glType = GL_UNSIGNED_BYTE;
            emulatorFrameworkFormat = FRAMEWORK_FORMAT_YV12;
            break;

        case HAL_PIXEL_FORMAT_YCbCr_420_888:
            yuv_format = true;
            // We are going to use RGB888 on the host
            glFormat = GL_RGB;
            glType = GL_UNSIGNED_BYTE;
            emulatorFrameworkFormat = FRAMEWORK_FORMAT_YUV_420_888;
            break;

        default:
            ALOGE("%s:%d Unsupported format: format=%d, frameworkFormat=%d, usage=%x",
                  __func__, __LINE__, format, frameworkFormat, usage);
            RETURN_ERROR_CODE(-EINVAL);
        }

        const size_t align1 = align - 1;
        int stride;
        size_t bufferSize;

        if (yuv_format) {
            const size_t yStride = (width * bpp + align1) & ~align1;
            const size_t uvStride = (yStride / 2 + align1) & ~align1;
            const size_t uvHeight = height / 2;
            bufferSize = yStride * height + 2 * (uvHeight * uvStride);
            stride = yStride / bpp;
        } else {
            const size_t bpr = (width * bpp + align1) & ~align1;
            bufferSize = bpr * height;
            stride = bpr / bpp;
        }

        const int res = gralloc_module->alloc_buffer(
            usage,
            width, height, format,
            emulatorFrameworkFormat,
            glFormat, glType,
            bufferSize,
            pHandle);
        if (res) {
            return res;
        }

        *pStride = stride;
        return 0;
    }

    int gralloc_free(buffer_handle_t h) {
        return gralloc_module->free_buffer(h);
    }

    static int s_goldfish_gralloc30_device_close(hw_device_t* d) {
        goldfish_gralloc30_device_t* gd = from_hw_device(d);
        if (!gd) {
            RETURN_ERROR_CODE(-EINVAL);
        }

        std::unique_ptr<goldfish_gralloc30_device_t> deleter(gd);
        return 0;
    }

    static int s_gralloc_alloc(alloc_device_t* ad,
                         int w, int h, int format, int usage,
                         buffer_handle_t* pHandle, int* pStride) {
        goldfish_gralloc30_device_t* gd = from_alloc_device(ad);
        if (!gd) {
            RETURN_ERROR_CODE(-EINVAL);
        }

        return gd->gralloc_alloc(w, h, format, usage, pHandle, pStride);
    }

    static int s_gralloc_free(alloc_device_t* ad, buffer_handle_t h) {
        goldfish_gralloc30_device_t* gd = from_alloc_device(ad);
        if (!gd) {
            RETURN_ERROR_CODE(-EINVAL);
        }

        return gd->gralloc_free(h);
    }

    static goldfish_gralloc30_device_t* from_hw_device(hw_device_t* d) {
        if (!d) {
            RETURN_ERROR(nullptr);
        }

        if (d->close == &s_goldfish_gralloc30_device_close) {
            return reinterpret_cast<goldfish_gralloc30_device_t*>(d);
        } else {
            RETURN_ERROR(nullptr);
        }
    }

    static goldfish_gralloc30_device_t* from_alloc_device(alloc_device_t* d) {
        if (!d) {
            RETURN_ERROR(nullptr);
        }

        return from_hw_device(&d->common);
    }
};

template <class T> T& unconst(const T& x) { return const_cast<T&>(x); }

const uint32_t CB_HANDLE_MAGIC_30 = CB_HANDLE_MAGIC_BASE | 0x2;

struct cb_handle_30_t : public cb_handle_t {
    cb_handle_30_t(address_space_handle_t p_bufferFd,
                   QEMU_PIPE_HANDLE p_hostHandleRefCountFd,
                   uint32_t p_hostHandle,
                   int32_t p_usage,
                   int32_t p_width,
                   int32_t p_height,
                   int32_t p_format,
                   int32_t p_glFormat,
                   int32_t p_glType,
                   uint32_t p_bufSize,
                   void* p_bufPtr,
                   int32_t p_bufferPtrPid,
                   uint32_t p_mmapedSize,
                   uint64_t p_mmapedOffset)
            : cb_handle_t(p_bufferFd,
                          p_hostHandleRefCountFd,
                          CB_HANDLE_MAGIC_30,
                          p_hostHandle,
                          p_usage,
                          p_width,
                          p_height,
                          p_format,
                          p_glFormat,
                          p_glType,
                          p_bufSize,
                          p_bufPtr,
                          p_mmapedOffset),
              bufferFdAsInt(p_bufferFd),
              bufferPtrPid(p_bufferPtrPid),
              mmapedSize(p_mmapedSize) {
        numInts = CB_HANDLE_NUM_INTS(numFds);
    }

    bool isValid() const { return (version == sizeof(native_handle_t)) && (magic == CB_HANDLE_MAGIC_30); }

    static cb_handle_30_t* from(void* p) {
        if (!p) { return nullptr; }
        cb_handle_30_t* cb = static_cast<cb_handle_30_t*>(p);
        return cb->isValid() ? cb : nullptr;
    }

    static const cb_handle_30_t* from(const void* p) {
        return from(const_cast<void*>(p));
    }

    static cb_handle_30_t* from_unconst(const void* p) {
        return from(const_cast<void*>(p));
    }

    int32_t  bufferFdAsInt;         // int copy of bufferFd, to check if fd was duped
    int32_t  bufferPtrPid;          // pid where bufferPtr belongs to
    uint32_t mmapedSize;            // real allocation side
};

// goldfish_address_space_host_malloc_handle_manager_t uses
// GoldfishAddressSpaceHostMemoryAllocator and GoldfishAddressSpaceBlock
// to allocate buffers on the host.
// It keeps track of usage of host handles allocated by rcCreateColorBufferDMA
// on the guest by qemu_pipe_open("refcount").
class goldfish_address_space_host_malloc_buffer_manager_t : public buffer_manager_t {
public:
    goldfish_address_space_host_malloc_buffer_manager_t(goldfish_gralloc30_module_t* gr): m_gr(gr) {
        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(false);
        CRASH_IF(!host_memory_allocator.is_opened(),
                 "GoldfishAddressSpaceHostMemoryAllocator failed to open");

        GoldfishAddressSpaceBlock bufferBits;
        CRASH_IF(host_memory_allocator.hostMalloc(&bufferBits, 256),
                 "hostMalloc failed");

        m_physAddrToOffset = bufferBits.physAddr() - bufferBits.offset();
    }

    uint64_t getMmapedPhysAddr(uint64_t offset) const override {
        return m_physAddrToOffset + offset;
    }

    int alloc_buffer(int usage,
                     int width, int height, int format,
                     EmulatorFrameworkFormat emulatorFrameworkFormat,
                     int glFormat, int glType,
                     size_t bufferSize,
                     buffer_handle_t* pHandle) override {
        const HostConnectionSession conn = m_gr->getHostConnectionSession();
        ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();

        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(
            rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator);
        if (!host_memory_allocator.is_opened()) { RETURN_ERROR_CODE(-EIO); }

        GoldfishAddressSpaceBlock bufferBits;
        if (host_memory_allocator.hostMalloc(&bufferBits, bufferSize)) { RETURN_ERROR_CODE(-EIO); }

        uint32_t hostHandle = 0;
        QEMU_PIPE_HANDLE hostHandleRefCountFd = QEMU_PIPE_INVALID_HANDLE;
        if (need_host_cb(usage, format)) {
            hostHandleRefCountFd = qemu_pipe_open("refcount");
            if (!qemu_pipe_valid(hostHandleRefCountFd)) { RETURN_ERROR_CODE(-EIO); }

            const GLenum allocFormat =
                (HAL_PIXEL_FORMAT_RGBX_8888 == format) ? GL_RGB : glFormat;

            hostHandle = rcEnc->rcCreateColorBufferDMA(
                rcEnc,
                width, height,
                allocFormat, emulatorFrameworkFormat);
            if (!hostHandle) {
                qemu_pipe_close(hostHandleRefCountFd);
                RETURN_ERROR_CODE(-EIO);
            }
            if (qemu_pipe_write(hostHandleRefCountFd, &hostHandle, sizeof(hostHandle)) != sizeof(hostHandle)) {
                rcEnc->rcCloseColorBuffer(rcEnc, hostHandle);
                qemu_pipe_close(hostHandleRefCountFd);
                RETURN_ERROR_CODE(-EIO);
            }
        }

        std::unique_ptr<cb_handle_30_t> handle =
            std::make_unique<cb_handle_30_t>(
                host_memory_allocator.release(), hostHandleRefCountFd,
                hostHandle,
                usage, width, height,
                format, glFormat, glType,
                bufferSize, bufferBits.guestPtr(), getpid(),
                bufferBits.size(), bufferBits.offset());
        bufferBits.release();

        *pHandle = handle.release();
        return 0;
    }

    int free_buffer(buffer_handle_t h) override {
        std::unique_ptr<cb_handle_30_t> handle(cb_handle_30_t::from_unconst(h));
        if (!handle) {
            RETURN_ERROR_CODE(-EINVAL);
        }

        if (handle->bufferPtrPid != getpid()) { RETURN_ERROR_CODE(-EACCES); }
        if (handle->bufferFd != handle->bufferFdAsInt) { RETURN_ERROR_CODE(-EACCES); }

        if (qemu_pipe_valid(handle->hostHandleRefCountFd)) {
            qemu_pipe_close(handle->hostHandleRefCountFd);
        }
        // We can't recycle the address block and host resources because this
        // fd could be duped. The kernel will take care of it when the last fd
        // will be closed.
        if (handle->mmapedSize > 0) {
            GoldfishAddressSpaceBlock::memoryUnmap(handle->getBufferPtr(), handle->mmapedSize);
        }
        GoldfishAddressSpaceHostMemoryAllocator::closeHandle(handle->bufferFd);

        return 0;
    }

    int register_buffer(buffer_handle_t h) override {
#ifndef HOST_BUILD
        cb_handle_30_t *handle = cb_handle_30_t::from_unconst(h);
        if (!handle) { RETURN_ERROR_CODE(-EINVAL); }

        if (handle->mmapedSize > 0) {
            void* ptr;
            const int res = GoldfishAddressSpaceBlock::memoryMap(
                handle->getBufferPtr(),
                handle->mmapedSize,
                handle->bufferFd,
                handle->getMmapedOffset(),
                &ptr);
            if (res) {
                RETURN_ERROR_CODE(-res);
            }

            handle->setBufferPtr(ptr);
        }
        if (handle->hostHandle) {
            const HostConnectionSession conn = m_gr->getHostConnectionSession();
            ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
            rcEnc->rcOpenColorBuffer2(rcEnc, handle->hostHandle);
        }

        handle->bufferFdAsInt = handle->bufferFd;
        handle->bufferPtrPid = getpid();
#endif  // HOST_BUILD

        return 0;
    }

    int unregister_buffer(buffer_handle_t h) override {
#ifndef HOST_BUILD
        cb_handle_30_t *handle = cb_handle_30_t::from_unconst(h);
        if (!handle) { RETURN_ERROR_CODE(-EINVAL); }

        if (handle->bufferPtrPid != getpid()) { RETURN_ERROR_CODE(-EACCES); }
        if (handle->bufferFd != handle->bufferFdAsInt) { RETURN_ERROR_CODE(-EACCES); }

        if (handle->hostHandle) {
            const HostConnectionSession conn = m_gr->getHostConnectionSession();
            ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
            rcEnc->rcCloseColorBuffer(rcEnc, handle->hostHandle);
        }
        if (handle->mmapedSize > 0) {
            GoldfishAddressSpaceBlock::memoryUnmap(handle->getBufferPtr(), handle->mmapedSize);
        }

        handle->bufferFdAsInt = -1;
        handle->bufferPtrPid = -1;
#endif  // HOST_BUILD
        return 0;
    }

    static bool need_host_cb(const int usage, const int format) {
        return ((usage & GOLDFISH_GRALLOC_USAGE_GPU_DATA_BUFFER)
                   || (format != HAL_PIXEL_FORMAT_BLOB &&
                       format != HAL_PIXEL_FORMAT_RAW16 &&
                       format != HAL_PIXEL_FORMAT_Y16))
               && (usage & (GRALLOC_USAGE_HW_TEXTURE
                            | GRALLOC_USAGE_HW_RENDER
                            | GRALLOC_USAGE_HW_2D
                            | GRALLOC_USAGE_HW_COMPOSER
                            | GRALLOC_USAGE_HW_VIDEO_ENCODER
                            | GRALLOC_USAGE_HW_FB
                            | GRALLOC_USAGE_SW_READ_MASK));
    }

private:
    goldfish_gralloc30_module_t* m_gr;
    uint64_t m_physAddrToOffset;
};

std::unique_ptr<buffer_manager_t> create_buffer_manager(goldfish_gralloc30_module_t* gr) {
    if (!gr) {
        RETURN_ERROR(nullptr);
    }

    // TODO: negotiate with the host the best way to allocate memory.

    return std::make_unique<goldfish_address_space_host_malloc_buffer_manager_t>(gr);
}

int gralloc_register_buffer(const gralloc_module_t* gralloc_module, buffer_handle_t h) {
    private_module_t* module = private_module_t::from_gralloc_module(gralloc_module);
    if (!module) {
        RETURN_ERROR_CODE(-EINVAL);
    }

    return module->impl()->register_buffer(h);
}

int gralloc_unregister_buffer(const gralloc_module_t* gralloc_module, buffer_handle_t h) {
    private_module_t* module = private_module_t::from_gralloc_module(gralloc_module);
    if (!module) {
        RETURN_ERROR_CODE(-EINVAL);
    }

   return module->impl()->unregister_buffer(h);
}

int gralloc_lock(const gralloc_module_t* gralloc_module,
                 buffer_handle_t bh, int usage,
                 int l, int t, int w, int h,
                 void** vaddr) {
    private_module_t* module = private_module_t::from_gralloc_module(gralloc_module);
    if (!module) {
        RETURN_ERROR_CODE(-EINVAL);
    }

    cb_handle_t* handle = cb_handle_t::from_unconst(bh);
    if (!handle) {
        RETURN_ERROR_CODE(-EINVAL);
    }

    return module->impl()->lock(*handle, usage, l, t, w, h, vaddr);
}

int gralloc_unlock(const gralloc_module_t* gralloc_module, buffer_handle_t bh) {
    private_module_t* module = private_module_t::from_gralloc_module(gralloc_module);
    if (!module) {
        RETURN_ERROR_CODE(-EINVAL);
    }

    cb_handle_t* handle = cb_handle_t::from_unconst(bh);
    if (!handle) {
        RETURN_ERROR_CODE(-EINVAL);
    }

    return module->impl()->unlock(*handle);
}

int gralloc_lock_ycbcr(const gralloc_module_t* gralloc_module,
                       buffer_handle_t bh, int usage,
                       int l, int t, int w, int h,
                       android_ycbcr *ycbcr) {
    private_module_t* module = private_module_t::from_gralloc_module(gralloc_module);
    if (!module) {
        RETURN_ERROR_CODE(-EINVAL);
    }

    cb_handle_t* handle = cb_handle_t::from_unconst(bh);
    if (!handle) {
        RETURN_ERROR_CODE(-EINVAL);
    }

    return module->impl()->lock_ycbcr(*handle, usage, l, t, w, h, ycbcr);
}

int gralloc_device_open_gpu0(private_module_t* module, hw_device_t** device) {
    std::unique_ptr<goldfish_gralloc30_device_t> gralloc_device =
        std::make_unique<goldfish_gralloc30_device_t>(module);
    if (!gralloc_device) {
        RETURN_ERROR_CODE(-ENOMEM);
    }

    *device = gralloc_device->get_hw_device_ptr();
    gralloc_device.release();
    return 0;
}

int gralloc_device_open(const hw_module_t* hw_module,
                        const char* name,
                        hw_device_t** device) {
    private_module_t* module = private_module_t::from_hw_module(hw_module);
    if (!module) {
        RETURN_ERROR_CODE(-EINVAL);
    }
    if (!name) {
        RETURN_ERROR_CODE(-EINVAL);
    }
    if (!device) {
        RETURN_ERROR_CODE(-EINVAL);
    }

    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
        return gralloc_device_open_gpu0(module, device);
    }

    RETURN_ERROR_CODE(-EINVAL);
}

struct hw_module_methods_t gralloc_module_methods = {
    .open = &gralloc_device_open
};
}  // namespace

extern "C" __attribute__((visibility("default")))
struct private_module_t HAL_MODULE_INFO_SYM = {
    .base = {
        .common = {
            .tag = HARDWARE_MODULE_TAG,
            .module_api_version = GRALLOC_MODULE_API_VERSION_0_2,
            .hal_api_version = 0,
            .id = GRALLOC_HARDWARE_MODULE_ID,
            .name = GOLDFISH_GRALLOC_MODULE_NAME,
            .author = "The Android Open Source Project",
            .methods = &gralloc_module_methods,
            .dso = nullptr,
            .reserved = {0}
        },
        .registerBuffer   = &gralloc_register_buffer,
        .unregisterBuffer = &gralloc_unregister_buffer,
        .lock             = &gralloc_lock,
        .unlock           = &gralloc_unlock,
        .perform          = nullptr,  /* reserved for future use */
        .lock_ycbcr       = &gralloc_lock_ycbcr,
    },
};
