diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-11-09 21:51:21 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2011-11-09 21:51:21 +0000 |
commit | 6238667682aba89cba7916fea49328ae4f1e648d (patch) | |
tree | 433e359512a931ffbe3e1e4738369e100b24a597 | |
parent | 35d17ec7c10be8db87dccd0a9e70b2de6b45b494 (diff) | |
parent | 3b2681bad989013154f90c4b9c31f074af1f822c (diff) | |
download | frameworks_base-6238667682aba89cba7916fea49328ae4f1e648d.zip frameworks_base-6238667682aba89cba7916fea49328ae4f1e648d.tar.gz frameworks_base-6238667682aba89cba7916fea49328ae4f1e648d.tar.bz2 |
am 3b2681ba: am 3af8b88d: Merge "Add drop box reports of low memory." into ics-mr1
* commit '3b2681bad989013154f90c4b9c31f074af1f822c':
Add drop box reports of low memory.
-rw-r--r-- | cmds/am/src/com/android/commands/am/Am.java | 20 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 21 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 2 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 104 |
4 files changed, 125 insertions, 22 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 4f72289..7c03a2f 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -109,6 +109,10 @@ public class Am { runStartService(); } else if (op.equals("force-stop")) { runForceStop(); + } else if (op.equals("kill")) { + runKill(); + } else if (op.equals("kill-all")) { + runKillAll(); } else if (op.equals("instrument")) { runInstrument(); } else if (op.equals("broadcast")) { @@ -484,6 +488,14 @@ public class Am { mAm.forceStopPackage(nextArgRequired()); } + private void runKill() throws Exception { + mAm.killBackgroundProcesses(nextArgRequired()); + } + + private void runKillAll() throws Exception { + mAm.killAllBackgroundProcesses(); + } + private void sendBroadcast() throws Exception { Intent intent = makeIntent(); IntentReceiver receiver = new IntentReceiver(); @@ -1179,6 +1191,8 @@ public class Am { " [--R COUNT] [-S] <INTENT>\n" + " am startservice <INTENT>\n" + " am force-stop <PACKAGE>\n" + + " am kill <PACKAGE>\n" + + " am kill-all\n" + " am broadcast <INTENT>\n" + " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" + " [--no-window-animation] <COMPONENT>\n" + @@ -1202,6 +1216,12 @@ public class Am { "\n" + "am force-stop: force stop everything associated with <PACKAGE>.\n" + "\n" + + "am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" + + " processes that are safe to kill -- that is, will not impact the user\n" + + " experience.\n" + + "\n" + + "am kill-all: Kill all background processes.\n" + + "\n" + "am broadcast: send a broadcast Intent.\n" + "\n" + "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" + diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index b4471f0..7994d7c 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1092,6 +1092,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } + + case KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + killAllBackgroundProcesses(); + reply.writeNoException(); + return true; + } case FORCE_STOP_PACKAGE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); @@ -2906,7 +2913,7 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - + public void killBackgroundProcesses(String packageName) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -2917,7 +2924,17 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - + + public void killAllBackgroundProcesses() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + public void forceStopPackage(String packageName) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 26813bf..5222d37 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -234,6 +234,7 @@ public interface IActivityManager extends IInterface { public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException; public void killBackgroundProcesses(final String packageName) throws RemoteException; + public void killAllBackgroundProcesses() throws RemoteException; public void forceStopPackage(final String packageName) throws RemoteException; // Note: probably don't want to allow applications access to these. @@ -605,4 +606,5 @@ public interface IActivityManager extends IInterface { int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136; int SHOW_BOOT_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137; int DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+138; + int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139; } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 4fe8119..05d42ad 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1220,6 +1220,8 @@ public final class ActivityManagerService extends ActivityManagerNative } Thread thread = new Thread() { @Override public void run() { + StringBuilder dropBuilder = new StringBuilder(1024); + StringBuilder logBuilder = new StringBuilder(1024); try { java.lang.Process proc = Runtime.getRuntime().exec(new String[] { "procrank", }); @@ -1233,16 +1235,29 @@ public final class ActivityManagerService extends ActivityManagerNative break; } if (line.length() > 0) { - Slog.i(TAG, line); + logBuilder.append(line); + logBuilder.append('\n'); } + dropBuilder.append(line); + dropBuilder.append('\n'); } converter.close(); } catch (IOException e) { } StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true); - Slog.i(TAG, sw.toString()); + StringWriter catSw = new StringWriter(); + PrintWriter catPw = new PrintWriter(catSw); + dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true, catPw); + 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); + Slog.i(TAG, logBuilder.toString()); synchronized (ActivityManagerService.this) { long now = SystemClock.uptimeMillis(); if (mLastMemUsageReportTime < now) { @@ -1394,7 +1409,7 @@ public final class ActivityManagerService extends ActivityManagerNative return; } - mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false); + mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null); } } @@ -3192,7 +3207,49 @@ public final class ActivityManagerService extends ActivityManagerNative return; } killPackageProcessesLocked(packageName, pkgUid, - ProcessList.SERVICE_ADJ, false, true, true, false); + ProcessList.SERVICE_ADJ, false, true, true, false, "kill background"); + } + } finally { + Binder.restoreCallingIdentity(callingId); + } + } + + public void killAllBackgroundProcesses() { + if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) + != PackageManager.PERMISSION_GRANTED) { + String msg = "Permission Denial: killAllBackgroundProcesses() from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid() + + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + + long callingId = Binder.clearCallingIdentity(); + try { + synchronized(this) { + ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(); + for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) { + final int NA = apps.size(); + for (int ia=0; ia<NA; ia++) { + ProcessRecord app = apps.valueAt(ia); + if (app.persistent) { + // we don't kill persistent processes + continue; + } + if (app.removed) { + procs.add(app); + } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) { + app.removed = true; + procs.add(app); + } + } + } + + int N = procs.size(); + for (int i=0; i<N; i++) { + removeProcessLocked(procs.get(i), false, true, "kill all background"); + } } } finally { Binder.restoreCallingIdentity(callingId); @@ -3364,7 +3421,7 @@ public final class ActivityManagerService extends ActivityManagerNative private final boolean killPackageProcessesLocked(String packageName, int uid, int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit, - boolean evenPersistent) { + boolean evenPersistent, String reason) { ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(); // Remove all processes this package may have touched: all with the @@ -3399,7 +3456,7 @@ public final class ActivityManagerService extends ActivityManagerNative int N = procs.size(); for (int i=0; i<N; i++) { - removeProcessLocked(procs.get(i), callerWillRestart, allowRestart); + removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason); } return N > 0; } @@ -3430,7 +3487,7 @@ public final class ActivityManagerService extends ActivityManagerNative } boolean didSomething = killPackageProcessesLocked(name, uid, -100, - callerWillRestart, false, doit, evenPersistent); + callerWillRestart, false, doit, evenPersistent, "force stop"); TaskRecord lastTask = null; for (i=0; i<mMainStack.mHistory.size(); i++) { @@ -3518,11 +3575,11 @@ public final class ActivityManagerService extends ActivityManagerNative } private final boolean removeProcessLocked(ProcessRecord app, - boolean callerWillRestart, boolean allowRestart) { + boolean callerWillRestart, boolean allowRestart, String reason) { final String name = app.processName; final int uid = app.info.uid; if (DEBUG_PROCESSES) Slog.d( - TAG, "Force removing process " + app + " (" + name + TAG, "Force removing proc " + app.toShortString() + " (" + name + "/" + uid + ")"); mProcessNames.remove(name, uid); @@ -3537,9 +3594,10 @@ public final class ActivityManagerService extends ActivityManagerNative mPidsSelfLocked.remove(pid); mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } + Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason); handleAppDiedLocked(app, true, allowRestart); mLruProcesses.remove(app); - Process.killProcess(pid); + Process.killProcessQuiet(pid); if (app.persistent) { if (!callerWillRestart) { @@ -6846,7 +6904,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=procsToKill.size()-1; i>=0; i--) { ProcessRecord proc = procsToKill.get(i); Slog.i(TAG, "Removing system update proc: " + proc); - removeProcessLocked(proc, true, false); + removeProcessLocked(proc, true, false, "system update done"); } } @@ -7042,7 +7100,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Don't let services in this process be restarted and potentially // annoy the user repeatedly. Unless it is persistent, since those // processes run critical code. - removeProcessLocked(app, false, false); + removeProcessLocked(app, false, false, "crash"); mMainStack.resumeTopActivityLocked(null); return false; } @@ -9298,8 +9356,10 @@ public final class ActivityManagerService extends ActivityManagerNative } final void dumpApplicationMemoryUsage(FileDescriptor fd, - PrintWriter pw, String prefix, String[] args, boolean brief) { + PrintWriter pw, String prefix, String[] args, boolean brief, + PrintWriter categoryPw) { boolean dumpAll = false; + boolean oomOnly = false; int opti = 0; while (opti < args.length) { @@ -9310,9 +9370,12 @@ public final class ActivityManagerService extends ActivityManagerNative opti++; if ("-a".equals(opt)) { dumpAll = true; + } else if ("--oom".equals(opt)) { + oomOnly = true; } else if ("-h".equals(opt)) { - pw.println("meminfo dump options: [-a] [process]"); + pw.println("meminfo dump options: [-a] [--oom] [process]"); pw.println(" -a: include all available information for each process."); + pw.println(" --oom: only show processes organized by oom adj."); pw.println("If [process] is specified it can be the name or "); pw.println("pid of a specific process to dump."); return; @@ -9438,7 +9501,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - if (!brief) { + if (!brief && !oomOnly) { pw.println(); pw.println("Total PSS by process:"); dumpMemItems(pw, " ", procMems, true); @@ -9446,10 +9509,11 @@ public final class ActivityManagerService extends ActivityManagerNative } pw.println("Total PSS by OOM adjustment:"); dumpMemItems(pw, " ", oomMems, false); - if (!brief) { - pw.println(); - pw.println("Total PSS by category:"); - dumpMemItems(pw, " ", catMems, true); + if (!oomOnly) { + PrintWriter out = categoryPw != null ? categoryPw : pw; + out.println(); + out.println("Total PSS by category:"); + dumpMemItems(out, " ", catMems, true); } pw.println(); pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb"); |