/*
 * Copyright (C) 2018 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 "ReliableSurface.h"

#include <private/android/AHardwareBufferHelpers.h>

namespace android::uirenderer::renderthread {

// TODO: Re-enable after addressing more of the TODO's
// With this disabled we won't have a good up-front signal that the surface is no longer valid,
// however we can at least handle that reactively post-draw. There's just not a good mechanism
// to propagate this error back to the caller
constexpr bool DISABLE_BUFFER_PREFETCH = true;

// TODO: Make surface less protected
// This exists because perform is a varargs, and ANativeWindow has no va_list perform.
// So wrapping/chaining that is hard. Telling the compiler to ignore protected is easy, so we do
// that instead
struct SurfaceExposer : Surface {
    // Make warnings happy
    SurfaceExposer() = delete;

    using Surface::setBufferCount;
    using Surface::setSwapInterval;
    using Surface::dequeueBuffer;
    using Surface::queueBuffer;
    using Surface::cancelBuffer;
    using Surface::lockBuffer_DEPRECATED;
    using Surface::perform;
};

#define callProtected(surface, func, ...) ((*surface).*&SurfaceExposer::func)(__VA_ARGS__)

ReliableSurface::ReliableSurface(sp<Surface>&& surface) : mSurface(std::move(surface)) {
    LOG_ALWAYS_FATAL_IF(!mSurface, "Error, unable to wrap a nullptr");

    ANativeWindow::setSwapInterval = hook_setSwapInterval;
    ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
    ANativeWindow::cancelBuffer = hook_cancelBuffer;
    ANativeWindow::queueBuffer = hook_queueBuffer;
    ANativeWindow::query = hook_query;
    ANativeWindow::perform = hook_perform;

    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
    ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
    ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
    ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
}

ReliableSurface::~ReliableSurface() {
    clearReservedBuffer();
}

void ReliableSurface::perform(int operation, va_list args) {
    std::lock_guard _lock{mMutex};

    switch (operation) {
        case NATIVE_WINDOW_SET_USAGE:
            mUsage = va_arg(args, uint32_t);
            break;
        case NATIVE_WINDOW_SET_USAGE64:
            mUsage = va_arg(args, uint64_t);
            break;
        case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
            /* width */ va_arg(args, uint32_t);
            /* height */ va_arg(args, uint32_t);
            mFormat = va_arg(args, PixelFormat);
            break;
        case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
            mFormat = va_arg(args, PixelFormat);
            break;
    }
}

int ReliableSurface::reserveNext() {
    {
        std::lock_guard _lock{mMutex};
        if (mReservedBuffer) {
            ALOGW("reserveNext called but there was already a buffer reserved?");
            return OK;
        }
        if (mInErrorState) {
            return UNKNOWN_ERROR;
        }
        if (mHasDequeuedBuffer) {
            return OK;
        }
        if constexpr (DISABLE_BUFFER_PREFETCH) {
            return OK;
        }
    }

    // TODO: Update this to better handle when requested dimensions have changed
    // Currently the driver does this via query + perform but that's after we've already
    // reserved a buffer. Should we do that logic instead? Or should we drop
    // the backing Surface to the ground and go full manual on the IGraphicBufferProducer instead?

    int fenceFd = -1;
    ANativeWindowBuffer* buffer = nullptr;
    int result = callProtected(mSurface, dequeueBuffer, &buffer, &fenceFd);

    {
        std::lock_guard _lock{mMutex};
        LOG_ALWAYS_FATAL_IF(mReservedBuffer, "race condition in reserveNext");
        mReservedBuffer = buffer;
        mReservedFenceFd.reset(fenceFd);
    }

    return result;
}

void ReliableSurface::clearReservedBuffer() {
    ANativeWindowBuffer* buffer = nullptr;
    int releaseFd = -1;
    {
        std::lock_guard _lock{mMutex};
        if (mReservedBuffer) {
            ALOGW("Reserved buffer %p was never used", mReservedBuffer);
            buffer = mReservedBuffer;
            releaseFd = mReservedFenceFd.release();
        }
        mReservedBuffer = nullptr;
        mReservedFenceFd.reset();
        mHasDequeuedBuffer = false;
    }
    if (buffer) {
        callProtected(mSurface, cancelBuffer, buffer, releaseFd);
    }
}

int ReliableSurface::cancelBuffer(ANativeWindowBuffer* buffer, int fenceFd) {
    clearReservedBuffer();
    if (isFallbackBuffer(buffer)) {
        if (fenceFd > 0) {
            close(fenceFd);
        }
        return OK;
    }
    int result = callProtected(mSurface, cancelBuffer, buffer, fenceFd);
    return result;
}

int ReliableSurface::dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd) {
    {
        std::lock_guard _lock{mMutex};
        if (mReservedBuffer) {
            *buffer = mReservedBuffer;
            *fenceFd = mReservedFenceFd.release();
            mReservedBuffer = nullptr;
            return OK;
        }
    }

    int result = callProtected(mSurface, dequeueBuffer, buffer, fenceFd);
    if (result != OK) {
        ALOGW("dequeueBuffer failed, error = %d; switching to fallback", result);
        *buffer = acquireFallbackBuffer();
        *fenceFd = -1;
        return *buffer ? OK : INVALID_OPERATION;
    } else {
        std::lock_guard _lock{mMutex};
        mHasDequeuedBuffer = true;
    }
    return OK;
}

int ReliableSurface::queueBuffer(ANativeWindowBuffer* buffer, int fenceFd) {
    clearReservedBuffer();

    if (isFallbackBuffer(buffer)) {
        if (fenceFd > 0) {
            close(fenceFd);
        }
        return OK;
    }

    int result = callProtected(mSurface, queueBuffer, buffer, fenceFd);
    return result;
}

bool ReliableSurface::isFallbackBuffer(const ANativeWindowBuffer* windowBuffer) const {
    if (!mScratchBuffer || !windowBuffer) {
        return false;
    }
    ANativeWindowBuffer* scratchBuffer =
            AHardwareBuffer_to_ANativeWindowBuffer(mScratchBuffer.get());
    return windowBuffer == scratchBuffer;
}

ANativeWindowBuffer* ReliableSurface::acquireFallbackBuffer() {
    std::lock_guard _lock{mMutex};
    mInErrorState = true;

    if (mScratchBuffer) {
        return AHardwareBuffer_to_ANativeWindowBuffer(mScratchBuffer.get());
    }

    AHardwareBuffer_Desc desc;
    desc.usage = mUsage;
    desc.format = mFormat;
    desc.width = 1;
    desc.height = 1;
    desc.layers = 1;
    desc.rfu0 = 0;
    desc.rfu1 = 0;
    AHardwareBuffer* newBuffer = nullptr;
    int err = AHardwareBuffer_allocate(&desc, &newBuffer);
    if (err) {
        // Allocate failed, that sucks
        ALOGW("Failed to allocate scratch buffer, error=%d", err);
        return nullptr;
    }
    mScratchBuffer.reset(newBuffer);
    return AHardwareBuffer_to_ANativeWindowBuffer(newBuffer);
}

Surface* ReliableSurface::getWrapped(const ANativeWindow* window) {
    return getSelf(window)->mSurface.get();
}

int ReliableSurface::hook_setSwapInterval(ANativeWindow* window, int interval) {
    return callProtected(getWrapped(window), setSwapInterval, interval);
}

int ReliableSurface::hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer,
                                        int* fenceFd) {
    return getSelf(window)->dequeueBuffer(buffer, fenceFd);
}

int ReliableSurface::hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
                                       int fenceFd) {
    return getSelf(window)->cancelBuffer(buffer, fenceFd);
}

int ReliableSurface::hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
                                      int fenceFd) {
    return getSelf(window)->queueBuffer(buffer, fenceFd);
}

int ReliableSurface::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
                                                   ANativeWindowBuffer** buffer) {
    ANativeWindowBuffer* buf;
    int fenceFd = -1;
    int result = window->dequeueBuffer(window, &buf, &fenceFd);
    if (result != OK) {
        return result;
    }
    sp<Fence> fence(new Fence(fenceFd));
    int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
    if (waitResult != OK) {
        ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d", waitResult);
        window->cancelBuffer(window, buf, -1);
        return waitResult;
    }
    *buffer = buf;
    return result;
}

int ReliableSurface::hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
                                                  ANativeWindowBuffer* buffer) {
    return window->cancelBuffer(window, buffer, -1);
}

int ReliableSurface::hook_lockBuffer_DEPRECATED(ANativeWindow* window,
                                                ANativeWindowBuffer* buffer) {
    // This method is a no-op in Surface as well
    return OK;
}

int ReliableSurface::hook_queueBuffer_DEPRECATED(ANativeWindow* window,
                                                 ANativeWindowBuffer* buffer) {
    return window->queueBuffer(window, buffer, -1);
}

int ReliableSurface::hook_query(const ANativeWindow* window, int what, int* value) {
    return getWrapped(window)->query(what, value);
}

int ReliableSurface::hook_perform(ANativeWindow* window, int operation, ...) {
    // Drop the reserved buffer if there is one since this (probably) mutated buffer dimensions
    // TODO: Filter to things that only affect the reserved buffer
    // TODO: Can we mutate the reserved buffer in some cases?
    getSelf(window)->clearReservedBuffer();
    va_list args;
    va_start(args, operation);
    int result = callProtected(getWrapped(window), perform, operation, args);
    va_end(args);

    switch (operation) {
        case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
        case NATIVE_WINDOW_SET_USAGE:
        case NATIVE_WINDOW_SET_USAGE64:
            va_start(args, operation);
            getSelf(window)->perform(operation, args);
            va_end(args);
            break;
        default:
            break;
    }

    return result;
}

};  // namespace android::uirenderer::renderthread