• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package com.android.internal.os;
17 
18 import static android.os.Process.*;
19 
20 import android.annotation.Nullable;
21 import android.os.Process;
22 import android.util.SparseArray;
23 
24 public final class ProcfsMemoryUtil {
25     private static final int[] CMDLINE_OUT = new int[] { PROC_OUT_STRING };
26     private static final int[] OOM_SCORE_ADJ_OUT = new int[] { PROC_NEWLINE_TERM | PROC_OUT_LONG };
27     private static final String[] STATUS_KEYS = new String[] {
28             "Uid:",
29             "VmHWM:",
30             "VmRSS:",
31             "RssAnon:",
32             "RssShmem:",
33             "VmSwap:",
34     };
35     private static final String[] VMSTAT_KEYS = new String[] {
36             "oom_kill"
37     };
38 
ProcfsMemoryUtil()39     private ProcfsMemoryUtil() {}
40 
41     /**
42      * Reads memory stats of a process from procfs.
43      *
44      * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in
45      * /proc/pid/status in kilobytes or null if not available.
46      */
47     @Nullable
readMemorySnapshotFromProcfs(int pid)48     public static MemorySnapshot readMemorySnapshotFromProcfs(int pid) {
49         return readMemorySnapshotFromProcfs("/proc/" + pid + "/status");
50     }
51 
52     /**
53      * Reads memory stats of the current process from procfs.
54      *
55      * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in
56      * /proc/self/status in kilobytes or null if not available.
57      */
58     @Nullable
readMemorySnapshotFromProcfs()59     public static MemorySnapshot readMemorySnapshotFromProcfs() {
60         return readMemorySnapshotFromProcfs("/proc/self/status");
61     }
62 
readMemorySnapshotFromProcfs(String path)63     private static MemorySnapshot readMemorySnapshotFromProcfs(String path) {
64         long[] output = new long[STATUS_KEYS.length];
65         output[0] = -1;
66         output[3] = -1;
67         output[4] = -1;
68         output[5] = -1;
69         Process.readProcLines(path, STATUS_KEYS, output);
70         if (output[0] == -1 || output[3] == -1 || output[4] == -1 || output[5] == -1) {
71             // Could not open or parse file.
72             return null;
73         }
74         final MemorySnapshot snapshot = new MemorySnapshot();
75         snapshot.uid = (int) output[0];
76         snapshot.rssHighWaterMarkInKilobytes = (int) output[1];
77         snapshot.rssInKilobytes = (int) output[2];
78         snapshot.anonRssInKilobytes = (int) output[3];
79         snapshot.rssShmemKilobytes = (int) output[4];
80         snapshot.swapInKilobytes = (int) output[5];
81         return snapshot;
82     }
83 
84     /**
85      * Reads cmdline of a process from procfs.
86      *
87      * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
88      * if the file is not available.
89      */
readCmdlineFromProcfs(int pid)90     public static String readCmdlineFromProcfs(int pid) {
91         return readCmdlineFromProcfs("/proc/" + pid + "/cmdline");
92     }
93 
94     /**
95      * Reads cmdline of the current process from procfs.
96      *
97      * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
98      * if the file is not available.
99      */
readCmdlineFromProcfs()100     public static String readCmdlineFromProcfs() {
101         return readCmdlineFromProcfs("/proc/self/cmdline");
102     }
103 
readCmdlineFromProcfs(String path)104     private static String readCmdlineFromProcfs(String path) {
105         String[] cmdline = new String[1];
106         if (!Process.readProcFile(path, CMDLINE_OUT, cmdline, null, null)) {
107             return "";
108         }
109         return cmdline[0];
110     }
111 
112     /**
113      * Reads oom_score_adj of a process from procfs
114      *
115      * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails.
116      */
readOomScoreAdjFromProcfs(int pid)117     public static int readOomScoreAdjFromProcfs(int pid) {
118         return readOomScoreAdjFromProcfs("/proc/" + pid + "/oom_score_adj");
119     }
120 
121     /**
122      * Reads oom_score_adj of the current process from procfs
123      *
124      * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails.
125      */
readOomScoreAdjFromProcfs()126     public static int readOomScoreAdjFromProcfs() {
127         return readOomScoreAdjFromProcfs("/proc/self/oom_score_adj");
128     }
129 
readOomScoreAdjFromProcfs(String path)130     private static int readOomScoreAdjFromProcfs(String path) {
131         long[] oom_score_adj = new long[1];
132         if (Process.readProcFile(path, OOM_SCORE_ADJ_OUT, null, oom_score_adj, null)) {
133             return (int)oom_score_adj[0];
134         }
135         return 0;
136     }
137 
138     /**
139      * Scans all /proc/pid/cmdline entries and returns a mapping between pid and cmdline.
140      */
getProcessCmdlines()141     public static SparseArray<String> getProcessCmdlines() {
142         int[] pids = new int[1024];
143         pids = Process.getPids("/proc", pids);
144 
145         SparseArray<String> cmdlines = new SparseArray<>(pids.length);
146         for (int pid : pids) {
147             if (pid < 0) {
148                 break;
149             }
150             String cmdline = readCmdlineFromProcfs(pid);
151             if (cmdline.isEmpty()) {
152                 continue;
153             }
154             cmdlines.append(pid, cmdline);
155         }
156         return cmdlines;
157     }
158 
159     public static final class MemorySnapshot {
160         public int uid;
161         public int rssHighWaterMarkInKilobytes;
162         public int rssInKilobytes;
163         public int anonRssInKilobytes;
164         public int swapInKilobytes;
165         public int rssShmemKilobytes;
166     }
167 
168     /** Reads and parses selected entries of /proc/vmstat. */
169     @Nullable
readVmStat()170     public static VmStat readVmStat() {
171         long[] vmstat = new long[VMSTAT_KEYS.length];
172         vmstat[0] = -1;
173         Process.readProcLines("/proc/vmstat", VMSTAT_KEYS, vmstat);
174         if (vmstat[0] == -1) {
175             return null;
176         }
177         VmStat result = new VmStat();
178         result.oomKillCount = (int) vmstat[0];
179         return result;
180     }
181 
182     public static final class VmStat {
183         public int oomKillCount;
184     }
185 }
186