Am.java revision dfed4bc99f9f3d48ee7bf9e8ea051a8d5bc4f299
1/* 2** 3** Copyright 2007, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18 19package com.android.commands.am; 20 21import android.app.ActivityManager; 22import android.app.ActivityManager.StackInfo; 23import android.app.ActivityManagerNative; 24import android.app.IActivityContainer; 25import android.app.IActivityController; 26import android.app.IActivityManager; 27import android.app.IInstrumentationWatcher; 28import android.app.Instrumentation; 29import android.app.UiAutomationConnection; 30import android.content.ComponentName; 31import android.content.IIntentReceiver; 32import android.content.Intent; 33import android.content.pm.IPackageManager; 34import android.content.pm.ResolveInfo; 35import android.graphics.Rect; 36import android.net.Uri; 37import android.os.Binder; 38import android.os.Build; 39import android.os.Bundle; 40import android.os.IBinder; 41import android.os.ParcelFileDescriptor; 42import android.os.RemoteException; 43import android.os.ServiceManager; 44import android.os.SystemProperties; 45import android.os.UserHandle; 46import android.util.AndroidException; 47import android.view.IWindowManager; 48import com.android.internal.os.BaseCommand; 49 50import dalvik.system.VMRuntime; 51 52import java.io.BufferedReader; 53import java.io.File; 54import java.io.FileNotFoundException; 55import java.io.IOException; 56import java.io.InputStreamReader; 57import java.io.PrintStream; 58import java.net.URISyntaxException; 59import java.util.HashSet; 60import java.util.List; 61 62public class Am extends BaseCommand { 63 64 private IActivityManager mAm; 65 66 private int mStartFlags = 0; 67 private boolean mWaitOption = false; 68 private boolean mStopOption = false; 69 70 private int mRepeat = 0; 71 private int mUserId; 72 private String mReceiverPermission; 73 74 private String mProfileFile; 75 76 /** 77 * Command-line entry point. 78 * 79 * @param args The command-line arguments 80 */ 81 public static void main(String[] args) { 82 (new Am()).run(args); 83 } 84 85 @Override 86 public void onShowUsage(PrintStream out) { 87 out.println( 88 "usage: am [subcommand] [options]\n" + 89 "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" + 90 " [--R COUNT] [-S] [--opengl-trace]\n" + 91 " [--user <USER_ID> | current] <INTENT>\n" + 92 " am startservice [--user <USER_ID> | current] <INTENT>\n" + 93 " am stopservice [--user <USER_ID> | current] <INTENT>\n" + 94 " am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" + 95 " am kill [--user <USER_ID> | all | current] <PACKAGE>\n" + 96 " am kill-all\n" + 97 " am broadcast [--user <USER_ID> | all | current] <INTENT>\n" + 98 " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" + 99 " [--user <USER_ID> | current]\n" + 100 " [--no-window-animation]\n" + 101 " [--abi <ABI>]\n : Launch the instrumented process with the " + 102 " selected ABI. This assumes that the process supports the" + 103 " selected ABI." + 104 " <COMPONENT>\n" + 105 " am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" + 106 " am profile stop [--user <USER_ID> current] [<PROCESS>]\n" + 107 " am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" + 108 " am set-debug-app [-w] [--persistent] <PACKAGE>\n" + 109 " am clear-debug-app\n" + 110 " am monitor [--gdb <port>]\n" + 111 " am hang [--allow-restart]\n" + 112 " am restart\n" + 113 " am idle-maintenance\n" + 114 " am screen-compat [on|off] <PACKAGE>\n" + 115 " am to-uri [INTENT]\n" + 116 " am to-intent-uri [INTENT]\n" + 117 " am switch-user <USER_ID>\n" + 118 " am stop-user <USER_ID>\n" + 119 " am stack start <DISPLAY_ID> <INTENT>\n" + 120 " am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" + 121 " am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" + 122 " am stack list\n" + 123 " am stack info <STACK_ID>\n" + 124 " am lock-task <TASK_ID>\n" + 125 " am lock-task stop\n" + 126 "\n" + 127 "am start: start an Activity. Options are:\n" + 128 " -D: enable debugging\n" + 129 " -W: wait for launch to complete\n" + 130 " --start-profiler <FILE>: start profiler and send results to <FILE>\n" + 131 " -P <FILE>: like above, but profiling stops when app goes idle\n" + 132 " -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" + 133 " the top activity will be finished.\n" + 134 " -S: force stop the target app before starting the activity\n" + 135 " --opengl-trace: enable tracing of OpenGL functions\n" + 136 " --user <USER_ID> | current: Specify which user to run as; if not\n" + 137 " specified then run as the current user.\n" + 138 "\n" + 139 "am startservice: start a Service. Options are:\n" + 140 " --user <USER_ID> | current: Specify which user to run as; if not\n" + 141 " specified then run as the current user.\n" + 142 "\n" + 143 "am stopservice: stop a Service. Options are:\n" + 144 " --user <USER_ID> | current: Specify which user to run as; if not\n" + 145 " specified then run as the current user.\n" + 146 "\n" + 147 "am force-stop: force stop everything associated with <PACKAGE>.\n" + 148 " --user <USER_ID> | all | current: Specify user to force stop;\n" + 149 " all users if not specified.\n" + 150 "\n" + 151 "am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" + 152 " processes that are safe to kill -- that is, will not impact the user\n" + 153 " experience.\n" + 154 " --user <USER_ID> | all | current: Specify user whose processes to kill;\n" + 155 " all users if not specified.\n" + 156 "\n" + 157 "am kill-all: Kill all background processes.\n" + 158 "\n" + 159 "am broadcast: send a broadcast Intent. Options are:\n" + 160 " --user <USER_ID> | all | current: Specify which user to send to; if not\n" + 161 " specified then send to all users.\n" + 162 " --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" + 163 "\n" + 164 "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" + 165 " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" + 166 " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" + 167 " [-e perf true] to generate raw output for performance measurements.\n" + 168 " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" + 169 " common form is [-e <testrunner_flag> <value>[,<value>...]].\n" + 170 " -p <FILE>: write profiling data to <FILE>\n" + 171 " -w: wait for instrumentation to finish before returning. Required for\n" + 172 " test runners.\n" + 173 " --user <USER_ID> | current: Specify user instrumentation runs in;\n" + 174 " current user if not specified.\n" + 175 " --no-window-animation: turn off window animations while running.\n" + 176 "\n" + 177 "am profile: start and stop profiler on a process. The given <PROCESS> argument\n" + 178 " may be either a process name or pid. Options are:\n" + 179 " --user <USER_ID> | current: When supplying a process name,\n" + 180 " specify user of process to profile; uses current user if not specified.\n" + 181 "\n" + 182 "am dumpheap: dump the heap of a process. The given <PROCESS> argument may\n" + 183 " be either a process name or pid. Options are:\n" + 184 " -n: dump native heap instead of managed heap\n" + 185 " --user <USER_ID> | current: When supplying a process name,\n" + 186 " specify user of process to dump; uses current user if not specified.\n" + 187 "\n" + 188 "am set-debug-app: set application <PACKAGE> to debug. Options are:\n" + 189 " -w: wait for debugger when application starts\n" + 190 " --persistent: retain this value\n" + 191 "\n" + 192 "am clear-debug-app: clear the previously set-debug-app.\n" + 193 "\n" + 194 "am bug-report: request bug report generation; will launch UI\n" + 195 " when done to select where it should be delivered.\n" + 196 "\n" + 197 "am monitor: start monitoring for crashes or ANRs.\n" + 198 " --gdb: start gdbserv on the given port at crash/ANR\n" + 199 "\n" + 200 "am hang: hang the system.\n" + 201 " --allow-restart: allow watchdog to perform normal system restart\n" + 202 "\n" + 203 "am restart: restart the user-space system.\n" + 204 "\n" + 205 "am idle-maintenance: perform idle maintenance now.\n" + 206 "\n" + 207 "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" + 208 "\n" + 209 "am to-uri: print the given Intent specification as a URI.\n" + 210 "\n" + 211 "am to-intent-uri: print the given Intent specification as an intent: URI.\n" + 212 "\n" + 213 "am switch-user: switch to put USER_ID in the foreground, starting\n" + 214 " execution of that user if it is currently stopped.\n" + 215 "\n" + 216 "am stop-user: stop execution of USER_ID, not allowing it to run any\n" + 217 " code until a later explicit switch to it.\n" + 218 "\n" + 219 "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" + 220 "\n" + 221 "am stack movetask: move <TASK_ID> from its current stack to the top (true) or" + 222 " bottom (false) of <STACK_ID>.\n" + 223 "\n" + 224 "am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.\n" + 225 "\n" + 226 "am stack list: list all of the activity stacks and their sizes.\n" + 227 "\n" + 228 "am stack info: display the information about activity stack <STACK_ID>.\n" + 229 "\n" + 230 "am lock-task: bring <TASK_ID> to the front and don't allow other tasks to run\n" + 231 "\n" + 232 "<INTENT> specifications include these flags and arguments:\n" + 233 " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" + 234 " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" + 235 " [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" + 236 " [--esn <EXTRA_KEY> ...]\n" + 237 " [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" + 238 " [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" + 239 " [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" + 240 " [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" + 241 " [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" + 242 " [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" + 243 " [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" + 244 " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" + 245 " [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" + 246 " [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]\n" + 247 " (to embed a comma into a string escape it using \"\\,\")\n" + 248 " [-n <COMPONENT>] [-f <FLAGS>]\n" + 249 " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" + 250 " [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]\n" + 251 " [--debug-log-resolution] [--exclude-stopped-packages]\n" + 252 " [--include-stopped-packages]\n" + 253 " [--activity-brought-to-front] [--activity-clear-top]\n" + 254 " [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" + 255 " [--activity-launched-from-history] [--activity-multiple-task]\n" + 256 " [--activity-no-animation] [--activity-no-history]\n" + 257 " [--activity-no-user-action] [--activity-previous-is-top]\n" + 258 " [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" + 259 " [--activity-single-top] [--activity-clear-task]\n" + 260 " [--activity-task-on-home]\n" + 261 " [--receiver-registered-only] [--receiver-replace-pending]\n" + 262 " [--selector]\n" + 263 " [<URI> | <PACKAGE> | <COMPONENT>]\n" 264 ); 265 } 266 267 @Override 268 public void onRun() throws Exception { 269 270 mAm = ActivityManagerNative.getDefault(); 271 if (mAm == null) { 272 System.err.println(NO_SYSTEM_ERROR_CODE); 273 throw new AndroidException("Can't connect to activity manager; is the system running?"); 274 } 275 276 String op = nextArgRequired(); 277 278 if (op.equals("start")) { 279 runStart(); 280 } else if (op.equals("startservice")) { 281 runStartService(); 282 } else if (op.equals("stopservice")) { 283 runStopService(); 284 } else if (op.equals("force-stop")) { 285 runForceStop(); 286 } else if (op.equals("kill")) { 287 runKill(); 288 } else if (op.equals("kill-all")) { 289 runKillAll(); 290 } else if (op.equals("instrument")) { 291 runInstrument(); 292 } else if (op.equals("broadcast")) { 293 sendBroadcast(); 294 } else if (op.equals("profile")) { 295 runProfile(); 296 } else if (op.equals("dumpheap")) { 297 runDumpHeap(); 298 } else if (op.equals("set-debug-app")) { 299 runSetDebugApp(); 300 } else if (op.equals("clear-debug-app")) { 301 runClearDebugApp(); 302 } else if (op.equals("bug-report")) { 303 runBugReport(); 304 } else if (op.equals("monitor")) { 305 runMonitor(); 306 } else if (op.equals("hang")) { 307 runHang(); 308 } else if (op.equals("restart")) { 309 runRestart(); 310 } else if (op.equals("idle-maintenance")) { 311 runIdleMaintenance(); 312 } else if (op.equals("screen-compat")) { 313 runScreenCompat(); 314 } else if (op.equals("to-uri")) { 315 runToUri(false); 316 } else if (op.equals("to-intent-uri")) { 317 runToUri(true); 318 } else if (op.equals("switch-user")) { 319 runSwitchUser(); 320 } else if (op.equals("stop-user")) { 321 runStopUser(); 322 } else if (op.equals("stack")) { 323 runStack(); 324 } else if (op.equals("lock-task")) { 325 runLockTask(); 326 } else { 327 showError("Error: unknown command '" + op + "'"); 328 } 329 } 330 331 int parseUserArg(String arg) { 332 int userId; 333 if ("all".equals(arg)) { 334 userId = UserHandle.USER_ALL; 335 } else if ("current".equals(arg) || "cur".equals(arg)) { 336 userId = UserHandle.USER_CURRENT; 337 } else { 338 userId = Integer.parseInt(arg); 339 } 340 return userId; 341 } 342 343 private Intent makeIntent(int defUser) throws URISyntaxException { 344 Intent intent = new Intent(); 345 Intent baseIntent = intent; 346 boolean hasIntentInfo = false; 347 348 mStartFlags = 0; 349 mWaitOption = false; 350 mStopOption = false; 351 mRepeat = 0; 352 mProfileFile = null; 353 mUserId = defUser; 354 Uri data = null; 355 String type = null; 356 357 String opt; 358 while ((opt=nextOption()) != null) { 359 if (opt.equals("-a")) { 360 intent.setAction(nextArgRequired()); 361 if (intent == baseIntent) { 362 hasIntentInfo = true; 363 } 364 } else if (opt.equals("-d")) { 365 data = Uri.parse(nextArgRequired()); 366 if (intent == baseIntent) { 367 hasIntentInfo = true; 368 } 369 } else if (opt.equals("-t")) { 370 type = nextArgRequired(); 371 if (intent == baseIntent) { 372 hasIntentInfo = true; 373 } 374 } else if (opt.equals("-c")) { 375 intent.addCategory(nextArgRequired()); 376 if (intent == baseIntent) { 377 hasIntentInfo = true; 378 } 379 } else if (opt.equals("-e") || opt.equals("--es")) { 380 String key = nextArgRequired(); 381 String value = nextArgRequired(); 382 intent.putExtra(key, value); 383 } else if (opt.equals("--esn")) { 384 String key = nextArgRequired(); 385 intent.putExtra(key, (String) null); 386 } else if (opt.equals("--ei")) { 387 String key = nextArgRequired(); 388 String value = nextArgRequired(); 389 intent.putExtra(key, Integer.valueOf(value)); 390 } else if (opt.equals("--eu")) { 391 String key = nextArgRequired(); 392 String value = nextArgRequired(); 393 intent.putExtra(key, Uri.parse(value)); 394 } else if (opt.equals("--ecn")) { 395 String key = nextArgRequired(); 396 String value = nextArgRequired(); 397 ComponentName cn = ComponentName.unflattenFromString(value); 398 if (cn == null) throw new IllegalArgumentException("Bad component name: " + value); 399 intent.putExtra(key, cn); 400 } else if (opt.equals("--eia")) { 401 String key = nextArgRequired(); 402 String value = nextArgRequired(); 403 String[] strings = value.split(","); 404 int[] list = new int[strings.length]; 405 for (int i = 0; i < strings.length; i++) { 406 list[i] = Integer.valueOf(strings[i]); 407 } 408 intent.putExtra(key, list); 409 } else if (opt.equals("--el")) { 410 String key = nextArgRequired(); 411 String value = nextArgRequired(); 412 intent.putExtra(key, Long.valueOf(value)); 413 } else if (opt.equals("--ela")) { 414 String key = nextArgRequired(); 415 String value = nextArgRequired(); 416 String[] strings = value.split(","); 417 long[] list = new long[strings.length]; 418 for (int i = 0; i < strings.length; i++) { 419 list[i] = Long.valueOf(strings[i]); 420 } 421 intent.putExtra(key, list); 422 hasIntentInfo = true; 423 } else if (opt.equals("--ef")) { 424 String key = nextArgRequired(); 425 String value = nextArgRequired(); 426 intent.putExtra(key, Float.valueOf(value)); 427 hasIntentInfo = true; 428 } else if (opt.equals("--efa")) { 429 String key = nextArgRequired(); 430 String value = nextArgRequired(); 431 String[] strings = value.split(","); 432 float[] list = new float[strings.length]; 433 for (int i = 0; i < strings.length; i++) { 434 list[i] = Float.valueOf(strings[i]); 435 } 436 intent.putExtra(key, list); 437 hasIntentInfo = true; 438 } else if (opt.equals("--esa")) { 439 String key = nextArgRequired(); 440 String value = nextArgRequired(); 441 // Split on commas unless they are preceeded by an escape. 442 // The escape character must be escaped for the string and 443 // again for the regex, thus four escape characters become one. 444 String[] strings = value.split("(?<!\\\\),"); 445 intent.putExtra(key, strings); 446 hasIntentInfo = true; 447 } else if (opt.equals("--ez")) { 448 String key = nextArgRequired(); 449 String value = nextArgRequired(); 450 intent.putExtra(key, Boolean.valueOf(value)); 451 } else if (opt.equals("-n")) { 452 String str = nextArgRequired(); 453 ComponentName cn = ComponentName.unflattenFromString(str); 454 if (cn == null) throw new IllegalArgumentException("Bad component name: " + str); 455 intent.setComponent(cn); 456 if (intent == baseIntent) { 457 hasIntentInfo = true; 458 } 459 } else if (opt.equals("-f")) { 460 String str = nextArgRequired(); 461 intent.setFlags(Integer.decode(str).intValue()); 462 } else if (opt.equals("--grant-read-uri-permission")) { 463 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 464 } else if (opt.equals("--grant-write-uri-permission")) { 465 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 466 } else if (opt.equals("--grant-persistable-uri-permission")) { 467 intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); 468 } else if (opt.equals("--grant-prefix-uri-permission")) { 469 intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); 470 } else if (opt.equals("--exclude-stopped-packages")) { 471 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); 472 } else if (opt.equals("--include-stopped-packages")) { 473 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 474 } else if (opt.equals("--debug-log-resolution")) { 475 intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION); 476 } else if (opt.equals("--activity-brought-to-front")) { 477 intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); 478 } else if (opt.equals("--activity-clear-top")) { 479 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 480 } else if (opt.equals("--activity-clear-when-task-reset")) { 481 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 482 } else if (opt.equals("--activity-exclude-from-recents")) { 483 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 484 } else if (opt.equals("--activity-launched-from-history")) { 485 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY); 486 } else if (opt.equals("--activity-multiple-task")) { 487 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 488 } else if (opt.equals("--activity-no-animation")) { 489 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); 490 } else if (opt.equals("--activity-no-history")) { 491 intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 492 } else if (opt.equals("--activity-no-user-action")) { 493 intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION); 494 } else if (opt.equals("--activity-previous-is-top")) { 495 intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); 496 } else if (opt.equals("--activity-reorder-to-front")) { 497 intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 498 } else if (opt.equals("--activity-reset-task-if-needed")) { 499 intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 500 } else if (opt.equals("--activity-single-top")) { 501 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 502 } else if (opt.equals("--activity-clear-task")) { 503 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 504 } else if (opt.equals("--activity-task-on-home")) { 505 intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME); 506 } else if (opt.equals("--receiver-registered-only")) { 507 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 508 } else if (opt.equals("--receiver-replace-pending")) { 509 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 510 } else if (opt.equals("--selector")) { 511 intent.setDataAndType(data, type); 512 intent = new Intent(); 513 } else if (opt.equals("-D")) { 514 mStartFlags |= ActivityManager.START_FLAG_DEBUG; 515 } else if (opt.equals("-W")) { 516 mWaitOption = true; 517 } else if (opt.equals("-P")) { 518 mProfileFile = nextArgRequired(); 519 mStartFlags |= ActivityManager.START_FLAG_AUTO_STOP_PROFILER; 520 } else if (opt.equals("--start-profiler")) { 521 mProfileFile = nextArgRequired(); 522 mStartFlags &= ~ActivityManager.START_FLAG_AUTO_STOP_PROFILER; 523 } else if (opt.equals("-R")) { 524 mRepeat = Integer.parseInt(nextArgRequired()); 525 } else if (opt.equals("-S")) { 526 mStopOption = true; 527 } else if (opt.equals("--opengl-trace")) { 528 mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES; 529 } else if (opt.equals("--user")) { 530 mUserId = parseUserArg(nextArgRequired()); 531 } else if (opt.equals("--receiver-permission")) { 532 mReceiverPermission = nextArgRequired(); 533 } else { 534 System.err.println("Error: Unknown option: " + opt); 535 return null; 536 } 537 } 538 intent.setDataAndType(data, type); 539 540 final boolean hasSelector = intent != baseIntent; 541 if (hasSelector) { 542 // A selector was specified; fix up. 543 baseIntent.setSelector(intent); 544 intent = baseIntent; 545 } 546 547 String arg = nextArg(); 548 baseIntent = null; 549 if (arg == null) { 550 if (hasSelector) { 551 // If a selector has been specified, and no arguments 552 // have been supplied for the main Intent, then we can 553 // assume it is ACTION_MAIN CATEGORY_LAUNCHER; we don't 554 // need to have a component name specified yet, the 555 // selector will take care of that. 556 baseIntent = new Intent(Intent.ACTION_MAIN); 557 baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); 558 } 559 } else if (arg.indexOf(':') >= 0) { 560 // The argument is a URI. Fully parse it, and use that result 561 // to fill in any data not specified so far. 562 baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME); 563 } else if (arg.indexOf('/') >= 0) { 564 // The argument is a component name. Build an Intent to launch 565 // it. 566 baseIntent = new Intent(Intent.ACTION_MAIN); 567 baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); 568 baseIntent.setComponent(ComponentName.unflattenFromString(arg)); 569 } else { 570 // Assume the argument is a package name. 571 baseIntent = new Intent(Intent.ACTION_MAIN); 572 baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); 573 baseIntent.setPackage(arg); 574 } 575 if (baseIntent != null) { 576 Bundle extras = intent.getExtras(); 577 intent.replaceExtras((Bundle)null); 578 Bundle uriExtras = baseIntent.getExtras(); 579 baseIntent.replaceExtras((Bundle)null); 580 if (intent.getAction() != null && baseIntent.getCategories() != null) { 581 HashSet<String> cats = new HashSet<String>(baseIntent.getCategories()); 582 for (String c : cats) { 583 baseIntent.removeCategory(c); 584 } 585 } 586 intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR); 587 if (extras == null) { 588 extras = uriExtras; 589 } else if (uriExtras != null) { 590 uriExtras.putAll(extras); 591 extras = uriExtras; 592 } 593 intent.replaceExtras(extras); 594 hasIntentInfo = true; 595 } 596 597 if (!hasIntentInfo) throw new IllegalArgumentException("No intent supplied"); 598 return intent; 599 } 600 601 private void runStartService() throws Exception { 602 Intent intent = makeIntent(UserHandle.USER_CURRENT); 603 if (mUserId == UserHandle.USER_ALL) { 604 System.err.println("Error: Can't start activity with user 'all'"); 605 return; 606 } 607 System.out.println("Starting service: " + intent); 608 ComponentName cn = mAm.startService(null, intent, intent.getType(), mUserId); 609 if (cn == null) { 610 System.err.println("Error: Not found; no service started."); 611 } else if (cn.getPackageName().equals("!")) { 612 System.err.println("Error: Requires permission " + cn.getClassName()); 613 } else if (cn.getPackageName().equals("!!")) { 614 System.err.println("Error: " + cn.getClassName()); 615 } 616 } 617 618 private void runStopService() throws Exception { 619 Intent intent = makeIntent(UserHandle.USER_CURRENT); 620 if (mUserId == UserHandle.USER_ALL) { 621 System.err.println("Error: Can't stop activity with user 'all'"); 622 return; 623 } 624 System.out.println("Stopping service: " + intent); 625 int result = mAm.stopService(null, intent, intent.getType(), mUserId); 626 if (result == 0) { 627 System.err.println("Service not stopped: was not running."); 628 } else if (result == 1) { 629 System.err.println("Service stopped"); 630 } else if (result == -1) { 631 System.err.println("Error stopping service"); 632 } 633 } 634 635 private void runStart() throws Exception { 636 Intent intent = makeIntent(UserHandle.USER_CURRENT); 637 638 if (mUserId == UserHandle.USER_ALL) { 639 System.err.println("Error: Can't start service with user 'all'"); 640 return; 641 } 642 643 String mimeType = intent.getType(); 644 if (mimeType == null && intent.getData() != null 645 && "content".equals(intent.getData().getScheme())) { 646 mimeType = mAm.getProviderMimeType(intent.getData(), mUserId); 647 } 648 649 do { 650 if (mStopOption) { 651 String packageName; 652 if (intent.getComponent() != null) { 653 packageName = intent.getComponent().getPackageName(); 654 } else { 655 IPackageManager pm = IPackageManager.Stub.asInterface( 656 ServiceManager.getService("package")); 657 if (pm == null) { 658 System.err.println("Error: Package manager not running; aborting"); 659 return; 660 } 661 List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0, 662 mUserId); 663 if (activities == null || activities.size() <= 0) { 664 System.err.println("Error: Intent does not match any activities: " 665 + intent); 666 return; 667 } else if (activities.size() > 1) { 668 System.err.println("Error: Intent matches multiple activities; can't stop: " 669 + intent); 670 return; 671 } 672 packageName = activities.get(0).activityInfo.packageName; 673 } 674 System.out.println("Stopping: " + packageName); 675 mAm.forceStopPackage(packageName, mUserId); 676 Thread.sleep(250); 677 } 678 679 System.out.println("Starting: " + intent); 680 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 681 682 ParcelFileDescriptor fd = null; 683 684 if (mProfileFile != null) { 685 try { 686 fd = ParcelFileDescriptor.open( 687 new File(mProfileFile), 688 ParcelFileDescriptor.MODE_CREATE | 689 ParcelFileDescriptor.MODE_TRUNCATE | 690 ParcelFileDescriptor.MODE_READ_WRITE); 691 } catch (FileNotFoundException e) { 692 System.err.println("Error: Unable to open file: " + mProfileFile); 693 return; 694 } 695 } 696 697 IActivityManager.WaitResult result = null; 698 int res; 699 if (mWaitOption) { 700 result = mAm.startActivityAndWait(null, null, intent, mimeType, 701 null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId); 702 res = result.result; 703 } else { 704 res = mAm.startActivityAsUser(null, null, intent, mimeType, 705 null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId); 706 } 707 PrintStream out = mWaitOption ? System.out : System.err; 708 boolean launched = false; 709 switch (res) { 710 case ActivityManager.START_SUCCESS: 711 launched = true; 712 break; 713 case ActivityManager.START_SWITCHES_CANCELED: 714 launched = true; 715 out.println( 716 "Warning: Activity not started because the " 717 + " current activity is being kept for the user."); 718 break; 719 case ActivityManager.START_DELIVERED_TO_TOP: 720 launched = true; 721 out.println( 722 "Warning: Activity not started, intent has " 723 + "been delivered to currently running " 724 + "top-most instance."); 725 break; 726 case ActivityManager.START_RETURN_INTENT_TO_CALLER: 727 launched = true; 728 out.println( 729 "Warning: Activity not started because intent " 730 + "should be handled by the caller"); 731 break; 732 case ActivityManager.START_TASK_TO_FRONT: 733 launched = true; 734 out.println( 735 "Warning: Activity not started, its current " 736 + "task has been brought to the front"); 737 break; 738 case ActivityManager.START_INTENT_NOT_RESOLVED: 739 out.println( 740 "Error: Activity not started, unable to " 741 + "resolve " + intent.toString()); 742 break; 743 case ActivityManager.START_CLASS_NOT_FOUND: 744 out.println(NO_CLASS_ERROR_CODE); 745 out.println("Error: Activity class " + 746 intent.getComponent().toShortString() 747 + " does not exist."); 748 break; 749 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: 750 out.println( 751 "Error: Activity not started, you requested to " 752 + "both forward and receive its result"); 753 break; 754 case ActivityManager.START_PERMISSION_DENIED: 755 out.println( 756 "Error: Activity not started, you do not " 757 + "have permission to access it."); 758 break; 759 case ActivityManager.START_NOT_VOICE_COMPATIBLE: 760 out.println( 761 "Error: Activity not started, voice control not allowed for: " 762 + intent); 763 break; 764 default: 765 out.println( 766 "Error: Activity not started, unknown error code " + res); 767 break; 768 } 769 if (mWaitOption && launched) { 770 if (result == null) { 771 result = new IActivityManager.WaitResult(); 772 result.who = intent.getComponent(); 773 } 774 System.out.println("Status: " + (result.timeout ? "timeout" : "ok")); 775 if (result.who != null) { 776 System.out.println("Activity: " + result.who.flattenToShortString()); 777 } 778 if (result.thisTime >= 0) { 779 System.out.println("ThisTime: " + result.thisTime); 780 } 781 if (result.totalTime >= 0) { 782 System.out.println("TotalTime: " + result.totalTime); 783 } 784 System.out.println("Complete"); 785 } 786 mRepeat--; 787 if (mRepeat > 1) { 788 mAm.unhandledBack(); 789 } 790 } while (mRepeat > 1); 791 } 792 793 private void runForceStop() throws Exception { 794 int userId = UserHandle.USER_ALL; 795 796 String opt; 797 while ((opt=nextOption()) != null) { 798 if (opt.equals("--user")) { 799 userId = parseUserArg(nextArgRequired()); 800 } else { 801 System.err.println("Error: Unknown option: " + opt); 802 return; 803 } 804 } 805 mAm.forceStopPackage(nextArgRequired(), userId); 806 } 807 808 private void runKill() throws Exception { 809 int userId = UserHandle.USER_ALL; 810 811 String opt; 812 while ((opt=nextOption()) != null) { 813 if (opt.equals("--user")) { 814 userId = parseUserArg(nextArgRequired()); 815 } else { 816 System.err.println("Error: Unknown option: " + opt); 817 return; 818 } 819 } 820 mAm.killBackgroundProcesses(nextArgRequired(), userId); 821 } 822 823 private void runKillAll() throws Exception { 824 mAm.killAllBackgroundProcesses(); 825 } 826 827 private void sendBroadcast() throws Exception { 828 Intent intent = makeIntent(UserHandle.USER_ALL); 829 IntentReceiver receiver = new IntentReceiver(); 830 System.out.println("Broadcasting: " + intent); 831 mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, mReceiverPermission, 832 android.app.AppOpsManager.OP_NONE, true, false, mUserId); 833 receiver.waitForFinish(); 834 } 835 836 private void runInstrument() throws Exception { 837 String profileFile = null; 838 boolean wait = false; 839 boolean rawMode = false; 840 boolean no_window_animation = false; 841 int userId = UserHandle.USER_CURRENT; 842 Bundle args = new Bundle(); 843 String argKey = null, argValue = null; 844 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 845 String abi = null; 846 847 String opt; 848 while ((opt=nextOption()) != null) { 849 if (opt.equals("-p")) { 850 profileFile = nextArgRequired(); 851 } else if (opt.equals("-w")) { 852 wait = true; 853 } else if (opt.equals("-r")) { 854 rawMode = true; 855 } else if (opt.equals("-e")) { 856 argKey = nextArgRequired(); 857 argValue = nextArgRequired(); 858 args.putString(argKey, argValue); 859 } else if (opt.equals("--no_window_animation") 860 || opt.equals("--no-window-animation")) { 861 no_window_animation = true; 862 } else if (opt.equals("--user")) { 863 userId = parseUserArg(nextArgRequired()); 864 } else if (opt.equals("--abi")) { 865 abi = nextArgRequired(); 866 } else { 867 System.err.println("Error: Unknown option: " + opt); 868 return; 869 } 870 } 871 872 if (userId == UserHandle.USER_ALL) { 873 System.err.println("Error: Can't start instrumentation with user 'all'"); 874 return; 875 } 876 877 String cnArg = nextArgRequired(); 878 ComponentName cn = ComponentName.unflattenFromString(cnArg); 879 if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg); 880 881 InstrumentationWatcher watcher = null; 882 UiAutomationConnection connection = null; 883 if (wait) { 884 watcher = new InstrumentationWatcher(); 885 watcher.setRawOutput(rawMode); 886 connection = new UiAutomationConnection(); 887 } 888 889 float[] oldAnims = null; 890 if (no_window_animation) { 891 oldAnims = wm.getAnimationScales(); 892 wm.setAnimationScale(0, 0.0f); 893 wm.setAnimationScale(1, 0.0f); 894 } 895 896 if (abi != null) { 897 final String[] supportedAbis = Build.SUPPORTED_ABIS; 898 boolean matched = false; 899 for (String supportedAbi : supportedAbis) { 900 if (supportedAbi.equals(abi)) { 901 matched = true; 902 break; 903 } 904 } 905 906 if (!matched) { 907 throw new AndroidException( 908 "INSTRUMENTATION_FAILED: Unsupported instruction set " + abi); 909 } 910 } 911 912 if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, 913 abi)) { 914 throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString()); 915 } 916 917 if (watcher != null) { 918 if (!watcher.waitForFinish()) { 919 System.out.println("INSTRUMENTATION_ABORTED: System has crashed."); 920 } 921 } 922 923 if (oldAnims != null) { 924 wm.setAnimationScales(oldAnims); 925 } 926 } 927 928 static void removeWallOption() { 929 String props = SystemProperties.get("dalvik.vm.extra-opts"); 930 if (props != null && props.contains("-Xprofile:wallclock")) { 931 props = props.replace("-Xprofile:wallclock", ""); 932 props = props.trim(); 933 SystemProperties.set("dalvik.vm.extra-opts", props); 934 } 935 } 936 937 private void runProfile() throws Exception { 938 String profileFile = null; 939 boolean start = false; 940 boolean wall = false; 941 int userId = UserHandle.USER_CURRENT; 942 int profileType = 0; 943 944 String process = null; 945 946 String cmd = nextArgRequired(); 947 948 if ("start".equals(cmd)) { 949 start = true; 950 String opt; 951 while ((opt=nextOption()) != null) { 952 if (opt.equals("--user")) { 953 userId = parseUserArg(nextArgRequired()); 954 } else if (opt.equals("--wall")) { 955 wall = true; 956 } else { 957 System.err.println("Error: Unknown option: " + opt); 958 return; 959 } 960 } 961 process = nextArgRequired(); 962 } else if ("stop".equals(cmd)) { 963 String opt; 964 while ((opt=nextOption()) != null) { 965 if (opt.equals("--user")) { 966 userId = parseUserArg(nextArgRequired()); 967 } else { 968 System.err.println("Error: Unknown option: " + opt); 969 return; 970 } 971 } 972 process = nextArg(); 973 } else { 974 // Compatibility with old syntax: process is specified first. 975 process = cmd; 976 cmd = nextArgRequired(); 977 if ("start".equals(cmd)) { 978 start = true; 979 } else if (!"stop".equals(cmd)) { 980 throw new IllegalArgumentException("Profile command " + process + " not valid"); 981 } 982 } 983 984 if (userId == UserHandle.USER_ALL) { 985 System.err.println("Error: Can't profile with user 'all'"); 986 return; 987 } 988 989 ParcelFileDescriptor fd = null; 990 991 if (start) { 992 profileFile = nextArgRequired(); 993 try { 994 fd = ParcelFileDescriptor.open( 995 new File(profileFile), 996 ParcelFileDescriptor.MODE_CREATE | 997 ParcelFileDescriptor.MODE_TRUNCATE | 998 ParcelFileDescriptor.MODE_READ_WRITE); 999 } catch (FileNotFoundException e) { 1000 System.err.println("Error: Unable to open file: " + profileFile); 1001 return; 1002 } 1003 } 1004 1005 try { 1006 if (wall) { 1007 // XXX doesn't work -- this needs to be set before booting. 1008 String props = SystemProperties.get("dalvik.vm.extra-opts"); 1009 if (props == null || !props.contains("-Xprofile:wallclock")) { 1010 props = props + " -Xprofile:wallclock"; 1011 //SystemProperties.set("dalvik.vm.extra-opts", props); 1012 } 1013 } else if (start) { 1014 //removeWallOption(); 1015 } 1016 if (!mAm.profileControl(process, userId, start, profileFile, fd, profileType)) { 1017 wall = false; 1018 throw new AndroidException("PROFILE FAILED on process " + process); 1019 } 1020 } finally { 1021 if (!wall) { 1022 //removeWallOption(); 1023 } 1024 } 1025 } 1026 1027 private void runDumpHeap() throws Exception { 1028 boolean managed = true; 1029 int userId = UserHandle.USER_CURRENT; 1030 1031 String opt; 1032 while ((opt=nextOption()) != null) { 1033 if (opt.equals("--user")) { 1034 userId = parseUserArg(nextArgRequired()); 1035 if (userId == UserHandle.USER_ALL) { 1036 System.err.println("Error: Can't dump heap with user 'all'"); 1037 return; 1038 } 1039 } else if (opt.equals("-n")) { 1040 managed = false; 1041 } else { 1042 System.err.println("Error: Unknown option: " + opt); 1043 return; 1044 } 1045 } 1046 String process = nextArgRequired(); 1047 String heapFile = nextArgRequired(); 1048 ParcelFileDescriptor fd = null; 1049 1050 try { 1051 File file = new File(heapFile); 1052 file.delete(); 1053 fd = ParcelFileDescriptor.open(file, 1054 ParcelFileDescriptor.MODE_CREATE | 1055 ParcelFileDescriptor.MODE_TRUNCATE | 1056 ParcelFileDescriptor.MODE_READ_WRITE); 1057 } catch (FileNotFoundException e) { 1058 System.err.println("Error: Unable to open file: " + heapFile); 1059 return; 1060 } 1061 1062 if (!mAm.dumpHeap(process, userId, managed, heapFile, fd)) { 1063 throw new AndroidException("HEAP DUMP FAILED on process " + process); 1064 } 1065 } 1066 1067 private void runSetDebugApp() throws Exception { 1068 boolean wait = false; 1069 boolean persistent = false; 1070 1071 String opt; 1072 while ((opt=nextOption()) != null) { 1073 if (opt.equals("-w")) { 1074 wait = true; 1075 } else if (opt.equals("--persistent")) { 1076 persistent = true; 1077 } else { 1078 System.err.println("Error: Unknown option: " + opt); 1079 return; 1080 } 1081 } 1082 1083 String pkg = nextArgRequired(); 1084 mAm.setDebugApp(pkg, wait, persistent); 1085 } 1086 1087 private void runClearDebugApp() throws Exception { 1088 mAm.setDebugApp(null, false, true); 1089 } 1090 1091 private void runBugReport() throws Exception { 1092 mAm.requestBugReport(); 1093 System.out.println("Your lovely bug report is being created; please be patient."); 1094 } 1095 1096 private void runSwitchUser() throws Exception { 1097 String user = nextArgRequired(); 1098 mAm.switchUser(Integer.parseInt(user)); 1099 } 1100 1101 private void runStopUser() throws Exception { 1102 String user = nextArgRequired(); 1103 int res = mAm.stopUser(Integer.parseInt(user), null); 1104 if (res != ActivityManager.USER_OP_SUCCESS) { 1105 String txt = ""; 1106 switch (res) { 1107 case ActivityManager.USER_OP_IS_CURRENT: 1108 txt = " (Can't stop current user)"; 1109 break; 1110 case ActivityManager.USER_OP_UNKNOWN_USER: 1111 txt = " (Unknown user " + user + ")"; 1112 break; 1113 } 1114 System.err.println("Switch failed: " + res + txt); 1115 } 1116 } 1117 1118 class MyActivityController extends IActivityController.Stub { 1119 final String mGdbPort; 1120 1121 static final int STATE_NORMAL = 0; 1122 static final int STATE_CRASHED = 1; 1123 static final int STATE_EARLY_ANR = 2; 1124 static final int STATE_ANR = 3; 1125 1126 int mState; 1127 1128 static final int RESULT_DEFAULT = 0; 1129 1130 static final int RESULT_CRASH_DIALOG = 0; 1131 static final int RESULT_CRASH_KILL = 1; 1132 1133 static final int RESULT_EARLY_ANR_CONTINUE = 0; 1134 static final int RESULT_EARLY_ANR_KILL = 1; 1135 1136 static final int RESULT_ANR_DIALOG = 0; 1137 static final int RESULT_ANR_KILL = 1; 1138 static final int RESULT_ANR_WAIT = 1; 1139 1140 int mResult; 1141 1142 Process mGdbProcess; 1143 Thread mGdbThread; 1144 boolean mGotGdbPrint; 1145 1146 MyActivityController(String gdbPort) { 1147 mGdbPort = gdbPort; 1148 } 1149 1150 @Override 1151 public boolean activityResuming(String pkg) { 1152 synchronized (this) { 1153 System.out.println("** Activity resuming: " + pkg); 1154 } 1155 return true; 1156 } 1157 1158 @Override 1159 public boolean activityStarting(Intent intent, String pkg) { 1160 synchronized (this) { 1161 System.out.println("** Activity starting: " + pkg); 1162 } 1163 return true; 1164 } 1165 1166 @Override 1167 public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg, 1168 long timeMillis, String stackTrace) { 1169 synchronized (this) { 1170 System.out.println("** ERROR: PROCESS CRASHED"); 1171 System.out.println("processName: " + processName); 1172 System.out.println("processPid: " + pid); 1173 System.out.println("shortMsg: " + shortMsg); 1174 System.out.println("longMsg: " + longMsg); 1175 System.out.println("timeMillis: " + timeMillis); 1176 System.out.println("stack:"); 1177 System.out.print(stackTrace); 1178 System.out.println("#"); 1179 int result = waitControllerLocked(pid, STATE_CRASHED); 1180 return result == RESULT_CRASH_KILL ? false : true; 1181 } 1182 } 1183 1184 @Override 1185 public int appEarlyNotResponding(String processName, int pid, String annotation) { 1186 synchronized (this) { 1187 System.out.println("** ERROR: EARLY PROCESS NOT RESPONDING"); 1188 System.out.println("processName: " + processName); 1189 System.out.println("processPid: " + pid); 1190 System.out.println("annotation: " + annotation); 1191 int result = waitControllerLocked(pid, STATE_EARLY_ANR); 1192 if (result == RESULT_EARLY_ANR_KILL) return -1; 1193 return 0; 1194 } 1195 } 1196 1197 @Override 1198 public int appNotResponding(String processName, int pid, String processStats) { 1199 synchronized (this) { 1200 System.out.println("** ERROR: PROCESS NOT RESPONDING"); 1201 System.out.println("processName: " + processName); 1202 System.out.println("processPid: " + pid); 1203 System.out.println("processStats:"); 1204 System.out.print(processStats); 1205 System.out.println("#"); 1206 int result = waitControllerLocked(pid, STATE_ANR); 1207 if (result == RESULT_ANR_KILL) return -1; 1208 if (result == RESULT_ANR_WAIT) return 1; 1209 return 0; 1210 } 1211 } 1212 1213 @Override 1214 public int systemNotResponding(String message) { 1215 synchronized (this) { 1216 System.out.println("** ERROR: PROCESS NOT RESPONDING"); 1217 System.out.println("message: " + message); 1218 System.out.println("#"); 1219 System.out.println("Allowing system to die."); 1220 return -1; 1221 } 1222 } 1223 1224 void killGdbLocked() { 1225 mGotGdbPrint = false; 1226 if (mGdbProcess != null) { 1227 System.out.println("Stopping gdbserver"); 1228 mGdbProcess.destroy(); 1229 mGdbProcess = null; 1230 } 1231 if (mGdbThread != null) { 1232 mGdbThread.interrupt(); 1233 mGdbThread = null; 1234 } 1235 } 1236 1237 int waitControllerLocked(int pid, int state) { 1238 if (mGdbPort != null) { 1239 killGdbLocked(); 1240 1241 try { 1242 System.out.println("Starting gdbserver on port " + mGdbPort); 1243 System.out.println("Do the following:"); 1244 System.out.println(" adb forward tcp:" + mGdbPort + " tcp:" + mGdbPort); 1245 System.out.println(" gdbclient app_process :" + mGdbPort); 1246 1247 mGdbProcess = Runtime.getRuntime().exec(new String[] { 1248 "gdbserver", ":" + mGdbPort, "--attach", Integer.toString(pid) 1249 }); 1250 final InputStreamReader converter = new InputStreamReader( 1251 mGdbProcess.getInputStream()); 1252 mGdbThread = new Thread() { 1253 @Override 1254 public void run() { 1255 BufferedReader in = new BufferedReader(converter); 1256 String line; 1257 int count = 0; 1258 while (true) { 1259 synchronized (MyActivityController.this) { 1260 if (mGdbThread == null) { 1261 return; 1262 } 1263 if (count == 2) { 1264 mGotGdbPrint = true; 1265 MyActivityController.this.notifyAll(); 1266 } 1267 } 1268 try { 1269 line = in.readLine(); 1270 if (line == null) { 1271 return; 1272 } 1273 System.out.println("GDB: " + line); 1274 count++; 1275 } catch (IOException e) { 1276 return; 1277 } 1278 } 1279 } 1280 }; 1281 mGdbThread.start(); 1282 1283 // Stupid waiting for .5s. Doesn't matter if we end early. 1284 try { 1285 this.wait(500); 1286 } catch (InterruptedException e) { 1287 } 1288 1289 } catch (IOException e) { 1290 System.err.println("Failure starting gdbserver: " + e); 1291 killGdbLocked(); 1292 } 1293 } 1294 mState = state; 1295 System.out.println(""); 1296 printMessageForState(); 1297 1298 while (mState != STATE_NORMAL) { 1299 try { 1300 wait(); 1301 } catch (InterruptedException e) { 1302 } 1303 } 1304 1305 killGdbLocked(); 1306 1307 return mResult; 1308 } 1309 1310 void resumeController(int result) { 1311 synchronized (this) { 1312 mState = STATE_NORMAL; 1313 mResult = result; 1314 notifyAll(); 1315 } 1316 } 1317 1318 void printMessageForState() { 1319 switch (mState) { 1320 case STATE_NORMAL: 1321 System.out.println("Monitoring activity manager... available commands:"); 1322 break; 1323 case STATE_CRASHED: 1324 System.out.println("Waiting after crash... available commands:"); 1325 System.out.println("(c)ontinue: show crash dialog"); 1326 System.out.println("(k)ill: immediately kill app"); 1327 break; 1328 case STATE_EARLY_ANR: 1329 System.out.println("Waiting after early ANR... available commands:"); 1330 System.out.println("(c)ontinue: standard ANR processing"); 1331 System.out.println("(k)ill: immediately kill app"); 1332 break; 1333 case STATE_ANR: 1334 System.out.println("Waiting after ANR... available commands:"); 1335 System.out.println("(c)ontinue: show ANR dialog"); 1336 System.out.println("(k)ill: immediately kill app"); 1337 System.out.println("(w)ait: wait some more"); 1338 break; 1339 } 1340 System.out.println("(q)uit: finish monitoring"); 1341 } 1342 1343 void run() throws RemoteException { 1344 try { 1345 printMessageForState(); 1346 1347 mAm.setActivityController(this); 1348 mState = STATE_NORMAL; 1349 1350 InputStreamReader converter = new InputStreamReader(System.in); 1351 BufferedReader in = new BufferedReader(converter); 1352 String line; 1353 1354 while ((line = in.readLine()) != null) { 1355 boolean addNewline = true; 1356 if (line.length() <= 0) { 1357 addNewline = false; 1358 } else if ("q".equals(line) || "quit".equals(line)) { 1359 resumeController(RESULT_DEFAULT); 1360 break; 1361 } else if (mState == STATE_CRASHED) { 1362 if ("c".equals(line) || "continue".equals(line)) { 1363 resumeController(RESULT_CRASH_DIALOG); 1364 } else if ("k".equals(line) || "kill".equals(line)) { 1365 resumeController(RESULT_CRASH_KILL); 1366 } else { 1367 System.out.println("Invalid command: " + line); 1368 } 1369 } else if (mState == STATE_ANR) { 1370 if ("c".equals(line) || "continue".equals(line)) { 1371 resumeController(RESULT_ANR_DIALOG); 1372 } else if ("k".equals(line) || "kill".equals(line)) { 1373 resumeController(RESULT_ANR_KILL); 1374 } else if ("w".equals(line) || "wait".equals(line)) { 1375 resumeController(RESULT_ANR_WAIT); 1376 } else { 1377 System.out.println("Invalid command: " + line); 1378 } 1379 } else if (mState == STATE_EARLY_ANR) { 1380 if ("c".equals(line) || "continue".equals(line)) { 1381 resumeController(RESULT_EARLY_ANR_CONTINUE); 1382 } else if ("k".equals(line) || "kill".equals(line)) { 1383 resumeController(RESULT_EARLY_ANR_KILL); 1384 } else { 1385 System.out.println("Invalid command: " + line); 1386 } 1387 } else { 1388 System.out.println("Invalid command: " + line); 1389 } 1390 1391 synchronized (this) { 1392 if (addNewline) { 1393 System.out.println(""); 1394 } 1395 printMessageForState(); 1396 } 1397 } 1398 1399 } catch (IOException e) { 1400 e.printStackTrace(); 1401 } finally { 1402 mAm.setActivityController(null); 1403 } 1404 } 1405 } 1406 1407 private void runMonitor() throws Exception { 1408 String opt; 1409 String gdbPort = null; 1410 while ((opt=nextOption()) != null) { 1411 if (opt.equals("--gdb")) { 1412 gdbPort = nextArgRequired(); 1413 } else { 1414 System.err.println("Error: Unknown option: " + opt); 1415 return; 1416 } 1417 } 1418 1419 MyActivityController controller = new MyActivityController(gdbPort); 1420 controller.run(); 1421 } 1422 1423 private void runHang() throws Exception { 1424 String opt; 1425 boolean allowRestart = false; 1426 while ((opt=nextOption()) != null) { 1427 if (opt.equals("--allow-restart")) { 1428 allowRestart = true; 1429 } else { 1430 System.err.println("Error: Unknown option: " + opt); 1431 return; 1432 } 1433 } 1434 1435 System.out.println("Hanging the system..."); 1436 mAm.hang(new Binder(), allowRestart); 1437 } 1438 1439 private void runRestart() throws Exception { 1440 String opt; 1441 while ((opt=nextOption()) != null) { 1442 System.err.println("Error: Unknown option: " + opt); 1443 return; 1444 } 1445 1446 System.out.println("Restart the system..."); 1447 mAm.restart(); 1448 } 1449 1450 private void runIdleMaintenance() throws Exception { 1451 String opt; 1452 while ((opt=nextOption()) != null) { 1453 System.err.println("Error: Unknown option: " + opt); 1454 return; 1455 } 1456 1457 System.out.println("Performing idle maintenance..."); 1458 Intent intent = new Intent( 1459 "com.android.server.IdleMaintenanceService.action.FORCE_IDLE_MAINTENANCE"); 1460 mAm.broadcastIntent(null, intent, null, null, 0, null, null, null, 1461 android.app.AppOpsManager.OP_NONE, true, false, UserHandle.USER_ALL); 1462 } 1463 1464 private void runScreenCompat() throws Exception { 1465 String mode = nextArgRequired(); 1466 boolean enabled; 1467 if ("on".equals(mode)) { 1468 enabled = true; 1469 } else if ("off".equals(mode)) { 1470 enabled = false; 1471 } else { 1472 System.err.println("Error: enabled mode must be 'on' or 'off' at " + mode); 1473 return; 1474 } 1475 1476 String packageName = nextArgRequired(); 1477 do { 1478 try { 1479 mAm.setPackageScreenCompatMode(packageName, enabled 1480 ? ActivityManager.COMPAT_MODE_ENABLED 1481 : ActivityManager.COMPAT_MODE_DISABLED); 1482 } catch (RemoteException e) { 1483 } 1484 packageName = nextArg(); 1485 } while (packageName != null); 1486 } 1487 1488 private void runToUri(boolean intentScheme) throws Exception { 1489 Intent intent = makeIntent(UserHandle.USER_CURRENT); 1490 System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0)); 1491 } 1492 1493 private class IntentReceiver extends IIntentReceiver.Stub { 1494 private boolean mFinished = false; 1495 1496 @Override 1497 public void performReceive(Intent intent, int resultCode, String data, Bundle extras, 1498 boolean ordered, boolean sticky, int sendingUser) { 1499 String line = "Broadcast completed: result=" + resultCode; 1500 if (data != null) line = line + ", data=\"" + data + "\""; 1501 if (extras != null) line = line + ", extras: " + extras; 1502 System.out.println(line); 1503 synchronized (this) { 1504 mFinished = true; 1505 notifyAll(); 1506 } 1507 } 1508 1509 public synchronized void waitForFinish() { 1510 try { 1511 while (!mFinished) wait(); 1512 } catch (InterruptedException e) { 1513 throw new IllegalStateException(e); 1514 } 1515 } 1516 } 1517 1518 private class InstrumentationWatcher extends IInstrumentationWatcher.Stub { 1519 private boolean mFinished = false; 1520 private boolean mRawMode = false; 1521 1522 /** 1523 * Set or reset "raw mode". In "raw mode", all bundles are dumped. In "pretty mode", 1524 * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that. 1525 * @param rawMode true for raw mode, false for pretty mode. 1526 */ 1527 public void setRawOutput(boolean rawMode) { 1528 mRawMode = rawMode; 1529 } 1530 1531 @Override 1532 public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) { 1533 synchronized (this) { 1534 // pretty printer mode? 1535 String pretty = null; 1536 if (!mRawMode && results != null) { 1537 pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 1538 } 1539 if (pretty != null) { 1540 System.out.print(pretty); 1541 } else { 1542 if (results != null) { 1543 for (String key : results.keySet()) { 1544 System.out.println( 1545 "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key)); 1546 } 1547 } 1548 System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode); 1549 } 1550 notifyAll(); 1551 } 1552 } 1553 1554 @Override 1555 public void instrumentationFinished(ComponentName name, int resultCode, 1556 Bundle results) { 1557 synchronized (this) { 1558 // pretty printer mode? 1559 String pretty = null; 1560 if (!mRawMode && results != null) { 1561 pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 1562 } 1563 if (pretty != null) { 1564 System.out.println(pretty); 1565 } else { 1566 if (results != null) { 1567 for (String key : results.keySet()) { 1568 System.out.println( 1569 "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key)); 1570 } 1571 } 1572 System.out.println("INSTRUMENTATION_CODE: " + resultCode); 1573 } 1574 mFinished = true; 1575 notifyAll(); 1576 } 1577 } 1578 1579 public boolean waitForFinish() { 1580 synchronized (this) { 1581 while (!mFinished) { 1582 try { 1583 if (!mAm.asBinder().pingBinder()) { 1584 return false; 1585 } 1586 wait(1000); 1587 } catch (InterruptedException e) { 1588 throw new IllegalStateException(e); 1589 } 1590 } 1591 } 1592 return true; 1593 } 1594 } 1595 1596 private void runStack() throws Exception { 1597 String op = nextArgRequired(); 1598 if (op.equals("start")) { 1599 runStackStart(); 1600 } else if (op.equals("movetask")) { 1601 runStackMoveTask(); 1602 } else if (op.equals("resize")) { 1603 runStackResize(); 1604 } else if (op.equals("list")) { 1605 runStackList(); 1606 } else if (op.equals("info")) { 1607 runStackInfo(); 1608 } else { 1609 showError("Error: unknown command '" + op + "'"); 1610 return; 1611 } 1612 } 1613 1614 private void runStackStart() throws Exception { 1615 String displayIdStr = nextArgRequired(); 1616 int displayId = Integer.valueOf(displayIdStr); 1617 Intent intent = makeIntent(UserHandle.USER_CURRENT); 1618 1619 try { 1620 IBinder homeActivityToken = mAm.getHomeActivityToken(); 1621 IActivityContainer container = mAm.createActivityContainer(homeActivityToken, null); 1622 container.attachToDisplay(displayId); 1623 container.startActivity(intent); 1624 } catch (RemoteException e) { 1625 } 1626 } 1627 1628 private void runStackMoveTask() throws Exception { 1629 String taskIdStr = nextArgRequired(); 1630 int taskId = Integer.valueOf(taskIdStr); 1631 String stackIdStr = nextArgRequired(); 1632 int stackId = Integer.valueOf(stackIdStr); 1633 String toTopStr = nextArgRequired(); 1634 final boolean toTop; 1635 if ("true".equals(toTopStr)) { 1636 toTop = true; 1637 } else if ("false".equals(toTopStr)) { 1638 toTop = false; 1639 } else { 1640 System.err.println("Error: bad toTop arg: " + toTopStr); 1641 return; 1642 } 1643 1644 try { 1645 mAm.moveTaskToStack(taskId, stackId, toTop); 1646 } catch (RemoteException e) { 1647 } 1648 } 1649 1650 private void runStackResize() throws Exception { 1651 String stackIdStr = nextArgRequired(); 1652 int stackId = Integer.valueOf(stackIdStr); 1653 String leftStr = nextArgRequired(); 1654 int left = Integer.valueOf(leftStr); 1655 String topStr = nextArgRequired(); 1656 int top = Integer.valueOf(topStr); 1657 String rightStr = nextArgRequired(); 1658 int right = Integer.valueOf(rightStr); 1659 String bottomStr = nextArgRequired(); 1660 int bottom = Integer.valueOf(bottomStr); 1661 1662 try { 1663 mAm.resizeStack(stackId, new Rect(left, top, right, bottom)); 1664 } catch (RemoteException e) { 1665 } 1666 } 1667 1668 private void runStackList() throws Exception { 1669 try { 1670 List<StackInfo> stacks = mAm.getAllStackInfos(); 1671 for (StackInfo info : stacks) { 1672 System.out.println(info); 1673 } 1674 } catch (RemoteException e) { 1675 } 1676 } 1677 1678 private void runStackInfo() throws Exception { 1679 try { 1680 String stackIdStr = nextArgRequired(); 1681 int stackId = Integer.valueOf(stackIdStr); 1682 StackInfo info = mAm.getStackInfo(stackId); 1683 System.out.println(info); 1684 } catch (RemoteException e) { 1685 } 1686 } 1687 1688 private void runLockTask() throws Exception { 1689 String taskIdStr = nextArgRequired(); 1690 try { 1691 if (taskIdStr.equals("stop")) { 1692 mAm.stopLockTaskMode(); 1693 } else { 1694 int taskId = Integer.valueOf(taskIdStr); 1695 mAm.startLockTaskMode(taskId); 1696 } 1697 System.err.println("Activity manager is " + (mAm.isInLockTaskMode() ? "" : "not ") + 1698 "in lockTaskMode"); 1699 } catch (RemoteException e) { 1700 } 1701 } 1702} 1703