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