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