/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#define LOG_TAG "powerhal-libperfmgr"

#include "InteractionHandler.h"

#include <android-base/properties.h>
#include <fcntl.h>
#include <perfmgr/HintManager.h>
#include <poll.h>
#include <sys/eventfd.h>
#include <time.h>
#include <unistd.h>
#include <utils/Log.h>
#include <utils/Trace.h>

#include <array>
#include <memory>

#define MAX_LENGTH 64

#define MSINSEC 1000L
#define NSINMS 1000000L

namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {

namespace {

static const bool kDisplayIdleSupport =
        ::android::base::GetBoolProperty("vendor.powerhal.disp.idle_support", true);
static const std::array<const char *, 2> kDispIdlePath = {"/sys/class/drm/card0/device/idle_state",
                                                          "/sys/class/graphics/fb0/idle_state"};
static const uint32_t kWaitMs =
        ::android::base::GetUintProperty("vendor.powerhal.disp.idle_wait", /*default*/ 100U);
static const uint32_t kMinDurationMs =
        ::android::base::GetUintProperty("vendor.powerhal.interaction.min", /*default*/ 1400U);
static const uint32_t kMaxDurationMs =
        ::android::base::GetUintProperty("vendor.powerhal.interaction.max", /*default*/ 5650U);
static const uint32_t kDurationOffsetMs =
        ::android::base::GetUintProperty("vendor.powerhal.interaction.offset", /*default*/ 650U);

static size_t CalcTimespecDiffMs(struct timespec start, struct timespec end) {
    size_t diff_in_ms = 0;
    diff_in_ms += (end.tv_sec - start.tv_sec) * MSINSEC;
    diff_in_ms += (end.tv_nsec - start.tv_nsec) / NSINMS;
    return diff_in_ms;
}

static int FbIdleOpen(void) {
    int fd;
    for (const auto &path : kDispIdlePath) {
        fd = open(path, O_RDONLY);
        if (fd >= 0)
            return fd;
    }
    ALOGE("Unable to open fb idle state path (%d)", errno);
    return -1;
}

}  // namespace

using ::android::perfmgr::HintManager;

InteractionHandler::InteractionHandler()
    : mState(INTERACTION_STATE_UNINITIALIZED), mDurationMs(0) {}

InteractionHandler::~InteractionHandler() {
    Exit();
}

bool InteractionHandler::Init() {
    std::lock_guard<std::mutex> lk(mLock);

    if (mState != INTERACTION_STATE_UNINITIALIZED)
        return true;

    int fd = FbIdleOpen();
    if (fd < 0)
        return false;
    mIdleFd = fd;

    mEventFd = eventfd(0, EFD_NONBLOCK);
    if (mEventFd < 0) {
        ALOGE("Unable to create event fd (%d)", errno);
        close(mIdleFd);
        return false;
    }

    mState = INTERACTION_STATE_IDLE;
    mThread = std::unique_ptr<std::thread>(new std::thread(&InteractionHandler::Routine, this));

    return true;
}

void InteractionHandler::Exit() {
    std::unique_lock<std::mutex> lk(mLock);
    if (mState == INTERACTION_STATE_UNINITIALIZED)
        return;

    AbortWaitLocked();
    mState = INTERACTION_STATE_UNINITIALIZED;
    lk.unlock();

    mCond.notify_all();
    mThread->join();

    close(mEventFd);
    close(mIdleFd);
}

void InteractionHandler::PerfLock() {
    ALOGV("%s: acquiring perf lock", __func__);
    if (!HintManager::GetInstance()->DoHint("INTERACTION")) {
        ALOGE("%s: do hint INTERACTION failed", __func__);
    }
}

void InteractionHandler::PerfRel() {
    ALOGV("%s: releasing perf lock", __func__);
    if (!HintManager::GetInstance()->EndHint("INTERACTION")) {
        ALOGE("%s: end hint INTERACTION failed", __func__);
    }
}

void InteractionHandler::Acquire(int32_t duration) {
    ATRACE_CALL();

    std::lock_guard<std::mutex> lk(mLock);

    int inputDuration = duration + kDurationOffsetMs;
    int finalDuration;
    if (inputDuration > kMaxDurationMs)
        finalDuration = kMaxDurationMs;
    else if (inputDuration > kMinDurationMs)
        finalDuration = inputDuration;
    else
        finalDuration = kMinDurationMs;

    // Fallback to do boost directly
    // 1) override property is set OR
    // 2) InteractionHandler not initialized
    if (!kDisplayIdleSupport || mState == INTERACTION_STATE_UNINITIALIZED) {
        HintManager::GetInstance()->DoHint("INTERACTION", std::chrono::milliseconds(finalDuration));
        return;
    }

    struct timespec cur_timespec;
    clock_gettime(CLOCK_MONOTONIC, &cur_timespec);
    if (mState != INTERACTION_STATE_IDLE && finalDuration <= mDurationMs) {
        size_t elapsed_time = CalcTimespecDiffMs(mLastTimespec, cur_timespec);
        // don't hint if previous hint's duration covers this hint's duration
        if (elapsed_time <= (mDurationMs - finalDuration)) {
            ALOGV("%s: Previous duration (%d) cover this (%d) elapsed: %lld", __func__,
                  static_cast<int>(mDurationMs), static_cast<int>(finalDuration),
                  static_cast<long long>(elapsed_time));
            return;
        }
    }
    mLastTimespec = cur_timespec;
    mDurationMs = finalDuration;

    ALOGV("%s: input: %d final duration: %d", __func__, duration, finalDuration);

    if (mState == INTERACTION_STATE_WAITING)
        AbortWaitLocked();
    else if (mState == INTERACTION_STATE_IDLE)
        PerfLock();

    mState = INTERACTION_STATE_INTERACTION;
    mCond.notify_one();
}

void InteractionHandler::Release() {
    std::lock_guard<std::mutex> lk(mLock);
    if (mState == INTERACTION_STATE_WAITING) {
        ATRACE_CALL();
        PerfRel();
        mState = INTERACTION_STATE_IDLE;
    } else {
        // clear any wait aborts pending in event fd
        uint64_t val;
        ssize_t ret = read(mEventFd, &val, sizeof(val));

        ALOGW_IF(ret < 0, "%s: failed to clear eventfd (%zd, %d)", __func__, ret, errno);
    }
}

// should be called while locked
void InteractionHandler::AbortWaitLocked() {
    uint64_t val = 1;
    ssize_t ret = write(mEventFd, &val, sizeof(val));
    if (ret != sizeof(val))
        ALOGW("Unable to write to event fd (%zd)", ret);
}

void InteractionHandler::WaitForIdle(int32_t wait_ms, int32_t timeout_ms) {
    char data[MAX_LENGTH];
    ssize_t ret;
    struct pollfd pfd[2];

    ATRACE_CALL();

    ALOGV("%s: wait:%d timeout:%d", __func__, wait_ms, timeout_ms);

    pfd[0].fd = mEventFd;
    pfd[0].events = POLLIN;
    pfd[1].fd = mIdleFd;
    pfd[1].events = POLLPRI | POLLERR;

    ret = poll(pfd, 1, wait_ms);
    if (ret > 0) {
        ALOGV("%s: wait aborted", __func__);
        return;
    } else if (ret < 0) {
        ALOGE("%s: error in poll while waiting", __func__);
        return;
    }

    ret = pread(mIdleFd, data, sizeof(data), 0);
    if (!ret) {
        ALOGE("%s: Unexpected EOF!", __func__);
        return;
    }

    if (!strncmp(data, "idle", 4)) {
        ALOGV("%s: already idle", __func__);
        return;
    }

    ret = poll(pfd, 2, timeout_ms);
    if (ret < 0)
        ALOGE("%s: Error on waiting for idle (%zd)", __func__, ret);
    else if (ret == 0)
        ALOGV("%s: timed out waiting for idle", __func__);
    else if (pfd[0].revents)
        ALOGV("%s: wait for idle aborted", __func__);
    else if (pfd[1].revents)
        ALOGV("%s: idle detected", __func__);
}

void InteractionHandler::Routine() {
    pthread_setname_np(pthread_self(), "DispIdle");
    std::unique_lock<std::mutex> lk(mLock, std::defer_lock);

    while (true) {
        lk.lock();
        mCond.wait(lk, [&] { return mState != INTERACTION_STATE_IDLE; });
        if (mState == INTERACTION_STATE_UNINITIALIZED)
            return;
        mState = INTERACTION_STATE_WAITING;
        lk.unlock();

        WaitForIdle(kWaitMs, mDurationMs);
        Release();
    }
}

}  // namespace pixel
}  // namespace impl
}  // namespace power
}  // namespace hardware
}  // namespace google
}  // namespace aidl
