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