private void getName(Stats st, String cmdlineFile) { String newName = st.name; if (st.name == null || st.name.equals("app_process") || st.name.equals("<pre-initialized>")) { String cmdName = readFile(cmdlineFile, '\0'); if (cmdName != null && cmdName.length() > 1) { newName = cmdName; int i = newName.lastIndexOf("/"); if (i > 0 && i < newName.length() - 1) { newName = newName.substring(i + 1); } } if (newName == null) { newName = st.baseName; } } if (st.name == null || !newName.equals(st.name)) { st.name = newName; st.nameWidth = onMeasureProcessName(st.name); } }
private int[] collectStats( String statsFile, int parentPid, boolean first, int[] curPids, ArrayList<Stats> allProcs) { int[] pids = Process.getPids(statsFile, curPids); int NP = (pids == null) ? 0 : pids.length; int NS = allProcs.size(); int curStatsIndex = 0; for (int i = 0; i < NP; i++) { int pid = pids[i]; if (pid < 0) { NP = pid; break; } Stats st = curStatsIndex < NS ? allProcs.get(curStatsIndex) : null; if (st != null && st.pid == pid) { // Update an existing process... st.added = false; st.working = false; curStatsIndex++; if (DEBUG) Slog.v( TAG, "Existing " + (parentPid < 0 ? "process" : "thread") + " pid " + pid + ": " + st); if (st.interesting) { final long uptime = SystemClock.uptimeMillis(); final long[] procStats = mProcessStatsData; if (!Process.readProcFile( st.statFile.toString(), PROCESS_STATS_FORMAT, null, procStats, null)) { continue; } final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS]; final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS]; final long utime = procStats[PROCESS_STAT_UTIME] * mJiffyMillis; final long stime = procStats[PROCESS_STAT_STIME] * mJiffyMillis; if (utime == st.base_utime && stime == st.base_stime) { st.rel_utime = 0; st.rel_stime = 0; st.rel_minfaults = 0; st.rel_majfaults = 0; if (st.active) { st.active = false; } continue; } if (!st.active) { st.active = true; } if (parentPid < 0) { getName(st, st.cmdlineFile); if (st.threadStats != null) { mCurThreadPids = collectStats(st.threadsDir, pid, false, mCurThreadPids, st.threadStats); } } if (DEBUG) Slog.v( "Load", "Stats changed " + st.name + " pid=" + st.pid + " utime=" + utime + "-" + st.base_utime + " stime=" + stime + "-" + st.base_stime + " minfaults=" + minfaults + "-" + st.base_minfaults + " majfaults=" + majfaults + "-" + st.base_majfaults); st.rel_uptime = uptime - st.base_uptime; st.base_uptime = uptime; st.rel_utime = (int) (utime - st.base_utime); st.rel_stime = (int) (stime - st.base_stime); st.base_utime = utime; st.base_stime = stime; st.rel_minfaults = (int) (minfaults - st.base_minfaults); st.rel_majfaults = (int) (majfaults - st.base_majfaults); st.base_minfaults = minfaults; st.base_majfaults = majfaults; st.working = true; } continue; } if (st == null || st.pid > pid) { // We have a new process! st = new Stats(pid, parentPid, mIncludeThreads); allProcs.add(curStatsIndex, st); curStatsIndex++; NS++; if (DEBUG) Slog.v(TAG, "New " + (parentPid < 0 ? "process" : "thread") + " pid " + pid + ": " + st); final String[] procStatsString = mProcessFullStatsStringData; final long[] procStats = mProcessFullStatsData; st.base_uptime = SystemClock.uptimeMillis(); String path = st.statFile.toString(); // Slog.d(TAG, "Reading proc file: " + path); if (Process.readProcFile( path, PROCESS_FULL_STATS_FORMAT, procStatsString, procStats, null)) { // This is a possible way to filter out processes that // are actually kernel threads... do we want to? Some // of them do use CPU, but there can be a *lot* that are // not doing anything. st.vsize = procStats[PROCESS_FULL_STAT_VSIZE]; if (true || procStats[PROCESS_FULL_STAT_VSIZE] != 0) { st.interesting = true; st.baseName = procStatsString[0]; st.base_minfaults = procStats[PROCESS_FULL_STAT_MINOR_FAULTS]; st.base_majfaults = procStats[PROCESS_FULL_STAT_MAJOR_FAULTS]; st.base_utime = procStats[PROCESS_FULL_STAT_UTIME] * mJiffyMillis; st.base_stime = procStats[PROCESS_FULL_STAT_STIME] * mJiffyMillis; } else { Slog.i(TAG, "Skipping kernel process pid " + pid + " name " + procStatsString[0]); st.baseName = procStatsString[0]; } } else { Slog.w(TAG, "Skipping unknown process pid " + pid); st.baseName = "<unknown>"; st.base_utime = st.base_stime = 0; st.base_minfaults = st.base_majfaults = 0; } if (parentPid < 0) { getName(st, st.cmdlineFile); if (st.threadStats != null) { mCurThreadPids = collectStats(st.threadsDir, pid, true, mCurThreadPids, st.threadStats); } } else if (st.interesting) { st.name = st.baseName; st.nameWidth = onMeasureProcessName(st.name); } if (DEBUG) Slog.v( "Load", "Stats added " + st.name + " pid=" + st.pid + " utime=" + st.base_utime + " stime=" + st.base_stime + " minfaults=" + st.base_minfaults + " majfaults=" + st.base_majfaults); st.rel_utime = 0; st.rel_stime = 0; st.rel_minfaults = 0; st.rel_majfaults = 0; st.added = true; if (!first && st.interesting) { st.working = true; } continue; } // This process has gone away! st.rel_utime = 0; st.rel_stime = 0; st.rel_minfaults = 0; st.rel_majfaults = 0; st.removed = true; st.working = true; allProcs.remove(curStatsIndex); NS--; if (DEBUG) Slog.v( TAG, "Removed " + (parentPid < 0 ? "process" : "thread") + " pid " + pid + ": " + st); // Decrement the loop counter so that we process the current pid // again the next time through the loop. i--; continue; } while (curStatsIndex < NS) { // This process has gone away! final Stats st = allProcs.get(curStatsIndex); st.rel_utime = 0; st.rel_stime = 0; st.rel_minfaults = 0; st.rel_majfaults = 0; st.removed = true; st.working = true; allProcs.remove(curStatsIndex); NS--; if (localLOGV) Slog.v(TAG, "Removed pid " + st.pid + ": " + st); } return pids; }