summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dianne Hackborn <hackbod@google.com> 2015-10-28 18:00:57 -0700
committer Dianne Hackborn <hackbod@google.com> 2015-10-29 16:39:43 -0700
commit2e44107bf7d9ad97833933422ccd241bf53ff50c (patch)
treeedde4e6c2d32e7209cf8699b754e06a6244948cd
parent4c9564567b016e44d8ae2fe638df5e72391b843c (diff)
Implement shell commands for battery and activity services.
The battery service just implements the existing commands that are available through dump. The activity service implements the small set of commands that are available through dump (not the rest of the dump commands), and also introduces some of the simple "am" shell commands as a proof-of-concept of moving those into the service implementation. Change-Id: If5ff80930dde787703e2682e43c36ce1dab05d69
-rw-r--r--core/java/android/os/ShellCommand.java3
-rw-r--r--services/core/java/com/android/server/BatteryService.java190
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java97
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java211
4 files changed, 377 insertions, 124 deletions
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index d64273a36eac..73c2c804bdf1 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -44,7 +44,7 @@ public abstract class ShellCommand {
private FastPrintWriter mOutPrintWriter;
private FastPrintWriter mErrPrintWriter;
- public void exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ResultReceiver resultReceiver) {
mTarget = target;
mIn = in;
@@ -89,6 +89,7 @@ public abstract class ShellCommand {
mResultReceiver.send(res, null);
}
if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget);
+ return res;
}
public PrintWriter getOutPrintWriter() {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 2eeaec96b581..61fe62fb88a4 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -19,6 +19,8 @@ package com.android.server;
import android.database.ContentObserver;
import android.os.BatteryStats;
+import android.os.ResultReceiver;
+import android.os.ShellCommand;
import com.android.internal.app.IBatteryStats;
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
@@ -96,7 +98,6 @@ public final class BatteryService extends SystemService {
// discharge stats before the device dies.
private int mCriticalBatteryLevel;
- private static final int DUMP_MAX_LENGTH = 24 * 1024;
private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "--unplugged" };
private static final String DUMPSYS_DATA_PATH = "/data/system/";
@@ -106,6 +107,7 @@ public final class BatteryService extends SystemService {
private final Context mContext;
private final IBatteryStats mBatteryStats;
+ BinderService mBinderService;
private final Handler mHandler;
private final Object mLock = new Object();
@@ -162,7 +164,18 @@ public final class BatteryService extends SystemService {
// watch for invalid charger messages if the invalid_charger switch exists
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
- mInvalidChargerObserver.startObserving(
+ UEventObserver invalidChargerObserver = new UEventObserver() {
+ @Override
+ public void onUEvent(UEvent event) {
+ final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
+ synchronized (mLock) {
+ if (mInvalidCharger != invalidCharger) {
+ mInvalidCharger = invalidCharger;
+ }
+ }
+ }
+ };
+ invalidChargerObserver.startObserving(
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
}
@@ -178,7 +191,8 @@ public final class BatteryService extends SystemService {
// Should never happen.
}
- publishBinderService("battery", new BinderService());
+ mBinderService = new BinderService();
+ publishBinderService("battery", mBinderService);
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
@@ -593,7 +607,6 @@ public final class BatteryService extends SystemService {
} catch (NumberFormatException e) {
Slog.e(TAG, "Invalid DischargeThresholds GService string: " +
durationThresholdString + " or " + dischargeThresholdString);
- return;
}
}
}
@@ -616,27 +629,40 @@ public final class BatteryService extends SystemService {
}
}
- private void dumpInternal(PrintWriter pw, String[] args) {
- synchronized (mLock) {
- if (args == null || args.length == 0 || "-a".equals(args[0])) {
- pw.println("Current Battery Service state:");
- if (mUpdatesStopped) {
- pw.println(" (UPDATES STOPPED -- use 'reset' to restart)");
- }
- pw.println(" AC powered: " + mBatteryProps.chargerAcOnline);
- pw.println(" USB powered: " + mBatteryProps.chargerUsbOnline);
- pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline);
- pw.println(" Max charging current: " + mBatteryProps.maxChargingCurrent);
- pw.println(" status: " + mBatteryProps.batteryStatus);
- pw.println(" health: " + mBatteryProps.batteryHealth);
- pw.println(" present: " + mBatteryProps.batteryPresent);
- pw.println(" level: " + mBatteryProps.batteryLevel);
- pw.println(" scale: " + BATTERY_SCALE);
- pw.println(" voltage: " + mBatteryProps.batteryVoltage);
- pw.println(" temperature: " + mBatteryProps.batteryTemperature);
- pw.println(" technology: " + mBatteryProps.batteryTechnology);
+ class Shell extends ShellCommand {
+ @Override
+ public int onCommand(String cmd) {
+ return onShellCommand(this, cmd);
+ }
+
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ dumpHelp(pw);
+ }
+ }
+
+ static void dumpHelp(PrintWriter pw) {
+ pw.println("Battery service (battery) commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
+ pw.println(" Force a battery property value, freezing battery state.");
+ pw.println(" unplug");
+ pw.println(" Force battery unplugged, freezing battery state.");
+ pw.println(" reset");
+ pw.println(" Unfreeze battery state, returning to current hardware values.");
+ }
- } else if ("unplug".equals(args[0])) {
+ int onShellCommand(Shell shell, String cmd) {
+ if (cmd == null) {
+ return shell.handleDefaultCommands(cmd);
+ }
+ PrintWriter pw = shell.getOutPrintWriter();
+ switch (cmd) {
+ case "unplug": {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
if (!mUpdatesStopped) {
mLastBatteryProps.set(mBatteryProps);
}
@@ -650,30 +676,50 @@ public final class BatteryService extends SystemService {
} finally {
Binder.restoreCallingIdentity(ident);
}
+ } break;
+ case "set": {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+ final String key = shell.getNextArg();
+ if (key == null) {
+ pw.println("No property specified");
+ return -1;
- } else if (args.length == 3 && "set".equals(args[0])) {
- String key = args[1];
- String value = args[2];
+ }
+ final String value = shell.getNextArg();
+ if (value == null) {
+ pw.println("No value specified");
+ return -1;
+
+ }
try {
if (!mUpdatesStopped) {
mLastBatteryProps.set(mBatteryProps);
}
boolean update = true;
- if ("ac".equals(key)) {
- mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
- } else if ("usb".equals(key)) {
- mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0;
- } else if ("wireless".equals(key)) {
- mBatteryProps.chargerWirelessOnline = Integer.parseInt(value) != 0;
- } else if ("status".equals(key)) {
- mBatteryProps.batteryStatus = Integer.parseInt(value);
- } else if ("level".equals(key)) {
- mBatteryProps.batteryLevel = Integer.parseInt(value);
- } else if ("invalid".equals(key)) {
- mInvalidCharger = Integer.parseInt(value);
- } else {
- pw.println("Unknown set option: " + key);
- update = false;
+ switch (key) {
+ case "ac":
+ mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
+ break;
+ case "usb":
+ mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0;
+ break;
+ case "wireless":
+ mBatteryProps.chargerWirelessOnline = Integer.parseInt(value) != 0;
+ break;
+ case "status":
+ mBatteryProps.batteryStatus = Integer.parseInt(value);
+ break;
+ case "level":
+ mBatteryProps.batteryLevel = Integer.parseInt(value);
+ break;
+ case "invalid":
+ mInvalidCharger = Integer.parseInt(value);
+ break;
+ default:
+ pw.println("Unknown set option: " + key);
+ update = false;
+ break;
}
if (update) {
long ident = Binder.clearCallingIdentity();
@@ -686,9 +732,12 @@ public final class BatteryService extends SystemService {
}
} catch (NumberFormatException ex) {
pw.println("Bad value: " + value);
+ return -1;
}
-
- } else if (args.length == 1 && "reset".equals(args[0])) {
+ } break;
+ case "reset": {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
long ident = Binder.clearCallingIdentity();
try {
if (mUpdatesStopped) {
@@ -699,26 +748,38 @@ public final class BatteryService extends SystemService {
} finally {
Binder.restoreCallingIdentity(ident);
}
- } else {
- pw.println("Dump current battery state, or:");
- pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
- pw.println(" unplug");
- pw.println(" reset");
- }
+ } break;
+ default:
+ return shell.handleDefaultCommands(cmd);
}
+ return 0;
}
- private final UEventObserver mInvalidChargerObserver = new UEventObserver() {
- @Override
- public void onUEvent(UEventObserver.UEvent event) {
- final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
- synchronized (mLock) {
- if (mInvalidCharger != invalidCharger) {
- mInvalidCharger = invalidCharger;
+ private void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
+ synchronized (mLock) {
+ if (args == null || args.length == 0 || "-a".equals(args[0])) {
+ pw.println("Current Battery Service state:");
+ if (mUpdatesStopped) {
+ pw.println(" (UPDATES STOPPED -- use 'reset' to restart)");
}
+ pw.println(" AC powered: " + mBatteryProps.chargerAcOnline);
+ pw.println(" USB powered: " + mBatteryProps.chargerUsbOnline);
+ pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline);
+ pw.println(" Max charging current: " + mBatteryProps.maxChargingCurrent);
+ pw.println(" status: " + mBatteryProps.batteryStatus);
+ pw.println(" health: " + mBatteryProps.batteryHealth);
+ pw.println(" present: " + mBatteryProps.batteryPresent);
+ pw.println(" level: " + mBatteryProps.batteryLevel);
+ pw.println(" scale: " + BATTERY_SCALE);
+ pw.println(" voltage: " + mBatteryProps.batteryVoltage);
+ pw.println(" temperature: " + mBatteryProps.batteryTemperature);
+ pw.println(" technology: " + mBatteryProps.batteryTechnology);
+ } else {
+ Shell shell = new Shell();
+ shell.exec(mBinderService, null, fd, null, args, new ResultReceiver(null));
}
}
- };
+ }
private final class Led {
private final Light mBatteryLight;
@@ -776,8 +837,7 @@ public final class BatteryService extends SystemService {
}
private final class BatteryListener extends IBatteryPropertiesListener.Stub {
- @Override
- public void batteryPropertiesChanged(BatteryProperties props) {
+ @Override public void batteryPropertiesChanged(BatteryProperties props) {
final long identity = Binder.clearCallingIdentity();
try {
BatteryService.this.update(props);
@@ -788,8 +848,7 @@ public final class BatteryService extends SystemService {
}
private final class BinderService extends Binder {
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -799,7 +858,12 @@ public final class BatteryService extends SystemService {
return;
}
- dumpInternal(pw, args);
+ dumpInternal(fd, pw, args);
+ }
+
+ @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+ (new Shell()).exec(this, in, out, err, args, resultReceiver);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dfe5751267fd..d5ee5e846277 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -69,6 +69,7 @@ import android.graphics.Rect;
import android.os.BatteryStats;
import android.os.PersistableBundle;
import android.os.PowerManager;
+import android.os.ResultReceiver;
import android.os.Trace;
import android.os.TransactionTooLargeException;
import android.os.WorkSource;
@@ -13083,6 +13084,13 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+ (new ActivityManagerShellCommand(this, false)).exec(
+ this, in, out, err, args, resultReceiver);
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (checkCallingPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -13119,34 +13127,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
dumpClient = true;
} else if ("-h".equals(opt)) {
- pw.println("Activity manager dump options:");
- pw.println(" [-a] [-c] [-p package] [-h] [cmd] ...");
- pw.println(" cmd may be one of:");
- pw.println(" a[ctivities]: activity stack state");
- pw.println(" r[recents]: recent activities state");
- pw.println(" b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state");
- pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state");
- pw.println(" p[rocesses] [PACKAGE_NAME]: process state");
- pw.println(" o[om]: out of memory management");
- pw.println(" perm[issions]: URI permission grant state");
- pw.println(" prov[iders] [COMP_SPEC ...]: content provider state");
- pw.println(" provider [COMP_SPEC]: provider client-side state");
- pw.println(" s[ervices] [COMP_SPEC ...]: service state");
- pw.println(" as[sociations]: tracked app associations");
- pw.println(" service [COMP_SPEC]: service client-side state");
- pw.println(" package [PACKAGE_NAME]: all state related to given package");
- pw.println(" all: dump all activities");
- pw.println(" top: dump the top activity");
- pw.println(" write: write all pending state to storage");
- pw.println(" track-associations: enable association tracking");
- pw.println(" untrack-associations: disable and clear association tracking");
- pw.println(" cmd may also be a COMP_SPEC to dump activities.");
- pw.println(" COMP_SPEC may be a component name (com.foo/.myApp),");
- pw.println(" a partial substring in a component name, a");
- pw.println(" hex object identifier.");
- pw.println(" -a: include all available server state.");
- pw.println(" -c: include client state.");
- pw.println(" -p: limit output to given package.");
+ ActivityManagerShellCommand.dumpHelp(pw, true);
return;
} else {
pw.println("Unknown argument: " + opt + "; use -h for help");
@@ -13283,36 +13264,15 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
mServices.dumpServicesLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
}
- } else if ("write".equals(cmd)) {
- mTaskPersister.flush();
- pw.println("All tasks persisted.");
- return;
- } else if ("track-associations".equals(cmd)) {
- synchronized (this) {
- if (!mTrackingAssociations) {
- mTrackingAssociations = true;
- pw.println("Association tracking started.");
- } else {
- pw.println("Association tracking already enabled.");
- }
- }
- return;
- } else if ("untrack-associations".equals(cmd)) {
- synchronized (this) {
- if (mTrackingAssociations) {
- mTrackingAssociations = false;
- mAssociations.clear();
- pw.println("Association tracking stopped.");
- } else {
- pw.println("Association tracking not running.");
- }
- }
- return;
} else {
// Dumping a single activity?
if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
- pw.println("Bad activity command, or no activities match: " + cmd);
- pw.println("Use -h for help.");
+ ActivityManagerShellCommand shell = new ActivityManagerShellCommand(this, true);
+ int res = shell.exec(this, null, fd, null, args, new ResultReceiver(null));
+ if (res < 0) {
+ pw.println("Bad activity command, or no activities match: " + cmd);
+ pw.println("Use -h for help.");
+ }
}
}
if (!more) {
@@ -13563,17 +13523,34 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (mActiveUids.size() > 0) {
- if (needSep) {
- pw.println();
+ boolean printed = false;
+ int whichAppId = -1;
+ if (dumpPackage != null) {
+ try {
+ ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
+ dumpPackage, 0);
+ whichAppId = UserHandle.getAppId(info.uid);
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ }
}
- pw.println(" UID states:");
for (int i=0; i<mActiveUids.size(); i++) {
UidRecord uidRec = mActiveUids.valueAt(i);
+ if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != whichAppId) {
+ continue;
+ }
+ if (!printed) {
+ printed = true;
+ if (needSep) {
+ pw.println();
+ }
+ pw.println(" UID states:");
+ needSep = true;
+ printedAnything = true;
+ }
pw.print(" UID "); UserHandle.formatUid(pw, uidRec.uid);
pw.print(": "); pw.println(uidRec);
}
- needSep = true;
- printedAnything = true;
}
if (mLruProcesses.size() > 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
new file mode 100644
index 000000000000..d1e7e85b6d51
--- /dev/null
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.IActivityManager;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+
+class ActivityManagerShellCommand extends ShellCommand {
+ // IPC interface to activity manager -- don't need to do additional security checks.
+ final IActivityManager mInterface;
+
+ // Internal service impl -- must perform security checks before touching.
+ final ActivityManagerService mInternal;
+
+ final boolean mDumping;
+
+ ActivityManagerShellCommand(ActivityManagerService service, boolean dumping) {
+ mInterface = service;
+ mInternal = service;
+ mDumping = dumping;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+ PrintWriter pw = getOutPrintWriter();
+ try {
+ switch (cmd) {
+ case "force-stop":
+ return runForceStop(pw);
+ case "kill":
+ return runKill(pw);
+ case "kill-all":
+ return runKillAll(pw);
+ case "write":
+ return runWrite(pw);
+ case "track-associations":
+ return runTrackAssociations(pw);
+ case "untrack-associations":
+ return runUntrackAssociations(pw);
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ } catch (RemoteException e) {
+ pw.println("Remote exception: " + e);
+ }
+ return -1;
+ }
+
+ int runForceStop(PrintWriter pw) throws RemoteException {
+ int userId = UserHandle.USER_ALL;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ if (opt.equals("--user")) {
+ userId = parseUserArg(getNextArgRequired());
+ } else {
+ pw.println("Error: Unknown option: " + opt);
+ return -1;
+ }
+ }
+ mInterface.forceStopPackage(getNextArgRequired(), userId);
+ return 0;
+ }
+
+ int runKill(PrintWriter pw) throws RemoteException {
+ int userId = UserHandle.USER_ALL;
+
+ String opt;
+ while ((opt=getNextOption()) != null) {
+ if (opt.equals("--user")) {
+ userId = parseUserArg(getNextArgRequired());
+ } else {
+ pw.println("Error: Unknown option: " + opt);
+ return -1;
+ }
+ }
+ mInterface.killBackgroundProcesses(getNextArgRequired(), userId);
+ return 0;
+ }
+
+ int runKillAll(PrintWriter pw) throws RemoteException {
+ mInterface.killAllBackgroundProcesses();
+ return 0;
+ }
+
+ int runWrite(PrintWriter pw) {
+ mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
+ "registerUidObserver()");
+ mInternal.mTaskPersister.flush();
+ pw.println("All tasks persisted.");
+ return 0;
+ }
+
+ int runTrackAssociations(PrintWriter pw) {
+ mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
+ "registerUidObserver()");
+ synchronized (mInternal) {
+ if (!mInternal.mTrackingAssociations) {
+ mInternal.mTrackingAssociations = true;
+ pw.println("Association tracking started.");
+ } else {
+ pw.println("Association tracking already enabled.");
+ }
+ }
+ return 0;
+ }
+
+ int runUntrackAssociations(PrintWriter pw) {
+ mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
+ "registerUidObserver()");
+ synchronized (mInternal) {
+ if (mInternal.mTrackingAssociations) {
+ mInternal.mTrackingAssociations = false;
+ mInternal.mAssociations.clear();
+ pw.println("Association tracking stopped.");
+ } else {
+ pw.println("Association tracking not running.");
+ }
+ }
+ return 0;
+ }
+
+ int parseUserArg(String arg) {
+ int userId;
+ if ("all".equals(arg)) {
+ userId = UserHandle.USER_ALL;
+ } else if ("current".equals(arg) || "cur".equals(arg)) {
+ userId = UserHandle.USER_CURRENT;
+ } else {
+ try {
+ userId = Integer.parseInt(arg);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Bad user number: " + arg);
+ }
+ }
+ return userId;
+ }
+
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ dumpHelp(pw, mDumping);
+ }
+
+ static void dumpHelp(PrintWriter pw, boolean dumping) {
+ if (dumping) {
+ pw.println("Activity manager dump options:");
+ pw.println(" [-a] [-c] [-p PACKAGE] [-h] [WHAT] ...");
+ pw.println(" WHAT may be one of:");
+ pw.println(" a[ctivities]: activity stack state");
+ pw.println(" r[recents]: recent activities state");
+ pw.println(" b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state");
+ pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state");
+ pw.println(" p[rocesses] [PACKAGE_NAME]: process state");
+ pw.println(" o[om]: out of memory management");
+ pw.println(" perm[issions]: URI permission grant state");
+ pw.println(" prov[iders] [COMP_SPEC ...]: content provider state");
+ pw.println(" provider [COMP_SPEC]: provider client-side state");
+ pw.println(" s[ervices] [COMP_SPEC ...]: service state");
+ pw.println(" as[sociations]: tracked app associations");
+ pw.println(" service [COMP_SPEC]: service client-side state");
+ pw.println(" package [PACKAGE_NAME]: all state related to given package");
+ pw.println(" all: dump all activities");
+ pw.println(" top: dump the top activity");
+ pw.println(" WHAT may also be a COMP_SPEC to dump activities.");
+ pw.println(" COMP_SPEC may be a component name (com.foo/.myApp),");
+ pw.println(" a partial substring in a component name, a");
+ pw.println(" hex object identifier.");
+ pw.println(" -a: include all available server state.");
+ pw.println(" -c: include client state.");
+ pw.println(" -p: limit output to given package.");
+ } else {
+ pw.println("Activity manager (activity) commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println(" force-stop [--user <USER_ID> | all | current] <PACKAGE>");
+ pw.println(" Complete stop the given application package.");
+ pw.println(" kill [--user <USER_ID> | all | current] <PACKAGE>");
+ pw.println(" Kill all processes associated with the given application.");
+ pw.println(" kill-all");
+ pw.println(" Kill all processes that are safe to kill (cached, etc)");
+ pw.println(" write");
+ pw.println(" Write all pending state to storage.");
+ pw.println(" track-associations");
+ pw.println(" Enable association tracking.");
+ pw.println(" untrack-associations");
+ pw.println(" Disable and clear association tracking.");
+ }
+ }
+}