blob: f693ed1033f9f4a7ea8fa495ec37bf347e637d19 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
17package com.android.server;
18
19import static android.os.Process.*;
20
21import android.os.Process;
22import android.os.SystemClock;
Joe Onorato8a9b2202010-02-26 18:56:32 -080023import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
25import java.io.File;
26import java.io.FileInputStream;
27import java.io.PrintWriter;
28import java.io.StringWriter;
29import java.util.ArrayList;
30import java.util.Collections;
31import java.util.Comparator;
Amith Yamasanie43530a2009-08-21 13:11:37 -070032import java.util.StringTokenizer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033
34public class ProcessStats {
35 private static final String TAG = "ProcessStats";
36 private static final boolean DEBUG = false;
Joe Onorato43a17652011-04-06 19:22:23 -070037 private static final boolean localLOGV = DEBUG || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
39 private static final int[] PROCESS_STATS_FORMAT = new int[] {
40 PROC_SPACE_TERM,
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -070041 PROC_SPACE_TERM|PROC_PARENS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042 PROC_SPACE_TERM,
43 PROC_SPACE_TERM,
44 PROC_SPACE_TERM,
45 PROC_SPACE_TERM,
46 PROC_SPACE_TERM,
47 PROC_SPACE_TERM,
48 PROC_SPACE_TERM,
Dianne Hackborn151ceb92009-08-06 12:40:56 -070049 PROC_SPACE_TERM|PROC_OUT_LONG, // 9: minor faults
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050 PROC_SPACE_TERM,
Dianne Hackborn151ceb92009-08-06 12:40:56 -070051 PROC_SPACE_TERM|PROC_OUT_LONG, // 11: major faults
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 PROC_SPACE_TERM,
53 PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime
54 PROC_SPACE_TERM|PROC_OUT_LONG // 14: stime
55 };
56
Dianne Hackborn151ceb92009-08-06 12:40:56 -070057 static final int PROCESS_STAT_MINOR_FAULTS = 0;
58 static final int PROCESS_STAT_MAJOR_FAULTS = 1;
59 static final int PROCESS_STAT_UTIME = 2;
60 static final int PROCESS_STAT_STIME = 3;
61
Amith Yamasanieaeb6632009-06-03 15:16:10 -070062 /** Stores user time and system time in 100ths of a second. */
Dianne Hackborn151ceb92009-08-06 12:40:56 -070063 private final long[] mProcessStatsData = new long[4];
Amith Yamasanieaeb6632009-06-03 15:16:10 -070064 /** Stores user time and system time in 100ths of a second. */
Dianne Hackborn151ceb92009-08-06 12:40:56 -070065 private final long[] mSinglePidStatsData = new long[4];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066
67 private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
68 PROC_SPACE_TERM,
69 PROC_SPACE_TERM|PROC_PARENS|PROC_OUT_STRING, // 1: name
70 PROC_SPACE_TERM,
71 PROC_SPACE_TERM,
72 PROC_SPACE_TERM,
73 PROC_SPACE_TERM,
74 PROC_SPACE_TERM,
75 PROC_SPACE_TERM,
76 PROC_SPACE_TERM,
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -070077 PROC_SPACE_TERM|PROC_OUT_LONG, // 9: minor faults
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078 PROC_SPACE_TERM,
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -070079 PROC_SPACE_TERM|PROC_OUT_LONG, // 11: major faults
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 PROC_SPACE_TERM,
81 PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime
Dianne Hackborn287952c2010-09-22 22:34:31 -070082 PROC_SPACE_TERM|PROC_OUT_LONG, // 14: stime
83 PROC_SPACE_TERM,
84 PROC_SPACE_TERM,
85 PROC_SPACE_TERM,
86 PROC_SPACE_TERM,
87 PROC_SPACE_TERM,
88 PROC_SPACE_TERM,
89 PROC_SPACE_TERM|PROC_OUT_LONG, // 21: vsize
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 };
91
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -070092 static final int PROCESS_FULL_STAT_MINOR_FAULTS = 1;
93 static final int PROCESS_FULL_STAT_MAJOR_FAULTS = 2;
94 static final int PROCESS_FULL_STAT_UTIME = 3;
95 static final int PROCESS_FULL_STAT_STIME = 4;
Dianne Hackborn287952c2010-09-22 22:34:31 -070096 static final int PROCESS_FULL_STAT_VSIZE = 5;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -070097
Dianne Hackborn287952c2010-09-22 22:34:31 -070098 private final String[] mProcessFullStatsStringData = new String[6];
99 private final long[] mProcessFullStatsData = new long[6];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100
101 private static final int[] SYSTEM_CPU_FORMAT = new int[] {
102 PROC_SPACE_TERM|PROC_COMBINE,
103 PROC_SPACE_TERM|PROC_OUT_LONG, // 1: user time
104 PROC_SPACE_TERM|PROC_OUT_LONG, // 2: nice time
105 PROC_SPACE_TERM|PROC_OUT_LONG, // 3: sys time
106 PROC_SPACE_TERM|PROC_OUT_LONG, // 4: idle time
107 PROC_SPACE_TERM|PROC_OUT_LONG, // 5: iowait time
108 PROC_SPACE_TERM|PROC_OUT_LONG, // 6: irq time
109 PROC_SPACE_TERM|PROC_OUT_LONG // 7: softirq time
110 };
111
112 private final long[] mSystemCpuData = new long[7];
113
114 private static final int[] LOAD_AVERAGE_FORMAT = new int[] {
115 PROC_SPACE_TERM|PROC_OUT_FLOAT, // 0: 1 min
116 PROC_SPACE_TERM|PROC_OUT_FLOAT, // 1: 5 mins
117 PROC_SPACE_TERM|PROC_OUT_FLOAT // 2: 15 mins
118 };
119
120 private final float[] mLoadAverageData = new float[3];
121
122 private final boolean mIncludeThreads;
123
124 private float mLoad1 = 0;
125 private float mLoad5 = 0;
126 private float mLoad15 = 0;
127
128 private long mCurrentSampleTime;
129 private long mLastSampleTime;
130
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700131 private long mCurrentSampleRealTime;
132 private long mLastSampleRealTime;
133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 private long mBaseUserTime;
135 private long mBaseSystemTime;
136 private long mBaseIoWaitTime;
137 private long mBaseIrqTime;
138 private long mBaseSoftIrqTime;
139 private long mBaseIdleTime;
140 private int mRelUserTime;
141 private int mRelSystemTime;
142 private int mRelIoWaitTime;
143 private int mRelIrqTime;
144 private int mRelSoftIrqTime;
145 private int mRelIdleTime;
146
147 private int[] mCurPids;
148 private int[] mCurThreadPids;
149
150 private final ArrayList<Stats> mProcStats = new ArrayList<Stats>();
151 private final ArrayList<Stats> mWorkingProcs = new ArrayList<Stats>();
152 private boolean mWorkingProcsSorted;
153
154 private boolean mFirst = true;
155
156 private byte[] mBuffer = new byte[256];
Amith Yamasanie43530a2009-08-21 13:11:37 -0700157
158 /**
159 * The time in microseconds that the CPU has been running at each speed.
160 */
161 private long[] mCpuSpeedTimes;
162
163 /**
164 * The relative time in microseconds that the CPU has been running at each speed.
165 */
166 private long[] mRelCpuSpeedTimes;
167
168 /**
169 * The different speeds that the CPU can be running at.
170 */
171 private long[] mCpuSpeeds;
172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 public static class Stats {
174 public final int pid;
175 final String statFile;
176 final String cmdlineFile;
177 final String threadsDir;
178 final ArrayList<Stats> threadStats;
179 final ArrayList<Stats> workingThreads;
180
Dianne Hackborn287952c2010-09-22 22:34:31 -0700181 public boolean interesting;
182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 public String baseName;
184 public String name;
185 int nameWidth;
186
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700187 public long base_uptime;
188 public long rel_uptime;
189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 public long base_utime;
191 public long base_stime;
192 public int rel_utime;
193 public int rel_stime;
194
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700195 public long base_minfaults;
196 public long base_majfaults;
197 public int rel_minfaults;
198 public int rel_majfaults;
199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 public boolean active;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700201 public boolean working;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 public boolean added;
203 public boolean removed;
204
205 Stats(int _pid, int parentPid, boolean includeThreads) {
206 pid = _pid;
207 if (parentPid < 0) {
208 final File procDir = new File("/proc", Integer.toString(pid));
209 statFile = new File(procDir, "stat").toString();
210 cmdlineFile = new File(procDir, "cmdline").toString();
211 threadsDir = (new File(procDir, "task")).toString();
212 if (includeThreads) {
213 threadStats = new ArrayList<Stats>();
214 workingThreads = new ArrayList<Stats>();
215 } else {
216 threadStats = null;
217 workingThreads = null;
218 }
219 } else {
220 final File procDir = new File("/proc", Integer.toString(
221 parentPid));
222 final File taskDir = new File(
223 new File(procDir, "task"), Integer.toString(pid));
224 statFile = new File(taskDir, "stat").toString();
225 cmdlineFile = null;
226 threadsDir = null;
227 threadStats = null;
228 workingThreads = null;
229 }
230 }
231 }
232
233 private final static Comparator<Stats> sLoadComparator = new Comparator<Stats>() {
234 public final int
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700235 compare(Stats sta, Stats stb) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 int ta = sta.rel_utime + sta.rel_stime;
237 int tb = stb.rel_utime + stb.rel_stime;
238 if (ta != tb) {
239 return ta > tb ? -1 : 1;
240 }
241 if (sta.added != stb.added) {
242 return sta.added ? -1 : 1;
243 }
244 if (sta.removed != stb.removed) {
245 return sta.added ? -1 : 1;
246 }
247 return 0;
248 }
249 };
250
251
252 public ProcessStats(boolean includeThreads) {
253 mIncludeThreads = includeThreads;
254 }
255
256 public void onLoadChanged(float load1, float load5, float load15) {
257 }
258
259 public int onMeasureProcessName(String name) {
260 return 0;
261 }
262
263 public void init() {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700264 if (DEBUG) Slog.v(TAG, "Init: " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 mFirst = true;
266 update();
267 }
268
269 public void update() {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700270 if (DEBUG) Slog.v(TAG, "Update: " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 mLastSampleTime = mCurrentSampleTime;
272 mCurrentSampleTime = SystemClock.uptimeMillis();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700273 mLastSampleRealTime = mCurrentSampleRealTime;
274 mCurrentSampleRealTime = SystemClock.elapsedRealtime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275
276 final long[] sysCpu = mSystemCpuData;
277 if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT,
278 null, sysCpu, null)) {
279 // Total user time is user + nice time.
280 final long usertime = sysCpu[0]+sysCpu[1];
281 // Total system time is simply system time.
282 final long systemtime = sysCpu[2];
283 // Total idle time is simply idle time.
284 final long idletime = sysCpu[3];
285 // Total irq time is iowait + irq + softirq time.
286 final long iowaittime = sysCpu[4];
287 final long irqtime = sysCpu[5];
288 final long softirqtime = sysCpu[6];
289
290 mRelUserTime = (int)(usertime - mBaseUserTime);
291 mRelSystemTime = (int)(systemtime - mBaseSystemTime);
292 mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);
293 mRelIrqTime = (int)(irqtime - mBaseIrqTime);
294 mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
295 mRelIdleTime = (int)(idletime - mBaseIdleTime);
296
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700297 if (DEBUG) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800298 Slog.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 + " S:" + sysCpu[2] + " I:" + sysCpu[3]
300 + " W:" + sysCpu[4] + " Q:" + sysCpu[5]
301 + " O:" + sysCpu[6]);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800302 Slog.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);
304 }
305
306 mBaseUserTime = usertime;
307 mBaseSystemTime = systemtime;
308 mBaseIoWaitTime = iowaittime;
309 mBaseIrqTime = irqtime;
310 mBaseSoftIrqTime = softirqtime;
311 mBaseIdleTime = idletime;
312 }
313
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700314 mCurPids = collectStats("/proc", -1, mFirst, mCurPids, mProcStats);
315
316 final float[] loadAverages = mLoadAverageData;
317 if (Process.readProcFile("/proc/loadavg", LOAD_AVERAGE_FORMAT,
318 null, null, loadAverages)) {
319 float load1 = loadAverages[0];
320 float load5 = loadAverages[1];
321 float load15 = loadAverages[2];
322 if (load1 != mLoad1 || load5 != mLoad5 || load15 != mLoad15) {
323 mLoad1 = load1;
324 mLoad5 = load5;
325 mLoad15 = load15;
326 onLoadChanged(load1, load5, load15);
327 }
328 }
329
330 if (DEBUG) Slog.i(TAG, "*** TIME TO COLLECT STATS: "
331 + (SystemClock.uptimeMillis()-mCurrentSampleTime));
332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 mWorkingProcsSorted = false;
334 mFirst = false;
335 }
336
337 private int[] collectStats(String statsFile, int parentPid, boolean first,
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700338 int[] curPids, ArrayList<Stats> allProcs) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 int[] pids = Process.getPids(statsFile, curPids);
341 int NP = (pids == null) ? 0 : pids.length;
342 int NS = allProcs.size();
343 int curStatsIndex = 0;
344 for (int i=0; i<NP; i++) {
345 int pid = pids[i];
346 if (pid < 0) {
347 NP = pid;
348 break;
349 }
350 Stats st = curStatsIndex < NS ? allProcs.get(curStatsIndex) : null;
351
352 if (st != null && st.pid == pid) {
353 // Update an existing process...
354 st.added = false;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700355 st.working = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 curStatsIndex++;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700357 if (DEBUG) Slog.v(TAG, "Existing "
358 + (parentPid < 0 ? "process" : "thread")
359 + " pid " + pid + ": " + st);
360
Dianne Hackborn287952c2010-09-22 22:34:31 -0700361 if (st.interesting) {
362 final long uptime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
Dianne Hackborn287952c2010-09-22 22:34:31 -0700364 final long[] procStats = mProcessStatsData;
365 if (!Process.readProcFile(st.statFile.toString(),
366 PROCESS_STATS_FORMAT, null, procStats, null)) {
367 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369
Dianne Hackborn287952c2010-09-22 22:34:31 -0700370 final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS];
371 final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS];
372 final long utime = procStats[PROCESS_STAT_UTIME];
373 final long stime = procStats[PROCESS_STAT_STIME];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374
Dianne Hackborn287952c2010-09-22 22:34:31 -0700375 if (utime == st.base_utime && stime == st.base_stime) {
376 st.rel_utime = 0;
377 st.rel_stime = 0;
378 st.rel_minfaults = 0;
379 st.rel_majfaults = 0;
380 if (st.active) {
381 st.active = false;
382 }
383 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 }
Dianne Hackborn287952c2010-09-22 22:34:31 -0700385
386 if (!st.active) {
387 st.active = true;
388 }
389
390 if (parentPid < 0) {
391 getName(st, st.cmdlineFile);
392 if (st.threadStats != null) {
393 mCurThreadPids = collectStats(st.threadsDir, pid, false,
394 mCurThreadPids, st.threadStats);
395 }
396 }
397
398 if (DEBUG) Slog.v("Load", "Stats changed " + st.name + " pid=" + st.pid
399 + " utime=" + utime + "-" + st.base_utime
400 + " stime=" + stime + "-" + st.base_stime
401 + " minfaults=" + minfaults + "-" + st.base_minfaults
402 + " majfaults=" + majfaults + "-" + st.base_majfaults);
403
404 st.rel_uptime = uptime - st.base_uptime;
405 st.base_uptime = uptime;
406 st.rel_utime = (int)(utime - st.base_utime);
407 st.rel_stime = (int)(stime - st.base_stime);
408 st.base_utime = utime;
409 st.base_stime = stime;
410 st.rel_minfaults = (int)(minfaults - st.base_minfaults);
411 st.rel_majfaults = (int)(majfaults - st.base_majfaults);
412 st.base_minfaults = minfaults;
413 st.base_majfaults = majfaults;
414 st.working = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 }
416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 continue;
418 }
419
420 if (st == null || st.pid > pid) {
421 // We have a new process!
422 st = new Stats(pid, parentPid, mIncludeThreads);
423 allProcs.add(curStatsIndex, st);
424 curStatsIndex++;
425 NS++;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700426 if (DEBUG) Slog.v(TAG, "New "
427 + (parentPid < 0 ? "process" : "thread")
428 + " pid " + pid + ": " + st);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429
430 final String[] procStatsString = mProcessFullStatsStringData;
431 final long[] procStats = mProcessFullStatsData;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700432 st.base_uptime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 if (Process.readProcFile(st.statFile.toString(),
434 PROCESS_FULL_STATS_FORMAT, procStatsString,
435 procStats, null)) {
Dianne Hackborn287952c2010-09-22 22:34:31 -0700436 // This is a possible way to filter out processes that
437 // are actually kernel threads... do we want to? Some
438 // of them do use CPU, but there can be a *lot* that are
439 // not doing anything.
440 if (true || procStats[PROCESS_FULL_STAT_VSIZE] != 0) {
441 st.interesting = true;
442 st.baseName = procStatsString[0];
443 st.base_minfaults = procStats[PROCESS_FULL_STAT_MINOR_FAULTS];
444 st.base_majfaults = procStats[PROCESS_FULL_STAT_MAJOR_FAULTS];
445 st.base_utime = procStats[PROCESS_FULL_STAT_UTIME];
446 st.base_stime = procStats[PROCESS_FULL_STAT_STIME];
447 } else {
448 Slog.i(TAG, "Skipping kernel process pid " + pid
449 + " name " + procStatsString[0]);
450 st.baseName = procStatsString[0];
451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 } else {
Dianne Hackborn287952c2010-09-22 22:34:31 -0700453 Slog.w(TAG, "Skipping unknown process pid " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 st.baseName = "<unknown>";
455 st.base_utime = st.base_stime = 0;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700456 st.base_minfaults = st.base_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
458
459 if (parentPid < 0) {
460 getName(st, st.cmdlineFile);
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700461 if (st.threadStats != null) {
462 mCurThreadPids = collectStats(st.threadsDir, pid, true,
463 mCurThreadPids, st.threadStats);
464 }
Dianne Hackborn287952c2010-09-22 22:34:31 -0700465 } else if (st.interesting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 st.name = st.baseName;
467 st.nameWidth = onMeasureProcessName(st.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700469
470 if (DEBUG) Slog.v("Load", "Stats added " + st.name + " pid=" + st.pid
471 + " utime=" + st.base_utime + " stime=" + st.base_stime
472 + " minfaults=" + st.base_minfaults + " majfaults=" + st.base_majfaults);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 st.rel_utime = 0;
475 st.rel_stime = 0;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700476 st.rel_minfaults = 0;
477 st.rel_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 st.added = true;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700479 if (!first && st.interesting) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700480 st.working = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 }
482 continue;
483 }
484
485 // This process has gone away!
486 st.rel_utime = 0;
487 st.rel_stime = 0;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700488 st.rel_minfaults = 0;
489 st.rel_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 st.removed = true;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700491 st.working = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 allProcs.remove(curStatsIndex);
493 NS--;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700494 if (DEBUG) Slog.v(TAG, "Removed "
495 + (parentPid < 0 ? "process" : "thread")
496 + " pid " + pid + ": " + st);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 // Decrement the loop counter so that we process the current pid
498 // again the next time through the loop.
499 i--;
500 continue;
501 }
502
503 while (curStatsIndex < NS) {
504 // This process has gone away!
505 final Stats st = allProcs.get(curStatsIndex);
506 st.rel_utime = 0;
507 st.rel_stime = 0;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700508 st.rel_minfaults = 0;
509 st.rel_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 st.removed = true;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700511 st.working = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 allProcs.remove(curStatsIndex);
513 NS--;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800514 if (localLOGV) Slog.v(TAG, "Removed pid " + st.pid + ": " + st);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 }
516
517 return pids;
518 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -0700519
520 public long getCpuTimeForPid(int pid) {
521 final String statFile = "/proc/" + pid + "/stat";
522 final long[] statsData = mSinglePidStatsData;
523 if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
524 null, statsData, null)) {
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700525 long time = statsData[PROCESS_STAT_UTIME]
526 + statsData[PROCESS_STAT_STIME];
Amith Yamasanieaeb6632009-06-03 15:16:10 -0700527 return time;
528 }
529 return 0;
530 }
531
Amith Yamasanie43530a2009-08-21 13:11:37 -0700532 /**
533 * Returns the times spent at each CPU speed, since the last call to this method. If this
534 * is the first time, it will return 1 for each value.
535 * @return relative times spent at different speed steps.
536 */
537 public long[] getLastCpuSpeedTimes() {
538 if (mCpuSpeedTimes == null) {
539 mCpuSpeedTimes = getCpuSpeedTimes(null);
540 mRelCpuSpeedTimes = new long[mCpuSpeedTimes.length];
541 for (int i = 0; i < mCpuSpeedTimes.length; i++) {
542 mRelCpuSpeedTimes[i] = 1; // Initialize
543 }
544 } else {
545 getCpuSpeedTimes(mRelCpuSpeedTimes);
546 for (int i = 0; i < mCpuSpeedTimes.length; i++) {
547 long temp = mRelCpuSpeedTimes[i];
548 mRelCpuSpeedTimes[i] -= mCpuSpeedTimes[i];
549 mCpuSpeedTimes[i] = temp;
550 }
551 }
552 return mRelCpuSpeedTimes;
553 }
554
555 private long[] getCpuSpeedTimes(long[] out) {
556 long[] tempTimes = out;
557 long[] tempSpeeds = mCpuSpeeds;
558 final int MAX_SPEEDS = 20;
559 if (out == null) {
560 tempTimes = new long[MAX_SPEEDS]; // Hopefully no more than that
561 tempSpeeds = new long[MAX_SPEEDS];
562 }
563 int speed = 0;
564 String file = readFile("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state", '\0');
Brad Fitzpatrick2eb239f2009-09-21 15:30:21 +0400565 // Note: file may be null on kernels without cpufreq (i.e. the emulator's)
566 if (file != null) {
567 StringTokenizer st = new StringTokenizer(file, "\n ");
568 while (st.hasMoreElements()) {
569 String token = st.nextToken();
570 try {
571 long val = Long.parseLong(token);
572 tempSpeeds[speed] = val;
573 token = st.nextToken();
574 val = Long.parseLong(token);
575 tempTimes[speed] = val;
576 speed++;
577 if (speed == MAX_SPEEDS) break; // No more
578 if (localLOGV && out == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800579 Slog.v(TAG, "First time : Speed/Time = " + tempSpeeds[speed - 1]
Brad Fitzpatrick2eb239f2009-09-21 15:30:21 +0400580 + "\t" + tempTimes[speed - 1]);
581 }
582 } catch (NumberFormatException nfe) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800583 Slog.i(TAG, "Unable to parse time_in_state");
Amith Yamasanie43530a2009-08-21 13:11:37 -0700584 }
Amith Yamasanie43530a2009-08-21 13:11:37 -0700585 }
586 }
587 if (out == null) {
588 out = new long[speed];
589 mCpuSpeeds = new long[speed];
590 System.arraycopy(tempSpeeds, 0, mCpuSpeeds, 0, speed);
591 System.arraycopy(tempTimes, 0, out, 0, speed);
592 }
593 return out;
594 }
595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 final public int getLastUserTime() {
597 return mRelUserTime;
598 }
599
600 final public int getLastSystemTime() {
601 return mRelSystemTime;
602 }
603
604 final public int getLastIoWaitTime() {
605 return mRelIoWaitTime;
606 }
607
608 final public int getLastIrqTime() {
609 return mRelIrqTime;
610 }
611
612 final public int getLastSoftIrqTime() {
613 return mRelSoftIrqTime;
614 }
615
616 final public int getLastIdleTime() {
617 return mRelIdleTime;
618 }
619
620 final public float getTotalCpuPercent() {
621 return ((float)(mRelUserTime+mRelSystemTime+mRelIrqTime)*100)
622 / (mRelUserTime+mRelSystemTime+mRelIrqTime+mRelIdleTime);
623 }
624
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700625 final void buildWorkingProcs() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 if (!mWorkingProcsSorted) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700627 mWorkingProcs.clear();
628 final int N = mProcStats.size();
629 for (int i=0; i<N; i++) {
630 Stats stats = mProcStats.get(i);
631 if (stats.working) {
632 mWorkingProcs.add(stats);
633 if (stats.threadStats != null && stats.threadStats.size() > 1) {
634 stats.workingThreads.clear();
635 final int M = stats.threadStats.size();
636 for (int j=0; j<M; j++) {
637 Stats tstats = stats.threadStats.get(j);
638 if (tstats.working) {
639 stats.workingThreads.add(tstats);
640 }
641 }
642 Collections.sort(stats.workingThreads, sLoadComparator);
643 }
644 }
645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 Collections.sort(mWorkingProcs, sLoadComparator);
647 mWorkingProcsSorted = true;
648 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700649 }
650
Dianne Hackborn287952c2010-09-22 22:34:31 -0700651 final public int countStats() {
652 return mProcStats.size();
653 }
654
655 final public Stats getStats(int index) {
656 return mProcStats.get(index);
657 }
658
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700659 final public int countWorkingStats() {
660 buildWorkingProcs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 return mWorkingProcs.size();
662 }
663
664 final public Stats getWorkingStats(int index) {
665 return mWorkingProcs.get(index);
666 }
667
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700668 final public String printCurrentLoad() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 StringWriter sw = new StringWriter();
670 PrintWriter pw = new PrintWriter(sw);
671 pw.print("Load: ");
672 pw.print(mLoad1);
673 pw.print(" / ");
674 pw.print(mLoad5);
675 pw.print(" / ");
676 pw.println(mLoad15);
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700677 return sw.toString();
678 }
679
680 final public String printCurrentState(long now) {
681 buildWorkingProcs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700683 StringWriter sw = new StringWriter();
684 PrintWriter pw = new PrintWriter(sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685
686 pw.print("CPU usage from ");
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700687 if (now > mLastSampleTime) {
688 pw.print(now-mLastSampleTime);
689 pw.print("ms to ");
690 pw.print(now-mCurrentSampleTime);
691 pw.print("ms ago");
692 } else {
693 pw.print(mLastSampleTime-now);
694 pw.print("ms to ");
695 pw.print(mCurrentSampleTime-now);
696 pw.print("ms later");
697 }
698
699 long sampleTime = mCurrentSampleTime - mLastSampleTime;
700 long sampleRealTime = mCurrentSampleRealTime - mLastSampleRealTime;
701 long percAwake = (sampleTime*100) / sampleRealTime;
702 if (percAwake != 100) {
703 pw.print(" with ");
704 pw.print(percAwake);
705 pw.print("% awake");
706 }
707 pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700709 final int totalTime = mRelUserTime + mRelSystemTime + mRelIoWaitTime
710 + mRelIrqTime + mRelSoftIrqTime + mRelIdleTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700712 if (DEBUG) Slog.i(TAG, "totalTime " + totalTime + " over sample time "
713 + (mCurrentSampleTime-mLastSampleTime));
714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 int N = mWorkingProcs.size();
716 for (int i=0; i<N; i++) {
717 Stats st = mWorkingProcs.get(i);
718 printProcessCPU(pw, st.added ? " +" : (st.removed ? " -": " "),
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700719 st.pid, st.name, (int)(st.rel_uptime+5)/10,
720 st.rel_utime, st.rel_stime, 0, 0, 0, st.rel_minfaults, st.rel_majfaults);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 if (!st.removed && st.workingThreads != null) {
722 int M = st.workingThreads.size();
723 for (int j=0; j<M; j++) {
724 Stats tst = st.workingThreads.get(j);
725 printProcessCPU(pw,
726 tst.added ? " +" : (tst.removed ? " -": " "),
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700727 tst.pid, tst.name, (int)(st.rel_uptime+5)/10,
728 tst.rel_utime, tst.rel_stime, 0, 0, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 }
730 }
731 }
732
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700733 printProcessCPU(pw, "", -1, "TOTAL", totalTime, mRelUserTime, mRelSystemTime,
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700734 mRelIoWaitTime, mRelIrqTime, mRelSoftIrqTime, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735
736 return sw.toString();
737 }
738
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700739 private void printRatio(PrintWriter pw, long numerator, long denominator) {
740 long thousands = (numerator*1000)/denominator;
741 long hundreds = thousands/10;
742 pw.print(hundreds);
743 if (hundreds < 10) {
744 long remainder = thousands - (hundreds*10);
745 if (remainder != 0) {
746 pw.print('.');
747 pw.print(remainder);
748 }
749 }
750 }
751
752 private void printProcessCPU(PrintWriter pw, String prefix, int pid, String label,
753 int totalTime, int user, int system, int iowait, int irq, int softIrq,
754 int minFaults, int majFaults) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 pw.print(prefix);
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700756 if (totalTime == 0) totalTime = 1;
757 printRatio(pw, user+system+iowait+irq+softIrq, totalTime);
758 pw.print("% ");
759 if (pid >= 0) {
760 pw.print(pid);
761 pw.print("/");
762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 pw.print(label);
764 pw.print(": ");
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700765 printRatio(pw, user, totalTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 pw.print("% user + ");
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700767 printRatio(pw, system, totalTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 pw.print("% kernel");
769 if (iowait > 0) {
770 pw.print(" + ");
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700771 printRatio(pw, iowait, totalTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 pw.print("% iowait");
773 }
774 if (irq > 0) {
775 pw.print(" + ");
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700776 printRatio(pw, irq, totalTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 pw.print("% irq");
778 }
779 if (softIrq > 0) {
780 pw.print(" + ");
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700781 printRatio(pw, softIrq, totalTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 pw.print("% softirq");
783 }
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700784 if (minFaults > 0 || majFaults > 0) {
785 pw.print(" / faults:");
786 if (minFaults > 0) {
787 pw.print(" ");
788 pw.print(minFaults);
789 pw.print(" minor");
790 }
791 if (majFaults > 0) {
792 pw.print(" ");
793 pw.print(majFaults);
794 pw.print(" major");
795 }
796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 pw.println();
798 }
799
800 private String readFile(String file, char endChar) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -0800801 FileInputStream is = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 try {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -0800803 is = new FileInputStream(file);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 int len = is.read(mBuffer);
805 is.close();
806
807 if (len > 0) {
808 int i;
809 for (i=0; i<len; i++) {
810 if (mBuffer[i] == endChar) {
811 break;
812 }
813 }
Christian Mehlmauer4136c982010-05-25 20:04:09 +0200814 return new String(mBuffer, 0, i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 }
816 } catch (java.io.FileNotFoundException e) {
817 } catch (java.io.IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -0800818 } finally {
819 if (is != null) {
820 try {
821 is.close();
822 } catch (java.io.IOException e) {
823 }
824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 }
826 return null;
827 }
828
829 private void getName(Stats st, String cmdlineFile) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700830 String newName = st.name;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700831 if (st.name == null || st.name.equals("app_process")
832 || st.name.equals("<pre-initialized>")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 String cmdName = readFile(cmdlineFile, '\0');
834 if (cmdName != null && cmdName.length() > 1) {
835 newName = cmdName;
836 int i = newName.lastIndexOf("/");
837 if (i > 0 && i < newName.length()-1) {
838 newName = newName.substring(i+1);
839 }
840 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -0700841 if (newName == null) {
842 newName = st.baseName;
843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 }
845 if (st.name == null || !newName.equals(st.name)) {
846 st.name = newName;
847 st.nameWidth = onMeasureProcessName(st.name);
848 }
849 }
850}