1/* 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; 33import java.util.StringTokenizer; 34 35public class ProcessStats { 36 private static final String TAG = "ProcessStats"; 37 private static final boolean DEBUG = false; 38 private static final boolean localLOGV = DEBUG || Config.LOGV; 39 40 private static final int[] PROCESS_STATS_FORMAT = new int[] { 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, 49 PROC_SPACE_TERM, 50 PROC_SPACE_TERM|PROC_OUT_LONG, // 9: minor faults 51 PROC_SPACE_TERM, 52 PROC_SPACE_TERM|PROC_OUT_LONG, // 11: major faults 53 PROC_SPACE_TERM, 54 PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime 55 PROC_SPACE_TERM|PROC_OUT_LONG // 14: stime 56 }; 57 58 static final int PROCESS_STAT_MINOR_FAULTS = 0; 59 static final int PROCESS_STAT_MAJOR_FAULTS = 1; 60 static final int PROCESS_STAT_UTIME = 2; 61 static final int PROCESS_STAT_STIME = 3; 62 63 /** Stores user time and system time in 100ths of a second. */ 64 private final long[] mProcessStatsData = new long[4]; 65 /** Stores user time and system time in 100ths of a second. */ 66 private final long[] mSinglePidStatsData = new long[4]; 67 68 private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] { 69 PROC_SPACE_TERM, 70 PROC_SPACE_TERM|PROC_PARENS|PROC_OUT_STRING, // 1: name 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, 82 PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime 83 PROC_SPACE_TERM|PROC_OUT_LONG // 14: stime 84 }; 85 86 private final String[] mProcessFullStatsStringData = new String[3]; 87 private final long[] mProcessFullStatsData = new long[3]; 88 89 private static final int[] SYSTEM_CPU_FORMAT = new int[] { 90 PROC_SPACE_TERM|PROC_COMBINE, 91 PROC_SPACE_TERM|PROC_OUT_LONG, // 1: user time 92 PROC_SPACE_TERM|PROC_OUT_LONG, // 2: nice time 93 PROC_SPACE_TERM|PROC_OUT_LONG, // 3: sys time 94 PROC_SPACE_TERM|PROC_OUT_LONG, // 4: idle time 95 PROC_SPACE_TERM|PROC_OUT_LONG, // 5: iowait time 96 PROC_SPACE_TERM|PROC_OUT_LONG, // 6: irq time 97 PROC_SPACE_TERM|PROC_OUT_LONG // 7: softirq time 98 }; 99 100 private final long[] mSystemCpuData = new long[7]; 101 102 private static final int[] LOAD_AVERAGE_FORMAT = new int[] { 103 PROC_SPACE_TERM|PROC_OUT_FLOAT, // 0: 1 min 104 PROC_SPACE_TERM|PROC_OUT_FLOAT, // 1: 5 mins 105 PROC_SPACE_TERM|PROC_OUT_FLOAT // 2: 15 mins 106 }; 107 108 private final float[] mLoadAverageData = new float[3]; 109 110 private final boolean mIncludeThreads; 111 112 private float mLoad1 = 0; 113 private float mLoad5 = 0; 114 private float mLoad15 = 0; 115 116 private long mCurrentSampleTime; 117 private long mLastSampleTime; 118 119 private long mBaseUserTime; 120 private long mBaseSystemTime; 121 private long mBaseIoWaitTime; 122 private long mBaseIrqTime; 123 private long mBaseSoftIrqTime; 124 private long mBaseIdleTime; 125 private int mRelUserTime; 126 private int mRelSystemTime; 127 private int mRelIoWaitTime; 128 private int mRelIrqTime; 129 private int mRelSoftIrqTime; 130 private int mRelIdleTime; 131 132 private int[] mCurPids; 133 private int[] mCurThreadPids; 134 135 private final ArrayList<Stats> mProcStats = new ArrayList<Stats>(); 136 private final ArrayList<Stats> mWorkingProcs = new ArrayList<Stats>(); 137 private boolean mWorkingProcsSorted; 138 139 private boolean mFirst = true; 140 141 private byte[] mBuffer = new byte[256]; 142 143 /** 144 * The time in microseconds that the CPU has been running at each speed. 145 */ 146 private long[] mCpuSpeedTimes; 147 148 /** 149 * The relative time in microseconds that the CPU has been running at each speed. 150 */ 151 private long[] mRelCpuSpeedTimes; 152 153 /** 154 * The different speeds that the CPU can be running at. 155 */ 156 private long[] mCpuSpeeds; 157 158 public static class Stats { 159 public final int pid; 160 final String statFile; 161 final String cmdlineFile; 162 final String threadsDir; 163 final ArrayList<Stats> threadStats; 164 final ArrayList<Stats> workingThreads; 165 166 public String baseName; 167 public String name; 168 int nameWidth; 169 170 public long base_utime; 171 public long base_stime; 172 public int rel_utime; 173 public int rel_stime; 174 175 public long base_minfaults; 176 public long base_majfaults; 177 public int rel_minfaults; 178 public int rel_majfaults; 179 180 public boolean active; 181 public boolean added; 182 public boolean removed; 183 184 Stats(int _pid, int parentPid, boolean includeThreads) { 185 pid = _pid; 186 if (parentPid < 0) { 187 final File procDir = new File("/proc", Integer.toString(pid)); 188 statFile = new File(procDir, "stat").toString(); 189 cmdlineFile = new File(procDir, "cmdline").toString(); 190 threadsDir = (new File(procDir, "task")).toString(); 191 if (includeThreads) { 192 threadStats = new ArrayList<Stats>(); 193 workingThreads = new ArrayList<Stats>(); 194 } else { 195 threadStats = null; 196 workingThreads = null; 197 } 198 } else { 199 final File procDir = new File("/proc", Integer.toString( 200 parentPid)); 201 final File taskDir = new File( 202 new File(procDir, "task"), Integer.toString(pid)); 203 statFile = new File(taskDir, "stat").toString(); 204 cmdlineFile = null; 205 threadsDir = null; 206 threadStats = null; 207 workingThreads = null; 208 } 209 } 210 } 211 212 private final static Comparator<Stats> sLoadComparator = new Comparator<Stats>() { 213 public final int 214 compare(Stats sta, Stats stb) 215 { 216 int ta = sta.rel_utime + sta.rel_stime; 217 int tb = stb.rel_utime + stb.rel_stime; 218 if (ta != tb) { 219 return ta > tb ? -1 : 1; 220 } 221 if (sta.added != stb.added) { 222 return sta.added ? -1 : 1; 223 } 224 if (sta.removed != stb.removed) { 225 return sta.added ? -1 : 1; 226 } 227 return 0; 228 } 229 }; 230 231 232 public ProcessStats(boolean includeThreads) { 233 mIncludeThreads = includeThreads; 234 } 235 236 public void onLoadChanged(float load1, float load5, float load15) { 237 } 238 239 public int onMeasureProcessName(String name) { 240 return 0; 241 } 242 243 public void init() { 244 mFirst = true; 245 update(); 246 } 247 248 public void update() { 249 mLastSampleTime = mCurrentSampleTime; 250 mCurrentSampleTime = SystemClock.uptimeMillis(); 251 252 final float[] loadAverages = mLoadAverageData; 253 if (Process.readProcFile("/proc/loadavg", LOAD_AVERAGE_FORMAT, 254 null, null, loadAverages)) { 255 float load1 = loadAverages[0]; 256 float load5 = loadAverages[1]; 257 float load15 = loadAverages[2]; 258 if (load1 != mLoad1 || load5 != mLoad5 || load15 != mLoad15) { 259 mLoad1 = load1; 260 mLoad5 = load5; 261 mLoad15 = load15; 262 onLoadChanged(load1, load5, load15); 263 } 264 } 265 266 mCurPids = collectStats("/proc", -1, mFirst, mCurPids, 267 mProcStats, mWorkingProcs); 268 mFirst = false; 269 270 final long[] sysCpu = mSystemCpuData; 271 if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, 272 null, sysCpu, null)) { 273 // Total user time is user + nice time. 274 final long usertime = sysCpu[0]+sysCpu[1]; 275 // Total system time is simply system time. 276 final long systemtime = sysCpu[2]; 277 // Total idle time is simply idle time. 278 final long idletime = sysCpu[3]; 279 // Total irq time is iowait + irq + softirq time. 280 final long iowaittime = sysCpu[4]; 281 final long irqtime = sysCpu[5]; 282 final long softirqtime = sysCpu[6]; 283 284 mRelUserTime = (int)(usertime - mBaseUserTime); 285 mRelSystemTime = (int)(systemtime - mBaseSystemTime); 286 mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime); 287 mRelIrqTime = (int)(irqtime - mBaseIrqTime); 288 mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime); 289 mRelIdleTime = (int)(idletime - mBaseIdleTime); 290 291 if (false) { 292 Log.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1] 293 + " S:" + sysCpu[2] + " I:" + sysCpu[3] 294 + " W:" + sysCpu[4] + " Q:" + sysCpu[5] 295 + " O:" + sysCpu[6]); 296 Log.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime 297 + " I:" + mRelIdleTime + " Q:" + mRelIrqTime); 298 } 299 300 mBaseUserTime = usertime; 301 mBaseSystemTime = systemtime; 302 mBaseIoWaitTime = iowaittime; 303 mBaseIrqTime = irqtime; 304 mBaseSoftIrqTime = softirqtime; 305 mBaseIdleTime = idletime; 306 } 307 308 mWorkingProcsSorted = false; 309 mFirst = false; 310 } 311 312 private int[] collectStats(String statsFile, int parentPid, boolean first, 313 int[] curPids, ArrayList<Stats> allProcs, 314 ArrayList<Stats> workingProcs) { 315 316 workingProcs.clear(); 317 318 int[] pids = Process.getPids(statsFile, curPids); 319 int NP = (pids == null) ? 0 : pids.length; 320 int NS = allProcs.size(); 321 int curStatsIndex = 0; 322 for (int i=0; i<NP; i++) { 323 int pid = pids[i]; 324 if (pid < 0) { 325 NP = pid; 326 break; 327 } 328 Stats st = curStatsIndex < NS ? allProcs.get(curStatsIndex) : null; 329 330 if (st != null && st.pid == pid) { 331 // Update an existing process... 332 st.added = false; 333 curStatsIndex++; 334 if (localLOGV) Log.v(TAG, "Existing pid " + pid + ": " + st); 335 336 final long[] procStats = mProcessStatsData; 337 if (!Process.readProcFile(st.statFile.toString(), 338 PROCESS_STATS_FORMAT, null, procStats, null)) { 339 continue; 340 } 341 342 final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS]; 343 final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS]; 344 final long utime = procStats[PROCESS_STAT_UTIME]; 345 final long stime = procStats[PROCESS_STAT_STIME]; 346 347 if (utime == st.base_utime && stime == st.base_stime) { 348 st.rel_utime = 0; 349 st.rel_stime = 0; 350 st.rel_minfaults = 0; 351 st.rel_majfaults = 0; 352 if (st.active) { 353 st.active = false; 354 } 355 continue; 356 } 357 358 if (!st.active) { 359 st.active = true; 360 } 361 362 if (parentPid < 0) { 363 getName(st, st.cmdlineFile); 364 if (st.threadStats != null) { 365 mCurThreadPids = collectStats(st.threadsDir, pid, false, 366 mCurThreadPids, st.threadStats, 367 st.workingThreads); 368 } 369 } 370 371 st.rel_utime = (int)(utime - st.base_utime); 372 st.rel_stime = (int)(stime - st.base_stime); 373 st.base_utime = utime; 374 st.base_stime = stime; 375 st.rel_minfaults = (int)(minfaults - st.base_minfaults); 376 st.rel_majfaults = (int)(majfaults - st.base_majfaults); 377 st.base_minfaults = minfaults; 378 st.base_majfaults = majfaults; 379 //Log.i("Load", "Stats changed " + name + " pid=" + st.pid 380 // + " name=" + st.name + " utime=" + utime 381 // + " stime=" + stime); 382 workingProcs.add(st); 383 continue; 384 } 385 386 if (st == null || st.pid > pid) { 387 // We have a new process! 388 st = new Stats(pid, parentPid, mIncludeThreads); 389 allProcs.add(curStatsIndex, st); 390 curStatsIndex++; 391 NS++; 392 if (localLOGV) Log.v(TAG, "New pid " + pid + ": " + st); 393 394 final String[] procStatsString = mProcessFullStatsStringData; 395 final long[] procStats = mProcessFullStatsData; 396 if (Process.readProcFile(st.statFile.toString(), 397 PROCESS_FULL_STATS_FORMAT, procStatsString, 398 procStats, null)) { 399 st.baseName = parentPid < 0 400 ? procStatsString[0] : Integer.toString(pid); 401 st.base_utime = 0; //procStats[1]; 402 st.base_stime = 0; //procStats[2]; 403 st.base_minfaults = st.base_majfaults = 0; 404 } else { 405 st.baseName = "<unknown>"; 406 st.base_utime = st.base_stime = 0; 407 st.base_minfaults = st.base_majfaults = 0; 408 } 409 410 if (parentPid < 0) { 411 getName(st, st.cmdlineFile); 412 } else { 413 st.name = st.baseName; 414 st.nameWidth = onMeasureProcessName(st.name); 415 if (st.threadStats != null) { 416 mCurThreadPids = collectStats(st.threadsDir, pid, true, 417 mCurThreadPids, st.threadStats, 418 st.workingThreads); 419 } 420 } 421 422 //Log.i("Load", "New process: " + st.pid + " " + st.name); 423 st.rel_utime = 0; 424 st.rel_stime = 0; 425 st.rel_minfaults = 0; 426 st.rel_majfaults = 0; 427 st.added = true; 428 if (!first) { 429 workingProcs.add(st); 430 } 431 continue; 432 } 433 434 // This process has gone away! 435 st.rel_utime = 0; 436 st.rel_stime = 0; 437 st.rel_minfaults = 0; 438 st.rel_majfaults = 0; 439 st.removed = true; 440 workingProcs.add(st); 441 allProcs.remove(curStatsIndex); 442 NS--; 443 if (localLOGV) Log.v(TAG, "Removed pid " + st.pid + ": " + st); 444 // Decrement the loop counter so that we process the current pid 445 // again the next time through the loop. 446 i--; 447 continue; 448 } 449 450 while (curStatsIndex < NS) { 451 // This process has gone away! 452 final Stats st = allProcs.get(curStatsIndex); 453 st.rel_utime = 0; 454 st.rel_stime = 0; 455 st.rel_minfaults = 0; 456 st.rel_majfaults = 0; 457 st.removed = true; 458 workingProcs.add(st); 459 allProcs.remove(curStatsIndex); 460 NS--; 461 if (localLOGV) Log.v(TAG, "Removed pid " + st.pid + ": " + st); 462 } 463 464 return pids; 465 } 466 467 public long getCpuTimeForPid(int pid) { 468 final String statFile = "/proc/" + pid + "/stat"; 469 final long[] statsData = mSinglePidStatsData; 470 if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT, 471 null, statsData, null)) { 472 long time = statsData[PROCESS_STAT_UTIME] 473 + statsData[PROCESS_STAT_STIME]; 474 return time; 475 } 476 return 0; 477 } 478 479 /** 480 * Returns the times spent at each CPU speed, since the last call to this method. If this 481 * is the first time, it will return 1 for each value. 482 * @return relative times spent at different speed steps. 483 */ 484 public long[] getLastCpuSpeedTimes() { 485 if (mCpuSpeedTimes == null) { 486 mCpuSpeedTimes = getCpuSpeedTimes(null); 487 mRelCpuSpeedTimes = new long[mCpuSpeedTimes.length]; 488 for (int i = 0; i < mCpuSpeedTimes.length; i++) { 489 mRelCpuSpeedTimes[i] = 1; // Initialize 490 } 491 } else { 492 getCpuSpeedTimes(mRelCpuSpeedTimes); 493 for (int i = 0; i < mCpuSpeedTimes.length; i++) { 494 long temp = mRelCpuSpeedTimes[i]; 495 mRelCpuSpeedTimes[i] -= mCpuSpeedTimes[i]; 496 mCpuSpeedTimes[i] = temp; 497 } 498 } 499 return mRelCpuSpeedTimes; 500 } 501 502 private long[] getCpuSpeedTimes(long[] out) { 503 long[] tempTimes = out; 504 long[] tempSpeeds = mCpuSpeeds; 505 final int MAX_SPEEDS = 20; 506 if (out == null) { 507 tempTimes = new long[MAX_SPEEDS]; // Hopefully no more than that 508 tempSpeeds = new long[MAX_SPEEDS]; 509 } 510 int speed = 0; 511 String file = readFile("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state", '\0'); 512 // Note: file may be null on kernels without cpufreq (i.e. the emulator's) 513 if (file != null) { 514 StringTokenizer st = new StringTokenizer(file, "\n "); 515 while (st.hasMoreElements()) { 516 String token = st.nextToken(); 517 try { 518 long val = Long.parseLong(token); 519 tempSpeeds[speed] = val; 520 token = st.nextToken(); 521 val = Long.parseLong(token); 522 tempTimes[speed] = val; 523 speed++; 524 if (speed == MAX_SPEEDS) break; // No more 525 if (localLOGV && out == null) { 526 Log.v(TAG, "First time : Speed/Time = " + tempSpeeds[speed - 1] 527 + "\t" + tempTimes[speed - 1]); 528 } 529 } catch (NumberFormatException nfe) { 530 Log.i(TAG, "Unable to parse time_in_state"); 531 } 532 } 533 } 534 if (out == null) { 535 out = new long[speed]; 536 mCpuSpeeds = new long[speed]; 537 System.arraycopy(tempSpeeds, 0, mCpuSpeeds, 0, speed); 538 System.arraycopy(tempTimes, 0, out, 0, speed); 539 } 540 return out; 541 } 542 543 final public int getLastUserTime() { 544 return mRelUserTime; 545 } 546 547 final public int getLastSystemTime() { 548 return mRelSystemTime; 549 } 550 551 final public int getLastIoWaitTime() { 552 return mRelIoWaitTime; 553 } 554 555 final public int getLastIrqTime() { 556 return mRelIrqTime; 557 } 558 559 final public int getLastSoftIrqTime() { 560 return mRelSoftIrqTime; 561 } 562 563 final public int getLastIdleTime() { 564 return mRelIdleTime; 565 } 566 567 final public float getTotalCpuPercent() { 568 return ((float)(mRelUserTime+mRelSystemTime+mRelIrqTime)*100) 569 / (mRelUserTime+mRelSystemTime+mRelIrqTime+mRelIdleTime); 570 } 571 572 final public int countWorkingStats() { 573 if (!mWorkingProcsSorted) { 574 Collections.sort(mWorkingProcs, sLoadComparator); 575 mWorkingProcsSorted = true; 576 } 577 return mWorkingProcs.size(); 578 } 579 580 final public Stats getWorkingStats(int index) { 581 return mWorkingProcs.get(index); 582 } 583 584 final public String printCurrentState() { 585 if (!mWorkingProcsSorted) { 586 Collections.sort(mWorkingProcs, sLoadComparator); 587 mWorkingProcsSorted = true; 588 } 589 590 StringWriter sw = new StringWriter(); 591 PrintWriter pw = new PrintWriter(sw); 592 pw.print("Load: "); 593 pw.print(mLoad1); 594 pw.print(" / "); 595 pw.print(mLoad5); 596 pw.print(" / "); 597 pw.println(mLoad15); 598 599 long now = SystemClock.uptimeMillis(); 600 601 pw.print("CPU usage from "); 602 pw.print(now-mLastSampleTime); 603 pw.print("ms to "); 604 pw.print(now-mCurrentSampleTime); 605 pw.println("ms ago:"); 606 607 final int totalTime = mRelUserTime + mRelSystemTime + mRelIoWaitTime 608 + mRelIrqTime + mRelSoftIrqTime + mRelIdleTime; 609 610 int N = mWorkingProcs.size(); 611 for (int i=0; i<N; i++) { 612 Stats st = mWorkingProcs.get(i); 613 printProcessCPU(pw, st.added ? " +" : (st.removed ? " -": " "), 614 st.name, totalTime, st.rel_utime, st.rel_stime, 0, 0, 0, 615 st.rel_minfaults, st.rel_majfaults); 616 if (!st.removed && st.workingThreads != null) { 617 int M = st.workingThreads.size(); 618 for (int j=0; j<M; j++) { 619 Stats tst = st.workingThreads.get(j); 620 printProcessCPU(pw, 621 tst.added ? " +" : (tst.removed ? " -": " "), 622 tst.name, totalTime, tst.rel_utime, tst.rel_stime, 623 0, 0, 0, 0, 0); 624 } 625 } 626 } 627 628 printProcessCPU(pw, "", "TOTAL", totalTime, mRelUserTime, mRelSystemTime, 629 mRelIoWaitTime, mRelIrqTime, mRelSoftIrqTime, 0, 0); 630 631 return sw.toString(); 632 } 633 634 private void printProcessCPU(PrintWriter pw, String prefix, String label, int totalTime, 635 int user, int system, int iowait, int irq, int softIrq, int minFaults, int majFaults) { 636 pw.print(prefix); 637 pw.print(label); 638 pw.print(": "); 639 if (totalTime == 0) totalTime = 1; 640 pw.print(((user+system+iowait+irq+softIrq)*100)/totalTime); 641 pw.print("% = "); 642 pw.print((user*100)/totalTime); 643 pw.print("% user + "); 644 pw.print((system*100)/totalTime); 645 pw.print("% kernel"); 646 if (iowait > 0) { 647 pw.print(" + "); 648 pw.print((iowait*100)/totalTime); 649 pw.print("% iowait"); 650 } 651 if (irq > 0) { 652 pw.print(" + "); 653 pw.print((irq*100)/totalTime); 654 pw.print("% irq"); 655 } 656 if (softIrq > 0) { 657 pw.print(" + "); 658 pw.print((softIrq*100)/totalTime); 659 pw.print("% softirq"); 660 } 661 if (minFaults > 0 || majFaults > 0) { 662 pw.print(" / faults:"); 663 if (minFaults > 0) { 664 pw.print(" "); 665 pw.print(minFaults); 666 pw.print(" minor"); 667 } 668 if (majFaults > 0) { 669 pw.print(" "); 670 pw.print(majFaults); 671 pw.print(" major"); 672 } 673 } 674 pw.println(); 675 } 676 677 private String readFile(String file, char endChar) { 678 try { 679 FileInputStream is = new FileInputStream(file); 680 int len = is.read(mBuffer); 681 is.close(); 682 683 if (len > 0) { 684 int i; 685 for (i=0; i<len; i++) { 686 if (mBuffer[i] == endChar) { 687 break; 688 } 689 } 690 return new String(mBuffer, 0, 0, i); 691 } 692 } catch (java.io.FileNotFoundException e) { 693 } catch (java.io.IOException e) { 694 } 695 return null; 696 } 697 698 private void getName(Stats st, String cmdlineFile) { 699 String newName = st.baseName; 700 if (st.baseName == null || st.baseName.equals("app_process")) { 701 String cmdName = readFile(cmdlineFile, '\0'); 702 if (cmdName != null && cmdName.length() > 1) { 703 newName = cmdName; 704 int i = newName.lastIndexOf("/"); 705 if (i > 0 && i < newName.length()-1) { 706 newName = newName.substring(i+1); 707 } 708 } 709 } 710 if (st.name == null || !newName.equals(st.name)) { 711 st.name = newName; 712 st.nameWidth = onMeasureProcessName(st.name); 713 } 714 } 715} 716 717