blob: 67677c6cf17e2dd1823e8c4db47138bf6642b5f3 [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 */
Tej Singh250e7aa2020-01-16 13:16:21 -080016package com.android.server.stats.pull;
Rafal Slawik196532a2019-09-13 11:50:27 +010017
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;
Ioannis Ilkos754eb072020-01-27 16:42:24 +000022import android.util.SparseArray;
Rafal Slawik196532a2019-09-13 11:50:27 +010023
Tej Singh250e7aa2020-01-16 13:16:21 -080024public final class ProcfsMemoryUtil {
Ioannis Ilkos9035a222019-11-07 18:57:48 +000025 private static final int[] CMDLINE_OUT = new int[] { PROC_OUT_STRING };
26 private static final String[] STATUS_KEYS = new String[] {
27 "Uid:",
28 "VmHWM:",
29 "VmRSS:",
30 "RssAnon:",
31 "VmSwap:"
32 };
Rafal Slawik196532a2019-09-13 11:50:27 +010033
34 private ProcfsMemoryUtil() {}
35
36 /**
Rafal Slawik21d3f512019-09-24 20:00:18 +010037 * Reads memory stats of a process from procfs. Returns values of the VmHWM, VmRss, AnonRSS,
38 * VmSwap fields in /proc/pid/status in kilobytes or null if not available.
Rafal Slawik196532a2019-09-13 11:50:27 +010039 */
Rafal Slawik21d3f512019-09-24 20:00:18 +010040 @Nullable
Tej Singh250e7aa2020-01-16 13:16:21 -080041 public static MemorySnapshot readMemorySnapshotFromProcfs(int pid) {
Ioannis Ilkos9035a222019-11-07 18:57:48 +000042 long[] output = new long[STATUS_KEYS.length];
43 output[0] = -1;
44 Process.readProcLines("/proc/" + pid + "/status", STATUS_KEYS, output);
45 if (output[0] == -1 || (output[3] == 0 && output[4] == 0)) {
46 // Could not open file or anon rss / swap are 0 indicating the process is in a zombie
47 // state.
Rafal Slawik21d3f512019-09-24 20:00:18 +010048 return null;
49 }
Ioannis Ilkos9035a222019-11-07 18:57:48 +000050 final MemorySnapshot snapshot = new MemorySnapshot();
51 snapshot.uid = (int) output[0];
52 snapshot.rssHighWaterMarkInKilobytes = (int) output[1];
53 snapshot.rssInKilobytes = (int) output[2];
54 snapshot.anonRssInKilobytes = (int) output[3];
55 snapshot.swapInKilobytes = (int) output[4];
56 return snapshot;
Rafal Slawik196532a2019-09-13 11:50:27 +010057 }
58
Rafal Slawik203c3db2019-09-25 19:53:01 +010059 /**
60 * Reads cmdline of a process from procfs.
61 *
62 * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
63 * if the file is not available.
64 */
Tej Singh250e7aa2020-01-16 13:16:21 -080065 public static String readCmdlineFromProcfs(int pid) {
Ioannis Ilkos9035a222019-11-07 18:57:48 +000066 String[] cmdline = new String[1];
67 if (!Process.readProcFile("/proc/" + pid + "/cmdline", CMDLINE_OUT, cmdline, null, null)) {
Rafal Slawik196532a2019-09-13 11:50:27 +010068 return "";
69 }
Ioannis Ilkos9035a222019-11-07 18:57:48 +000070 return cmdline[0];
71 }
72
Ioannis Ilkos754eb072020-01-27 16:42:24 +000073 /**
74 * Scans all /proc/pid/cmdline entries and returns a mapping between pid and cmdline.
75 */
76 public static SparseArray<String> getProcessCmdlines() {
Ioannis Ilkos9035a222019-11-07 18:57:48 +000077 int[] pids = new int[1024];
78 pids = Process.getPids("/proc", pids);
Ioannis Ilkos754eb072020-01-27 16:42:24 +000079
80 SparseArray<String> cmdlines = new SparseArray<>(pids.length);
Ioannis Ilkos9035a222019-11-07 18:57:48 +000081 for (int pid : pids) {
82 if (pid < 0) {
Ioannis Ilkos754eb072020-01-27 16:42:24 +000083 break;
Ioannis Ilkos9035a222019-11-07 18:57:48 +000084 }
85 String cmdline = readCmdlineFromProcfs(pid);
86 if (cmdline.isEmpty()) {
87 continue;
88 }
Ioannis Ilkos754eb072020-01-27 16:42:24 +000089 cmdlines.append(pid, cmdline);
Ioannis Ilkos9035a222019-11-07 18:57:48 +000090 }
Ioannis Ilkos754eb072020-01-27 16:42:24 +000091 return cmdlines;
Rafal Slawik196532a2019-09-13 11:50:27 +010092 }
Rafal Slawik7efcefb2019-09-20 11:16:20 +010093
Tej Singh250e7aa2020-01-16 13:16:21 -080094 public static final class MemorySnapshot {
Rafal Slawik21d3f512019-09-24 20:00:18 +010095 public int uid;
96 public int rssHighWaterMarkInKilobytes;
Rafal Slawik7efcefb2019-09-20 11:16:20 +010097 public int rssInKilobytes;
98 public int anonRssInKilobytes;
99 public int swapInKilobytes;
Rafal Slawik7efcefb2019-09-20 11:16:20 +0100100 }
Rafal Slawik196532a2019-09-13 11:50:27 +0100101}