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

#include <sys/sysinfo.h>

#include <android-base/stringprintf.h>
#include <cputimeinstate.h>

namespace android {

static constexpr uint64_t NSEC_PER_MSEC = 1000000;

static struct {
    jclass clazz;
    jmethodID put;
    jmethodID get;
} gSparseArrayClassInfo;

static jfieldID gmData;

static jlongArray getUidArray(JNIEnv *env, jobject sparseAr, uint32_t uid, jsize sz) {
    jlongArray ar = (jlongArray)env->CallObjectMethod(sparseAr, gSparseArrayClassInfo.get, uid);
    if (!ar) {
        ar = env->NewLongArray(sz);
        if (ar == nullptr) return ar;
        env->CallVoidMethod(sparseAr, gSparseArrayClassInfo.put, uid, ar);
    }
    return ar;
}

static void copy2DVecToArray(JNIEnv *env, jlongArray ar, std::vector<std::vector<uint64_t>> &vec) {
    jsize start = 0;
    for (auto &subVec : vec) {
        for (uint32_t i = 0; i < subVec.size(); ++i) subVec[i] /= NSEC_PER_MSEC;
        env->SetLongArrayRegion(ar, start, subVec.size(),
                                reinterpret_cast<const jlong *>(subVec.data()));
        start += subVec.size();
    }
}

static jboolean KernelCpuUidFreqTimeBpfMapReader_removeUidRange(JNIEnv *env, jclass, jint startUid,
                                                                jint endUid) {
    for (uint32_t uid = startUid; uid <= endUid; ++uid) {
        if (!android::bpf::clearUidTimes(uid)) return false;
    }
    return true;
}

static jboolean KernelCpuUidFreqTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) {
    static uint64_t lastUpdate = 0;
    uint64_t newLastUpdate = lastUpdate;
    auto sparseAr = env->GetObjectField(thiz, gmData);
    if (sparseAr == nullptr) return false;
    auto data = android::bpf::getUidsUpdatedCpuFreqTimes(&newLastUpdate);
    if (!data.has_value()) return false;

    jsize s = 0;
    for (auto &[uid, times] : *data) {
        if (s == 0) {
            for (const auto &subVec : times) s += subVec.size();
        }
        jlongArray ar = getUidArray(env, sparseAr, uid, s);
        if (ar == nullptr) return false;
        copy2DVecToArray(env, ar, times);
    }
    lastUpdate = newLastUpdate;
    return true;
}

static const JNINativeMethod gFreqTimeMethods[] = {
        {"removeUidRange", "(II)Z", (void *)KernelCpuUidFreqTimeBpfMapReader_removeUidRange},
        {"readBpfData", "()Z", (void *)KernelCpuUidFreqTimeBpfMapReader_readBpfData},
};

static jboolean KernelCpuUidActiveTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) {
    static uint64_t lastUpdate = 0;
    uint64_t newLastUpdate = lastUpdate;
    auto sparseAr = env->GetObjectField(thiz, gmData);
    if (sparseAr == nullptr) return false;
    auto data = android::bpf::getUidsUpdatedConcurrentTimes(&newLastUpdate);
    if (!data.has_value()) return false;

    for (auto &[uid, times] : *data) {
        // TODO: revise calling code so we can divide by NSEC_PER_MSEC here instead
        for (auto &time : times.active) time /= NSEC_PER_MSEC;
        jlongArray ar = getUidArray(env, sparseAr, uid, times.active.size());
        if (ar == nullptr) return false;
        env->SetLongArrayRegion(ar, 0, times.active.size(),
                                reinterpret_cast<const jlong *>(times.active.data()));
    }
    lastUpdate = newLastUpdate;
    return true;
}

static jlongArray KernelCpuUidActiveTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) {
    jlong nCpus = get_nprocs_conf();

    auto ar = env->NewLongArray(1);
    if (ar != nullptr) env->SetLongArrayRegion(ar, 0, 1, &nCpus);
    return ar;
}

static const JNINativeMethod gActiveTimeMethods[] = {
        {"readBpfData", "()Z", (void *)KernelCpuUidActiveTimeBpfMapReader_readBpfData},
        {"getDataDimensions", "()[J", (void *)KernelCpuUidActiveTimeBpfMapReader_getDataDimensions},
};

static jboolean KernelCpuUidClusterTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) {
    static uint64_t lastUpdate = 0;
    uint64_t newLastUpdate = lastUpdate;
    auto sparseAr = env->GetObjectField(thiz, gmData);
    if (sparseAr == nullptr) return false;
    auto data = android::bpf::getUidsUpdatedConcurrentTimes(&newLastUpdate);
    if (!data.has_value()) return false;

    jsize s = 0;
    for (auto &[uid, times] : *data) {
        if (s == 0) {
            for (const auto &subVec : times.policy) s += subVec.size();
        }
        jlongArray ar = getUidArray(env, sparseAr, uid, s);
        if (ar == nullptr) return false;
        copy2DVecToArray(env, ar, times.policy);
    }
    lastUpdate = newLastUpdate;
    return true;
}

static jlongArray KernelCpuUidClusterTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) {
    auto times = android::bpf::getUidConcurrentTimes(0);
    if (!times.has_value()) return nullptr;

    std::vector<jlong> clusterCores;
    for (const auto &vec : times->policy) clusterCores.push_back(vec.size());
    auto ar = env->NewLongArray(clusterCores.size());
    if (ar != nullptr) env->SetLongArrayRegion(ar, 0, clusterCores.size(), clusterCores.data());
    return ar;
}

static const JNINativeMethod gClusterTimeMethods[] = {
        {"readBpfData", "()Z", (void *)KernelCpuUidClusterTimeBpfMapReader_readBpfData},
        {"getDataDimensions", "()[J",
         (void *)KernelCpuUidClusterTimeBpfMapReader_getDataDimensions},
};

struct readerMethods {
    const char *name;
    const JNINativeMethod *methods;
    int numMethods;
};

static const readerMethods gAllMethods[] = {
        {"KernelCpuUidFreqTimeBpfMapReader", gFreqTimeMethods, NELEM(gFreqTimeMethods)},
        {"KernelCpuUidActiveTimeBpfMapReader", gActiveTimeMethods, NELEM(gActiveTimeMethods)},
        {"KernelCpuUidClusterTimeBpfMapReader", gClusterTimeMethods, NELEM(gClusterTimeMethods)},
};

int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env) {
    gSparseArrayClassInfo.clazz = FindClassOrDie(env, "android/util/SparseArray");
    gSparseArrayClassInfo.clazz = MakeGlobalRefOrDie(env, gSparseArrayClassInfo.clazz);
    gSparseArrayClassInfo.put =
            GetMethodIDOrDie(env, gSparseArrayClassInfo.clazz, "put", "(ILjava/lang/Object;)V");
    gSparseArrayClassInfo.get =
            GetMethodIDOrDie(env, gSparseArrayClassInfo.clazz, "get", "(I)Ljava/lang/Object;");
    constexpr auto readerName = "com/android/internal/os/KernelCpuUidBpfMapReader";
    auto c = FindClassOrDie(env, readerName);
    gmData = GetFieldIDOrDie(env, c, "mData", "Landroid/util/SparseArray;");

    int ret = 0;
    for (const auto &m : gAllMethods) {
        auto fullName = android::base::StringPrintf("%s$%s", readerName, m.name);
        ret = RegisterMethodsOrDie(env, fullName.c_str(), m.methods, m.numMethods);
        if (ret < 0) break;
    }
    return ret;
}

} // namespace android
