Loading core/java/android/os/Debug.java +23 −0 Original line number Diff line number Diff line Loading @@ -2503,4 +2503,27 @@ public final class Debug * @hide */ public static native long getZramFreeKb(); /** * Return memory size in kilobytes allocated for ION heaps. * * @hide */ public static native long getIonHeapsSizeKb(); /** * Return memory size in kilobytes allocated for ION pools. * * @hide */ public static native long getIonPoolsSizeKb(); /** * Return ION memory mapped by processes in kB. * Notes: * * Warning: Might impact performance as it reads /proc/<pid>/maps files for each process. * * @hide */ public static native long getIonMappedSizeKb(); } core/java/com/android/internal/util/MemInfoReader.java +9 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,15 @@ public final class MemInfoReader { * that are mapped in to processes. */ public long getCachedSizeKb() { return mInfos[Debug.MEMINFO_BUFFERS] + mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE] long kReclaimable = mInfos[Debug.MEMINFO_KRECLAIMABLE]; // Note: MEMINFO_KRECLAIMABLE includes MEMINFO_SLAB_RECLAIMABLE and ION pools. // Fall back to using MEMINFO_SLAB_RECLAIMABLE in case of older kernels that do // not include KReclaimable meminfo field. if (kReclaimable == 0) { kReclaimable = mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE]; } return mInfos[Debug.MEMINFO_BUFFERS] + kReclaimable + mInfos[Debug.MEMINFO_CACHED] - mInfos[Debug.MEMINFO_MAPPED]; } Loading core/jni/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -233,6 +233,7 @@ cc_library_shared { static_libs: [ "libasync_safe", "libdmabufinfo", "libgif", "libseccomp_policy", "libgrallocusage", Loading core/jni/android_os_Debug.cpp +60 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedUtfChars.h> #include "jni.h" #include <dmabufinfo/dmabufinfo.h> #include <meminfo/procmeminfo.h> #include <meminfo/sysmeminfo.h> #include <memtrack/memtrack.h> Loading Loading @@ -779,6 +780,59 @@ static jlong android_os_Debug_getFreeZramKb(JNIEnv* env, jobject clazz) { return zramFreeKb; } static jlong android_os_Debug_getIonHeapsSizeKb(JNIEnv* env, jobject clazz) { jlong heapsSizeKb = 0; uint64_t size; if (meminfo::ReadIonHeapsSizeKb(&size)) { heapsSizeKb = size; } return heapsSizeKb; } static jlong android_os_Debug_getIonPoolsSizeKb(JNIEnv* env, jobject clazz) { jlong poolsSizeKb = 0; uint64_t size; if (meminfo::ReadIonPoolsSizeKb(&size)) { poolsSizeKb = size; } return poolsSizeKb; } static jlong android_os_Debug_getIonMappedSizeKb(JNIEnv* env, jobject clazz) { jlong ionPss = 0; std::vector<dmabufinfo::DmaBuffer> dmabufs; std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir); if (!dir) { LOG(ERROR) << "Failed to open /proc directory"; return false; } struct dirent* dent; while ((dent = readdir(dir.get()))) { if (dent->d_type != DT_DIR) continue; int pid = atoi(dent->d_name); if (pid == 0) { continue; } if (!AppendDmaBufInfo(pid, &dmabufs, false)) { LOG(ERROR) << "Failed to read maps for pid " << pid; } } for (dmabufinfo::DmaBuffer buf : dmabufs) { ionPss += buf.size() / 1024; } return ionPss; } /* * JNI registration. */ Loading Loading @@ -822,6 +876,12 @@ static const JNINativeMethod gMethods[] = { (void*)android_os_Debug_getUnreachableMemory }, { "getZramFreeKb", "()J", (void*)android_os_Debug_getFreeZramKb }, { "getIonHeapsSizeKb", "()J", (void*)android_os_Debug_getIonHeapsSizeKb }, { "getIonPoolsSizeKb", "()J", (void*)android_os_Debug_getIonPoolsSizeKb }, { "getIonMappedSizeKb", "()J", (void*)android_os_Debug_getIonMappedSizeKb }, }; int register_android_os_Debug(JNIEnv *env) Loading services/core/java/com/android/server/am/ActivityManagerService.java +34 −6 Original line number Diff line number Diff line Loading @@ -12799,14 +12799,31 @@ public class ActivityManagerService extends IActivityManager.Stub pw.println(totalPss - cachedPss); } } long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) long kernelUsed = memInfo.getKernelUsedSizeKb(); final long ionHeap = Debug.getIonHeapsSizeKb(); if (ionHeap > 0) { final long ionMapped = Debug.getIonMappedSizeKb(); final long ionUnmapped = ionHeap - ionMapped; final long ionPool = Debug.getIonPoolsSizeKb(); pw.print(" ION: "); pw.print(stringifyKBSize(ionHeap + ionPool)); pw.print(" ("); pw.print(stringifyKBSize(ionMapped)); pw.print(" mapped + "); pw.print(stringifyKBSize(ionUnmapped)); pw.print(" unmapped + "); pw.print(stringifyKBSize(ionPool)); pw.println(" pools)"); kernelUsed += ionUnmapped; } final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb(); - kernelUsed - memInfo.getZramTotalSizeKb(); if (!opts.isCompact) { pw.print(" Used RAM: "); pw.print(stringifyKBSize(totalPss - cachedPss + memInfo.getKernelUsedSizeKb())); pw.print(" ("); + kernelUsed)); pw.print(" ("); pw.print(stringifyKBSize(totalPss - cachedPss)); pw.print(" used pss + "); pw.print(stringifyKBSize(memInfo.getKernelUsedSizeKb())); pw.print(" kernel)\n"); pw.print(stringifyKBSize(kernelUsed)); pw.print(" kernel)\n"); pw.print(" Lost RAM: "); pw.println(stringifyKBSize(lostRAM)); } else { pw.print("lostram,"); pw.println(lostRAM); Loading Loading @@ -13525,14 +13542,25 @@ public class ActivityManagerService extends IActivityManager.Stub memInfoBuilder.append(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb() + memInfo.getFreeSizeKb())); memInfoBuilder.append("\n"); long kernelUsed = memInfo.getKernelUsedSizeKb(); final long ionHeap = Debug.getIonHeapsSizeKb(); if (ionHeap > 0) { final long ionMapped = Debug.getIonMappedSizeKb(); final long ionUnmapped = ionHeap - ionMapped; final long ionPool = Debug.getIonPoolsSizeKb(); memInfoBuilder.append(" ION: "); memInfoBuilder.append(stringifyKBSize(ionHeap + ionPool)); memInfoBuilder.append("\n"); kernelUsed += ionUnmapped; } memInfoBuilder.append(" Used RAM: "); memInfoBuilder.append(stringifyKBSize( totalPss - cachedPss + memInfo.getKernelUsedSizeKb())); totalPss - cachedPss + kernelUsed)); memInfoBuilder.append("\n"); memInfoBuilder.append(" Lost RAM: "); memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb())); - kernelUsed - memInfo.getZramTotalSizeKb())); memInfoBuilder.append("\n"); Slog.i(TAG, "Low on memory:"); Slog.i(TAG, shortNativeBuilder.toString()); Loading
core/java/android/os/Debug.java +23 −0 Original line number Diff line number Diff line Loading @@ -2503,4 +2503,27 @@ public final class Debug * @hide */ public static native long getZramFreeKb(); /** * Return memory size in kilobytes allocated for ION heaps. * * @hide */ public static native long getIonHeapsSizeKb(); /** * Return memory size in kilobytes allocated for ION pools. * * @hide */ public static native long getIonPoolsSizeKb(); /** * Return ION memory mapped by processes in kB. * Notes: * * Warning: Might impact performance as it reads /proc/<pid>/maps files for each process. * * @hide */ public static native long getIonMappedSizeKb(); }
core/java/com/android/internal/util/MemInfoReader.java +9 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,15 @@ public final class MemInfoReader { * that are mapped in to processes. */ public long getCachedSizeKb() { return mInfos[Debug.MEMINFO_BUFFERS] + mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE] long kReclaimable = mInfos[Debug.MEMINFO_KRECLAIMABLE]; // Note: MEMINFO_KRECLAIMABLE includes MEMINFO_SLAB_RECLAIMABLE and ION pools. // Fall back to using MEMINFO_SLAB_RECLAIMABLE in case of older kernels that do // not include KReclaimable meminfo field. if (kReclaimable == 0) { kReclaimable = mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE]; } return mInfos[Debug.MEMINFO_BUFFERS] + kReclaimable + mInfos[Debug.MEMINFO_CACHED] - mInfos[Debug.MEMINFO_MAPPED]; } Loading
core/jni/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -233,6 +233,7 @@ cc_library_shared { static_libs: [ "libasync_safe", "libdmabufinfo", "libgif", "libseccomp_policy", "libgrallocusage", Loading
core/jni/android_os_Debug.cpp +60 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedUtfChars.h> #include "jni.h" #include <dmabufinfo/dmabufinfo.h> #include <meminfo/procmeminfo.h> #include <meminfo/sysmeminfo.h> #include <memtrack/memtrack.h> Loading Loading @@ -779,6 +780,59 @@ static jlong android_os_Debug_getFreeZramKb(JNIEnv* env, jobject clazz) { return zramFreeKb; } static jlong android_os_Debug_getIonHeapsSizeKb(JNIEnv* env, jobject clazz) { jlong heapsSizeKb = 0; uint64_t size; if (meminfo::ReadIonHeapsSizeKb(&size)) { heapsSizeKb = size; } return heapsSizeKb; } static jlong android_os_Debug_getIonPoolsSizeKb(JNIEnv* env, jobject clazz) { jlong poolsSizeKb = 0; uint64_t size; if (meminfo::ReadIonPoolsSizeKb(&size)) { poolsSizeKb = size; } return poolsSizeKb; } static jlong android_os_Debug_getIonMappedSizeKb(JNIEnv* env, jobject clazz) { jlong ionPss = 0; std::vector<dmabufinfo::DmaBuffer> dmabufs; std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir); if (!dir) { LOG(ERROR) << "Failed to open /proc directory"; return false; } struct dirent* dent; while ((dent = readdir(dir.get()))) { if (dent->d_type != DT_DIR) continue; int pid = atoi(dent->d_name); if (pid == 0) { continue; } if (!AppendDmaBufInfo(pid, &dmabufs, false)) { LOG(ERROR) << "Failed to read maps for pid " << pid; } } for (dmabufinfo::DmaBuffer buf : dmabufs) { ionPss += buf.size() / 1024; } return ionPss; } /* * JNI registration. */ Loading Loading @@ -822,6 +876,12 @@ static const JNINativeMethod gMethods[] = { (void*)android_os_Debug_getUnreachableMemory }, { "getZramFreeKb", "()J", (void*)android_os_Debug_getFreeZramKb }, { "getIonHeapsSizeKb", "()J", (void*)android_os_Debug_getIonHeapsSizeKb }, { "getIonPoolsSizeKb", "()J", (void*)android_os_Debug_getIonPoolsSizeKb }, { "getIonMappedSizeKb", "()J", (void*)android_os_Debug_getIonMappedSizeKb }, }; int register_android_os_Debug(JNIEnv *env) Loading
services/core/java/com/android/server/am/ActivityManagerService.java +34 −6 Original line number Diff line number Diff line Loading @@ -12799,14 +12799,31 @@ public class ActivityManagerService extends IActivityManager.Stub pw.println(totalPss - cachedPss); } } long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) long kernelUsed = memInfo.getKernelUsedSizeKb(); final long ionHeap = Debug.getIonHeapsSizeKb(); if (ionHeap > 0) { final long ionMapped = Debug.getIonMappedSizeKb(); final long ionUnmapped = ionHeap - ionMapped; final long ionPool = Debug.getIonPoolsSizeKb(); pw.print(" ION: "); pw.print(stringifyKBSize(ionHeap + ionPool)); pw.print(" ("); pw.print(stringifyKBSize(ionMapped)); pw.print(" mapped + "); pw.print(stringifyKBSize(ionUnmapped)); pw.print(" unmapped + "); pw.print(stringifyKBSize(ionPool)); pw.println(" pools)"); kernelUsed += ionUnmapped; } final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb(); - kernelUsed - memInfo.getZramTotalSizeKb(); if (!opts.isCompact) { pw.print(" Used RAM: "); pw.print(stringifyKBSize(totalPss - cachedPss + memInfo.getKernelUsedSizeKb())); pw.print(" ("); + kernelUsed)); pw.print(" ("); pw.print(stringifyKBSize(totalPss - cachedPss)); pw.print(" used pss + "); pw.print(stringifyKBSize(memInfo.getKernelUsedSizeKb())); pw.print(" kernel)\n"); pw.print(stringifyKBSize(kernelUsed)); pw.print(" kernel)\n"); pw.print(" Lost RAM: "); pw.println(stringifyKBSize(lostRAM)); } else { pw.print("lostram,"); pw.println(lostRAM); Loading Loading @@ -13525,14 +13542,25 @@ public class ActivityManagerService extends IActivityManager.Stub memInfoBuilder.append(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb() + memInfo.getFreeSizeKb())); memInfoBuilder.append("\n"); long kernelUsed = memInfo.getKernelUsedSizeKb(); final long ionHeap = Debug.getIonHeapsSizeKb(); if (ionHeap > 0) { final long ionMapped = Debug.getIonMappedSizeKb(); final long ionUnmapped = ionHeap - ionMapped; final long ionPool = Debug.getIonPoolsSizeKb(); memInfoBuilder.append(" ION: "); memInfoBuilder.append(stringifyKBSize(ionHeap + ionPool)); memInfoBuilder.append("\n"); kernelUsed += ionUnmapped; } memInfoBuilder.append(" Used RAM: "); memInfoBuilder.append(stringifyKBSize( totalPss - cachedPss + memInfo.getKernelUsedSizeKb())); totalPss - cachedPss + kernelUsed)); memInfoBuilder.append("\n"); memInfoBuilder.append(" Lost RAM: "); memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb() - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb())); - kernelUsed - memInfo.getZramTotalSizeKb())); memInfoBuilder.append("\n"); Slog.i(TAG, "Low on memory:"); Slog.i(TAG, shortNativeBuilder.toString());