blob: af80e20cc0e6679e60e2055b89b7b234e05484f4 [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;
23import android.util.Config;
24import android.util.Log;
25
26import java.io.File;
27import java.io.FileInputStream;
28import java.io.PrintWriter;
29import java.io.StringWriter;
30import java.util.ArrayList;
31import java.util.Collections;
32import java.util.Comparator;
33
34public class ProcessStats {
35 private static final String TAG = "ProcessStats";
36 private static final boolean DEBUG = false;
37 private static final boolean localLOGV = DEBUG || Config.LOGV;
38
39 private static final int[] PROCESS_STATS_FORMAT = new int[] {
40 PROC_SPACE_TERM,
41 PROC_SPACE_TERM,
42 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,
77 PROC_SPACE_TERM,
78 PROC_SPACE_TERM,
79 PROC_SPACE_TERM,
80 PROC_SPACE_TERM,
81 PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime
82 PROC_SPACE_TERM|PROC_OUT_LONG // 14: stime
83 };
84
85 private final String[] mProcessFullStatsStringData = new String[3];
86 private final long[] mProcessFullStatsData = new long[3];
87
88 private static final int[] SYSTEM_CPU_FORMAT = new int[] {
89 PROC_SPACE_TERM|PROC_COMBINE,
90 PROC_SPACE_TERM|PROC_OUT_LONG, // 1: user time
91 PROC_SPACE_TERM|PROC_OUT_LONG, // 2: nice time
92 PROC_SPACE_TERM|PROC_OUT_LONG, // 3: sys time
93 PROC_SPACE_TERM|PROC_OUT_LONG, // 4: idle time
94 PROC_SPACE_TERM|PROC_OUT_LONG, // 5: iowait time
95 PROC_SPACE_TERM|PROC_OUT_LONG, // 6: irq time
96 PROC_SPACE_TERM|PROC_OUT_LONG // 7: softirq time
97 };
98
99 private final long[] mSystemCpuData = new long[7];
100
101 private static final int[] LOAD_AVERAGE_FORMAT = new int[] {
102 PROC_SPACE_TERM|PROC_OUT_FLOAT, // 0: 1 min
103 PROC_SPACE_TERM|PROC_OUT_FLOAT, // 1: 5 mins
104 PROC_SPACE_TERM|PROC_OUT_FLOAT // 2: 15 mins
105 };
106
107 private final float[] mLoadAverageData = new float[3];
108
109 private final boolean mIncludeThreads;
110
111 private float mLoad1 = 0;
112 private float mLoad5 = 0;
113 private float mLoad15 = 0;
114
115 private long mCurrentSampleTime;
116 private long mLastSampleTime;
117
118 private long mBaseUserTime;
119 private long mBaseSystemTime;
120 private long mBaseIoWaitTime;
121 private long mBaseIrqTime;
122 private long mBaseSoftIrqTime;
123 private long mBaseIdleTime;
124 private int mRelUserTime;
125 private int mRelSystemTime;
126 private int mRelIoWaitTime;
127 private int mRelIrqTime;
128 private int mRelSoftIrqTime;
129 private int mRelIdleTime;
130
131 private int[] mCurPids;
132 private int[] mCurThreadPids;
133
134 private final ArrayList<Stats> mProcStats = new ArrayList<Stats>();
135 private final ArrayList<Stats> mWorkingProcs = new ArrayList<Stats>();
136 private boolean mWorkingProcsSorted;
137
138 private boolean mFirst = true;
139
140 private byte[] mBuffer = new byte[256];
141
142 public static class Stats {
143 public final int pid;
144 final String statFile;
145 final String cmdlineFile;
146 final String threadsDir;
147 final ArrayList<Stats> threadStats;
148 final ArrayList<Stats> workingThreads;
149
150 public String baseName;
151 public String name;
152 int nameWidth;
153
154 public long base_utime;
155 public long base_stime;
156 public int rel_utime;
157 public int rel_stime;
158
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700159 public long base_minfaults;
160 public long base_majfaults;
161 public int rel_minfaults;
162 public int rel_majfaults;
163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 public boolean active;
165 public boolean added;
166 public boolean removed;
167
168 Stats(int _pid, int parentPid, boolean includeThreads) {
169 pid = _pid;
170 if (parentPid < 0) {
171 final File procDir = new File("/proc", Integer.toString(pid));
172 statFile = new File(procDir, "stat").toString();
173 cmdlineFile = new File(procDir, "cmdline").toString();
174 threadsDir = (new File(procDir, "task")).toString();
175 if (includeThreads) {
176 threadStats = new ArrayList<Stats>();
177 workingThreads = new ArrayList<Stats>();
178 } else {
179 threadStats = null;
180 workingThreads = null;
181 }
182 } else {
183 final File procDir = new File("/proc", Integer.toString(
184 parentPid));
185 final File taskDir = new File(
186 new File(procDir, "task"), Integer.toString(pid));
187 statFile = new File(taskDir, "stat").toString();
188 cmdlineFile = null;
189 threadsDir = null;
190 threadStats = null;
191 workingThreads = null;
192 }
193 }
194 }
195
196 private final static Comparator<Stats> sLoadComparator = new Comparator<Stats>() {
197 public final int
198 compare(Stats sta, Stats stb)
199 {
200 int ta = sta.rel_utime + sta.rel_stime;
201 int tb = stb.rel_utime + stb.rel_stime;
202 if (ta != tb) {
203 return ta > tb ? -1 : 1;
204 }
205 if (sta.added != stb.added) {
206 return sta.added ? -1 : 1;
207 }
208 if (sta.removed != stb.removed) {
209 return sta.added ? -1 : 1;
210 }
211 return 0;
212 }
213 };
214
215
216 public ProcessStats(boolean includeThreads) {
217 mIncludeThreads = includeThreads;
218 }
219
220 public void onLoadChanged(float load1, float load5, float load15) {
221 }
222
223 public int onMeasureProcessName(String name) {
224 return 0;
225 }
226
227 public void init() {
228 mFirst = true;
229 update();
230 }
231
232 public void update() {
233 mLastSampleTime = mCurrentSampleTime;
234 mCurrentSampleTime = SystemClock.uptimeMillis();
235
236 final float[] loadAverages = mLoadAverageData;
237 if (Process.readProcFile("/proc/loadavg", LOAD_AVERAGE_FORMAT,
238 null, null, loadAverages)) {
239 float load1 = loadAverages[0];
240 float load5 = loadAverages[1];
241 float load15 = loadAverages[2];
242 if (load1 != mLoad1 || load5 != mLoad5 || load15 != mLoad15) {
243 mLoad1 = load1;
244 mLoad5 = load5;
245 mLoad15 = load15;
246 onLoadChanged(load1, load5, load15);
247 }
248 }
249
250 mCurPids = collectStats("/proc", -1, mFirst, mCurPids,
251 mProcStats, mWorkingProcs);
252 mFirst = false;
253
254 final long[] sysCpu = mSystemCpuData;
255 if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT,
256 null, sysCpu, null)) {
257 // Total user time is user + nice time.
258 final long usertime = sysCpu[0]+sysCpu[1];
259 // Total system time is simply system time.
260 final long systemtime = sysCpu[2];
261 // Total idle time is simply idle time.
262 final long idletime = sysCpu[3];
263 // Total irq time is iowait + irq + softirq time.
264 final long iowaittime = sysCpu[4];
265 final long irqtime = sysCpu[5];
266 final long softirqtime = sysCpu[6];
267
268 mRelUserTime = (int)(usertime - mBaseUserTime);
269 mRelSystemTime = (int)(systemtime - mBaseSystemTime);
270 mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);
271 mRelIrqTime = (int)(irqtime - mBaseIrqTime);
272 mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
273 mRelIdleTime = (int)(idletime - mBaseIdleTime);
274
275 if (false) {
276 Log.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
277 + " S:" + sysCpu[2] + " I:" + sysCpu[3]
278 + " W:" + sysCpu[4] + " Q:" + sysCpu[5]
279 + " O:" + sysCpu[6]);
280 Log.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime
281 + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);
282 }
283
284 mBaseUserTime = usertime;
285 mBaseSystemTime = systemtime;
286 mBaseIoWaitTime = iowaittime;
287 mBaseIrqTime = irqtime;
288 mBaseSoftIrqTime = softirqtime;
289 mBaseIdleTime = idletime;
290 }
291
292 mWorkingProcsSorted = false;
293 mFirst = false;
294 }
295
296 private int[] collectStats(String statsFile, int parentPid, boolean first,
297 int[] curPids, ArrayList<Stats> allProcs,
298 ArrayList<Stats> workingProcs) {
299
300 workingProcs.clear();
301
302 int[] pids = Process.getPids(statsFile, curPids);
303 int NP = (pids == null) ? 0 : pids.length;
304 int NS = allProcs.size();
305 int curStatsIndex = 0;
306 for (int i=0; i<NP; i++) {
307 int pid = pids[i];
308 if (pid < 0) {
309 NP = pid;
310 break;
311 }
312 Stats st = curStatsIndex < NS ? allProcs.get(curStatsIndex) : null;
313
314 if (st != null && st.pid == pid) {
315 // Update an existing process...
316 st.added = false;
317 curStatsIndex++;
318 if (localLOGV) Log.v(TAG, "Existing pid " + pid + ": " + st);
319
320 final long[] procStats = mProcessStatsData;
321 if (!Process.readProcFile(st.statFile.toString(),
322 PROCESS_STATS_FORMAT, null, procStats, null)) {
323 continue;
324 }
325
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700326 final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS];
327 final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS];
328 final long utime = procStats[PROCESS_STAT_UTIME];
329 final long stime = procStats[PROCESS_STAT_STIME];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330
331 if (utime == st.base_utime && stime == st.base_stime) {
332 st.rel_utime = 0;
333 st.rel_stime = 0;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700334 st.rel_minfaults = 0;
335 st.rel_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 if (st.active) {
337 st.active = false;
338 }
339 continue;
340 }
341
342 if (!st.active) {
343 st.active = true;
344 }
345
346 if (parentPid < 0) {
347 getName(st, st.cmdlineFile);
348 if (st.threadStats != null) {
349 mCurThreadPids = collectStats(st.threadsDir, pid, false,
350 mCurThreadPids, st.threadStats,
351 st.workingThreads);
352 }
353 }
354
355 st.rel_utime = (int)(utime - st.base_utime);
356 st.rel_stime = (int)(stime - st.base_stime);
357 st.base_utime = utime;
358 st.base_stime = stime;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700359 st.rel_minfaults = (int)(minfaults - st.base_minfaults);
360 st.rel_majfaults = (int)(majfaults - st.base_majfaults);
361 st.base_minfaults = minfaults;
362 st.base_majfaults = majfaults;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 //Log.i("Load", "Stats changed " + name + " pid=" + st.pid
364 // + " name=" + st.name + " utime=" + utime
365 // + " stime=" + stime);
366 workingProcs.add(st);
367 continue;
368 }
369
370 if (st == null || st.pid > pid) {
371 // We have a new process!
372 st = new Stats(pid, parentPid, mIncludeThreads);
373 allProcs.add(curStatsIndex, st);
374 curStatsIndex++;
375 NS++;
376 if (localLOGV) Log.v(TAG, "New pid " + pid + ": " + st);
377
378 final String[] procStatsString = mProcessFullStatsStringData;
379 final long[] procStats = mProcessFullStatsData;
380 if (Process.readProcFile(st.statFile.toString(),
381 PROCESS_FULL_STATS_FORMAT, procStatsString,
382 procStats, null)) {
383 st.baseName = parentPid < 0
384 ? procStatsString[0] : Integer.toString(pid);
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700385 st.base_utime = 0; //procStats[1];
386 st.base_stime = 0; //procStats[2];
387 st.base_minfaults = st.base_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 } else {
389 st.baseName = "<unknown>";
390 st.base_utime = st.base_stime = 0;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700391 st.base_minfaults = st.base_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 }
393
394 if (parentPid < 0) {
395 getName(st, st.cmdlineFile);
396 } else {
397 st.name = st.baseName;
398 st.nameWidth = onMeasureProcessName(st.name);
399 if (st.threadStats != null) {
400 mCurThreadPids = collectStats(st.threadsDir, pid, true,
401 mCurThreadPids, st.threadStats,
402 st.workingThreads);
403 }
404 }
405
406 //Log.i("Load", "New process: " + st.pid + " " + st.name);
407 st.rel_utime = 0;
408 st.rel_stime = 0;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700409 st.rel_minfaults = 0;
410 st.rel_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 st.added = true;
412 if (!first) {
413 workingProcs.add(st);
414 }
415 continue;
416 }
417
418 // This process has gone away!
419 st.rel_utime = 0;
420 st.rel_stime = 0;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700421 st.rel_minfaults = 0;
422 st.rel_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 st.removed = true;
424 workingProcs.add(st);
425 allProcs.remove(curStatsIndex);
426 NS--;
427 if (localLOGV) Log.v(TAG, "Removed pid " + st.pid + ": " + st);
428 // Decrement the loop counter so that we process the current pid
429 // again the next time through the loop.
430 i--;
431 continue;
432 }
433
434 while (curStatsIndex < NS) {
435 // This process has gone away!
436 final Stats st = allProcs.get(curStatsIndex);
437 st.rel_utime = 0;
438 st.rel_stime = 0;
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700439 st.rel_minfaults = 0;
440 st.rel_majfaults = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 st.removed = true;
442 workingProcs.add(st);
443 allProcs.remove(curStatsIndex);
444 NS--;
445 if (localLOGV) Log.v(TAG, "Removed pid " + st.pid + ": " + st);
446 }
447
448 return pids;
449 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -0700450
451 public long getCpuTimeForPid(int pid) {
452 final String statFile = "/proc/" + pid + "/stat";
453 final long[] statsData = mSinglePidStatsData;
454 if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
455 null, statsData, null)) {
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700456 long time = statsData[PROCESS_STAT_UTIME]
457 + statsData[PROCESS_STAT_STIME];
Amith Yamasanieaeb6632009-06-03 15:16:10 -0700458 return time;
459 }
460 return 0;
461 }
462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 final public int getLastUserTime() {
464 return mRelUserTime;
465 }
466
467 final public int getLastSystemTime() {
468 return mRelSystemTime;
469 }
470
471 final public int getLastIoWaitTime() {
472 return mRelIoWaitTime;
473 }
474
475 final public int getLastIrqTime() {
476 return mRelIrqTime;
477 }
478
479 final public int getLastSoftIrqTime() {
480 return mRelSoftIrqTime;
481 }
482
483 final public int getLastIdleTime() {
484 return mRelIdleTime;
485 }
486
487 final public float getTotalCpuPercent() {
488 return ((float)(mRelUserTime+mRelSystemTime+mRelIrqTime)*100)
489 / (mRelUserTime+mRelSystemTime+mRelIrqTime+mRelIdleTime);
490 }
491
492 final public int countWorkingStats() {
493 if (!mWorkingProcsSorted) {
494 Collections.sort(mWorkingProcs, sLoadComparator);
495 mWorkingProcsSorted = true;
496 }
497 return mWorkingProcs.size();
498 }
499
500 final public Stats getWorkingStats(int index) {
501 return mWorkingProcs.get(index);
502 }
503
504 final public String printCurrentState() {
505 if (!mWorkingProcsSorted) {
506 Collections.sort(mWorkingProcs, sLoadComparator);
507 mWorkingProcsSorted = true;
508 }
509
510 StringWriter sw = new StringWriter();
511 PrintWriter pw = new PrintWriter(sw);
512 pw.print("Load: ");
513 pw.print(mLoad1);
514 pw.print(" / ");
515 pw.print(mLoad5);
516 pw.print(" / ");
517 pw.println(mLoad15);
518
519 long now = SystemClock.uptimeMillis();
520
521 pw.print("CPU usage from ");
522 pw.print(now-mLastSampleTime);
523 pw.print("ms to ");
524 pw.print(now-mCurrentSampleTime);
525 pw.println("ms ago:");
526
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700527 final int totalTime = mRelUserTime + mRelSystemTime + mRelIoWaitTime
528 + mRelIrqTime + mRelSoftIrqTime + mRelIdleTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529
530 int N = mWorkingProcs.size();
531 for (int i=0; i<N; i++) {
532 Stats st = mWorkingProcs.get(i);
533 printProcessCPU(pw, st.added ? " +" : (st.removed ? " -": " "),
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700534 st.name, totalTime, st.rel_utime, st.rel_stime, 0, 0, 0,
535 st.rel_minfaults, st.rel_majfaults);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 if (!st.removed && st.workingThreads != null) {
537 int M = st.workingThreads.size();
538 for (int j=0; j<M; j++) {
539 Stats tst = st.workingThreads.get(j);
540 printProcessCPU(pw,
541 tst.added ? " +" : (tst.removed ? " -": " "),
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700542 tst.name, totalTime, tst.rel_utime, tst.rel_stime,
543 0, 0, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 }
545 }
546 }
547
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700548 printProcessCPU(pw, "", "TOTAL", totalTime, mRelUserTime, mRelSystemTime,
549 mRelIoWaitTime, mRelIrqTime, mRelSoftIrqTime, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550
551 return sw.toString();
552 }
553
554 private void printProcessCPU(PrintWriter pw, String prefix, String label, int totalTime,
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700555 int user, int system, int iowait, int irq, int softIrq, int minFaults, int majFaults) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 pw.print(prefix);
557 pw.print(label);
558 pw.print(": ");
559 if (totalTime == 0) totalTime = 1;
560 pw.print(((user+system+iowait+irq+softIrq)*100)/totalTime);
561 pw.print("% = ");
562 pw.print((user*100)/totalTime);
563 pw.print("% user + ");
564 pw.print((system*100)/totalTime);
565 pw.print("% kernel");
566 if (iowait > 0) {
567 pw.print(" + ");
568 pw.print((iowait*100)/totalTime);
569 pw.print("% iowait");
570 }
571 if (irq > 0) {
572 pw.print(" + ");
573 pw.print((irq*100)/totalTime);
574 pw.print("% irq");
575 }
576 if (softIrq > 0) {
577 pw.print(" + ");
578 pw.print((softIrq*100)/totalTime);
579 pw.print("% softirq");
580 }
Dianne Hackborn151ceb92009-08-06 12:40:56 -0700581 if (minFaults > 0 || majFaults > 0) {
582 pw.print(" / faults:");
583 if (minFaults > 0) {
584 pw.print(" ");
585 pw.print(minFaults);
586 pw.print(" minor");
587 }
588 if (majFaults > 0) {
589 pw.print(" ");
590 pw.print(majFaults);
591 pw.print(" major");
592 }
593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 pw.println();
595 }
596
597 private String readFile(String file, char endChar) {
598 try {
599 FileInputStream is = new FileInputStream(file);
600 int len = is.read(mBuffer);
601 is.close();
602
603 if (len > 0) {
604 int i;
605 for (i=0; i<len; i++) {
606 if (mBuffer[i] == endChar) {
607 break;
608 }
609 }
610 return new String(mBuffer, 0, 0, i);
611 }
612 } catch (java.io.FileNotFoundException e) {
613 } catch (java.io.IOException e) {
614 }
615 return null;
616 }
617
618 private void getName(Stats st, String cmdlineFile) {
619 String newName = st.baseName;
620 if (st.baseName == null || st.baseName.equals("app_process")) {
621 String cmdName = readFile(cmdlineFile, '\0');
622 if (cmdName != null && cmdName.length() > 1) {
623 newName = cmdName;
624 int i = newName.lastIndexOf("/");
625 if (i > 0 && i < newName.length()-1) {
626 newName = newName.substring(i+1);
627 }
628 }
629 }
630 if (st.name == null || !newName.equals(st.name)) {
631 st.name = newName;
632 st.nameWidth = onMeasureProcessName(st.name);
633 }
634 }
635}
636