@@ -1220,6 +1220,8 @@ public void handleMessage(Message msg) {
12201220 }
12211221 Thread thread = new Thread() {
12221222 @Override public void run() {
1223+ StringBuilder dropBuilder = new StringBuilder(1024);
1224+ StringBuilder logBuilder = new StringBuilder(1024);
12231225 try {
12241226 java.lang.Process proc = Runtime.getRuntime().exec(new String[] {
12251227 "procrank", });
@@ -1233,16 +1235,29 @@ public void handleMessage(Message msg) {
12331235 break;
12341236 }
12351237 if (line.length() > 0) {
1236- Slog.i(TAG, line);
1238+ logBuilder.append(line);
1239+ logBuilder.append('\n');
12371240 }
1241+ dropBuilder.append(line);
1242+ dropBuilder.append('\n');
12381243 }
12391244 converter.close();
12401245 } catch (IOException e) {
12411246 }
12421247 StringWriter sw = new StringWriter();
12431248 PrintWriter pw = new PrintWriter(sw);
1244- dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true);
1245- Slog.i(TAG, sw.toString());
1249+ StringWriter catSw = new StringWriter();
1250+ PrintWriter catPw = new PrintWriter(catSw);
1251+ dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true, catPw);
1252+ String memUsage = sw.toString();
1253+ dropBuilder.append('\n');
1254+ dropBuilder.append(memUsage);
1255+ dropBuilder.append(catSw.toString());
1256+ logBuilder.append(memUsage);
1257+ addErrorToDropBox("watchdog", null, "system_server", null,
1258+ null, "Low on memory -- no more background processes",
1259+ dropBuilder.toString(), null, null);
1260+ Slog.i(TAG, logBuilder.toString());
12461261 synchronized (ActivityManagerService.this) {
12471262 long now = SystemClock.uptimeMillis();
12481263 if (mLastMemUsageReportTime < now) {
@@ -1394,7 +1409,7 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
13941409 return;
13951410 }
13961411
1397- mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false);
1412+ mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null );
13981413 }
13991414 }
14001415
@@ -3192,7 +3207,49 @@ public void killBackgroundProcesses(final String packageName) {
31923207 return;
31933208 }
31943209 killPackageProcessesLocked(packageName, pkgUid,
3195- ProcessList.SERVICE_ADJ, false, true, true, false);
3210+ ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
3211+ }
3212+ } finally {
3213+ Binder.restoreCallingIdentity(callingId);
3214+ }
3215+ }
3216+
3217+ public void killAllBackgroundProcesses() {
3218+ if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3219+ != PackageManager.PERMISSION_GRANTED) {
3220+ String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
3221+ + Binder.getCallingPid()
3222+ + ", uid=" + Binder.getCallingUid()
3223+ + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
3224+ Slog.w(TAG, msg);
3225+ throw new SecurityException(msg);
3226+ }
3227+
3228+ long callingId = Binder.clearCallingIdentity();
3229+ try {
3230+ synchronized(this) {
3231+ ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
3232+ for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3233+ final int NA = apps.size();
3234+ for (int ia=0; ia<NA; ia++) {
3235+ ProcessRecord app = apps.valueAt(ia);
3236+ if (app.persistent) {
3237+ // we don't kill persistent processes
3238+ continue;
3239+ }
3240+ if (app.removed) {
3241+ procs.add(app);
3242+ } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
3243+ app.removed = true;
3244+ procs.add(app);
3245+ }
3246+ }
3247+ }
3248+
3249+ int N = procs.size();
3250+ for (int i=0; i<N; i++) {
3251+ removeProcessLocked(procs.get(i), false, true, "kill all background");
3252+ }
31963253 }
31973254 } finally {
31983255 Binder.restoreCallingIdentity(callingId);
@@ -3364,7 +3421,7 @@ private void forceStopPackageLocked(final String packageName, int uid) {
33643421
33653422 private final boolean killPackageProcessesLocked(String packageName, int uid,
33663423 int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
3367- boolean evenPersistent) {
3424+ boolean evenPersistent, String reason ) {
33683425 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
33693426
33703427 // Remove all processes this package may have touched: all with the
@@ -3399,7 +3456,7 @@ private final boolean killPackageProcessesLocked(String packageName, int uid,
33993456
34003457 int N = procs.size();
34013458 for (int i=0; i<N; i++) {
3402- removeProcessLocked(procs.get(i), callerWillRestart, allowRestart);
3459+ removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason );
34033460 }
34043461 return N > 0;
34053462 }
@@ -3430,7 +3487,7 @@ private final boolean forceStopPackageLocked(String name, int uid,
34303487 }
34313488
34323489 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3433- callerWillRestart, false, doit, evenPersistent);
3490+ callerWillRestart, false, doit, evenPersistent, "force stop" );
34343491
34353492 TaskRecord lastTask = null;
34363493 for (i=0; i<mMainStack.mHistory.size(); i++) {
@@ -3518,11 +3575,11 @@ private final boolean forceStopPackageLocked(String name, int uid,
35183575 }
35193576
35203577 private final boolean removeProcessLocked(ProcessRecord app,
3521- boolean callerWillRestart, boolean allowRestart) {
3578+ boolean callerWillRestart, boolean allowRestart, String reason ) {
35223579 final String name = app.processName;
35233580 final int uid = app.info.uid;
35243581 if (DEBUG_PROCESSES) Slog.d(
3525- TAG, "Force removing process " + app + " (" + name
3582+ TAG, "Force removing proc " + app.toShortString() + " (" + name
35263583 + "/" + uid + ")");
35273584
35283585 mProcessNames.remove(name, uid);
@@ -3537,9 +3594,10 @@ private final boolean removeProcessLocked(ProcessRecord app,
35373594 mPidsSelfLocked.remove(pid);
35383595 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
35393596 }
3597+ Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason);
35403598 handleAppDiedLocked(app, true, allowRestart);
35413599 mLruProcesses.remove(app);
3542- Process.killProcess (pid);
3600+ Process.killProcessQuiet (pid);
35433601
35443602 if (app.persistent) {
35453603 if (!callerWillRestart) {
@@ -6846,7 +6904,7 @@ public void run() {
68466904 for (int i=procsToKill.size()-1; i>=0; i--) {
68476905 ProcessRecord proc = procsToKill.get(i);
68486906 Slog.i(TAG, "Removing system update proc: " + proc);
6849- removeProcessLocked(proc, true, false);
6907+ removeProcessLocked(proc, true, false, "system update done" );
68506908 }
68516909 }
68526910
@@ -7042,7 +7100,7 @@ private boolean handleAppCrashLocked(ProcessRecord app) {
70427100 // Don't let services in this process be restarted and potentially
70437101 // annoy the user repeatedly. Unless it is persistent, since those
70447102 // processes run critical code.
7045- removeProcessLocked(app, false, false);
7103+ removeProcessLocked(app, false, false, "crash" );
70467104 mMainStack.resumeTopActivityLocked(null);
70477105 return false;
70487106 }
@@ -9298,8 +9356,10 @@ public int compare(MemItem lhs, MemItem rhs) {
92989356 }
92999357
93009358 final void dumpApplicationMemoryUsage(FileDescriptor fd,
9301- PrintWriter pw, String prefix, String[] args, boolean brief) {
9359+ PrintWriter pw, String prefix, String[] args, boolean brief,
9360+ PrintWriter categoryPw) {
93029361 boolean dumpAll = false;
9362+ boolean oomOnly = false;
93039363
93049364 int opti = 0;
93059365 while (opti < args.length) {
@@ -9310,9 +9370,12 @@ final void dumpApplicationMemoryUsage(FileDescriptor fd,
93109370 opti++;
93119371 if ("-a".equals(opt)) {
93129372 dumpAll = true;
9373+ } else if ("--oom".equals(opt)) {
9374+ oomOnly = true;
93139375 } else if ("-h".equals(opt)) {
9314- pw.println("meminfo dump options: [-a] [process]");
9376+ pw.println("meminfo dump options: [-a] [--oom] [ process]");
93159377 pw.println(" -a: include all available information for each process.");
9378+ pw.println(" --oom: only show processes organized by oom adj.");
93169379 pw.println("If [process] is specified it can be the name or ");
93179380 pw.println("pid of a specific process to dump.");
93189381 return;
@@ -9438,18 +9501,19 @@ final void dumpApplicationMemoryUsage(FileDescriptor fd,
94389501 }
94399502 }
94409503
9441- if (!brief) {
9504+ if (!brief && !oomOnly ) {
94429505 pw.println();
94439506 pw.println("Total PSS by process:");
94449507 dumpMemItems(pw, " ", procMems, true);
94459508 pw.println();
94469509 }
94479510 pw.println("Total PSS by OOM adjustment:");
94489511 dumpMemItems(pw, " ", oomMems, false);
9449- if (!brief) {
9450- pw.println();
9451- pw.println("Total PSS by category:");
9452- dumpMemItems(pw, " ", catMems, true);
9512+ if (!oomOnly) {
9513+ PrintWriter out = categoryPw != null ? categoryPw : pw;
9514+ out.println();
9515+ out.println("Total PSS by category:");
9516+ dumpMemItems(out, " ", catMems, true);
94539517 }
94549518 pw.println();
94559519 pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb");
0 commit comments