blob: c1eacce1f304d56773d608164a371e358518cf5b [file] [log] [blame]
Rafal Slawik196532a2019-09-13 11:50:27 +01001/*
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 */
16package com.android.server.stats;
17
Ioannis Ilkos9035a222019-11-07 18:57:48 +000018import static android.os.Process.PROC_OUT_STRING;
19
Rafal Slawik21d3f512019-09-24 20:00:18 +010020import android.annotation.Nullable;
Ioannis Ilkos9035a222019-11-07 18:57:48 +000021import android.os.Process;
Rafal Slawik196532a2019-09-13 11:50:27 +010022
Ioannis Ilkos9035a222019-11-07 18:57:48 +000023import java.util.function.BiConsumer;
Rafal Slawik196532a2019-09-13 11:50:27 +010024
25final class ProcfsMemoryUtil {
Ioannis Ilkos9035a222019-11-07 18:57:48 +000026 private static final int[] CMDLINE_OUT = new int[] { PROC_OUT_STRING };
27 private static final String[] STATUS_KEYS = new String[] {
28 "Uid:",
29 "VmHWM:",
30 "VmRSS:",
31 "RssAnon:",
32 "VmSwap:"
33 };
Rafal Slawik196532a2019-09-13 11:50:27 +010034
35 private ProcfsMemoryUtil() {}
36
37 /**
Rafal Slawik21d3f512019-09-24 20:00:18 +010038 * Reads memory stats of a process from procfs. Returns values of the VmHWM, VmRss, AnonRSS,
39 * VmSwap fields in /proc/pid/status in kilobytes or null if not available.
Rafal Slawik196532a2019-09-13 11:50:27 +010040 */
Rafal Slawik21d3f512019-09-24 20:00:18 +010041 @Nullable
Rafal Slawik7efcefb2019-09-20 11:16:20 +010042 static MemorySnapshot readMemorySnapshotFromProcfs(int pid) {
Ioannis Ilkos9035a222019-11-07 18:57:48 +000043 long[] output = new long[STATUS_KEYS.length];
44 output[0] = -1;
45 Process.readProcLines("/proc/" + pid + "/status", STATUS_KEYS, output);
46 if (output[0] == -1 || (output[3] == 0 && output[4] == 0)) {
47 // Could not open file or anon rss / swap are 0 indicating the process is in a zombie
48 // state.
Rafal Slawik21d3f512019-09-24 20:00:18 +010049 return null;
50 }
Ioannis Ilkos9035a222019-11-07 18:57:48 +000051 final MemorySnapshot snapshot = new MemorySnapshot();
52 snapshot.uid = (int) output[0];
53 snapshot.rssHighWaterMarkInKilobytes = (int) output[1];
54 snapshot.rssInKilobytes = (int) output[2];
55 snapshot.anonRssInKilobytes = (int) output[3];
56 snapshot.swapInKilobytes = (int) output[4];
57 return snapshot;
Rafal Slawik196532a2019-09-13 11:50:27 +010058 }
59
Rafal Slawik203c3db2019-09-25 19:53:01 +010060 /**
61 * Reads cmdline of a process from procfs.
62 *
63 * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
64 * if the file is not available.
65 */
Ioannis Ilkos9035a222019-11-07 18:57:48 +000066 static String readCmdlineFromProcfs(int pid) {
67 String[] cmdline = new String[1];
68 if (!Process.readProcFile("/proc/" + pid + "/cmdline", CMDLINE_OUT, cmdline, null, null)) {
Rafal Slawik196532a2019-09-13 11:50:27 +010069 return "";
70 }
Ioannis Ilkos9035a222019-11-07 18:57:48 +000071 return cmdline[0];
72 }
73
74 static void forEachPid(BiConsumer<Integer, String> func) {
75 int[] pids = new int[1024];
76 pids = Process.getPids("/proc", pids);
77 for (int pid : pids) {
78 if (pid < 0) {
79 return;
80 }
81 String cmdline = readCmdlineFromProcfs(pid);
82 if (cmdline.isEmpty()) {
83 continue;
84 }
85 func.accept(pid, cmdline);
86 }
Rafal Slawik196532a2019-09-13 11:50:27 +010087 }
Rafal Slawik7efcefb2019-09-20 11:16:20 +010088
Rafal Slawik7efcefb2019-09-20 11:16:20 +010089 static final class MemorySnapshot {
Rafal Slawik21d3f512019-09-24 20:00:18 +010090 public int uid;
91 public int rssHighWaterMarkInKilobytes;
Rafal Slawik7efcefb2019-09-20 11:16:20 +010092 public int rssInKilobytes;
93 public int anonRssInKilobytes;
94 public int swapInKilobytes;
Rafal Slawik7efcefb2019-09-20 11:16:20 +010095 }
Rafal Slawik196532a2019-09-13 11:50:27 +010096}