diff options
author | Dianne Hackborn <hackbod@google.com> | 2013-04-04 18:50:23 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2013-04-08 13:08:37 -0700 |
commit | 79f7ec70ebd5758ce54fd5b6fcd60fd27457cba6 (patch) | |
tree | 6bc7542adfb792659a153a5000fb94a3ed6abb6a /cmds/am | |
parent | bab9687e6473072d6ff4f7ea5a7b21bcfbf95744 (diff) | |
download | frameworks_base-79f7ec70ebd5758ce54fd5b6fcd60fd27457cba6.zip frameworks_base-79f7ec70ebd5758ce54fd5b6fcd60fd27457cba6.tar.gz frameworks_base-79f7ec70ebd5758ce54fd5b6fcd60fd27457cba6.tar.bz2 |
Have audio service clean up new receivers in crashing processes.
The new media button receiver with only a pending intent (no
component name) could be left hanging if the process that
registered it went away. These semantically need to be tied
to the calling process's lifetime; we now clean them up when
the calling process goes away.
Also added some additional cleanup of media button receivers
when packages change (updated, cleared).
And on top of that, a new "media" command for doing media
things. Currently lets you send media keys and monitor
remote display data.
Oh and finally added a new BaseCommand base class for
implementing these command line utilities.
Change-Id: Iba1d56f10bab1eec4a94a7bb1d1c2ae614c8bcf5
Diffstat (limited to 'cmds/am')
-rw-r--r-- | cmds/am/src/com/android/commands/am/Am.java | 361 |
1 files changed, 145 insertions, 216 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 1c02960..ccb9e1f 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -39,6 +39,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.util.AndroidException; import android.view.IWindowManager; +import com.android.internal.os.BaseCommand; import java.io.BufferedReader; import java.io.File; @@ -50,12 +51,9 @@ import java.net.URISyntaxException; import java.util.HashSet; import java.util.List; -public class Am { +public class Am extends BaseCommand { private IActivityManager mAm; - private String[] mArgs; - private int mNextArg; - private String mCurArgData; private int mStartFlags = 0; private boolean mWaitOption = false; @@ -67,33 +65,155 @@ public class Am { private String mProfileFile; - // These are magic strings understood by the Eclipse plugin. - private static final String FATAL_ERROR_CODE = "Error type 1"; - private static final String NO_SYSTEM_ERROR_CODE = "Error type 2"; - private static final String NO_CLASS_ERROR_CODE = "Error type 3"; - /** * Command-line entry point. * * @param args The command-line arguments */ public static void main(String[] args) { - try { - (new Am()).run(args); - } catch (IllegalArgumentException e) { - showUsage(); - System.err.println("Error: " + e.getMessage()); - } catch (Exception e) { - e.printStackTrace(System.err); - System.exit(1); - } + (new Am()).run(args); } - private void run(String[] args) throws Exception { - if (args.length < 1) { - showUsage(); - return; - } + public void onShowUsage(PrintStream out) { + out.println( + "usage: am [subcommand] [options]\n" + + "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" + + " [--R COUNT] [-S] [--opengl-trace]\n" + + " [--user <USER_ID> | current] <INTENT>\n" + + " am startservice [--user <USER_ID> | current] <INTENT>\n" + + " am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" + + " am kill [--user <USER_ID> | all | current] <PACKAGE>\n" + + " am kill-all\n" + + " am broadcast [--user <USER_ID> | all | current] <INTENT>\n" + + " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" + + " [--user <USER_ID> | current]\n" + + " [--no-window-animation] <COMPONENT>\n" + + " am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" + + " am profile stop [--user <USER_ID> current] [<PROCESS>]\n" + + " am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" + + " am set-debug-app [-w] [--persistent] <PACKAGE>\n" + + " am clear-debug-app\n" + + " am monitor [--gdb <port>]\n" + + " am screen-compat [on|off] <PACKAGE>\n" + + " am to-uri [INTENT]\n" + + " am to-intent-uri [INTENT]\n" + + " am switch-user <USER_ID>\n" + + " am stop-user <USER_ID>\n" + + "\n" + + "am start: start an Activity. Options are:\n" + + " -D: enable debugging\n" + + " -W: wait for launch to complete\n" + + " --start-profiler <FILE>: start profiler and send results to <FILE>\n" + + " -P <FILE>: like above, but profiling stops when app goes idle\n" + + " -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" + + " the top activity will be finished.\n" + + " -S: force stop the target app before starting the activity\n" + + " --opengl-trace: enable tracing of OpenGL functions\n" + + " --user <USER_ID> | current: Specify which user to run as; if not\n" + + " specified then run as the current user.\n" + + "\n" + + "am startservice: start a Service. Options are:\n" + + " --user <USER_ID> | current: Specify which user to run as; if not\n" + + " specified then run as the current user.\n" + + "\n" + + "am force-stop: force stop everything associated with <PACKAGE>.\n" + + " --user <USER_ID> | all | current: Specify user to force stop;\n" + + " all users if not specified.\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" + + " --user <USER_ID> | all | current: Specify user whose processes to kill;\n" + + " all users if not specified.\n" + + "\n" + + "am kill-all: Kill all background processes.\n" + + "\n" + + "am broadcast: send a broadcast Intent. Options are:\n" + + " --user <USER_ID> | all | current: Specify which user to send to; if not\n" + + " specified then send to all users.\n" + + " --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" + + "\n" + + "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" + + " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" + + " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" + + " [-e perf true] to generate raw output for performance measurements.\n" + + " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" + + " common form is [-e <testrunner_flag> <value>[,<value>...]].\n" + + " -p <FILE>: write profiling data to <FILE>\n" + + " -w: wait for instrumentation to finish before returning. Required for\n" + + " test runners.\n" + + " --user <USER_ID> | current: Specify user instrumentation runs in;\n" + + " current user if not specified.\n" + + " --no-window-animation: turn off window animations will running.\n" + + "\n" + + "am profile: start and stop profiler on a process. The given <PROCESS> argument\n" + + " may be either a process name or pid. Options are:\n" + + " --user <USER_ID> | current: When supplying a process name,\n" + + " specify user of process to profile; uses current user if not specified.\n" + + "\n" + + "am dumpheap: dump the heap of a process. The given <PROCESS> argument may\n" + + " be either a process name or pid. Options are:\n" + + " -n: dump native heap instead of managed heap\n" + + " --user <USER_ID> | current: When supplying a process name,\n" + + " specify user of process to dump; uses current user if not specified.\n" + + "\n" + + "am set-debug-app: set application <PACKAGE> 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 bug-report: request bug report generation; will launch UI\n" + + " when done to select where it should be delivered.\n" + + "\n" + + "am monitor: start monitoring for crashes or ANRs.\n" + + " --gdb: start gdbserv on the given port at crash/ANR\n" + + "\n" + + "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" + + "\n" + + "am to-uri: print the given Intent specification as a URI.\n" + + "\n" + + "am to-intent-uri: print the given Intent specification as an intent: URI.\n" + + "\n" + + "am switch-user: switch to put USER_ID in the foreground, starting\n" + + " execution of that user if it is currently stopped.\n" + + "\n" + + "am stop-user: stop execution of USER_ID, not allowing it to run any\n" + + " code until a later explicit switch to it.\n" + + "\n" + + "<INTENT> specifications include these flags and arguments:\n" + + " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" + + " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" + + " [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" + + " [--esn <EXTRA_KEY> ...]\n" + + " [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" + + " [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" + + " [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" + + " [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" + + " [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" + + " [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" + + " [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" + + " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" + + " [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" + + " [-n <COMPONENT>] [-f <FLAGS>]\n" + + " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" + + " [--debug-log-resolution] [--exclude-stopped-packages]\n" + + " [--include-stopped-packages]\n" + + " [--activity-brought-to-front] [--activity-clear-top]\n" + + " [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" + + " [--activity-launched-from-history] [--activity-multiple-task]\n" + + " [--activity-no-animation] [--activity-no-history]\n" + + " [--activity-no-user-action] [--activity-previous-is-top]\n" + + " [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" + + " [--activity-single-top] [--activity-clear-task]\n" + + " [--activity-task-on-home]\n" + + " [--receiver-registered-only] [--receiver-replace-pending]\n" + + " [--selector]\n" + + " [<URI> | <PACKAGE> | <COMPONENT>]\n" + ); + } + + public void onRun() throws Exception { mAm = ActivityManagerNative.getDefault(); if (mAm == null) { @@ -101,9 +221,7 @@ public class Am { throw new AndroidException("Can't connect to activity manager; is the system running?"); } - mArgs = args; - String op = args[0]; - mNextArg = 1; + String op = nextArgRequired(); if (op.equals("start")) { runStart(); @@ -142,7 +260,7 @@ public class Am { } else if (op.equals("stop-user")) { runStopUser(); } else { - throw new IllegalArgumentException("Unknown command: " + op); + showError("Error: unknown command '" + op + "'"); } } @@ -1303,193 +1421,4 @@ public class Am { return true; } } - - private String nextOption() { - if (mCurArgData != null) { - String prev = mArgs[mNextArg - 1]; - throw new IllegalArgumentException("No argument expected after \"" + prev + "\""); - } - if (mNextArg >= mArgs.length) { - return null; - } - String arg = mArgs[mNextArg]; - if (!arg.startsWith("-")) { - return null; - } - mNextArg++; - if (arg.equals("--")) { - return null; - } - if (arg.length() > 1 && arg.charAt(1) != '-') { - if (arg.length() > 2) { - mCurArgData = arg.substring(2); - return arg.substring(0, 2); - } else { - mCurArgData = null; - return arg; - } - } - mCurArgData = null; - return arg; - } - - private String nextArg() { - if (mCurArgData != null) { - String arg = mCurArgData; - mCurArgData = null; - return arg; - } else if (mNextArg < mArgs.length) { - return mArgs[mNextArg++]; - } else { - return null; - } - } - - private String nextArgRequired() { - String arg = nextArg(); - if (arg == null) { - String prev = mArgs[mNextArg - 1]; - throw new IllegalArgumentException("Argument expected after \"" + prev + "\""); - } - return arg; - } - - private static void showUsage() { - System.err.println( - "usage: am [subcommand] [options]\n" + - "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" + - " [--R COUNT] [-S] [--opengl-trace]\n" + - " [--user <USER_ID> | current] <INTENT>\n" + - " am startservice [--user <USER_ID> | current] <INTENT>\n" + - " am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" + - " am kill [--user <USER_ID> | all | current] <PACKAGE>\n" + - " am kill-all\n" + - " am broadcast [--user <USER_ID> | all | current] <INTENT>\n" + - " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" + - " [--user <USER_ID> | current]\n" + - " [--no-window-animation] <COMPONENT>\n" + - " am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" + - " am profile stop [--user <USER_ID> current] [<PROCESS>]\n" + - " am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" + - " am set-debug-app [-w] [--persistent] <PACKAGE>\n" + - " am clear-debug-app\n" + - " am monitor [--gdb <port>]\n" + - " am screen-compat [on|off] <PACKAGE>\n" + - " am to-uri [INTENT]\n" + - " am to-intent-uri [INTENT]\n" + - " am switch-user <USER_ID>\n" + - " am stop-user <USER_ID>\n" + - "\n" + - "am start: start an Activity. Options are:\n" + - " -D: enable debugging\n" + - " -W: wait for launch to complete\n" + - " --start-profiler <FILE>: start profiler and send results to <FILE>\n" + - " -P <FILE>: like above, but profiling stops when app goes idle\n" + - " -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" + - " the top activity will be finished.\n" + - " -S: force stop the target app before starting the activity\n" + - " --opengl-trace: enable tracing of OpenGL functions\n" + - " --user <USER_ID> | current: Specify which user to run as; if not\n" + - " specified then run as the current user.\n" + - "\n" + - "am startservice: start a Service. Options are:\n" + - " --user <USER_ID> | current: Specify which user to run as; if not\n" + - " specified then run as the current user.\n" + - "\n" + - "am force-stop: force stop everything associated with <PACKAGE>.\n" + - " --user <USER_ID> | all | current: Specify user to force stop;\n" + - " all users if not specified.\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" + - " --user <USER_ID> | all | current: Specify user whose processes to kill;\n" + - " all users if not specified.\n" + - "\n" + - "am kill-all: Kill all background processes.\n" + - "\n" + - "am broadcast: send a broadcast Intent. Options are:\n" + - " --user <USER_ID> | all | current: Specify which user to send to; if not\n" + - " specified then send to all users.\n" + - " --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" + - "\n" + - "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" + - " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" + - " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" + - " [-e perf true] to generate raw output for performance measurements.\n" + - " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" + - " common form is [-e <testrunner_flag> <value>[,<value>...]].\n" + - " -p <FILE>: write profiling data to <FILE>\n" + - " -w: wait for instrumentation to finish before returning. Required for\n" + - " test runners.\n" + - " --user <USER_ID> | current: Specify user instrumentation runs in;\n" + - " current user if not specified.\n" + - " --no-window-animation: turn off window animations will running.\n" + - "\n" + - "am profile: start and stop profiler on a process. The given <PROCESS> argument\n" + - " may be either a process name or pid. Options are:\n" + - " --user <USER_ID> | current: When supplying a process name,\n" + - " specify user of process to profile; uses current user if not specified.\n" + - "\n" + - "am dumpheap: dump the heap of a process. The given <PROCESS> argument may\n" + - " be either a process name or pid. Options are:\n" + - " -n: dump native heap instead of managed heap\n" + - " --user <USER_ID> | current: When supplying a process name,\n" + - " specify user of process to dump; uses current user if not specified.\n" + - "\n" + - "am set-debug-app: set application <PACKAGE> 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 bug-report: request bug report generation; will launch UI\n" + - " when done to select where it should be delivered.\n" + - "\n" + - "am monitor: start monitoring for crashes or ANRs.\n" + - " --gdb: start gdbserv on the given port at crash/ANR\n" + - "\n" + - "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" + - "\n" + - "am to-uri: print the given Intent specification as a URI.\n" + - "\n" + - "am to-intent-uri: print the given Intent specification as an intent: URI.\n" + - "\n" + - "am switch-user: switch to put USER_ID in the foreground, starting\n" + - " execution of that user if it is currently stopped.\n" + - "\n" + - "am stop-user: stop execution of USER_ID, not allowing it to run any\n" + - " code until a later explicit switch to it.\n" + - "\n" + - "<INTENT> specifications include these flags and arguments:\n" + - " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" + - " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" + - " [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" + - " [--esn <EXTRA_KEY> ...]\n" + - " [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" + - " [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" + - " [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" + - " [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" + - " [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" + - " [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" + - " [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" + - " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" + - " [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" + - " [-n <COMPONENT>] [-f <FLAGS>]\n" + - " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" + - " [--debug-log-resolution] [--exclude-stopped-packages]\n" + - " [--include-stopped-packages]\n" + - " [--activity-brought-to-front] [--activity-clear-top]\n" + - " [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" + - " [--activity-launched-from-history] [--activity-multiple-task]\n" + - " [--activity-no-animation] [--activity-no-history]\n" + - " [--activity-no-user-action] [--activity-previous-is-top]\n" + - " [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" + - " [--activity-single-top] [--activity-clear-task]\n" + - " [--activity-task-on-home]\n" + - " [--receiver-registered-only] [--receiver-replace-pending]\n" + - " [--selector]\n" + - " [<URI> | <PACKAGE> | <COMPONENT>]\n" - ); - } } |