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