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