/*
 * 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 "WakeLockEntryList.h"

#include <android-base/file.h>
#include <android-base/logging.h>

#include <iomanip>

using android::base::ReadFdToString;

namespace android {
namespace system {
namespace suspend {
namespace V1_0 {

static std::ostream& operator<<(std::ostream& out, const WakeLockInfo& entry) {
    const char* sep = " | ";
    const char* notApplicable = "---";
    bool kernelWakelock = entry.isKernelWakelock;

    // clang-format off
    out << sep
        << std::left << std::setw(30) << entry.name << sep
        << std::right << std::setw(6)
        << ((kernelWakelock) ? notApplicable : std::to_string(entry.pid)) << sep
        << std::left << std::setw(6) << ((kernelWakelock) ? "Kernel" : "Native") << sep
        << std::left << std::setw(8) << ((entry.isActive) ? "Active" : "Inactive") << sep
        << std::right << std::setw(12) << entry.activeCount << sep
        << std::right << std::setw(12) << std::to_string(entry.totalTime) + "ms" << sep
        << std::right << std::setw(12) << std::to_string(entry.maxTime) + "ms" << sep
        << std::right << std::setw(12)
        << ((kernelWakelock) ? std::to_string(entry.eventCount) : notApplicable) << sep
        << std::right << std::setw(12)
        << ((kernelWakelock) ? std::to_string(entry.wakeupCount) : notApplicable) << sep
        << std::right << std::setw(12)
        << ((kernelWakelock) ? std::to_string(entry.expireCount) : notApplicable) << sep
        << std::right << std::setw(20)
        << ((kernelWakelock) ? std::to_string(entry.preventSuspendTime) + "ms" : notApplicable)
        << sep
        << std::right << std::setw(16) << std::to_string(entry.lastChange) + "ms" << sep;
    // clang-format on

    return out;
}

std::ostream& operator<<(std::ostream& out, const WakeLockEntryList& list) {
    std::vector<WakeLockInfo> wlStats;
    list.getWakeLockStats(&wlStats);
    int width = 194;
    const char* sep = " | ";
    std::stringstream ss;
    ss << "  " << std::setfill('-') << std::setw(width) << "\n";
    std::string div = ss.str();

    out << div;

    std::stringstream header;
    header << sep << std::right << std::setw(((width - 14) / 2) + 14) << "WAKELOCK STATS"
           << std::right << std::setw((width - 14) / 2) << sep << "\n";
    out << header.str();

    out << div;

    // Col names
    // clang-format off
    out << sep
        << std::left << std::setw(30) << "NAME" << sep
        << std::left << std::setw(6) << "PID" << sep
        << std::left << std::setw(6) << "TYPE" << sep
        << std::left << std::setw(8) << "STATUS" << sep
        << std::left << std::setw(12) << "ACTIVE COUNT" << sep
        << std::left << std::setw(12) << "TOTAL TIME" << sep
        << std::left << std::setw(12) << "MAX TIME" << sep
        << std::left << std::setw(12) << "EVENT COUNT" << sep
        << std::left << std::setw(12) << "WAKEUP COUNT" << sep
        << std::left << std::setw(12) << "EXPIRE COUNT" << sep
        << std::left << std::setw(20) << "PREVENT SUSPEND TIME" << sep
        << std::left << std::setw(16) << "LAST CHANGE" << sep
        << "\n";
    // clang-format on

    out << div;

    // Rows
    for (const WakeLockInfo& entry : wlStats) {
        out << entry << "\n";
    }

    out << div;
    return out;
}

/**
 * Returns the monotonic time in milliseconds.
 */
TimestampType getTimeNow() {
    timespec monotime;
    clock_gettime(CLOCK_MONOTONIC, &monotime);
    return std::chrono::duration_cast<std::chrono::milliseconds>(
               std::chrono::nanoseconds{monotime.tv_nsec})
               .count() +
           std::chrono::duration_cast<std::chrono::milliseconds>(
               std::chrono::seconds{monotime.tv_sec})
               .count();
}

WakeLockEntryList::WakeLockEntryList(size_t capacity, unique_fd kernelWakelockStatsFd)
    : mCapacity(capacity), mKernelWakelockStatsFd(std::move(kernelWakelockStatsFd)) {}

/**
 * Evicts LRU from back of list if stats is at capacity.
 */
void WakeLockEntryList::evictIfFull() {
    if (mStats.size() == mCapacity) {
        auto evictIt = mStats.end();
        std::advance(evictIt, -1);
        auto evictKey = std::make_pair(evictIt->name, evictIt->pid);
        mLookupTable.erase(evictKey);
        mStats.erase(evictIt);
        LOG(ERROR) << "WakeLock Stats: Stats capacity met, consider adjusting capacity to "
                      "avoid stats eviction.";
    }
}

/**
 * Inserts entry as MRU.
 */
void WakeLockEntryList::insertEntry(WakeLockInfo entry) {
    auto key = std::make_pair(entry.name, entry.pid);
    mStats.emplace_front(std::move(entry));
    mLookupTable[key] = mStats.begin();
}

/**
 * Removes entry from the stats list.
 */
void WakeLockEntryList::deleteEntry(std::list<WakeLockInfo>::iterator entry) {
    auto key = std::make_pair(entry->name, entry->pid);
    mLookupTable.erase(key);
    mStats.erase(entry);
}

/**
 * Creates and returns a native wakelock entry.
 */
WakeLockInfo WakeLockEntryList::createNativeEntry(const std::string& name, int pid,
                                                  TimestampType timeNow) const {
    WakeLockInfo info;

    info.name = name;
    // It only makes sense to create a new entry on initial activation of the lock.
    info.activeCount = 1;
    info.lastChange = timeNow;
    info.maxTime = 0;
    info.totalTime = 0;
    info.isActive = true;
    info.activeTime = 0;
    info.isKernelWakelock = false;

    info.pid = pid;

    info.eventCount = 0;
    info.expireCount = 0;
    info.preventSuspendTime = 0;
    info.wakeupCount = 0;

    return info;
}

/*
 * Checks whether a given directory entry is a stat file we're interested in.
 */
static bool isStatFile(const struct dirent* de) {
    const char* statName = de->d_name;
    if (!strcmp(statName, ".") || !strcmp(statName, "..") || !strcmp(statName, "device") ||
        !strcmp(statName, "power") || !strcmp(statName, "subsystem") ||
        !strcmp(statName, "uevent")) {
        return false;
    }
    return true;
}

/*
 * Creates and returns a kernel wakelock entry with data read from mKernelWakelockStatsFd
 */
WakeLockInfo WakeLockEntryList::createKernelEntry(const std::string& kwlId) const {
    WakeLockInfo info;

    info.activeCount = 0;
    info.lastChange = 0;
    info.maxTime = 0;
    info.totalTime = 0;
    info.isActive = false;
    info.activeTime = 0;
    info.isKernelWakelock = true;

    info.pid = -1;  // N/A

    info.eventCount = 0;
    info.expireCount = 0;
    info.preventSuspendTime = 0;
    info.wakeupCount = 0;

    unique_fd wakelockFd{TEMP_FAILURE_RETRY(
        openat(mKernelWakelockStatsFd, kwlId.c_str(), O_DIRECTORY | O_CLOEXEC | O_RDONLY))};
    if (wakelockFd < 0) {
        char buf[PATH_MAX];
        ssize_t data_length =
            readlinkat(mKernelWakelockStatsFd, kwlId.c_str(), buf, sizeof(buf) - 1);
        if (data_length <= 0 || strncmp(kwlId.c_str(), buf, kwlId.length()) == 0) {
            buf[0] = '\0';
        }
        PLOG(ERROR) << "Error opening kernel wakelock stats for: " << kwlId << " (" << buf << ")";
    }

    std::unique_ptr<DIR, decltype(&closedir)> wakelockDp(fdopendir(dup(wakelockFd.get())),
                                                         &closedir);
    if (wakelockDp) {
        struct dirent* de;
        while ((de = readdir(wakelockDp.get()))) {
            if (!isStatFile(de)) {
                continue;
            }

            std::string statName(de->d_name);
            unique_fd statFd{
                TEMP_FAILURE_RETRY(openat(wakelockFd, statName.c_str(), O_CLOEXEC | O_RDONLY))};
            if (statFd < 0) {
                PLOG(ERROR) << "Error opening " << statName << " for " << kwlId;
            }

            std::string valStr;
            if (!ReadFdToString(statFd.get(), &valStr)) {
                PLOG(ERROR) << "Error reading " << statName << " for " << kwlId;
                continue;
            }

            // Trim newline
            valStr.erase(std::remove(valStr.begin(), valStr.end(), '\n'), valStr.end());

            if (statName == "name") {
                info.name = valStr;
                continue;
            }

            int64_t statVal = std::stoll(valStr);

            if (statName == "active_count") {
                info.activeCount = statVal;
            } else if (statName == "active_time_ms") {
                info.activeTime = statVal;
            } else if (statName == "event_count") {
                info.eventCount = statVal;
            } else if (statName == "expire_count") {
                info.expireCount = statVal;
            } else if (statName == "last_change_ms") {
                info.lastChange = statVal;
            } else if (statName == "max_time_ms") {
                info.maxTime = statVal;
            } else if (statName == "prevent_suspend_time_ms") {
                info.preventSuspendTime = statVal;
            } else if (statName == "total_time_ms") {
                info.totalTime = statVal;
            } else if (statName == "wakeup_count") {
                info.wakeupCount = statVal;
            }
        }
    }

    // Derived stats
    info.isActive = info.activeTime > 0;

    return info;
}

void WakeLockEntryList::getKernelWakelockStats(std::vector<WakeLockInfo>* aidl_return) const {
    std::unique_ptr<DIR, decltype(&closedir)> dp(fdopendir(dup(mKernelWakelockStatsFd.get())),
                                                 &closedir);
    if (dp) {
        // rewinddir, else subsequent calls will not get any kernel wakelocks.
        rewinddir(dp.get());

        struct dirent* de;
        while ((de = readdir(dp.get()))) {
            std::string kwlId(de->d_name);
            if ((kwlId == ".") || (kwlId == "..")) {
                continue;
            }
            WakeLockInfo entry = createKernelEntry(kwlId);
            aidl_return->emplace_back(std::move(entry));
        }
    }
}

void WakeLockEntryList::updateOnAcquire(const std::string& name, int pid) {
    TimestampType timeNow = getTimeNow();

    std::lock_guard<std::mutex> lock(mStatsLock);

    auto key = std::make_pair(name, pid);
    auto it = mLookupTable.find(key);
    if (it == mLookupTable.end()) {
        evictIfFull();
        WakeLockInfo newEntry = createNativeEntry(name, pid, timeNow);
        insertEntry(newEntry);
    } else {
        auto staleEntry = it->second;
        WakeLockInfo updatedEntry = *staleEntry;

        // Update entry
        updatedEntry.isActive = true;
        updatedEntry.activeTime = 0;
        updatedEntry.activeCount++;
        updatedEntry.lastChange = timeNow;

        deleteEntry(staleEntry);
        insertEntry(std::move(updatedEntry));
    }
}

void WakeLockEntryList::updateOnRelease(const std::string& name, int pid) {
    TimestampType timeNow = getTimeNow();

    std::lock_guard<std::mutex> lock(mStatsLock);

    auto key = std::make_pair(name, pid);
    auto it = mLookupTable.find(key);
    if (it == mLookupTable.end()) {
        LOG(INFO) << "WakeLock Stats: A stats entry for, \"" << name
                  << "\" was not found. This is most likely due to it being evicted.";
    } else {
        auto staleEntry = it->second;
        WakeLockInfo updatedEntry = *staleEntry;

        // Update entry
        TimestampType timeDelta = timeNow - updatedEntry.lastChange;
        updatedEntry.isActive = false;
        updatedEntry.activeTime += timeDelta;
        updatedEntry.maxTime = std::max(updatedEntry.maxTime, updatedEntry.activeTime);
        updatedEntry.activeTime = 0;  // No longer active
        updatedEntry.totalTime += timeDelta;
        updatedEntry.lastChange = timeNow;

        deleteEntry(staleEntry);
        insertEntry(std::move(updatedEntry));
    }
}
/**
 * Updates the native wakelock stats based on the current time.
 */
void WakeLockEntryList::updateNow() {
    std::lock_guard<std::mutex> lock(mStatsLock);

    TimestampType timeNow = getTimeNow();

    for (std::list<WakeLockInfo>::iterator it = mStats.begin(); it != mStats.end(); ++it) {
        if (it->isActive) {
            TimestampType timeDelta = timeNow - it->lastChange;
            it->activeTime += timeDelta;
            it->maxTime = std::max(it->maxTime, it->activeTime);
            it->totalTime += timeDelta;
            it->lastChange = timeNow;
        }
    }
}

void WakeLockEntryList::getWakeLockStats(std::vector<WakeLockInfo>* aidl_return) const {
    // Under no circumstances should the lock be held while getting kernel wakelock stats
    {
        std::lock_guard<std::mutex> lock(mStatsLock);
        for (const WakeLockInfo& entry : mStats) {
            aidl_return->emplace_back(entry);
        }
    }
    getKernelWakelockStats(aidl_return);
}

}  // namespace V1_0
}  // namespace suspend
}  // namespace system
}  // namespace android
