/*
 * Copyright (C) 2021 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 "pixelstats: MmMetrics"

#include <aidl/android/frameworks/stats/IStats.h>
#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android/binder_manager.h>
#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
#include <pixelstats/MmMetricsReporter.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <utils/Log.h>

#define SZ_4K 0x00001000
#define SZ_2M 0x00200000

namespace android {
namespace hardware {
namespace google {
namespace pixel {

using aidl::android::frameworks::stats::IStats;
using aidl::android::frameworks::stats::VendorAtom;
using aidl::android::frameworks::stats::VendorAtomValue;
using android::base::ReadFileToString;
using android::base::StartsWith;
using android::hardware::google::pixel::PixelAtoms::CmaStatus;
using android::hardware::google::pixel::PixelAtoms::CmaStatusExt;
using android::hardware::google::pixel::PixelAtoms::PixelMmMetricsPerDay;
using android::hardware::google::pixel::PixelAtoms::PixelMmMetricsPerHour;

const std::vector<MmMetricsReporter::MmMetricsInfo> MmMetricsReporter::kMmMetricsPerHourInfo = {
        {"nr_free_pages", PixelMmMetricsPerHour::kFreePagesFieldNumber, false},
        {"nr_anon_pages", PixelMmMetricsPerHour::kAnonPagesFieldNumber, false},
        {"nr_file_pages", PixelMmMetricsPerHour::kFilePagesFieldNumber, false},
        {"nr_slab_reclaimable", PixelMmMetricsPerHour::kSlabReclaimableFieldNumber, false},
        {"nr_zspages", PixelMmMetricsPerHour::kZspagesFieldNumber, false},
        {"nr_unevictable", PixelMmMetricsPerHour::kUnevictableFieldNumber, false},
};

const std::vector<MmMetricsReporter::MmMetricsInfo> MmMetricsReporter::kMmMetricsPerDayInfo = {
        {"workingset_refault", PixelMmMetricsPerDay::kWorkingsetRefaultFieldNumber, true},
        {"workingset_refault_file", PixelMmMetricsPerDay::kWorkingsetRefaultFieldNumber, true},
        {"pswpin", PixelMmMetricsPerDay::kPswpinFieldNumber, true},
        {"pswpout", PixelMmMetricsPerDay::kPswpoutFieldNumber, true},
        {"allocstall_dma", PixelMmMetricsPerDay::kAllocstallDmaFieldNumber, true},
        {"allocstall_dma32", PixelMmMetricsPerDay::kAllocstallDma32FieldNumber, true},
        {"allocstall_normal", PixelMmMetricsPerDay::kAllocstallNormalFieldNumber, true},
        {"allocstall_movable", PixelMmMetricsPerDay::kAllocstallMovableFieldNumber, true},
        {"pgalloc_dma", PixelMmMetricsPerDay::kPgallocDmaFieldNumber, true},
        {"pgalloc_dma32", PixelMmMetricsPerDay::kPgallocDma32FieldNumber, true},
        {"pgalloc_normal", PixelMmMetricsPerDay::kPgallocNormalFieldNumber, true},
        {"pgalloc_movable", PixelMmMetricsPerDay::kPgallocMovableFieldNumber, true},
        {"pgsteal_kswapd", PixelMmMetricsPerDay::kPgstealKswapdFieldNumber, true},
        {"pgsteal_direct", PixelMmMetricsPerDay::kPgstealDirectFieldNumber, true},
        {"pgscan_kswapd", PixelMmMetricsPerDay::kPgscanKswapdFieldNumber, true},
        {"pgscan_direct", PixelMmMetricsPerDay::kPgscanDirectFieldNumber, true},
        {"oom_kill", PixelMmMetricsPerDay::kOomKillFieldNumber, true},
        {"pgalloc_costly_order", PixelMmMetricsPerDay::kPgallocHighFieldNumber, true},
        {"pgcache_hit", PixelMmMetricsPerDay::kPgcacheHitFieldNumber, true},
        {"pgcache_miss", PixelMmMetricsPerDay::kPgcacheMissFieldNumber, true},
};

const std::vector<MmMetricsReporter::MmMetricsInfo> MmMetricsReporter::kCmaStatusInfo = {
        {"alloc_pages_attempts", CmaStatus::kCmaAllocPagesAttemptsFieldNumber, true},
        {"alloc_pages_failfast_attempts", CmaStatus::kCmaAllocPagesSoftAttemptsFieldNumber, true},
        {"fail_pages", CmaStatus::kCmaFailPagesFieldNumber, true},
        {"fail_failfast_pages", CmaStatus::kCmaFailSoftPagesFieldNumber, true},
        {"migrated_pages", CmaStatus::kMigratedPagesFieldNumber, true},
};

const std::vector<MmMetricsReporter::MmMetricsInfo> MmMetricsReporter::kCmaStatusExtInfo = {
        {"latency_low", CmaStatusExt::kCmaAllocLatencyLowFieldNumber, false},
        {"latency_mid", CmaStatusExt::kCmaAllocLatencyMidFieldNumber, false},
        {"latency_high", CmaStatusExt::kCmaAllocLatencyHighFieldNumber, false},
};

static bool file_exists(const char *path) {
    struct stat sbuf;

    return (stat(path, &sbuf) == 0);
}

bool MmMetricsReporter::checkKernelMMMetricSupport() {
    const char *const require_all[] = {
            kVmstatPath,
            kGpuTotalPages,
            kPixelStatMm,
    };
    const char *const require_one[] = {
            kIonTotalPoolsPath,
            kIonTotalPoolsPathForLegacy,
    };

    for (auto &path : require_all) {
        if (!file_exists(path)) {
            ALOGI("MM Metrics not supported - no %s.", path);
            return false;
        }
    }

    std::string err_msg;
    for (auto &path : require_one) {
        if (file_exists(path)) {
            err_msg.clear();
            break;
        }
        err_msg += path;
        err_msg += ", ";
    }

    if (!err_msg.empty()) {
        err_msg.pop_back();  // remove last space
        err_msg.pop_back();  // remove last comma
        ALOGI("MM Metrics not supported - no IonTotalPools path.");
        return false;
    }
    return true;
}

static bool checkUserBuild() {
    return android::base::GetProperty("ro.build.type", "") == "user";
}

MmMetricsReporter::MmMetricsReporter()
    : kVmstatPath("/proc/vmstat"),
      kIonTotalPoolsPath("/sys/kernel/dma_heap/total_pools_kb"),
      kIonTotalPoolsPathForLegacy("/sys/kernel/ion/total_pools_kb"),
      kGpuTotalPages("/sys/kernel/pixel_stat/gpu/mem/total_page_count"),
      kPixelStatMm("/sys/kernel/pixel_stat/mm") {
    is_user_build_ = checkUserBuild();
    ker_mm_metrics_support_ = checkKernelMMMetricSupport();
}

bool MmMetricsReporter::ReadFileToUint(const char *const path, uint64_t *val) {
    std::string file_contents;

    if (!ReadFileToString(path, &file_contents)) {
        // Don't print this log if the file doesn't exist, since logs will be printed repeatedly.
        if (errno != ENOENT) {
            ALOGI("Unable to read %s - %s", path, strerror(errno));
        }
        return false;
    } else {
        file_contents = android::base::Trim(file_contents);
        if (!android::base::ParseUint(file_contents, val)) {
            ALOGI("Unable to convert %s to uint - %s", path, strerror(errno));
            return false;
        }
    }
    return true;
}

bool MmMetricsReporter::reportVendorAtom(const std::shared_ptr<IStats> &stats_client, int atom_id,
                                         const std::vector<VendorAtomValue> &values,
                                         const std::string &atom_name) {
    // Send vendor atom to IStats HAL
    VendorAtom event = {.reverseDomainName = "",
                        .atomId = atom_id,
                        .values = std::move(values)};
    const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
    if (!ret.isOk()) {
        ALOGE("Unable to report %s to Stats service", atom_name.c_str());
        return false;
    }
    return true;
}

/**
 * Parse the output of /proc/vmstat or the sysfs having the same output format.
 * The map containing pairs of {field_string, data} will be returned.
 */
std::map<std::string, uint64_t> MmMetricsReporter::readVmStat(const char *path) {
    std::string file_contents;
    std::map<std::string, uint64_t> vmstat_data;

    if (path == nullptr) {
        ALOGI("vmstat path is not specified");
        return vmstat_data;
    }

    if (!ReadFileToString(path, &file_contents)) {
        ALOGE("Unable to read vmstat from %s, err: %s", path, strerror(errno));
        return vmstat_data;
    }

    std::istringstream data(file_contents);
    std::string line;
    while (std::getline(data, line)) {
        std::vector<std::string> words = android::base::Split(line, " ");
        if (words.size() != 2)
            continue;

        uint64_t i;
        if (!android::base::ParseUint(words[1], &i))
            continue;

        vmstat_data[words[0]] = i;
    }
    return vmstat_data;
}

uint64_t MmMetricsReporter::getIonTotalPools() {
    uint64_t res;

    if (!ReadFileToUint(kIonTotalPoolsPathForLegacy, &res) || (res == 0)) {
        if (!ReadFileToUint(kIonTotalPoolsPath, &res)) {
            return 0;
        }
    }

    return res;
}

/**
 * Collect GPU memory from kGpuTotalPages and return the total number of 4K page.
 */
uint64_t MmMetricsReporter::getGpuMemory() {
    uint64_t gpu_size = 0;

    if (!ReadFileToUint(kGpuTotalPages, &gpu_size)) {
        return 0;
    }
    return gpu_size;
}

/**
 * fillAtomValues() is used to copy Mm metrics to values
 * metrics_info: This is a vector of MmMetricsInfo {field_string, atom_key, update_diff}
 *               field_string is used to get the data from mm_metrics.
 *               atom_key is the position where the data should be put into values.
 *               update_diff will be true if this is an accumulated data.
 *               metrics_info may have multiple entries with the same atom_key,
 *               e.g. workingset_refault and workingset_refault_file.
 * mm_metrics: This map contains pairs of {field_string, cur_value} collected
 *             from /proc/vmstat or the sysfs for the pixel specific metrics.
 *             e.g. {"nr_free_pages", 200000}
 *             Some data in mm_metrics are accumulated, e.g. pswpin.
 *             We upload the difference instead of the accumulated value
 *             when update_diff of the field is true.
 * prev_mm_metrics: The pointer to the metrics we collected last time.
 * atom_values: The atom values that will be reported later.
 */
void MmMetricsReporter::fillAtomValues(const std::vector<MmMetricsInfo> &metrics_info,
                                       const std::map<std::string, uint64_t> &mm_metrics,
                                       std::map<std::string, uint64_t> *prev_mm_metrics,
                                       std::vector<VendorAtomValue> *atom_values) {
    VendorAtomValue tmp;
    tmp.set<VendorAtomValue::longValue>(0);
    // resize atom_values to add all fields defined in metrics_info
    int max_idx = 0;
    for (auto &entry : metrics_info) {
        if (max_idx < entry.atom_key)
            max_idx = entry.atom_key;
    }
    int size = max_idx - kVendorAtomOffset + 1;
    if (atom_values->size() < size)
        atom_values->resize(size, tmp);

    for (auto &entry : metrics_info) {
        int atom_idx = entry.atom_key - kVendorAtomOffset;

        auto data = mm_metrics.find(entry.name);
        if (data == mm_metrics.end())
            continue;

        uint64_t cur_value = data->second;
        uint64_t prev_value = 0;
        if (prev_mm_metrics->size() != 0) {
            auto prev_data = prev_mm_metrics->find(entry.name);
            if (prev_data != prev_mm_metrics->end())
                prev_value = prev_data->second;
        }

        if (entry.update_diff) {
            tmp.set<VendorAtomValue::longValue>(cur_value - prev_value);
        } else {
            tmp.set<VendorAtomValue::longValue>(cur_value);
        }
        (*atom_values)[atom_idx] = tmp;
    }
    (*prev_mm_metrics) = mm_metrics;
}

void MmMetricsReporter::logPixelMmMetricsPerHour(const std::shared_ptr<IStats> &stats_client) {
    if (!MmMetricsSupported())
        return;

    std::map<std::string, uint64_t> vmstat = readVmStat(kVmstatPath);
    if (vmstat.size() == 0)
        return;

    uint64_t ion_total_pools = getIonTotalPools();
    uint64_t gpu_memory = getGpuMemory();

    std::vector<VendorAtomValue> values;
    bool is_first_atom = (prev_hour_vmstat_.size() == 0) ? true : false;
    fillAtomValues(kMmMetricsPerHourInfo, vmstat, &prev_hour_vmstat_, &values);

    // resize values to add the following fields
    VendorAtomValue tmp;
    tmp.set<VendorAtomValue::longValue>(0);
    int size = PixelMmMetricsPerHour::kGpuMemoryFieldNumber - kVendorAtomOffset + 1;
    if (values.size() < size) {
        values.resize(size, tmp);
    }
    tmp.set<VendorAtomValue::longValue>(ion_total_pools);
    values[PixelMmMetricsPerHour::kIonTotalPoolsFieldNumber - kVendorAtomOffset] = tmp;
    tmp.set<VendorAtomValue::longValue>(gpu_memory);
    values[PixelMmMetricsPerHour::kGpuMemoryFieldNumber - kVendorAtomOffset] = tmp;

    // Don't report the first atom to avoid big spike in accumulated values.
    if (!is_first_atom) {
        // Send vendor atom to IStats HAL
        reportVendorAtom(stats_client, PixelAtoms::Atom::kPixelMmMetricsPerHour, values,
                         "PixelMmMetricsPerHour");
    }
}

void MmMetricsReporter::logPixelMmMetricsPerDay(const std::shared_ptr<IStats> &stats_client) {
    if (!MmMetricsSupported())
        return;

    std::map<std::string, uint64_t> vmstat = readVmStat(kVmstatPath);
    if (vmstat.size() == 0)
        return;

    std::vector<VendorAtomValue> values;
    bool is_first_atom = (prev_day_vmstat_.size() == 0) ? true : false;
    fillAtomValues(kMmMetricsPerDayInfo, vmstat, &prev_day_vmstat_, &values);

    std::map<std::string, uint64_t> pixel_vmstat =
            readVmStat(android::base::StringPrintf("%s/vmstat", kPixelStatMm).c_str());
    fillAtomValues(kMmMetricsPerDayInfo, pixel_vmstat, &prev_day_pixel_vmstat_, &values);
    fillProcessStime(PixelMmMetricsPerDay::kKswapdStimeClksFieldNumber, "kswapd0", &kswapd_pid_,
                     &prev_kswapd_stime_, &values);
    fillProcessStime(PixelMmMetricsPerDay::kKcompactdStimeClksFieldNumber, "kcompactd0",
                     &kcompactd_pid_, &prev_kcompactd_stime_, &values);

    // Don't report the first atom to avoid big spike in accumulated values.
    if (!is_first_atom) {
        // Send vendor atom to IStats HAL
        reportVendorAtom(stats_client, PixelAtoms::Atom::kPixelMmMetricsPerDay, values,
                         "PixelMmMetricsPerDay");
    }
}

/**
 * Check if /proc/<pid>/comm is equal to name.
 */
bool MmMetricsReporter::isValidPid(int pid, const char *name) {
    if (pid <= 0)
        return false;

    std::string file_contents;
    std::string path = android::base::StringPrintf("/proc/%d/comm", pid);
    if (!ReadFileToString(path, &file_contents)) {
        ALOGI("Unable to read %s, err: %s", path.c_str(), strerror(errno));
        return false;
    }

    file_contents = android::base::Trim(file_contents);
    return !file_contents.compare(name);
}

/**
 * Return pid if /proc/<pid>/comm is equal to name, or -1 if not found.
 */
int MmMetricsReporter::findPidByProcessName(const char *name) {
    std::unique_ptr<DIR, int (*)(DIR *)> dir(opendir("/proc"), closedir);
    if (!dir)
        return -1;

    int pid;
    while (struct dirent *dp = readdir(dir.get())) {
        if (dp->d_type != DT_DIR)
            continue;

        if (!android::base::ParseInt(dp->d_name, &pid))
            continue;

        // Avoid avc denial since pixelstats-vendor doesn't have the permission to access /proc/1
        if (pid == 1)
            continue;

        std::string file_contents;
        std::string path = android::base::StringPrintf("/proc/%s/comm", dp->d_name);
        if (!ReadFileToString(path, &file_contents))
            continue;

        file_contents = android::base::Trim(file_contents);
        if (file_contents.compare(name))
            continue;

        return pid;
    }
    return -1;
}

/**
 * Get stime of a process from /proc/<pid>/stat
 * stime is the 15th field.
 */
uint64_t MmMetricsReporter::getStimeByPid(int pid) {
    const int stime_idx = 15;
    uint64_t stime;
    std::string file_contents;
    std::string path = android::base::StringPrintf("/proc/%d/stat", pid);
    if (!ReadFileToString(path, &file_contents)) {
        ALOGI("Unable to read %s, err: %s", path.c_str(), strerror(errno));
        return false;
    }

    std::vector<std::string> data = android::base::Split(file_contents, " ");
    if (data.size() < stime_idx) {
        ALOGI("Unable to find stime from %s. size: %lu", path.c_str(), data.size());
        return false;
    }

    if (android::base::ParseUint(data[stime_idx - 1], &stime))
        return stime;
    else
        return 0;
}

/**
 * Find stime of the process and copy it into atom_values
 * atom_key: Currently, it can only be kKswapdTimeFieldNumber or kKcompactdTimeFieldNumber
 * name: process name
 * pid: The pid of the process. It would be the pid we found last time,
 *      or -1 if not found.
 * prev_stime: The stime of the process collected last time.
 * atom_values: The atom we will report later.
 */
void MmMetricsReporter::fillProcessStime(int atom_key, const char *name, int *pid,
                                         uint64_t *prev_stime,
                                         std::vector<VendorAtomValue> *atom_values) {
    // resize atom_values if there is no space for this stime field.
    int atom_idx = atom_key - kVendorAtomOffset;
    int size = atom_idx + 1;
    VendorAtomValue tmp;
    tmp.set<VendorAtomValue::longValue>(0);
    if (atom_values->size() < size)
        atom_values->resize(size, tmp);

    if (!isValidPid(*pid, name)) {
        (*pid) = findPidByProcessName(name);
        if ((*pid) <= 0) {
            ALOGI("Unable to find pid of %s, err: %s", name, strerror(errno));
            return;
        }
    }

    uint64_t stime = getStimeByPid(*pid);
    tmp.set<VendorAtomValue::longValue>(stime - *prev_stime);
    (*atom_values)[atom_idx] = tmp;
    (*prev_stime) = stime;
}

/**
 * Collect CMA metrics from kPixelStatMm/cma/<cma_type>/<metric>
 * cma_type: CMA heap name
 * metrics_info: This is a vector of MmMetricsInfo {metric, atom_key, update_diff}.
 *               Currently, we only collect CMA metrics defined in metrics_info
 */
std::map<std::string, uint64_t> MmMetricsReporter::readCmaStat(
        const std::string &cma_type,
        const std::vector<MmMetricsReporter::MmMetricsInfo> &metrics_info) {
    uint64_t file_contents;
    std::map<std::string, uint64_t> cma_stat;
    for (auto &entry : metrics_info) {
        std::string path = android::base::StringPrintf("%s/cma/%s/%s", kPixelStatMm,
                                                       cma_type.c_str(), entry.name.c_str());
        if (!ReadFileToUint(path.c_str(), &file_contents))
            continue;
        cma_stat[entry.name] = file_contents;
    }
    return cma_stat;
}

/**
 * This function is to collect CMA metrics and upload them.
 * The CMA metrics are collected by readCmaStat(), copied into atom values
 * by fillAtomValues(), and then uploaded by reportVendorAtom(). The collected
 * metrics will be stored in prev_cma_stat_ and prev_cma_stat_ext_ according
 * to its CmaType.
 *
 * stats_client: The Stats service
 * atom_id: The id of atom. It can be PixelAtoms::Atom::kCmaStatus or kCmaStatusExt
 * cma_type: The name of CMA heap.
 * cma_name_offset: The offset of the field cma_heap_name in CmaStatus or CmaStatusExt
 * type_idx: The id of the CMA heap. We add this id in atom values to identify
 *           the CMA status data.
 * metrics_info: This is a vector of MmMetricsInfo {metric, atom_key, update_diff}.
 *               We only collect metrics defined in metrics_info from CMA heap path.
 * all_prev_cma_stat: This is the CMA status collected last time.
 *                    It is a map containing pairs of {type_idx, cma_stat}, and cma_stat is
 *                    a map contains pairs of {metric, cur_value}.
 *                    e.g. {CmaType::FARAWIMG, {"alloc_pages_attempts", 100000}, {...}, ....}
 *                    is collected from kPixelStatMm/cma/farawimg/alloc_pages_attempts
 */
void MmMetricsReporter::reportCmaStatusAtom(
        const std::shared_ptr<IStats> &stats_client, int atom_id, const std::string &cma_type,
        int cma_name_offset, const std::vector<MmMetricsInfo> &metrics_info,
        std::map<std::string, std::map<std::string, uint64_t>> *all_prev_cma_stat) {
    std::map<std::string, uint64_t> cma_stat = readCmaStat(cma_type, metrics_info);
    if (!cma_stat.empty()) {
        std::vector<VendorAtomValue> values;
        VendorAtomValue tmp;
        // type is an enum value corresponding to the CMA heap name. Since CMA heap name
        // can be added/removed/modified, it would take effort to maintain the mapping table.
        // We would like to store CMA heap name directly, so just set type to 0.
        tmp.set<VendorAtomValue::intValue>(0);
        values.push_back(tmp);

        std::map<std::string, uint64_t> prev_cma_stat;
        auto entry = all_prev_cma_stat->find(cma_type);
        if (entry != all_prev_cma_stat->end())
            prev_cma_stat = entry->second;

        bool is_first_atom = (prev_cma_stat.size() == 0) ? true : false;
        fillAtomValues(metrics_info, cma_stat, &prev_cma_stat, &values);

        int size = cma_name_offset - kVendorAtomOffset + 1;
        if (values.size() < size) {
            values.resize(size, tmp);
        }
        tmp.set<VendorAtomValue::stringValue>(cma_type);
        values[cma_name_offset - kVendorAtomOffset] = tmp;

        (*all_prev_cma_stat)[cma_type] = prev_cma_stat;
        if (!is_first_atom)
            reportVendorAtom(stats_client, atom_id, values, "CmaStatus");
    }
}

/**
 * Find the CMA heap defined in kCmaTypeInfo, and then call reportCmaStatusAtom()
 * to collect the CMA metrics from kPixelStatMm/cma/<cma_type> and upload them.
 */
void MmMetricsReporter::logCmaStatus(const std::shared_ptr<IStats> &stats_client) {
    if (!CmaMetricsSupported())
        return;

    std::string cma_root = android::base::StringPrintf("%s/cma", kPixelStatMm);
    std::unique_ptr<DIR, int (*)(DIR *)> dir(opendir(cma_root.c_str()), closedir);
    if (!dir)
        return;

    while (struct dirent *dp = readdir(dir.get())) {
        if (dp->d_type != DT_DIR)
            continue;

        std::string cma_type(dp->d_name);

        reportCmaStatusAtom(stats_client, PixelAtoms::Atom::kCmaStatus, cma_type,
                            CmaStatus::kCmaHeapNameFieldNumber, kCmaStatusInfo, &prev_cma_stat_);
        reportCmaStatusAtom(stats_client, PixelAtoms::Atom::kCmaStatusExt, cma_type,
                            CmaStatusExt::kCmaHeapNameFieldNumber, kCmaStatusExtInfo,
                            &prev_cma_stat_ext_);
    }
}

}  // namespace pixel
}  // namespace google
}  // namespace hardware
}  // namespace android
