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