/*
 * Copyright (C) 2007 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.
 */

#define LOG_TAG "GraphicBufferMapper"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0

#include <ui/GraphicBufferMapper.h>

// We would eliminate the non-conforming zero-length array, but we can't since
// this is effectively included from the Linux kernel
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wzero-length-array"
#include <sync/sync.h>
#pragma clang diagnostic pop

#include <utils/Log.h>
#include <utils/Trace.h>

#include <ui/GrallocMapper.h>
#include <ui/GraphicBuffer.h>

#include <system/graphics.h>

namespace android {
// ---------------------------------------------------------------------------

ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )

GraphicBufferMapper::GraphicBufferMapper()
  : mMapper(std::make_unique<const Gralloc2::Mapper>())
{
    if (!mMapper->valid()) {
        mLoader = std::make_unique<Gralloc1::Loader>();
        mDevice = mLoader->getDevice();
    }
}



status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
    } else {
        // This always returns GRALLOC1_BAD_HANDLE when handle is from a
        // remote process and mDevice is backed by Gralloc1On0Adapter.
        error = mDevice->retain(handle);
        if (error == GRALLOC1_ERROR_BAD_HANDLE &&
                mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
            ALOGE("registerBuffer by handle is not supported with "
                  "Gralloc1On0Adapter");
        }
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
            handle, error);

    return error;
}

status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        error = static_cast<gralloc1_error_t>(
                mMapper->retain(buffer->getNativeBuffer()->handle));
    } else {
        error = mDevice->retain(buffer);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
            buffer->getNativeBuffer()->handle, error);

    return error;
}

status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        mMapper->release(handle);
        error = GRALLOC1_ERROR_NONE;
    } else {
        error = mDevice->release(handle);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
            handle, error);

    return error;
}

static inline gralloc1_rect_t asGralloc1Rect(const Rect& rect) {
    gralloc1_rect_t outRect{};
    outRect.left = rect.left;
    outRect.top = rect.top;
    outRect.width = rect.width();
    outRect.height = rect.height();
    return outRect;
}


status_t GraphicBufferMapper::getDimensions(buffer_handle_t handle,
        uint32_t* outWidth, uint32_t* outHeight) const
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        mMapper->getDimensions(handle, outWidth, outHeight);
        error = GRALLOC1_ERROR_NONE;
    } else {
        error = mDevice->getDimensions(handle, outWidth, outHeight);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getDimensions(%p, ...): failed %d",
            handle, error);

    return error;
}

status_t GraphicBufferMapper::getFormat(buffer_handle_t handle,
        int32_t* outFormat) const
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        mMapper->getFormat(handle, outFormat);
        error = GRALLOC1_ERROR_NONE;
    } else {
        error = mDevice->getFormat(handle, outFormat);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getFormat(%p, ...): failed %d",
            handle, error);

    return error;
}

status_t GraphicBufferMapper::getLayerCount(buffer_handle_t handle,
        uint32_t* outLayerCount) const
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        mMapper->getLayerCount(handle, outLayerCount);
        error = GRALLOC1_ERROR_NONE;
    } else {
        error = mDevice->getLayerCount(handle, outLayerCount);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getLayerCount(%p, ...): failed %d",
            handle, error);

    return error;
}

status_t GraphicBufferMapper::getProducerUsage(buffer_handle_t handle,
        uint64_t* outProducerUsage) const
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        mMapper->getProducerUsage(handle, outProducerUsage);
        error = GRALLOC1_ERROR_NONE;
    } else {
        error = mDevice->getProducerUsage(handle, outProducerUsage);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
            "getProducerUsage(%p, ...): failed %d", handle, error);

    return error;
}

status_t GraphicBufferMapper::getConsumerUsage(buffer_handle_t handle,
        uint64_t* outConsumerUsage) const
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        mMapper->getConsumerUsage(handle, outConsumerUsage);
        error = GRALLOC1_ERROR_NONE;
    } else {
        error = mDevice->getConsumerUsage(handle, outConsumerUsage);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
            "getConsumerUsage(%p, ...): failed %d", handle, error);

    return error;
}

status_t GraphicBufferMapper::getBackingStore(buffer_handle_t handle,
        uint64_t* outBackingStore) const
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        mMapper->getBackingStore(handle, outBackingStore);
        error = GRALLOC1_ERROR_NONE;
    } else {
        error = mDevice->getBackingStore(handle, outBackingStore);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
            "getBackingStore(%p, ...): failed %d", handle, error);

    return error;
}

status_t GraphicBufferMapper::getStride(buffer_handle_t handle,
        uint32_t* outStride) const
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        mMapper->getStride(handle, outStride);
        error = GRALLOC1_ERROR_NONE;
    } else {
        error = mDevice->getStride(handle, outStride);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getStride(%p, ...): failed %d",
            handle, error);

    return error;
}

status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
        const Rect& bounds, void** vaddr)
{
    return lockAsync(handle, usage, bounds, vaddr, -1);
}

status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage,
        const Rect& bounds, android_ycbcr *ycbcr)
{
    return lockAsyncYCbCr(handle, usage, bounds, ycbcr, -1);
}

status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
{
    int32_t fenceFd = -1;
    status_t error = unlockAsync(handle, &fenceFd);
    if (error == NO_ERROR) {
        sync_wait(fenceFd, -1);
        close(fenceFd);
    }
    return error;
}

status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
        uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd)
{
    return lockAsync(handle, usage, usage, bounds, vaddr, fenceFd);
}

status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
        uint64_t producerUsage, uint64_t consumerUsage, const Rect& bounds,
        void** vaddr, int fenceFd)
{
    ATRACE_CALL();

    gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
    gralloc1_error_t error;
    if (mMapper->valid()) {
        const Gralloc2::IMapper::Rect& accessRect =
            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
        error = static_cast<gralloc1_error_t>(mMapper->lock(
                    handle, producerUsage, consumerUsage, accessRect,
                    fenceFd, vaddr));
    } else {
        sp<Fence> fence = new Fence(fenceFd);
        error = mDevice->lock(handle,
                static_cast<gralloc1_producer_usage_t>(producerUsage),
                static_cast<gralloc1_consumer_usage_t>(consumerUsage),
                &accessRegion, vaddr, fence);
    }

    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lock(%p, ...) failed: %d", handle,
            error);

    return error;
}

static inline bool isValidYCbCrPlane(const android_flex_plane_t& plane) {
    if (plane.bits_per_component != 8) {
        ALOGV("Invalid number of bits per component: %d",
                plane.bits_per_component);
        return false;
    }
    if (plane.bits_used != 8) {
        ALOGV("Invalid number of bits used: %d", plane.bits_used);
        return false;
    }

    bool hasValidIncrement = plane.h_increment == 1 ||
            (plane.component != FLEX_COMPONENT_Y && plane.h_increment == 2);
    hasValidIncrement = hasValidIncrement && plane.v_increment > 0;
    if (!hasValidIncrement) {
        ALOGV("Invalid increment: h %d v %d", plane.h_increment,
                plane.v_increment);
        return false;
    }

    return true;
}

status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
        uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
{
    ATRACE_CALL();

    gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);

    std::vector<android_flex_plane_t> planes;
    android_flex_layout_t flexLayout{};
    gralloc1_error_t error;

    if (mMapper->valid()) {
        const Gralloc2::IMapper::Rect& accessRect =
            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
        Gralloc2::FlexLayout layout{};
        error = static_cast<gralloc1_error_t>(mMapper->lock(
                    handle, usage, usage, accessRect, fenceFd, &layout));

        if (error == GRALLOC1_ERROR_NONE) {
            planes.resize(layout.planes.size());
            memcpy(planes.data(), layout.planes.data(),
                    sizeof(planes[0]) * planes.size());

            flexLayout.format = static_cast<android_flex_format_t>(
                    layout.format);
            flexLayout.num_planes = static_cast<uint32_t>(planes.size());
            flexLayout.planes = planes.data();
        }
    } else {
        sp<Fence> fence = new Fence(fenceFd);

        if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
            error = mDevice->lockYCbCr(handle,
                    static_cast<gralloc1_producer_usage_t>(usage),
                    static_cast<gralloc1_consumer_usage_t>(usage),
                    &accessRegion, ycbcr, fence);
            ALOGW_IF(error != GRALLOC1_ERROR_NONE,
                    "lockYCbCr(%p, ...) failed: %d", handle, error);
            return error;
        }

        uint32_t numPlanes = 0;
        error = mDevice->getNumFlexPlanes(handle, &numPlanes);

        if (error != GRALLOC1_ERROR_NONE) {
            ALOGV("Failed to retrieve number of flex planes: %d", error);
            return error;
        }
        if (numPlanes < 3) {
            ALOGV("Not enough planes for YCbCr (%u found)", numPlanes);
            return GRALLOC1_ERROR_UNSUPPORTED;
        }

        planes.resize(numPlanes);
        flexLayout.num_planes = numPlanes;
        flexLayout.planes = planes.data();

        error = mDevice->lockFlex(handle,
                static_cast<gralloc1_producer_usage_t>(usage),
                static_cast<gralloc1_consumer_usage_t>(usage),
                &accessRegion, &flexLayout, fence);
    }

    if (error != GRALLOC1_ERROR_NONE) {
        ALOGW("lockFlex(%p, ...) failed: %d", handle, error);
        return error;
    }
    if (flexLayout.format != FLEX_FORMAT_YCbCr) {
        ALOGV("Unable to convert flex-format buffer to YCbCr");
        unlock(handle);
        return GRALLOC1_ERROR_UNSUPPORTED;
    }

    // Find planes
    auto yPlane = planes.cend();
    auto cbPlane = planes.cend();
    auto crPlane = planes.cend();
    for (auto planeIter = planes.cbegin(); planeIter != planes.cend();
            ++planeIter) {
        if (planeIter->component == FLEX_COMPONENT_Y) {
            yPlane = planeIter;
        } else if (planeIter->component == FLEX_COMPONENT_Cb) {
            cbPlane = planeIter;
        } else if (planeIter->component == FLEX_COMPONENT_Cr) {
            crPlane = planeIter;
        }
    }
    if (yPlane == planes.cend()) {
        ALOGV("Unable to find Y plane");
        unlock(handle);
        return GRALLOC1_ERROR_UNSUPPORTED;
    }
    if (cbPlane == planes.cend()) {
        ALOGV("Unable to find Cb plane");
        unlock(handle);
        return GRALLOC1_ERROR_UNSUPPORTED;
    }
    if (crPlane == planes.cend()) {
        ALOGV("Unable to find Cr plane");
        unlock(handle);
        return GRALLOC1_ERROR_UNSUPPORTED;
    }

    // Validate planes
    if (!isValidYCbCrPlane(*yPlane)) {
        ALOGV("Y plane is invalid");
        unlock(handle);
        return GRALLOC1_ERROR_UNSUPPORTED;
    }
    if (!isValidYCbCrPlane(*cbPlane)) {
        ALOGV("Cb plane is invalid");
        unlock(handle);
        return GRALLOC1_ERROR_UNSUPPORTED;
    }
    if (!isValidYCbCrPlane(*crPlane)) {
        ALOGV("Cr plane is invalid");
        unlock(handle);
        return GRALLOC1_ERROR_UNSUPPORTED;
    }
    if (cbPlane->v_increment != crPlane->v_increment) {
        ALOGV("Cb and Cr planes have different step (%d vs. %d)",
                cbPlane->v_increment, crPlane->v_increment);
        unlock(handle);
        return GRALLOC1_ERROR_UNSUPPORTED;
    }
    if (cbPlane->h_increment != crPlane->h_increment) {
        ALOGV("Cb and Cr planes have different stride (%d vs. %d)",
                cbPlane->h_increment, crPlane->h_increment);
        unlock(handle);
        return GRALLOC1_ERROR_UNSUPPORTED;
    }

    // Pack plane data into android_ycbcr struct
    ycbcr->y = yPlane->top_left;
    ycbcr->cb = cbPlane->top_left;
    ycbcr->cr = crPlane->top_left;
    ycbcr->ystride = static_cast<size_t>(yPlane->v_increment);
    ycbcr->cstride = static_cast<size_t>(cbPlane->v_increment);
    ycbcr->chroma_step = static_cast<size_t>(cbPlane->h_increment);

    return error;
}

status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
{
    ATRACE_CALL();

    gralloc1_error_t error;
    if (mMapper->valid()) {
        *fenceFd = mMapper->unlock(handle);
        error = GRALLOC1_ERROR_NONE;
    } else {
        sp<Fence> fence = Fence::NO_FENCE;
        error = mDevice->unlock(handle, &fence);
        if (error != GRALLOC1_ERROR_NONE) {
            ALOGE("unlock(%p) failed: %d", handle, error);
            return error;
        }

        *fenceFd = fence->dup();
    }
    return error;
}

// ---------------------------------------------------------------------------
}; // namespace android
