1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.stats.pull; 18 19 import android.os.Debug; 20 21 /** 22 * Snapshots system-wide memory stats and computes unaccounted memory. 23 * Thread-safe. 24 */ 25 final class SystemMemoryUtil { SystemMemoryUtil()26 private SystemMemoryUtil() {} 27 getMetrics()28 static Metrics getMetrics() { 29 int totalIonKb = (int) Debug.getDmabufHeapTotalExportedKb(); 30 int gpuTotalUsageKb = (int) Debug.getGpuTotalUsageKb(); 31 int gpuPrivateAllocationsKb = (int) Debug.getGpuPrivateMemoryKb(); 32 int dmaBufTotalExportedKb = (int) Debug.getDmabufTotalExportedKb(); 33 34 long[] mInfos = new long[Debug.MEMINFO_COUNT]; 35 Debug.getMemInfo(mInfos); 36 37 long kReclaimableKb = mInfos[Debug.MEMINFO_KRECLAIMABLE]; 38 // Note: MEMINFO_KRECLAIMABLE includes MEMINFO_SLAB_RECLAIMABLE and ION pools. 39 // Fall back to using MEMINFO_SLAB_RECLAIMABLE in case of older kernels that do 40 // not include KReclaimable meminfo field. 41 if (kReclaimableKb == 0) { 42 kReclaimableKb = mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE]; 43 } 44 45 long accountedKb = mInfos[Debug.MEMINFO_FREE] 46 + mInfos[Debug.MEMINFO_ZRAM_TOTAL] 47 + mInfos[Debug.MEMINFO_BUFFERS] 48 + mInfos[Debug.MEMINFO_ACTIVE] 49 + mInfos[Debug.MEMINFO_INACTIVE] 50 + mInfos[Debug.MEMINFO_UNEVICTABLE] 51 + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE] 52 + kReclaimableKb 53 + mInfos[Debug.MEMINFO_VM_ALLOC_USED] 54 + mInfos[Debug.MEMINFO_PAGE_TABLES]; 55 56 if (!Debug.isVmapStack()) { 57 // See b/146088882 58 accountedKb += mInfos[Debug.MEMINFO_KERNEL_STACK]; 59 } 60 61 // If we can distinguish gpu private allocs it means the dmabuf metrics 62 // are supported already. 63 if (dmaBufTotalExportedKb >= 0 && gpuPrivateAllocationsKb >= 0) { 64 // If we can calculate the overlap between dma memory and gpu 65 // drivers we can do more accurate tracking. But this is only 66 // available on 5.4+ kernels. 67 accountedKb += dmaBufTotalExportedKb + gpuPrivateAllocationsKb; 68 } else { 69 // If we cannot distinguish, accept that we will double count the 70 // dma buffers also used by the gpu driver. 71 accountedKb += Math.max(0, gpuTotalUsageKb); 72 if (dmaBufTotalExportedKb >= 0) { 73 accountedKb += dmaBufTotalExportedKb; 74 } else if (totalIonKb >= 0) { 75 // ION is a subset of total exported dmabuf memory. 76 accountedKb += totalIonKb; 77 } 78 } 79 80 Metrics result = new Metrics(); 81 result.unreclaimableSlabKb = (int) mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]; 82 result.vmallocUsedKb = (int) mInfos[Debug.MEMINFO_VM_ALLOC_USED]; 83 result.pageTablesKb = (int) mInfos[Debug.MEMINFO_PAGE_TABLES]; 84 result.kernelStackKb = (int) mInfos[Debug.MEMINFO_KERNEL_STACK]; 85 result.shmemKb = (int) mInfos[Debug.MEMINFO_SHMEM]; 86 result.totalKb = (int) mInfos[Debug.MEMINFO_TOTAL]; 87 result.freeKb = (int) mInfos[Debug.MEMINFO_FREE]; 88 result.availableKb = (int) mInfos[Debug.MEMINFO_AVAILABLE]; 89 result.activeKb = (int) mInfos[Debug.MEMINFO_ACTIVE]; 90 result.inactiveKb = (int) mInfos[Debug.MEMINFO_INACTIVE]; 91 result.activeAnonKb = (int) mInfos[Debug.MEMINFO_ACTIVE_ANON]; 92 result.inactiveAnonKb = (int) mInfos[Debug.MEMINFO_INACTIVE_ANON]; 93 result.activeFileKb = (int) mInfos[Debug.MEMINFO_ACTIVE_FILE]; 94 result.inactiveFileKb = (int) mInfos[Debug.MEMINFO_INACTIVE_FILE]; 95 result.swapTotalKb = (int) mInfos[Debug.MEMINFO_SWAP_TOTAL]; 96 result.swapFreeKb = (int) mInfos[Debug.MEMINFO_SWAP_FREE]; 97 result.cmaTotalKb = (int) mInfos[Debug.MEMINFO_CMA_TOTAL]; 98 result.cmaFreeKb = (int) mInfos[Debug.MEMINFO_CMA_FREE]; 99 result.totalIonKb = totalIonKb; 100 result.gpuTotalUsageKb = gpuTotalUsageKb; 101 result.gpuPrivateAllocationsKb = gpuPrivateAllocationsKb; 102 result.dmaBufTotalExportedKb = dmaBufTotalExportedKb; 103 result.unaccountedKb = (int) (mInfos[Debug.MEMINFO_TOTAL] - accountedKb); 104 return result; 105 } 106 107 static final class Metrics { 108 public int unreclaimableSlabKb; 109 public int vmallocUsedKb; 110 public int pageTablesKb; 111 public int kernelStackKb; 112 public int shmemKb; 113 public int totalKb; 114 public int freeKb; 115 public int availableKb; 116 public int activeKb; 117 public int inactiveKb; 118 public int activeAnonKb; 119 public int inactiveAnonKb; 120 public int activeFileKb; 121 public int inactiveFileKb; 122 public int swapTotalKb; 123 public int swapFreeKb; 124 public int cmaTotalKb; 125 public int cmaFreeKb; 126 public int totalIonKb; 127 public int gpuTotalUsageKb; 128 public int gpuPrivateAllocationsKb; 129 public int dmaBufTotalExportedKb; 130 public int unaccountedKb; 131 } 132 } 133