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