Skip to content

Commit 3af8b88

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "Add drop box reports of low memory." into ics-mr1
2 parents a4293ba + e4d4fbc commit 3af8b88

File tree

4 files changed

+125
-22
lines changed

4 files changed

+125
-22
lines changed

cmds/am/src/com/android/commands/am/Am.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ private void run(String[] args) throws Exception {
109109
runStartService();
110110
} else if (op.equals("force-stop")) {
111111
runForceStop();
112+
} else if (op.equals("kill")) {
113+
runKill();
114+
} else if (op.equals("kill-all")) {
115+
runKillAll();
112116
} else if (op.equals("instrument")) {
113117
runInstrument();
114118
} else if (op.equals("broadcast")) {
@@ -484,6 +488,14 @@ private void runForceStop() throws Exception {
484488
mAm.forceStopPackage(nextArgRequired());
485489
}
486490

491+
private void runKill() throws Exception {
492+
mAm.killBackgroundProcesses(nextArgRequired());
493+
}
494+
495+
private void runKillAll() throws Exception {
496+
mAm.killAllBackgroundProcesses();
497+
}
498+
487499
private void sendBroadcast() throws Exception {
488500
Intent intent = makeIntent();
489501
IntentReceiver receiver = new IntentReceiver();
@@ -1179,6 +1191,8 @@ private static void showUsage() {
11791191
" [--R COUNT] [-S] <INTENT>\n" +
11801192
" am startservice <INTENT>\n" +
11811193
" am force-stop <PACKAGE>\n" +
1194+
" am kill <PACKAGE>\n" +
1195+
" am kill-all\n" +
11821196
" am broadcast <INTENT>\n" +
11831197
" am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
11841198
" [--no-window-animation] <COMPONENT>\n" +
@@ -1202,6 +1216,12 @@ private static void showUsage() {
12021216
"\n" +
12031217
"am force-stop: force stop everything associated with <PACKAGE>.\n" +
12041218
"\n" +
1219+
"am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" +
1220+
" processes that are safe to kill -- that is, will not impact the user\n" +
1221+
" experience.\n" +
1222+
"\n" +
1223+
"am kill-all: Kill all background processes.\n" +
1224+
"\n" +
12051225
"am broadcast: send a broadcast Intent.\n" +
12061226
"\n" +
12071227
"am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" +

core/java/android/app/ActivityManagerNative.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,13 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
10921092
reply.writeNoException();
10931093
return true;
10941094
}
1095+
1096+
case KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION: {
1097+
data.enforceInterface(IActivityManager.descriptor);
1098+
killAllBackgroundProcesses();
1099+
reply.writeNoException();
1100+
return true;
1101+
}
10951102

10961103
case FORCE_STOP_PACKAGE_TRANSACTION: {
10971104
data.enforceInterface(IActivityManager.descriptor);
@@ -2906,7 +2913,7 @@ public void signalPersistentProcesses(int sig) throws RemoteException {
29062913
data.recycle();
29072914
reply.recycle();
29082915
}
2909-
2916+
29102917
public void killBackgroundProcesses(String packageName) throws RemoteException {
29112918
Parcel data = Parcel.obtain();
29122919
Parcel reply = Parcel.obtain();
@@ -2917,7 +2924,17 @@ public void killBackgroundProcesses(String packageName) throws RemoteException {
29172924
data.recycle();
29182925
reply.recycle();
29192926
}
2920-
2927+
2928+
public void killAllBackgroundProcesses() throws RemoteException {
2929+
Parcel data = Parcel.obtain();
2930+
Parcel reply = Parcel.obtain();
2931+
data.writeInterfaceToken(IActivityManager.descriptor);
2932+
mRemote.transact(KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0);
2933+
reply.readException();
2934+
data.recycle();
2935+
reply.recycle();
2936+
}
2937+
29212938
public void forceStopPackage(String packageName) throws RemoteException {
29222939
Parcel data = Parcel.obtain();
29232940
Parcel reply = Parcel.obtain();

core/java/android/app/IActivityManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ public void showWaitingForDebugger(IApplicationThread who, boolean waiting)
234234
public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException;
235235

236236
public void killBackgroundProcesses(final String packageName) throws RemoteException;
237+
public void killAllBackgroundProcesses() throws RemoteException;
237238
public void forceStopPackage(final String packageName) throws RemoteException;
238239

239240
// Note: probably don't want to allow applications access to these.
@@ -605,4 +606,5 @@ private WaitResult(Parcel source) {
605606
int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136;
606607
int SHOW_BOOT_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137;
607608
int DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+138;
609+
int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139;
608610
}

services/java/com/android/server/am/ActivityManagerService.java

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)