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