From d8c98fee02b5498270344727d1289004d98c0e73 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Tue, 15 Nov 2011 11:29:38 -0800 Subject: [PATCH] Improve low memory dropbox reporting. The msg is now constructed to try to bin these reports in interesting ways. We'll see. Also change the tag name from watchdog to lowmem, since sharkey is kindly taking care of the back-end to handle this. Improve how we put processes into low memory states to better poke things like home and the previous app. Also clean up some debug output, and add a few new am comment options for controlling the current debug app. Change-Id: I562a931a95244a2727bb7a6e1fd80dec259cdae2 --- cmds/am/src/com/android/commands/am/Am.java | 37 +++++ .../server/am/ActivityManagerService.java | 155 ++++++++++++------ .../server/am/ContentProviderRecord.java | 9 +- 3 files changed, 149 insertions(+), 52 deletions(-) diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 7c03a2ff20204..140222ee7130c 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -121,6 +121,10 @@ public class Am { runProfile(); } else if (op.equals("dumpheap")) { runDumpHeap(); + } else if (op.equals("set-debug-app")) { + runSetDebugApp(); + } else if (op.equals("clear-debug-app")) { + runClearDebugApp(); } else if (op.equals("monitor")) { runMonitor(); } else if (op.equals("screen-compat")) { @@ -666,6 +670,31 @@ public class Am { } } + private void runSetDebugApp() throws Exception { + boolean wait = false; + boolean persistent = false; + + String opt; + while ((opt=nextOption()) != null) { + if (opt.equals("-w")) { + wait = true; + } else if (opt.equals("--persistent")) { + persistent = true; + } else { + System.err.println("Error: Unknown option: " + opt); + showUsage(); + return; + } + } + + String pkg = nextArgRequired(); + mAm.setDebugApp(pkg, wait, persistent); + } + + private void runClearDebugApp() throws Exception { + mAm.setDebugApp(null, false, true); + } + class MyActivityController extends IActivityController.Stub { final String mGdbPort; @@ -1199,6 +1228,8 @@ public class Am { " am profile [looper] start \n" + " am profile [looper] stop []\n" + " am dumpheap [flags] \n" + + " am set-debug-app [-w] [--persistent] \n" + + " am clear-debug-app\n" + " am monitor [--gdb ]\n" + " am screen-compat [on|off] \n" + " am display-size [reset|MxN]\n" + @@ -1240,6 +1271,12 @@ public class Am { "am dumpheap: dump the heap of a process. Options are:\n" + " -n: dump native heap instead of managed heap\n" + "\n" + + "am set-debug-app: set application to debug. Options are:\n" + + " -w: wait for debugger when application starts\n" + + " --persistent: retain this value\n" + + "\n" + + "am clear-debug-app: clear the previously set-debug-app.\n" + + "\n" + "am monitor: start monitoring for crashes or ANRs.\n" + " --gdb: start gdbserv on the given port at crash/ANR\n" + "\n" + diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 39e8c726b6ed6..b6f118482bca7 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1249,21 +1249,22 @@ public final class ActivityManagerService extends ActivityManagerNative StringWriter catSw = new StringWriter(); PrintWriter catPw = new PrintWriter(catSw); String[] emptyArgs = new String[] { }; - dumpApplicationMemoryUsage(null, pw, " ", emptyArgs, true, catPw); - pw.println(); - dumpProcessesLocked(null, pw, emptyArgs, 0, false); - pw.println(); - dumpServicesLocked(null, pw, emptyArgs, 0, false, false); - pw.println(); - dumpActivitiesLocked(null, pw, emptyArgs, 0, false, false); + StringBuilder tag = new StringBuilder(128); + dumpProcessesLocked(null, catPw, emptyArgs, 0, false); + catPw.println(); + dumpServicesLocked(null, catPw, emptyArgs, 0, false, false); + catPw.println(); + dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false); + catPw.println(); + tag.append("Low on memory -- "); + dumpApplicationMemoryUsage(null, pw, " ", emptyArgs, true, catPw, tag); String memUsage = sw.toString(); dropBuilder.append('\n'); dropBuilder.append(memUsage); dropBuilder.append(catSw.toString()); logBuilder.append(memUsage); - addErrorToDropBox("watchdog", null, "system_server", null, - null, "Low on memory -- no more background processes", - dropBuilder.toString(), null, null); + addErrorToDropBox("lowmem", null, "system_server", null, + null, tag.toString(), dropBuilder.toString(), null, null); Slog.i(TAG, logBuilder.toString()); synchronized (ActivityManagerService.this) { long now = SystemClock.uptimeMillis(); @@ -1416,7 +1417,8 @@ public final class ActivityManagerService extends ActivityManagerNative return; } - mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null); + mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, + false, null, null); } } @@ -8961,8 +8963,8 @@ public final class ActivityManagerService extends ActivityManagerNative if (!matcher.match(r, r.name)) { continue; } - pw.print(" "); pw.print(e.getKey()); pw.print(": "); - pw.println(r); + pw.print(" "); pw.print(e.getKey()); pw.println(":"); + pw.print(" "); pw.println(r); } needSep = true; } @@ -9346,16 +9348,20 @@ public final class ActivityManagerService extends ActivityManagerNative final static class MemItem { final String label; + final String shortLabel; final long pss; + final int id; ArrayList subitems; - public MemItem(String _label, long _pss) { + public MemItem(String _label, String _shortLabel, long _pss, int _id) { label = _label; + shortLabel = _shortLabel; pss = _pss; + id = _id; } } - final void dumpMemItems(PrintWriter pw, String prefix, ArrayList items, + static final void dumpMemItems(PrintWriter pw, String prefix, ArrayList items, boolean sort) { if (sort) { Collections.sort(items, new Comparator() { @@ -9373,16 +9379,56 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=0; i= 0) start++; + else start = 0; + int end = label.length(); + for (int i=0; i= memKB) { + long bucket = DUMP_MEM_BUCKETS[i]/1024; + out.append(bucket); + out.append("MB "); + out.append(label, start, end); + return; + } + } + out.append(memKB/1024); + out.append("MB "); + out.append(label, start, end); + } + + static final int[] DUMP_MEM_OOM_ADJ = new int[] { + ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ, + ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ, + ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ, + ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ + }; + static final String[] DUMP_MEM_OOM_LABEL = new String[] { + "System", "Persistent", "Foreground", + "Visible", "Perceptible", "Heavy Weight", + "Backup", "A Services", "Home", "Previous", + "B Services", "Background" + }; + final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix, String[] args, boolean brief, - PrintWriter categoryPw) { + PrintWriter categoryPw, StringBuilder outTag) { boolean dumpAll = false; boolean oomOnly = false; @@ -9438,20 +9484,9 @@ public final class ActivityManagerService extends ActivityManagerNative long nativePss=0, dalvikPss=0, otherPss=0; long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; - final int[] oomAdj = new int[] { - ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ, - ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ, - ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ, - ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ - }; - final String[] oomLabel = new String[] { - "System", "Persistent", "Foreground", - "Visible", "Perceptible", "Heavy Weight", - "Backup", "A Services", "Home", "Previous", - "B Services", "Background" - }; - long oomPss[] = new long[oomLabel.length]; - ArrayList[] oomProcs = (ArrayList[])new ArrayList[oomLabel.length]; + long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length]; + ArrayList[] oomProcs = (ArrayList[]) + new ArrayList[DUMP_MEM_OOM_LABEL.length]; long totalPss = 0; @@ -9481,7 +9516,7 @@ public final class ActivityManagerService extends ActivityManagerNative long myTotalPss = mi.getTotalPss(); totalPss += myTotalPss; MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")", - myTotalPss); + r.processName, myTotalPss, 0); procMems.add(pssItem); nativePss += mi.nativePss; @@ -9494,7 +9529,8 @@ public final class ActivityManagerService extends ActivityManagerNative } for (int oomIndex=0; oomIndex(); @@ -9510,22 +9546,47 @@ public final class ActivityManagerService extends ActivityManagerNative if (!isCheckinRequest && procs.size() > 1) { ArrayList catMems = new ArrayList(); - catMems.add(new MemItem("Native", nativePss)); - catMems.add(new MemItem("Dalvik", dalvikPss)); - catMems.add(new MemItem("Unknown", otherPss)); + catMems.add(new MemItem("Native", "Native", nativePss, -1)); + catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, -2)); + catMems.add(new MemItem("Unknown", "Unknown", otherPss, -3)); for (int j=0; j oomMems = new ArrayList(); for (int j=0; j 0) { + outTag.append(" "); + } + appendMemBucket(outTag, mi.pss, mi.shortLabel); + } + } + } + } + if (!brief && !oomOnly) { pw.println(); pw.println("Total PSS by process:"); @@ -9541,7 +9602,7 @@ public final class ActivityManagerService extends ActivityManagerNative dumpMemItems(out, " ", catMems, true); } pw.println(); - pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb"); + pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB"); } } @@ -13991,7 +14052,6 @@ public final class ActivityManagerService extends ActivityManagerNative // application processes based on their current state. int i = mLruProcesses.size(); int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ; - int numBg = 0; while (i > 0) { i--; ProcessRecord app = mLruProcesses.get(i); @@ -14015,12 +14075,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.processName, app.setAdj, "too many background"); app.killedBackground = true; Process.killProcessQuiet(app.pid); - } else { - numBg++; } - } else if (app.curAdj >= ProcessList.HOME_APP_ADJ - && app.curAdj != ProcessList.SERVICE_B_ADJ) { - numBg++; } } } @@ -14035,12 +14090,18 @@ public final class ActivityManagerService extends ActivityManagerNative // memory they want. if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) { final int N = mLruProcesses.size(); - factor = numBg/3; + factor = numHidden/3; + int minFactor = 2; + if (mHomeProcess != null) minFactor++; + if (mPreviousProcess != null) minFactor++; + if (factor < minFactor) factor = minFactor; step = 0; int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; for (i=0; i= ProcessList.HIDDEN_APP_MIN_ADJ && !app.killedBackground) { + if (app.curAdj >= ProcessList.HOME_APP_ADJ + && app.curAdj != ProcessList.SERVICE_B_ADJ + && !app.killedBackground) { if (app.trimMemoryLevel < curLevel && app.thread != null) { try { app.thread.scheduleTrimMemory(curLevel); diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java index 6f6266d8100c4..38355537e1c6f 100644 --- a/services/java/com/android/server/am/ContentProviderRecord.java +++ b/services/java/com/android/server/am/ContentProviderRecord.java @@ -73,15 +73,14 @@ class ContentProviderRecord extends ContentProviderHolder { pw.print("multiprocess="); pw.print(info.multiprocess); pw.print(" initOrder="); pw.println(info.initOrder); } + if (externals != 0) { + pw.print(prefix); pw.print("externals="); pw.println(externals); + } if (clients.size() > 0) { pw.print(prefix); pw.println("Clients:"); for (ProcessRecord cproc : clients) { - pw.print(prefix); pw.println(" - "); pw.println(cproc); + pw.print(prefix); pw.print(" - "); pw.println(cproc.toShortString()); } - pw.print(prefix); pw.print("clients="); pw.println(clients); - } - if (externals != 0) { - pw.print(prefix); pw.print("externals="); pw.println(externals); } }