Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4465267f authored by Sandeep Patil's avatar Sandeep Patil Committed by Android (Google) Code Review
Browse files

Merge "Start using libmeminfo for all memory stats gathering."

parents f674b60e be825416
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -274,6 +274,7 @@ cc_library_shared {
        "libicuuc",
        "libmedia",
        "libmediametrics",
        "libmeminfo",
        "libaudioclient",
        "libjpeg",
        "libusbhost",
+23 −114
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <atomic>
#include <iomanip>
#include <string>
#include <vector>

#include <debuggerd/client.h>
#include <log/log.h>
@@ -41,6 +42,7 @@
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedUtfChars.h>
#include "jni.h"
#include <meminfo/sysmeminfo.h>
#include <memtrack/memtrack.h>
#include <memunreachable/memunreachable.h>
#include "android_os_Debug.h"
@@ -712,6 +714,8 @@ static long get_allocated_vmalloc_memory() {
    return vmalloc_allocated_size;
}

// The 1:1 mapping of MEMINFO_* enums here must match with the constants from
// Debug.java.
enum {
    MEMINFO_TOTAL,
    MEMINFO_FREE,
@@ -731,138 +735,43 @@ enum {
    MEMINFO_COUNT
};

static long long get_zram_mem_used()
{
#define ZRAM_SYSFS "/sys/block/zram0/"
    UniqueFile mm_stat_file = MakeUniqueFile(ZRAM_SYSFS "mm_stat", "re");
    if (mm_stat_file) {
        long long mem_used_total = 0;

        int matched = fscanf(mm_stat_file.get(), "%*d %*d %lld %*d %*d %*d %*d", &mem_used_total);
        if (matched != 1)
            ALOGW("failed to parse " ZRAM_SYSFS "mm_stat");

        return mem_used_total;
    }

    UniqueFile mem_used_total_file = MakeUniqueFile(ZRAM_SYSFS "mem_used_total", "re");
    if (mem_used_total_file) {
        long long mem_used_total = 0;

        int matched = fscanf(mem_used_total_file.get(), "%lld", &mem_used_total);
        if (matched != 1)
            ALOGW("failed to parse " ZRAM_SYSFS "mem_used_total");

        return mem_used_total;
    }

    return 0;
}

static void android_os_Debug_getMemInfo(JNIEnv *env, jobject clazz, jlongArray out)
{
    char buffer[4096];
    size_t numFound = 0;

    if (out == NULL) {
        jniThrowNullPointerException(env, "out == null");
        return;
    }

    int fd = open("/proc/meminfo", O_RDONLY | O_CLOEXEC);

    if (fd < 0) {
        ALOGW("Unable to open /proc/meminfo: %s\n", strerror(errno));
    int outLen = env->GetArrayLength(out);
    if (outLen < MEMINFO_COUNT) {
        jniThrowRuntimeException(env, "outLen < MEMINFO_COUNT");
        return;
    }

    int len = read(fd, buffer, sizeof(buffer)-1);
    close(fd);

    if (len < 0) {
        ALOGW("Empty /proc/meminfo");
    // Read system memory info including ZRAM. The values are stored in the vector
    // in the same order as MEMINFO_* enum
    std::vector<uint64_t> mem(MEMINFO_COUNT);
    std::vector<std::string> tags(::android::meminfo::SysMemInfo::kDefaultSysMemInfoTags);
    tags.insert(tags.begin() + MEMINFO_ZRAM_TOTAL, "Zram:");
    ::android::meminfo::SysMemInfo smi;
    if (!smi.ReadMemInfo(tags, &mem)) {
        jniThrowRuntimeException(env, "SysMemInfo read failed");
        return;
    }
    buffer[len] = 0;

    static const char* const tags[] = {
            "MemTotal:",
            "MemFree:",
            "Buffers:",
            "Cached:",
            "Shmem:",
            "Slab:",
            "SReclaimable:",
            "SUnreclaim:",
            "SwapTotal:",
            "SwapFree:",
            "ZRam:",
            "Mapped:",
            "VmallocUsed:",
            "PageTables:",
            "KernelStack:",
            NULL
    };
    static const int tagsLen[] = {
            9,
            8,
            8,
            7,
            6,
            5,
            13,
            11,
            10,
            9,
            5,
            7,
            12,
            11,
            12,
            0
    };
    long mem[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

    char* p = buffer;
    while (*p && numFound < (sizeof(tagsLen) / sizeof(tagsLen[0]))) {
        int i = 0;
        while (tags[i]) {
            if (strncmp(p, tags[i], tagsLen[i]) == 0) {
                p += tagsLen[i];
                while (*p == ' ') p++;
                char* num = p;
                while (*p >= '0' && *p <= '9') p++;
                if (*p != 0) {
                    *p = 0;
                    p++;
                }
                mem[i] = atoll(num);
                numFound++;
                break;
            }
            i++;
        }
        while (*p && *p != '\n') {
            p++;
        }
        if (*p) p++;
    }

    mem[MEMINFO_ZRAM_TOTAL] = get_zram_mem_used() / 1024;
    // Recompute Vmalloc Used since the value in meminfo
    // doesn't account for I/O remapping which doesn't use RAM.
    mem[MEMINFO_VMALLOC_USED] = get_allocated_vmalloc_memory() / 1024;

    int maxNum = env->GetArrayLength(out);
    if (maxNum > MEMINFO_COUNT) {
        maxNum = MEMINFO_COUNT;
    }
    jlong* outArray = env->GetLongArrayElements(out, 0);
    if (outArray != NULL) {
        for (int i=0; i<maxNum; i++) {
        outLen = MEMINFO_COUNT;
        for (int i = 0; i < outLen; i++) {
            // TODO: move get_allocated_vmalloc_memory() to libmeminfo
            if (i == MEMINFO_VMALLOC_USED) {
                outArray[i] = get_allocated_vmalloc_memory() / 1024;
                continue;
            }
            outArray[i] = mem[i];
        }
    }

    env->ReleaseLongArrayElements(out, outArray, 0);
}

+26 −52
Original line number Diff line number Diff line
@@ -25,8 +25,12 @@
#include <cutils/sched_policy.h>
#include <utils/String8.h>
#include <utils/Vector.h>
#include <meminfo/sysmeminfo.h>
#include <processgroup/processgroup.h>

#include <string>
#include <vector>

#include "core_jni_helpers.h"

#include "android_util_Binder.h"
@@ -39,9 +43,11 @@
#include <inttypes.h>
#include <pwd.h>
#include <signal.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>

@@ -603,66 +609,34 @@ static int pid_compare(const void* v1, const void* v2)
    return *((const jint*)v1) - *((const jint*)v2);
}

static jlong getFreeMemoryImpl(const char* const sums[], const size_t sumsLen[], size_t num)
static jlong android_os_Process_getFreeMemory(JNIEnv* env, jobject clazz)
{
    int fd = open("/proc/meminfo", O_RDONLY | O_CLOEXEC);

    if (fd < 0) {
        ALOGW("Unable to open /proc/meminfo");
        return -1;
    }

    char buffer[2048];
    const int len = read(fd, buffer, sizeof(buffer)-1);
    close(fd);

    if (len < 0) {
        ALOGW("Unable to read /proc/meminfo");
        return -1;
    }
    buffer[len] = 0;

    size_t numFound = 0;
    jlong mem = 0;
    static const std::vector<std::string> memFreeTags = {
        ::android::meminfo::SysMemInfo::kMemFree,
        ::android::meminfo::SysMemInfo::kMemCached,
    };
    std::vector<uint64_t> mem(memFreeTags.size());
    ::android::meminfo::SysMemInfo smi;

    char* p = buffer;
    while (*p && numFound < num) {
        int i = 0;
        while (sums[i]) {
            if (strncmp(p, sums[i], sumsLen[i]) == 0) {
                p += sumsLen[i];
                while (*p == ' ') p++;
                char* num = p;
                while (*p >= '0' && *p <= '9') p++;
                if (*p != 0) {
                    *p = 0;
                    p++;
                    if (*p == 0) p--;
                }
                mem += atoll(num) * 1024;
                numFound++;
                break;
            }
            i++;
        }
        p++;
    if (!smi.ReadMemInfo(memFreeTags, &mem)) {
        jniThrowRuntimeException(env, "SysMemInfo read failed to get Free Memory");
        return -1L;
    }

    return numFound > 0 ? mem : -1;
    jlong sum = 0;
    std::for_each(mem.begin(), mem.end(), [&](uint64_t val) { sum += val; });
    return sum * 1024;
}

static jlong android_os_Process_getFreeMemory(JNIEnv* env, jobject clazz)
static jlong android_os_Process_getTotalMemory(JNIEnv* env, jobject clazz)
{
    static const char* const sums[] = { "MemFree:", "Cached:", NULL };
    static const size_t sumsLen[] = { strlen("MemFree:"), strlen("Cached:"), 0 };
    return getFreeMemoryImpl(sums, sumsLen, 2);
    struct sysinfo si;
    if (sysinfo(&si) == -1) {
        ALOGE("sysinfo failed: %s", strerror(errno));
        return -1;
    }

static jlong android_os_Process_getTotalMemory(JNIEnv* env, jobject clazz)
{
    static const char* const sums[] = { "MemTotal:", NULL };
    static const size_t sumsLen[] = { strlen("MemTotal:"), 0 };
    return getFreeMemoryImpl(sums, sumsLen, 1);
    return si.totalram;
}

void android_os_Process_readProcLines(JNIEnv* env, jobject clazz, jstring fileStr,