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