Merge "Improve debug output when an ANR happens." into gingerbread
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index a02c4e7..0c8c2fd 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/services/java/com/android/server/ProcessStats.java
@@ -39,7 +39,7 @@
private static final int[] PROCESS_STATS_FORMAT = new int[] {
PROC_SPACE_TERM,
- PROC_SPACE_TERM,
+ PROC_SPACE_TERM|PROC_PARENS,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
@@ -75,16 +75,21 @@
PROC_SPACE_TERM,
PROC_SPACE_TERM,
PROC_SPACE_TERM,
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 9: minor faults
PROC_SPACE_TERM,
- PROC_SPACE_TERM,
- PROC_SPACE_TERM,
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 11: major faults
PROC_SPACE_TERM,
PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime
PROC_SPACE_TERM|PROC_OUT_LONG // 14: stime
};
- private final String[] mProcessFullStatsStringData = new String[3];
- private final long[] mProcessFullStatsData = new long[3];
+ static final int PROCESS_FULL_STAT_MINOR_FAULTS = 1;
+ static final int PROCESS_FULL_STAT_MAJOR_FAULTS = 2;
+ static final int PROCESS_FULL_STAT_UTIME = 3;
+ static final int PROCESS_FULL_STAT_STIME = 4;
+
+ private final String[] mProcessFullStatsStringData = new String[5];
+ private final long[] mProcessFullStatsData = new long[5];
private static final int[] SYSTEM_CPU_FORMAT = new int[] {
PROC_SPACE_TERM|PROC_COMBINE,
@@ -116,6 +121,9 @@
private long mCurrentSampleTime;
private long mLastSampleTime;
+ private long mCurrentSampleRealTime;
+ private long mLastSampleRealTime;
+
private long mBaseUserTime;
private long mBaseSystemTime;
private long mBaseIoWaitTime;
@@ -167,6 +175,9 @@
public String name;
int nameWidth;
+ public long base_uptime;
+ public long rel_uptime;
+
public long base_utime;
public long base_stime;
public int rel_utime;
@@ -178,6 +189,7 @@
public int rel_majfaults;
public boolean active;
+ public boolean working;
public boolean added;
public boolean removed;
@@ -211,8 +223,7 @@
private final static Comparator<Stats> sLoadComparator = new Comparator<Stats>() {
public final int
- compare(Stats sta, Stats stb)
- {
+ compare(Stats sta, Stats stb) {
int ta = sta.rel_utime + sta.rel_stime;
int tb = stb.rel_utime + stb.rel_stime;
if (ta != tb) {
@@ -241,31 +252,17 @@
}
public void init() {
+ if (DEBUG) Slog.v(TAG, "Init: " + this);
mFirst = true;
update();
}
public void update() {
+ if (DEBUG) Slog.v(TAG, "Update: " + this);
mLastSampleTime = mCurrentSampleTime;
mCurrentSampleTime = SystemClock.uptimeMillis();
-
- final float[] loadAverages = mLoadAverageData;
- if (Process.readProcFile("/proc/loadavg", LOAD_AVERAGE_FORMAT,
- null, null, loadAverages)) {
- float load1 = loadAverages[0];
- float load5 = loadAverages[1];
- float load15 = loadAverages[2];
- if (load1 != mLoad1 || load5 != mLoad5 || load15 != mLoad15) {
- mLoad1 = load1;
- mLoad5 = load5;
- mLoad15 = load15;
- onLoadChanged(load1, load5, load15);
- }
- }
-
- mCurPids = collectStats("/proc", -1, mFirst, mCurPids,
- mProcStats, mWorkingProcs);
- mFirst = false;
+ mLastSampleRealTime = mCurrentSampleRealTime;
+ mCurrentSampleRealTime = SystemClock.elapsedRealtime();
final long[] sysCpu = mSystemCpuData;
if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT,
@@ -288,7 +285,7 @@
mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
mRelIdleTime = (int)(idletime - mBaseIdleTime);
- if (false) {
+ if (DEBUG) {
Slog.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
+ " S:" + sysCpu[2] + " I:" + sysCpu[3]
+ " W:" + sysCpu[4] + " Q:" + sysCpu[5]
@@ -305,16 +302,32 @@
mBaseIdleTime = idletime;
}
+ mCurPids = collectStats("/proc", -1, mFirst, mCurPids, mProcStats);
+
+ final float[] loadAverages = mLoadAverageData;
+ if (Process.readProcFile("/proc/loadavg", LOAD_AVERAGE_FORMAT,
+ null, null, loadAverages)) {
+ float load1 = loadAverages[0];
+ float load5 = loadAverages[1];
+ float load15 = loadAverages[2];
+ if (load1 != mLoad1 || load5 != mLoad5 || load15 != mLoad15) {
+ mLoad1 = load1;
+ mLoad5 = load5;
+ mLoad15 = load15;
+ onLoadChanged(load1, load5, load15);
+ }
+ }
+
+ if (DEBUG) Slog.i(TAG, "*** TIME TO COLLECT STATS: "
+ + (SystemClock.uptimeMillis()-mCurrentSampleTime));
+
mWorkingProcsSorted = false;
mFirst = false;
}
private int[] collectStats(String statsFile, int parentPid, boolean first,
- int[] curPids, ArrayList<Stats> allProcs,
- ArrayList<Stats> workingProcs) {
+ int[] curPids, ArrayList<Stats> allProcs) {
- workingProcs.clear();
-
int[] pids = Process.getPids(statsFile, curPids);
int NP = (pids == null) ? 0 : pids.length;
int NS = allProcs.size();
@@ -330,8 +343,13 @@
if (st != null && st.pid == pid) {
// Update an existing process...
st.added = false;
+ st.working = false;
curStatsIndex++;
- if (localLOGV) Slog.v(TAG, "Existing pid " + pid + ": " + st);
+ if (DEBUG) Slog.v(TAG, "Existing "
+ + (parentPid < 0 ? "process" : "thread")
+ + " pid " + pid + ": " + st);
+
+ final long uptime = SystemClock.uptimeMillis();
final long[] procStats = mProcessStatsData;
if (!Process.readProcFile(st.statFile.toString(),
@@ -363,11 +381,18 @@
getName(st, st.cmdlineFile);
if (st.threadStats != null) {
mCurThreadPids = collectStats(st.threadsDir, pid, false,
- mCurThreadPids, st.threadStats,
- st.workingThreads);
+ 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;
@@ -376,10 +401,7 @@
st.rel_majfaults = (int)(majfaults - st.base_majfaults);
st.base_minfaults = minfaults;
st.base_majfaults = majfaults;
- //Slog.i("Load", "Stats changed " + name + " pid=" + st.pid
- // + " name=" + st.name + " utime=" + utime
- // + " stime=" + stime);
- workingProcs.add(st);
+ st.working = true;
continue;
}
@@ -389,18 +411,21 @@
allProcs.add(curStatsIndex, st);
curStatsIndex++;
NS++;
- if (localLOGV) Slog.v(TAG, "New pid " + pid + ": " + st);
+ 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();
if (Process.readProcFile(st.statFile.toString(),
PROCESS_FULL_STATS_FORMAT, procStatsString,
procStats, null)) {
- st.baseName = parentPid < 0
- ? procStatsString[0] : Integer.toString(pid);
- st.base_utime = 0; //procStats[1];
- st.base_stime = 0; //procStats[2];
- st.base_minfaults = st.base_majfaults = 0;
+ 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];
+ st.base_stime = procStats[PROCESS_FULL_STAT_STIME];
} else {
st.baseName = "<unknown>";
st.base_utime = st.base_stime = 0;
@@ -409,24 +434,26 @@
if (parentPid < 0) {
getName(st, st.cmdlineFile);
+ if (st.threadStats != null) {
+ mCurThreadPids = collectStats(st.threadsDir, pid, true,
+ mCurThreadPids, st.threadStats);
+ }
} else {
st.name = st.baseName;
st.nameWidth = onMeasureProcessName(st.name);
- if (st.threadStats != null) {
- mCurThreadPids = collectStats(st.threadsDir, pid, true,
- mCurThreadPids, st.threadStats,
- st.workingThreads);
- }
}
+
+ 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);
- //Slog.i("Load", "New process: " + st.pid + " " + st.name);
st.rel_utime = 0;
st.rel_stime = 0;
st.rel_minfaults = 0;
st.rel_majfaults = 0;
st.added = true;
if (!first) {
- workingProcs.add(st);
+ st.working = true;
}
continue;
}
@@ -437,10 +464,12 @@
st.rel_minfaults = 0;
st.rel_majfaults = 0;
st.removed = true;
- workingProcs.add(st);
+ st.working = true;
allProcs.remove(curStatsIndex);
NS--;
- if (localLOGV) Slog.v(TAG, "Removed pid " + st.pid + ": " + st);
+ 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--;
@@ -455,7 +484,7 @@
st.rel_minfaults = 0;
st.rel_majfaults = 0;
st.removed = true;
- workingProcs.add(st);
+ st.working = true;
allProcs.remove(curStatsIndex);
NS--;
if (localLOGV) Slog.v(TAG, "Removed pid " + st.pid + ": " + st);
@@ -569,11 +598,34 @@
/ (mRelUserTime+mRelSystemTime+mRelIrqTime+mRelIdleTime);
}
- final public int countWorkingStats() {
+ final void buildWorkingProcs() {
if (!mWorkingProcsSorted) {
+ mWorkingProcs.clear();
+ final int N = mProcStats.size();
+ for (int i=0; i<N; i++) {
+ Stats stats = mProcStats.get(i);
+ if (stats.working) {
+ mWorkingProcs.add(stats);
+ if (stats.threadStats != null && stats.threadStats.size() > 1) {
+ stats.workingThreads.clear();
+ final int M = stats.threadStats.size();
+ for (int j=0; j<M; j++) {
+ Stats tstats = stats.threadStats.get(j);
+ if (tstats.working) {
+ stats.workingThreads.add(tstats);
+ }
+ }
+ Collections.sort(stats.workingThreads, sLoadComparator);
+ }
+ }
+ }
Collections.sort(mWorkingProcs, sLoadComparator);
mWorkingProcsSorted = true;
}
+ }
+
+ final public int countWorkingStats() {
+ buildWorkingProcs();
return mWorkingProcs.size();
}
@@ -581,12 +633,7 @@
return mWorkingProcs.get(index);
}
- final public String printCurrentState() {
- if (!mWorkingProcsSorted) {
- Collections.sort(mWorkingProcs, sLoadComparator);
- mWorkingProcsSorted = true;
- }
-
+ final public String printCurrentLoad() {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.print("Load: ");
@@ -595,67 +642,111 @@
pw.print(mLoad5);
pw.print(" / ");
pw.println(mLoad15);
+ return sw.toString();
+ }
+
+ final public String printCurrentState(long now) {
+ buildWorkingProcs();
- long now = SystemClock.uptimeMillis();
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
pw.print("CPU usage from ");
- pw.print(now-mLastSampleTime);
- pw.print("ms to ");
- pw.print(now-mCurrentSampleTime);
- pw.println("ms ago:");
+ if (now > mLastSampleTime) {
+ pw.print(now-mLastSampleTime);
+ pw.print("ms to ");
+ pw.print(now-mCurrentSampleTime);
+ pw.print("ms ago");
+ } else {
+ pw.print(mLastSampleTime-now);
+ pw.print("ms to ");
+ pw.print(mCurrentSampleTime-now);
+ pw.print("ms later");
+ }
+
+ long sampleTime = mCurrentSampleTime - mLastSampleTime;
+ long sampleRealTime = mCurrentSampleRealTime - mLastSampleRealTime;
+ long percAwake = (sampleTime*100) / sampleRealTime;
+ if (percAwake != 100) {
+ pw.print(" with ");
+ pw.print(percAwake);
+ pw.print("% awake");
+ }
+ pw.println(":");
final int totalTime = mRelUserTime + mRelSystemTime + mRelIoWaitTime
+ mRelIrqTime + mRelSoftIrqTime + mRelIdleTime;
+ if (DEBUG) Slog.i(TAG, "totalTime " + totalTime + " over sample time "
+ + (mCurrentSampleTime-mLastSampleTime));
+
int N = mWorkingProcs.size();
for (int i=0; i<N; i++) {
Stats st = mWorkingProcs.get(i);
printProcessCPU(pw, st.added ? " +" : (st.removed ? " -": " "),
- st.name, totalTime, st.rel_utime, st.rel_stime, 0, 0, 0,
- st.rel_minfaults, st.rel_majfaults);
+ st.pid, st.name, (int)(st.rel_uptime+5)/10,
+ st.rel_utime, st.rel_stime, 0, 0, 0, st.rel_minfaults, st.rel_majfaults);
if (!st.removed && st.workingThreads != null) {
int M = st.workingThreads.size();
for (int j=0; j<M; j++) {
Stats tst = st.workingThreads.get(j);
printProcessCPU(pw,
tst.added ? " +" : (tst.removed ? " -": " "),
- tst.name, totalTime, tst.rel_utime, tst.rel_stime,
- 0, 0, 0, 0, 0);
+ tst.pid, tst.name, (int)(st.rel_uptime+5)/10,
+ tst.rel_utime, tst.rel_stime, 0, 0, 0, 0, 0);
}
}
}
- printProcessCPU(pw, "", "TOTAL", totalTime, mRelUserTime, mRelSystemTime,
+ printProcessCPU(pw, "", -1, "TOTAL", totalTime, mRelUserTime, mRelSystemTime,
mRelIoWaitTime, mRelIrqTime, mRelSoftIrqTime, 0, 0);
return sw.toString();
}
- private void printProcessCPU(PrintWriter pw, String prefix, String label, int totalTime,
- int user, int system, int iowait, int irq, int softIrq, int minFaults, int majFaults) {
+ private void printRatio(PrintWriter pw, long numerator, long denominator) {
+ long thousands = (numerator*1000)/denominator;
+ long hundreds = thousands/10;
+ pw.print(hundreds);
+ if (hundreds < 10) {
+ long remainder = thousands - (hundreds*10);
+ if (remainder != 0) {
+ pw.print('.');
+ pw.print(remainder);
+ }
+ }
+ }
+
+ private void printProcessCPU(PrintWriter pw, String prefix, int pid, String label,
+ int totalTime, int user, int system, int iowait, int irq, int softIrq,
+ int minFaults, int majFaults) {
pw.print(prefix);
+ if (totalTime == 0) totalTime = 1;
+ printRatio(pw, user+system+iowait+irq+softIrq, totalTime);
+ pw.print("% ");
+ if (pid >= 0) {
+ pw.print(pid);
+ pw.print("/");
+ }
pw.print(label);
pw.print(": ");
- if (totalTime == 0) totalTime = 1;
- pw.print(((user+system+iowait+irq+softIrq)*100)/totalTime);
- pw.print("% = ");
- pw.print((user*100)/totalTime);
+ printRatio(pw, user, totalTime);
pw.print("% user + ");
- pw.print((system*100)/totalTime);
+ printRatio(pw, system, totalTime);
pw.print("% kernel");
if (iowait > 0) {
pw.print(" + ");
- pw.print((iowait*100)/totalTime);
+ printRatio(pw, iowait, totalTime);
pw.print("% iowait");
}
if (irq > 0) {
pw.print(" + ");
- pw.print((irq*100)/totalTime);
+ printRatio(pw, irq, totalTime);
pw.print("% irq");
}
if (softIrq > 0) {
pw.print(" + ");
- pw.print((softIrq*100)/totalTime);
+ printRatio(pw, softIrq, totalTime);
pw.print("% softirq");
}
if (minFaults > 0 || majFaults > 0) {
@@ -696,8 +787,8 @@
}
private void getName(Stats st, String cmdlineFile) {
- String newName = st.baseName;
- if (st.baseName == null || st.baseName.equals("app_process")) {
+ String newName = st.name;
+ if (st.name == null || st.name.equals("app_process")) {
String cmdName = readFile(cmdlineFile, '\0');
if (cmdName != null && cmdName.length() > 1) {
newName = cmdName;
@@ -706,6 +797,9 @@
newName = newName.substring(i+1);
}
}
+ if (newName == null) {
+ newName = st.baseName;
+ }
}
if (st.name == null || !newName.equals(st.name)) {
st.name = newName;
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index a742093..1b885f5 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -39,9 +39,6 @@
import android.util.Slog;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
@@ -113,8 +110,6 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MONITOR: {
- long now = SystemClock.uptimeMillis();
-
// See if we should force a reboot.
int rebootInterval = mReqRebootInterval >= 0
? mReqRebootInterval : Settings.Secure.getInt(
@@ -418,9 +413,9 @@
if (!waitedHalf) {
// We've waited half the deadlock-detection interval. Pull a stack
// trace and wait another half.
- ArrayList pids = new ArrayList();
+ ArrayList<Integer> pids = new ArrayList<Integer>();
pids.add(Process.myPid());
- File stack = ActivityManagerService.dumpStackTraces(true, pids);
+ ActivityManagerService.dumpStackTraces(true, pids, null, null);
waitedHalf = true;
continue;
}
@@ -430,15 +425,16 @@
// First collect stack traces from all threads of the system process.
// Then kill this process so that the system will restart.
- String name = (mCurrentMonitor != null) ? mCurrentMonitor.getClass().getName() : "null";
+ String name = (mCurrentMonitor != null) ?
+ mCurrentMonitor.getClass().getName() : "null";
EventLog.writeEvent(EventLogTags.WATCHDOG, name);
- ArrayList pids = new ArrayList();
+ ArrayList<Integer> pids = new ArrayList<Integer>();
pids.add(Process.myPid());
if (mPhonePid > 0) pids.add(mPhonePid);
// Pass !waitedHalf so that just in case we somehow wind up here without having
// dumped the halfway stacks, we properly re-initialize the trace file.
- File stack = ActivityManagerService.dumpStackTraces(!waitedHalf, pids);
+ File stack = ActivityManagerService.dumpStackTraces(!waitedHalf, pids, null, null);
// Give some extra time to make sure the stack traces get written.
// The system's been hanging for a minute, another second or two won't hurt much.
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 5d5e862..30dc5ea 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1355,7 +1355,9 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mActivityManagerService.mProcessStatsThread) {
- pw.print(mActivityManagerService.mProcessStats.printCurrentState());
+ pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
+ pw.print(mActivityManagerService.mProcessStats.printCurrentState(
+ SystemClock.uptimeMillis()));
}
}
}
@@ -2644,10 +2646,12 @@
* @param clearTraces causes the dump file to be erased prior to the new
* traces being written, if true; when false, the new traces will be
* appended to any existing file content.
- * @param pids of dalvik VM processes to dump stack traces for
+ * @param firstPids of dalvik VM processes to dump stack traces for first
+ * @param lastPids of dalvik VM processes to dump stack traces for last
* @return file containing stack traces, or null if no dump file is configured
*/
- public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
+ public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
+ ProcessStats processStats, SparseArray<Boolean> lastPids) {
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
if (tracesPath == null || tracesPath.length() == 0) {
return null;
@@ -2675,25 +2679,69 @@
try {
observer.startWatching();
- int num = pids.size();
- for (int i = 0; i < num; i++) {
- synchronized (observer) {
- Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
- observer.wait(200); // Wait for write-close, give up after 200msec
+
+ // First collect all of the stacks of the most important pids.
+ try {
+ int num = firstPids.size();
+ for (int i = 0; i < num; i++) {
+ synchronized (observer) {
+ Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
+ observer.wait(200); // Wait for write-close, give up after 200msec
+ }
+ }
+ } catch (InterruptedException e) {
+ Log.wtf(TAG, e);
+ }
+
+ // Next measure CPU usage.
+ if (processStats != null) {
+ processStats.init();
+ System.gc();
+ processStats.update();
+ try {
+ synchronized (processStats) {
+ processStats.wait(500); // measure over 1/2 second.
+ }
+ } catch (InterruptedException e) {
+ }
+ processStats.update();
+
+ // We'll take the stack crawls of just the top apps using CPU.
+ final int N = processStats.countWorkingStats();
+ int numProcs = 0;
+ for (int i=0; i<N && numProcs<5; i++) {
+ ProcessStats.Stats stats = processStats.getWorkingStats(i);
+ if (lastPids.indexOfKey(stats.pid) >= 0) {
+ numProcs++;
+ try {
+ synchronized (observer) {
+ Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
+ observer.wait(200); // Wait for write-close, give up after 200msec
+ }
+ } catch (InterruptedException e) {
+ Log.wtf(TAG, e);
+ }
+
+ }
}
}
- } catch (InterruptedException e) {
- Log.wtf(TAG, e);
+
+ return tracesFile;
+
} finally {
observer.stopWatching();
}
-
- return tracesFile;
}
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
ActivityRecord parent, final String annotation) {
- ArrayList<Integer> pids = new ArrayList<Integer>(20);
+ ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
+ SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
+
+ long anrTime = SystemClock.uptimeMillis();
+ if (MONITOR_CPU_USAGE) {
+ updateCpuStatsNow();
+ }
synchronized (this) {
// PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
@@ -2717,24 +2765,32 @@
annotation);
// Dump thread traces as quickly as we can, starting with "interesting" processes.
- pids.add(app.pid);
+ firstPids.add(app.pid);
int parentPid = app.pid;
if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
- if (parentPid != app.pid) pids.add(parentPid);
+ if (parentPid != app.pid) firstPids.add(parentPid);
- if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
+ if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord r = mLruProcesses.get(i);
if (r != null && r.thread != null) {
int pid = r.pid;
- if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
+ if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
+ if (r.persistent) {
+ firstPids.add(pid);
+ } else {
+ lastPids.put(pid, Boolean.TRUE);
+ }
+ }
}
}
}
- File tracesFile = dumpStackTraces(true, pids);
+ final ProcessStats processStats = new ProcessStats(true);
+
+ File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
// Log the ANR to the main log.
StringBuilder info = mStringBuilder;
@@ -2755,11 +2811,14 @@
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow();
synchronized (mProcessStatsThread) {
- cpuInfo = mProcessStats.printCurrentState();
+ cpuInfo = mProcessStats.printCurrentState(anrTime);
}
+ info.append(processStats.printCurrentLoad());
info.append(cpuInfo);
}
+ info.append(processStats.printCurrentState(anrTime));
+
Slog.e(TAG, info.toString());
if (tracesFile == null) {
// There is no trace file, so dump (only) the alleged culprit's threads to the log