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