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