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