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