/*
 * 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.
 */

#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#define LOG_TAG "android.hardware.power-service.mediatek-libperfmgr"

#include <fcntl.h>
#include <poll.h>
#include <sys/eventfd.h>
#include <time.h>
#include <unistd.h>
#include <utils/Log.h>
#include <utils/Trace.h>
#include <memory>

#include "InteractionHandler.h"

#define MAX_LENGTH 64

#define MSINSEC 1000L
#define USINMS 1000000L

static const std::vector<std::string> fb_idle_path = {"/sys/class/drm/card0/device/idle_state",
                                                       "/sys/class/graphics/fb0/idle_state"};

InteractionHandler::InteractionHandler(std::shared_ptr<HintManager> const &hint_manager)
    : mState(INTERACTION_STATE_UNINITIALIZED),
      mWaitMs(100),
      mMinDurationMs(1400),
      mMaxDurationMs(5650),
      mDurationMs(0),
      mHintManager(hint_manager) {}

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

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

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

    if (mState != INTERACTION_STATE_UNINITIALIZED)
        return true;

    mIdleFd = fb_idle_open();

    mEventFd = eventfd(0, EFD_NONBLOCK);
    if (mEventFd < 0) {
        ALOGE("Unable to create event fd (%d)", errno);
        if (mIdleFd >= 0) {
            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);
    if (mIdleFd >= 0) {
        close(mIdleFd);
    }
}

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

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

size_t InteractionHandler::CalcTimespecDiffMs(struct timespec start, struct timespec end) {
    size_t diff_in_us = 0;
    diff_in_us += (end.tv_sec - start.tv_sec) * MSINSEC;
    diff_in_us += (end.tv_nsec - start.tv_nsec) / USINMS;
    return diff_in_us;
}

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

    std::lock_guard<std::mutex> lk(mLock);
    if (mState == INTERACTION_STATE_UNINITIALIZED) {
        ALOGW("%s: called while uninitialized", __func__);
        return;
    }

    int inputDuration = duration + 650;
    int finalDuration;
    if (inputDuration > mMaxDurationMs)
        finalDuration = mMaxDurationMs;
    else if (inputDuration > mMinDurationMs)
        finalDuration = inputDuration;
    else
        finalDuration = mMinDurationMs;

    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;
    }

    if (mIdleFd < 0) {
        ret = poll(pfd, 1, timeout_ms);
        if (ret > 0) {
            ALOGV("%s: wait for duration aborted", __func__);
            return;
        } else if (ret < 0) {
            ALOGE("%s: Error on waiting for duration (%zd)", __func__, ret);
            return;
        }
        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() {
    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(mWaitMs, mDurationMs);
        Release();
    }
}
