Am.java revision 3da5c97460d859ec6d9e5fffb3902a3242d32bf4
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 static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 22import static android.app.ActivityManager.RESIZE_MODE_SYSTEM; 23import static android.app.ActivityManager.RESIZE_MODE_USER; 24 25import android.app.ActivityManager; 26import android.app.ActivityManager.StackInfo; 27import android.app.ActivityManagerNative; 28import android.app.IActivityContainer; 29import android.app.IActivityController; 30import android.app.IActivityManager; 31import android.app.IInstrumentationWatcher; 32import android.app.Instrumentation; 33import android.app.IStopUserCallback; 34import android.app.ProfilerInfo; 35import android.app.UiAutomationConnection; 36import android.app.usage.ConfigurationStats; 37import android.app.usage.IUsageStatsManager; 38import android.app.usage.UsageStatsManager; 39import android.content.ComponentCallbacks2; 40import android.content.ComponentName; 41import android.content.Context; 42import android.content.IIntentReceiver; 43import android.content.Intent; 44import android.content.pm.IPackageManager; 45import android.content.pm.ParceledListSlice; 46import android.content.pm.ResolveInfo; 47import android.content.pm.UserInfo; 48import android.content.res.Configuration; 49import android.graphics.Rect; 50import android.net.Uri; 51import android.os.Binder; 52import android.os.Build; 53import android.os.Bundle; 54import android.os.ParcelFileDescriptor; 55import android.os.RemoteException; 56import android.os.SELinux; 57import android.os.ServiceManager; 58import android.os.ShellCommand; 59import android.os.SystemClock; 60import android.os.SystemProperties; 61import android.os.UserHandle; 62import android.text.TextUtils; 63import android.util.AndroidException; 64import android.util.ArrayMap; 65import android.view.IWindowManager; 66 67import com.android.internal.os.BaseCommand; 68import com.android.internal.util.HexDump; 69import com.android.internal.util.Preconditions; 70 71import java.io.BufferedReader; 72import java.io.File; 73import java.io.FileNotFoundException; 74import java.io.IOException; 75import java.io.InputStreamReader; 76import java.io.PrintStream; 77import java.io.PrintWriter; 78import java.net.URISyntaxException; 79import java.util.ArrayList; 80import java.util.Collections; 81import java.util.Comparator; 82import java.util.HashSet; 83import java.util.List; 84 85public class Am extends BaseCommand { 86 87 private static final String SHELL_PACKAGE_NAME = "com.android.shell"; 88 89 // Is the object moving in a positive direction? 90 private static final boolean MOVING_FORWARD = true; 91 // Is the object moving in the horizontal plan? 92 private static final boolean MOVING_HORIZONTALLY = true; 93 // Is the object current point great then its target point? 94 private static final boolean GREATER_THAN_TARGET = true; 95 // Amount we reduce the stack size by when testing a task re-size. 96 private static final int STACK_BOUNDS_INSET = 10; 97 98 private IActivityManager mAm; 99 100 private int mStartFlags = 0; 101 private boolean mWaitOption = false; 102 private boolean mStopOption = false; 103 104 private int mRepeat = 0; 105 private int mUserId; 106 private String mReceiverPermission; 107 108 private String mProfileFile; 109 private int mSamplingInterval; 110 private boolean mAutoStop; 111 112 /** 113 * Command-line entry point. 114 * 115 * @param args The command-line arguments 116 */ 117 public static void main(String[] args) { 118 (new Am()).run(args); 119 } 120 121 @Override 122 public void onShowUsage(PrintStream out) { 123 PrintWriter pw = new PrintWriter(out); 124 pw.println( 125 "usage: am [subcommand] [options]\n" + 126 "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" + 127 " [--sampling INTERVAL] [-R COUNT] [-S]\n" + 128 " [--track-allocation] [--user <USER_ID> | current] <INTENT>\n" + 129 " am startservice [--user <USER_ID> | current] <INTENT>\n" + 130 " am stopservice [--user <USER_ID> | current] <INTENT>\n" + 131 " am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" + 132 " am kill [--user <USER_ID> | all | current] <PACKAGE>\n" + 133 " am kill-all\n" + 134 " am broadcast [--user <USER_ID> | all | current] <INTENT>\n" + 135 " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" + 136 " [--user <USER_ID> | current]\n" + 137 " [--no-window-animation] [--abi <ABI>] <COMPONENT>\n" + 138 " am profile start [--user <USER_ID> current] [--sampling INTERVAL] <PROCESS> <FILE>\n" + 139 " am profile stop [--user <USER_ID> current] [<PROCESS>]\n" + 140 " am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" + 141 " am set-debug-app [-w] [--persistent] <PACKAGE>\n" + 142 " am clear-debug-app\n" + 143 " am set-watch-heap <PROCESS> <MEM-LIMIT>\n" + 144 " am clear-watch-heap\n" + 145 " am bug-report [--progress]\n" + 146 " am monitor [--gdb <port>]\n" + 147 " am hang [--allow-restart]\n" + 148 " am restart\n" + 149 " am idle-maintenance\n" + 150 " am screen-compat [on|off] <PACKAGE>\n" + 151 " am package-importance <PACKAGE>\n" + 152 " am to-uri [INTENT]\n" + 153 " am to-intent-uri [INTENT]\n" + 154 " am to-app-uri [INTENT]\n" + 155 " am switch-user <USER_ID>\n" + 156 " am start-user <USER_ID>\n" + 157 " am unlock-user <USER_ID> [TOKEN_HEX]\n" + 158 " am stop-user [-w] [-f] <USER_ID>\n" + 159 " am stack start <DISPLAY_ID> <INTENT>\n" + 160 " am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" + 161 " am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" + 162 " am stack resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]\n" + 163 " am stack size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]\n" + 164 " am stack move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" + 165 " am stack positiontask <TASK_ID> <STACK_ID> <POSITION>\n" + 166 " am stack list\n" + 167 " am stack info <STACK_ID>\n" + 168 " am task lock <TASK_ID>\n" + 169 " am task lock stop\n" + 170 " am task resizeable <TASK_ID> [true|false]\n" + 171 " am task resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" + 172 " am task drag-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS] \n" + 173 " am task size-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS] \n" + 174 " am get-config\n" + 175 " am suppress-resize-config-changes <true|false>\n" + 176 " am set-inactive [--user <USER_ID>] <PACKAGE> true|false\n" + 177 " am get-inactive [--user <USER_ID>] <PACKAGE>\n" + 178 " am send-trim-memory [--user <USER_ID>] <PROCESS>\n" + 179 " [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]\n" + 180 " am get-current-user\n" + 181 "\n" + 182 "am start: start an Activity. Options are:\n" + 183 " -D: enable debugging\n" + 184 " -W: wait for launch to complete\n" + 185 " --start-profiler <FILE>: start profiler and send results to <FILE>\n" + 186 " --sampling INTERVAL: use sample profiling with INTERVAL microseconds\n" + 187 " between samples (use with --start-profiler)\n" + 188 " -P <FILE>: like above, but profiling stops when app goes idle\n" + 189 " -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" + 190 " the top activity will be finished.\n" + 191 " -S: force stop the target app before starting the activity\n" + 192 " --track-allocation: enable tracking of object allocations\n" + 193 " --user <USER_ID> | current: Specify which user to run as; if not\n" + 194 " specified then run as the current user.\n" + 195 "\n" + 196 "am startservice: start a Service. Options are:\n" + 197 " --user <USER_ID> | current: Specify which user to run as; if not\n" + 198 " specified then run as the current user.\n" + 199 "\n" + 200 "am stopservice: stop a Service. Options are:\n" + 201 " --user <USER_ID> | current: Specify which user to run as; if not\n" + 202 " specified then run as the current user.\n" + 203 "\n" + 204 "am force-stop: force stop everything associated with <PACKAGE>.\n" + 205 " --user <USER_ID> | all | current: Specify user to force stop;\n" + 206 " all users if not specified.\n" + 207 "\n" + 208 "am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" + 209 " processes that are safe to kill -- that is, will not impact the user\n" + 210 " experience.\n" + 211 " --user <USER_ID> | all | current: Specify user whose processes to kill;\n" + 212 " all users if not specified.\n" + 213 "\n" + 214 "am kill-all: Kill all background processes.\n" + 215 "\n" + 216 "am broadcast: send a broadcast Intent. Options are:\n" + 217 " --user <USER_ID> | all | current: Specify which user to send to; if not\n" + 218 " specified then send to all users.\n" + 219 " --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" + 220 "\n" + 221 "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" + 222 " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" + 223 " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" + 224 " [-e perf true] to generate raw output for performance measurements.\n" + 225 " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" + 226 " common form is [-e <testrunner_flag> <value>[,<value>...]].\n" + 227 " -p <FILE>: write profiling data to <FILE>\n" + 228 " -w: wait for instrumentation to finish before returning. Required for\n" + 229 " test runners.\n" + 230 " --user <USER_ID> | current: Specify user instrumentation runs in;\n" + 231 " current user if not specified.\n" + 232 " --no-window-animation: turn off window animations while running.\n" + 233 " --abi <ABI>: Launch the instrumented process with the selected ABI.\n" + 234 " This assumes that the process supports the selected ABI.\n" + 235 "\n" + 236 "am trace-ipc: Trace IPC transactions.\n" + 237 " start: start tracing IPC transactions.\n" + 238 " stop: stop tracing IPC transactions and dump the results to file.\n" + 239 " --dump-file <FILE>: Specify the file the trace should be dumped to.\n" + 240 "\n" + 241 "am profile: start and stop profiler on a process. The given <PROCESS> argument\n" + 242 " may be either a process name or pid. Options are:\n" + 243 " --user <USER_ID> | current: When supplying a process name,\n" + 244 " specify user of process to profile; uses current user if not specified.\n" + 245 "\n" + 246 "am dumpheap: dump the heap of a process. The given <PROCESS> argument may\n" + 247 " be either a process name or pid. Options are:\n" + 248 " -n: dump native heap instead of managed heap\n" + 249 " --user <USER_ID> | current: When supplying a process name,\n" + 250 " specify user of process to dump; uses current user if not specified.\n" + 251 "\n" + 252 "am set-debug-app: set application <PACKAGE> to debug. Options are:\n" + 253 " -w: wait for debugger when application starts\n" + 254 " --persistent: retain this value\n" + 255 "\n" + 256 "am clear-debug-app: clear the previously set-debug-app.\n" + 257 "\n" + 258 "am set-watch-heap: start monitoring pss size of <PROCESS>, if it is at or\n" + 259 " above <HEAP-LIMIT> then a heap dump is collected for the user to report\n" + 260 "\n" + 261 "am clear-watch-heap: clear the previously set-watch-heap.\n" + 262 "\n" + 263 "am bug-report: request bug report generation; will launch a notification\n" + 264 " when done to select where it should be delivered. Options are: \n" + 265 " --progress: will launch a notification right away to show its progress.\n" + 266 "\n" + 267 "am monitor: start monitoring for crashes or ANRs.\n" + 268 " --gdb: start gdbserv on the given port at crash/ANR\n" + 269 "\n" + 270 "am hang: hang the system.\n" + 271 " --allow-restart: allow watchdog to perform normal system restart\n" + 272 "\n" + 273 "am restart: restart the user-space system.\n" + 274 "\n" + 275 "am idle-maintenance: perform idle maintenance now.\n" + 276 "\n" + 277 "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" + 278 "\n" + 279 "am package-importance: print current importance of <PACKAGE>.\n" + 280 "\n" + 281 "am to-uri: print the given Intent specification as a URI.\n" + 282 "\n" + 283 "am to-intent-uri: print the given Intent specification as an intent: URI.\n" + 284 "\n" + 285 "am to-app-uri: print the given Intent specification as an android-app: URI.\n" + 286 "\n" + 287 "am switch-user: switch to put USER_ID in the foreground, starting\n" + 288 " execution of that user if it is currently stopped.\n" + 289 "\n" + 290 "am start-user: start USER_ID in background if it is currently stopped,\n" + 291 " use switch-user if you want to start the user in foreground.\n" + 292 "\n" + 293 "am stop-user: stop execution of USER_ID, not allowing it to run any\n" + 294 " code until a later explicit start or switch to it.\n" + 295 " -w: wait for stop-user to complete.\n" + 296 " -f: force stop even if there are related users that cannot be stopped.\n" + 297 "\n" + 298 "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" + 299 "\n" + 300 "am stack movetask: move <TASK_ID> from its current stack to the top (true) or" + 301 " bottom (false) of <STACK_ID>.\n" + 302 "\n" + 303 "am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.\n" + 304 "\n" + 305 "am stack resize-docked-stack: change docked stack to <LEFT,TOP,RIGHT,BOTTOM>\n" + 306 " and supplying temporary different task bounds indicated by\n" + 307 " <TASK_LEFT,TOP,RIGHT,BOTTOM>\n" + 308 "\n" + 309 "am stack size-docked-stack-test: test command for sizing docked stack by\n" + 310 " <STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottom\n" + 311 " applying the optional [DELAY_MS] between each step.\n" + 312 "\n" + 313 "am stack move-top-activity-to-pinned-stack: moves the top activity from\n" + 314 " <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the\n" + 315 " bounds of the pinned stack.\n" + 316 "\n" + 317 "am stack positiontask: place <TASK_ID> in <STACK_ID> at <POSITION>" + 318 "\n" + 319 "am stack list: list all of the activity stacks and their sizes.\n" + 320 "\n" + 321 "am stack info: display the information about activity stack <STACK_ID>.\n" + 322 "\n" + 323 "am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.\n" + 324 "\n" + 325 "am task lock stop: end the current task lock.\n" + 326 "\n" + 327 "am task resizeable: change if <TASK_ID> is resizeable (true) or not (false).\n" + 328 "\n" + 329 "am task resize: makes sure <TASK_ID> is in a stack with the specified bounds.\n" + 330 " Forces the task to be resizeable and creates a stack if no existing stack\n" + 331 " has the specified bounds.\n" + 332 "\n" + 333 "am task drag-task-test: test command for dragging/moving <TASK_ID> by\n" + 334 " <STEP_SIZE> increments around the screen applying the optional [DELAY_MS]\n" + 335 " between each step.\n" + 336 "\n" + 337 "am task size-task-test: test command for sizing <TASK_ID> by <STEP_SIZE>" + 338 " increments within the screen applying the optional [DELAY_MS] between\n" + 339 " each step.\n" + 340 "\n" + 341 "am get-config: retrieve the configuration and any recent configurations\n" + 342 " of the device.\n" + 343 "am suppress-resize-config-changes: suppresses configuration changes due to\n" + 344 " user resizing an activity/task.\n" + 345 "\n" + 346 "am set-inactive: sets the inactive state of an app.\n" + 347 "\n" + 348 "am get-inactive: returns the inactive state of an app.\n" + 349 "\n" + 350 "am send-trim-memory: send a memory trim event to a <PROCESS>.\n" + 351 "\n" + 352 "am get-current-user: returns id of the current foreground user.\n" + 353 "\n" 354 ); 355 Intent.printIntentArgsHelp(pw, ""); 356 pw.flush(); 357 } 358 359 @Override 360 public void onRun() throws Exception { 361 362 mAm = ActivityManagerNative.getDefault(); 363 if (mAm == null) { 364 System.err.println(NO_SYSTEM_ERROR_CODE); 365 throw new AndroidException("Can't connect to activity manager; is the system running?"); 366 } 367 368 String op = nextArgRequired(); 369 370 if (op.equals("start")) { 371 runStart(); 372 } else if (op.equals("startservice")) { 373 runStartService(); 374 } else if (op.equals("stopservice")) { 375 runStopService(); 376 } else if (op.equals("force-stop")) { 377 runForceStop(); 378 } else if (op.equals("kill")) { 379 runKill(); 380 } else if (op.equals("kill-all")) { 381 runKillAll(); 382 } else if (op.equals("instrument")) { 383 runInstrument(); 384 } else if (op.equals("trace-ipc")) { 385 runTraceIpc(); 386 } else if (op.equals("broadcast")) { 387 sendBroadcast(); 388 } else if (op.equals("profile")) { 389 runProfile(); 390 } else if (op.equals("dumpheap")) { 391 runDumpHeap(); 392 } else if (op.equals("set-debug-app")) { 393 runSetDebugApp(); 394 } else if (op.equals("clear-debug-app")) { 395 runClearDebugApp(); 396 } else if (op.equals("set-watch-heap")) { 397 runSetWatchHeap(); 398 } else if (op.equals("clear-watch-heap")) { 399 runClearWatchHeap(); 400 } else if (op.equals("bug-report")) { 401 runBugReport(); 402 } else if (op.equals("monitor")) { 403 runMonitor(); 404 } else if (op.equals("hang")) { 405 runHang(); 406 } else if (op.equals("restart")) { 407 runRestart(); 408 } else if (op.equals("idle-maintenance")) { 409 runIdleMaintenance(); 410 } else if (op.equals("screen-compat")) { 411 runScreenCompat(); 412 } else if (op.equals("package-importance")) { 413 runPackageImportance(); 414 } else if (op.equals("to-uri")) { 415 runToUri(0); 416 } else if (op.equals("to-intent-uri")) { 417 runToUri(Intent.URI_INTENT_SCHEME); 418 } else if (op.equals("to-app-uri")) { 419 runToUri(Intent.URI_ANDROID_APP_SCHEME); 420 } else if (op.equals("switch-user")) { 421 runSwitchUser(); 422 } else if (op.equals("start-user")) { 423 runStartUserInBackground(); 424 } else if (op.equals("unlock-user")) { 425 runUnlockUser(); 426 } else if (op.equals("stop-user")) { 427 runStopUser(); 428 } else if (op.equals("stack")) { 429 runStack(); 430 } else if (op.equals("task")) { 431 runTask(); 432 } else if (op.equals("get-config")) { 433 runGetConfig(); 434 } else if (op.equals("suppress-resize-config-changes")) { 435 runSuppressResizeConfigChanges(); 436 } else if (op.equals("set-inactive")) { 437 runSetInactive(); 438 } else if (op.equals("get-inactive")) { 439 runGetInactive(); 440 } else if (op.equals("send-trim-memory")) { 441 runSendTrimMemory(); 442 } else if (op.equals("get-current-user")) { 443 runGetCurrentUser(); 444 } else { 445 showError("Error: unknown command '" + op + "'"); 446 } 447 } 448 449 int parseUserArg(String arg) { 450 int userId; 451 if ("all".equals(arg)) { 452 userId = UserHandle.USER_ALL; 453 } else if ("current".equals(arg) || "cur".equals(arg)) { 454 userId = UserHandle.USER_CURRENT; 455 } else { 456 userId = Integer.parseInt(arg); 457 } 458 return userId; 459 } 460 461 private Intent makeIntent(int defUser) throws URISyntaxException { 462 mStartFlags = 0; 463 mWaitOption = false; 464 mStopOption = false; 465 mRepeat = 0; 466 mProfileFile = null; 467 mSamplingInterval = 0; 468 mAutoStop = false; 469 mUserId = defUser; 470 471 return Intent.parseCommandArgs(mArgs, new Intent.CommandOptionHandler() { 472 @Override 473 public boolean handleOption(String opt, ShellCommand cmd) { 474 if (opt.equals("-D")) { 475 mStartFlags |= ActivityManager.START_FLAG_DEBUG; 476 } else if (opt.equals("-W")) { 477 mWaitOption = true; 478 } else if (opt.equals("-P")) { 479 mProfileFile = nextArgRequired(); 480 mAutoStop = true; 481 } else if (opt.equals("--start-profiler")) { 482 mProfileFile = nextArgRequired(); 483 mAutoStop = false; 484 } else if (opt.equals("--sampling")) { 485 mSamplingInterval = Integer.parseInt(nextArgRequired()); 486 } else if (opt.equals("-R")) { 487 mRepeat = Integer.parseInt(nextArgRequired()); 488 } else if (opt.equals("-S")) { 489 mStopOption = true; 490 } else if (opt.equals("--track-allocation")) { 491 mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION; 492 } else if (opt.equals("--user")) { 493 mUserId = parseUserArg(nextArgRequired()); 494 } else if (opt.equals("--receiver-permission")) { 495 mReceiverPermission = nextArgRequired(); 496 } else { 497 return false; 498 } 499 return true; 500 } 501 }); 502 } 503 504 private void runStartService() throws Exception { 505 Intent intent = makeIntent(UserHandle.USER_CURRENT); 506 if (mUserId == UserHandle.USER_ALL) { 507 System.err.println("Error: Can't start activity with user 'all'"); 508 return; 509 } 510 System.out.println("Starting service: " + intent); 511 ComponentName cn = mAm.startService(null, intent, intent.getType(), 512 SHELL_PACKAGE_NAME, mUserId); 513 if (cn == null) { 514 System.err.println("Error: Not found; no service started."); 515 } else if (cn.getPackageName().equals("!")) { 516 System.err.println("Error: Requires permission " + cn.getClassName()); 517 } else if (cn.getPackageName().equals("!!")) { 518 System.err.println("Error: " + cn.getClassName()); 519 } 520 } 521 522 private void runStopService() throws Exception { 523 Intent intent = makeIntent(UserHandle.USER_CURRENT); 524 if (mUserId == UserHandle.USER_ALL) { 525 System.err.println("Error: Can't stop activity with user 'all'"); 526 return; 527 } 528 System.out.println("Stopping service: " + intent); 529 int result = mAm.stopService(null, intent, intent.getType(), mUserId); 530 if (result == 0) { 531 System.err.println("Service not stopped: was not running."); 532 } else if (result == 1) { 533 System.err.println("Service stopped"); 534 } else if (result == -1) { 535 System.err.println("Error stopping service"); 536 } 537 } 538 539 private void runStart() throws Exception { 540 Intent intent = makeIntent(UserHandle.USER_CURRENT); 541 542 if (mUserId == UserHandle.USER_ALL) { 543 System.err.println("Error: Can't start service with user 'all'"); 544 return; 545 } 546 547 String mimeType = intent.getType(); 548 if (mimeType == null && intent.getData() != null 549 && "content".equals(intent.getData().getScheme())) { 550 mimeType = mAm.getProviderMimeType(intent.getData(), mUserId); 551 } 552 553 do { 554 if (mStopOption) { 555 String packageName; 556 if (intent.getComponent() != null) { 557 packageName = intent.getComponent().getPackageName(); 558 } else { 559 IPackageManager pm = IPackageManager.Stub.asInterface( 560 ServiceManager.getService("package")); 561 if (pm == null) { 562 System.err.println("Error: Package manager not running; aborting"); 563 return; 564 } 565 List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0, 566 mUserId); 567 if (activities == null || activities.size() <= 0) { 568 System.err.println("Error: Intent does not match any activities: " 569 + intent); 570 return; 571 } else if (activities.size() > 1) { 572 System.err.println("Error: Intent matches multiple activities; can't stop: " 573 + intent); 574 return; 575 } 576 packageName = activities.get(0).activityInfo.packageName; 577 } 578 System.out.println("Stopping: " + packageName); 579 mAm.forceStopPackage(packageName, mUserId); 580 Thread.sleep(250); 581 } 582 583 System.out.println("Starting: " + intent); 584 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 585 586 ParcelFileDescriptor fd = null; 587 ProfilerInfo profilerInfo = null; 588 589 if (mProfileFile != null) { 590 try { 591 fd = openForSystemServer( 592 new File(mProfileFile), 593 ParcelFileDescriptor.MODE_CREATE | 594 ParcelFileDescriptor.MODE_TRUNCATE | 595 ParcelFileDescriptor.MODE_READ_WRITE); 596 } catch (FileNotFoundException e) { 597 System.err.println("Error: Unable to open file: " + mProfileFile); 598 System.err.println("Consider using a file under /data/local/tmp/"); 599 return; 600 } 601 profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop); 602 } 603 604 IActivityManager.WaitResult result = null; 605 int res; 606 final long startTime = SystemClock.uptimeMillis(); 607 if (mWaitOption) { 608 result = mAm.startActivityAndWait(null, null, intent, mimeType, 609 null, null, 0, mStartFlags, profilerInfo, null, mUserId); 610 res = result.result; 611 } else { 612 res = mAm.startActivityAsUser(null, null, intent, mimeType, 613 null, null, 0, mStartFlags, profilerInfo, null, mUserId); 614 } 615 final long endTime = SystemClock.uptimeMillis(); 616 PrintStream out = mWaitOption ? System.out : System.err; 617 boolean launched = false; 618 switch (res) { 619 case ActivityManager.START_SUCCESS: 620 launched = true; 621 break; 622 case ActivityManager.START_SWITCHES_CANCELED: 623 launched = true; 624 out.println( 625 "Warning: Activity not started because the " 626 + " current activity is being kept for the user."); 627 break; 628 case ActivityManager.START_DELIVERED_TO_TOP: 629 launched = true; 630 out.println( 631 "Warning: Activity not started, intent has " 632 + "been delivered to currently running " 633 + "top-most instance."); 634 break; 635 case ActivityManager.START_RETURN_INTENT_TO_CALLER: 636 launched = true; 637 out.println( 638 "Warning: Activity not started because intent " 639 + "should be handled by the caller"); 640 break; 641 case ActivityManager.START_TASK_TO_FRONT: 642 launched = true; 643 out.println( 644 "Warning: Activity not started, its current " 645 + "task has been brought to the front"); 646 break; 647 case ActivityManager.START_INTENT_NOT_RESOLVED: 648 out.println( 649 "Error: Activity not started, unable to " 650 + "resolve " + intent.toString()); 651 break; 652 case ActivityManager.START_CLASS_NOT_FOUND: 653 out.println(NO_CLASS_ERROR_CODE); 654 out.println("Error: Activity class " + 655 intent.getComponent().toShortString() 656 + " does not exist."); 657 break; 658 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: 659 out.println( 660 "Error: Activity not started, you requested to " 661 + "both forward and receive its result"); 662 break; 663 case ActivityManager.START_PERMISSION_DENIED: 664 out.println( 665 "Error: Activity not started, you do not " 666 + "have permission to access it."); 667 break; 668 case ActivityManager.START_NOT_VOICE_COMPATIBLE: 669 out.println( 670 "Error: Activity not started, voice control not allowed for: " 671 + intent); 672 break; 673 case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY: 674 out.println( 675 "Error: Not allowed to start background user activity" 676 + " that shouldn't be displayed for all users."); 677 break; 678 default: 679 out.println( 680 "Error: Activity not started, unknown error code " + res); 681 break; 682 } 683 if (mWaitOption && launched) { 684 if (result == null) { 685 result = new IActivityManager.WaitResult(); 686 result.who = intent.getComponent(); 687 } 688 System.out.println("Status: " + (result.timeout ? "timeout" : "ok")); 689 if (result.who != null) { 690 System.out.println("Activity: " + result.who.flattenToShortString()); 691 } 692 if (result.thisTime >= 0) { 693 System.out.println("ThisTime: " + result.thisTime); 694 } 695 if (result.totalTime >= 0) { 696 System.out.println("TotalTime: " + result.totalTime); 697 } 698 System.out.println("WaitTime: " + (endTime-startTime)); 699 System.out.println("Complete"); 700 } 701 mRepeat--; 702 if (mRepeat > 1) { 703 mAm.unhandledBack(); 704 } 705 } while (mRepeat > 1); 706 } 707 708 private void runForceStop() throws Exception { 709 int userId = UserHandle.USER_ALL; 710 711 String opt; 712 while ((opt=nextOption()) != null) { 713 if (opt.equals("--user")) { 714 userId = parseUserArg(nextArgRequired()); 715 } else { 716 System.err.println("Error: Unknown option: " + opt); 717 return; 718 } 719 } 720 mAm.forceStopPackage(nextArgRequired(), userId); 721 } 722 723 private void runKill() throws Exception { 724 int userId = UserHandle.USER_ALL; 725 726 String opt; 727 while ((opt=nextOption()) != null) { 728 if (opt.equals("--user")) { 729 userId = parseUserArg(nextArgRequired()); 730 } else { 731 System.err.println("Error: Unknown option: " + opt); 732 return; 733 } 734 } 735 mAm.killBackgroundProcesses(nextArgRequired(), userId); 736 } 737 738 private void runKillAll() throws Exception { 739 mAm.killAllBackgroundProcesses(); 740 } 741 742 private void sendBroadcast() throws Exception { 743 Intent intent = makeIntent(UserHandle.USER_CURRENT); 744 IntentReceiver receiver = new IntentReceiver(); 745 String[] requiredPermissions = mReceiverPermission == null ? null 746 : new String[] {mReceiverPermission}; 747 System.out.println("Broadcasting: " + intent); 748 mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, requiredPermissions, 749 android.app.AppOpsManager.OP_NONE, null, true, false, mUserId); 750 receiver.waitForFinish(); 751 } 752 753 private void runInstrument() throws Exception { 754 String profileFile = null; 755 boolean wait = false; 756 boolean rawMode = false; 757 boolean no_window_animation = false; 758 int userId = UserHandle.USER_CURRENT; 759 Bundle args = new Bundle(); 760 String argKey = null, argValue = null; 761 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 762 String abi = null; 763 764 String opt; 765 while ((opt=nextOption()) != null) { 766 if (opt.equals("-p")) { 767 profileFile = nextArgRequired(); 768 } else if (opt.equals("-w")) { 769 wait = true; 770 } else if (opt.equals("-r")) { 771 rawMode = true; 772 } else if (opt.equals("-e")) { 773 argKey = nextArgRequired(); 774 argValue = nextArgRequired(); 775 args.putString(argKey, argValue); 776 } else if (opt.equals("--no_window_animation") 777 || opt.equals("--no-window-animation")) { 778 no_window_animation = true; 779 } else if (opt.equals("--user")) { 780 userId = parseUserArg(nextArgRequired()); 781 } else if (opt.equals("--abi")) { 782 abi = nextArgRequired(); 783 } else { 784 System.err.println("Error: Unknown option: " + opt); 785 return; 786 } 787 } 788 789 if (userId == UserHandle.USER_ALL) { 790 System.err.println("Error: Can't start instrumentation with user 'all'"); 791 return; 792 } 793 794 String cnArg = nextArgRequired(); 795 ComponentName cn = ComponentName.unflattenFromString(cnArg); 796 if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg); 797 798 InstrumentationWatcher watcher = null; 799 UiAutomationConnection connection = null; 800 if (wait) { 801 watcher = new InstrumentationWatcher(); 802 watcher.setRawOutput(rawMode); 803 connection = new UiAutomationConnection(); 804 } 805 806 float[] oldAnims = null; 807 if (no_window_animation) { 808 oldAnims = wm.getAnimationScales(); 809 wm.setAnimationScale(0, 0.0f); 810 wm.setAnimationScale(1, 0.0f); 811 } 812 813 if (abi != null) { 814 final String[] supportedAbis = Build.SUPPORTED_ABIS; 815 boolean matched = false; 816 for (String supportedAbi : supportedAbis) { 817 if (supportedAbi.equals(abi)) { 818 matched = true; 819 break; 820 } 821 } 822 823 if (!matched) { 824 throw new AndroidException( 825 "INSTRUMENTATION_FAILED: Unsupported instruction set " + abi); 826 } 827 } 828 829 if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, abi)) { 830 throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString()); 831 } 832 833 if (watcher != null) { 834 if (!watcher.waitForFinish()) { 835 System.out.println("INSTRUMENTATION_ABORTED: System has crashed."); 836 } 837 } 838 839 if (oldAnims != null) { 840 wm.setAnimationScales(oldAnims); 841 } 842 } 843 844 private void runTraceIpc() throws Exception { 845 String op = nextArgRequired(); 846 if (op.equals("start")) { 847 runTraceIpcStart(); 848 } else if (op.equals("stop")) { 849 runTraceIpcStop(); 850 } else { 851 showError("Error: unknown command '" + op + "'"); 852 return; 853 } 854 } 855 856 private void runTraceIpcStart() throws Exception { 857 System.out.println("Starting IPC tracing."); 858 mAm.startBinderTracking(); 859 } 860 861 private void runTraceIpcStop() throws Exception { 862 String opt; 863 String filename = null; 864 while ((opt=nextOption()) != null) { 865 if (opt.equals("--dump-file")) { 866 filename = nextArgRequired(); 867 } else { 868 System.err.println("Error: Unknown option: " + opt); 869 return; 870 } 871 } 872 if (filename == null) { 873 System.err.println("Error: Specify filename to dump logs to."); 874 return; 875 } 876 877 ParcelFileDescriptor fd = null; 878 879 try { 880 File file = new File(filename); 881 file.delete(); 882 fd = openForSystemServer(file, 883 ParcelFileDescriptor.MODE_CREATE | 884 ParcelFileDescriptor.MODE_TRUNCATE | 885 ParcelFileDescriptor.MODE_READ_WRITE); 886 } catch (FileNotFoundException e) { 887 System.err.println("Error: Unable to open file: " + filename); 888 System.err.println("Consider using a file under /data/local/tmp/"); 889 return; 890 } 891 892 ; 893 if (!mAm.stopBinderTrackingAndDump(fd)) { 894 throw new AndroidException("STOP TRACE FAILED."); 895 } 896 897 System.out.println("Stopped IPC tracing. Dumping logs to: " + filename); 898 } 899 900 static void removeWallOption() { 901 String props = SystemProperties.get("dalvik.vm.extra-opts"); 902 if (props != null && props.contains("-Xprofile:wallclock")) { 903 props = props.replace("-Xprofile:wallclock", ""); 904 props = props.trim(); 905 SystemProperties.set("dalvik.vm.extra-opts", props); 906 } 907 } 908 909 private void runProfile() throws Exception { 910 String profileFile = null; 911 boolean start = false; 912 boolean wall = false; 913 int userId = UserHandle.USER_CURRENT; 914 int profileType = 0; 915 mSamplingInterval = 0; 916 917 String process = null; 918 919 String cmd = nextArgRequired(); 920 921 if ("start".equals(cmd)) { 922 start = true; 923 String opt; 924 while ((opt=nextOption()) != null) { 925 if (opt.equals("--user")) { 926 userId = parseUserArg(nextArgRequired()); 927 } else if (opt.equals("--wall")) { 928 wall = true; 929 } else if (opt.equals("--sampling")) { 930 mSamplingInterval = Integer.parseInt(nextArgRequired()); 931 } else { 932 System.err.println("Error: Unknown option: " + opt); 933 return; 934 } 935 } 936 process = nextArgRequired(); 937 } else if ("stop".equals(cmd)) { 938 String opt; 939 while ((opt=nextOption()) != null) { 940 if (opt.equals("--user")) { 941 userId = parseUserArg(nextArgRequired()); 942 } else { 943 System.err.println("Error: Unknown option: " + opt); 944 return; 945 } 946 } 947 process = nextArg(); 948 } else { 949 // Compatibility with old syntax: process is specified first. 950 process = cmd; 951 cmd = nextArgRequired(); 952 if ("start".equals(cmd)) { 953 start = true; 954 } else if (!"stop".equals(cmd)) { 955 throw new IllegalArgumentException("Profile command " + process + " not valid"); 956 } 957 } 958 959 if (userId == UserHandle.USER_ALL) { 960 System.err.println("Error: Can't profile with user 'all'"); 961 return; 962 } 963 964 ParcelFileDescriptor fd = null; 965 ProfilerInfo profilerInfo = null; 966 967 if (start) { 968 profileFile = nextArgRequired(); 969 try { 970 fd = openForSystemServer( 971 new File(profileFile), 972 ParcelFileDescriptor.MODE_CREATE | 973 ParcelFileDescriptor.MODE_TRUNCATE | 974 ParcelFileDescriptor.MODE_READ_WRITE); 975 } catch (FileNotFoundException e) { 976 System.err.println("Error: Unable to open file: " + profileFile); 977 System.err.println("Consider using a file under /data/local/tmp/"); 978 return; 979 } 980 profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false); 981 } 982 983 try { 984 if (wall) { 985 // XXX doesn't work -- this needs to be set before booting. 986 String props = SystemProperties.get("dalvik.vm.extra-opts"); 987 if (props == null || !props.contains("-Xprofile:wallclock")) { 988 props = props + " -Xprofile:wallclock"; 989 //SystemProperties.set("dalvik.vm.extra-opts", props); 990 } 991 } else if (start) { 992 //removeWallOption(); 993 } 994 if (!mAm.profileControl(process, userId, start, profilerInfo, profileType)) { 995 wall = false; 996 throw new AndroidException("PROFILE FAILED on process " + process); 997 } 998 } finally { 999 if (!wall) { 1000 //removeWallOption(); 1001 } 1002 } 1003 } 1004 1005 private void runDumpHeap() throws Exception { 1006 boolean managed = true; 1007 int userId = UserHandle.USER_CURRENT; 1008 1009 String opt; 1010 while ((opt=nextOption()) != null) { 1011 if (opt.equals("--user")) { 1012 userId = parseUserArg(nextArgRequired()); 1013 if (userId == UserHandle.USER_ALL) { 1014 System.err.println("Error: Can't dump heap with user 'all'"); 1015 return; 1016 } 1017 } else if (opt.equals("-n")) { 1018 managed = false; 1019 } else { 1020 System.err.println("Error: Unknown option: " + opt); 1021 return; 1022 } 1023 } 1024 String process = nextArgRequired(); 1025 String heapFile = nextArgRequired(); 1026 ParcelFileDescriptor fd = null; 1027 1028 try { 1029 File file = new File(heapFile); 1030 file.delete(); 1031 fd = openForSystemServer(file, 1032 ParcelFileDescriptor.MODE_CREATE | 1033 ParcelFileDescriptor.MODE_TRUNCATE | 1034 ParcelFileDescriptor.MODE_READ_WRITE); 1035 } catch (FileNotFoundException e) { 1036 System.err.println("Error: Unable to open file: " + heapFile); 1037 System.err.println("Consider using a file under /data/local/tmp/"); 1038 return; 1039 } 1040 1041 if (!mAm.dumpHeap(process, userId, managed, heapFile, fd)) { 1042 throw new AndroidException("HEAP DUMP FAILED on process " + process); 1043 } 1044 } 1045 1046 private void runSetDebugApp() throws Exception { 1047 boolean wait = false; 1048 boolean persistent = false; 1049 1050 String opt; 1051 while ((opt=nextOption()) != null) { 1052 if (opt.equals("-w")) { 1053 wait = true; 1054 } else if (opt.equals("--persistent")) { 1055 persistent = true; 1056 } else { 1057 System.err.println("Error: Unknown option: " + opt); 1058 return; 1059 } 1060 } 1061 1062 String pkg = nextArgRequired(); 1063 mAm.setDebugApp(pkg, wait, persistent); 1064 } 1065 1066 private void runClearDebugApp() throws Exception { 1067 mAm.setDebugApp(null, false, true); 1068 } 1069 1070 private void runSetWatchHeap() throws Exception { 1071 String proc = nextArgRequired(); 1072 String limit = nextArgRequired(); 1073 mAm.setDumpHeapDebugLimit(proc, 0, Long.parseLong(limit), null); 1074 } 1075 1076 private void runClearWatchHeap() throws Exception { 1077 String proc = nextArgRequired(); 1078 mAm.setDumpHeapDebugLimit(proc, 0, -1, null); 1079 } 1080 1081 private void runBugReport() throws Exception { 1082 String opt; 1083 int bugreportType = ActivityManager.BUGREPORT_OPTION_FULL; 1084 while ((opt=nextOption()) != null) { 1085 if (opt.equals("--progress")) { 1086 bugreportType = ActivityManager.BUGREPORT_OPTION_INTERACTIVE; 1087 } else { 1088 System.err.println("Error: Unknown option: " + opt); 1089 return; 1090 } 1091 } 1092 mAm.requestBugReport(bugreportType); 1093 System.out.println("Your lovely bug report is being created; please be patient."); 1094 } 1095 1096 private void runSwitchUser() throws Exception { 1097 String user = nextArgRequired(); 1098 mAm.switchUser(Integer.parseInt(user)); 1099 } 1100 1101 private void runStartUserInBackground() throws Exception { 1102 String user = nextArgRequired(); 1103 boolean success = mAm.startUserInBackground(Integer.parseInt(user)); 1104 if (success) { 1105 System.out.println("Success: user started"); 1106 } else { 1107 System.err.println("Error: could not start user"); 1108 } 1109 } 1110 1111 private void runUnlockUser() throws Exception { 1112 int userId = Integer.parseInt(nextArgRequired()); 1113 String tokenHex = nextArg(); 1114 byte[] token = null; 1115 if (tokenHex != null) { 1116 token = HexDump.hexStringToByteArray(tokenHex); 1117 } 1118 boolean success = mAm.unlockUser(userId, token); 1119 if (success) { 1120 System.out.println("Success: user unlocked"); 1121 } else { 1122 System.err.println("Error: could not unlock user"); 1123 } 1124 } 1125 1126 private static class StopUserCallback extends IStopUserCallback.Stub { 1127 private boolean mFinished = false; 1128 1129 public synchronized void waitForFinish() { 1130 try { 1131 while (!mFinished) wait(); 1132 } catch (InterruptedException e) { 1133 throw new IllegalStateException(e); 1134 } 1135 } 1136 1137 @Override 1138 public synchronized void userStopped(int userId) { 1139 mFinished = true; 1140 notifyAll(); 1141 } 1142 1143 @Override 1144 public synchronized void userStopAborted(int userId) { 1145 mFinished = true; 1146 notifyAll(); 1147 } 1148 } 1149 1150 private void runStopUser() throws Exception { 1151 boolean wait = false; 1152 boolean force = false; 1153 String opt; 1154 while ((opt = nextOption()) != null) { 1155 if ("-w".equals(opt)) { 1156 wait = true; 1157 } else if ("-f".equals(opt)) { 1158 force = true; 1159 } else { 1160 System.err.println("Error: unknown option: " + opt); 1161 return; 1162 } 1163 } 1164 int user = Integer.parseInt(nextArgRequired()); 1165 StopUserCallback callback = wait ? new StopUserCallback() : null; 1166 1167 int res = mAm.stopUser(user, force, callback); 1168 if (res != ActivityManager.USER_OP_SUCCESS) { 1169 String txt = ""; 1170 switch (res) { 1171 case ActivityManager.USER_OP_IS_CURRENT: 1172 txt = " (Can't stop current user)"; 1173 break; 1174 case ActivityManager.USER_OP_UNKNOWN_USER: 1175 txt = " (Unknown user " + user + ")"; 1176 break; 1177 case ActivityManager.USER_OP_ERROR_IS_SYSTEM: 1178 txt = " (System user cannot be stopped)"; 1179 break; 1180 case ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP: 1181 txt = " (Can't stop user " + user 1182 + " - one of its related users can't be stopped)"; 1183 break; 1184 } 1185 System.err.println("Switch failed: " + res + txt); 1186 } else if (callback != null) { 1187 callback.waitForFinish(); 1188 } 1189 } 1190 1191 class MyActivityController extends IActivityController.Stub { 1192 final String mGdbPort; 1193 1194 static final int STATE_NORMAL = 0; 1195 static final int STATE_CRASHED = 1; 1196 static final int STATE_EARLY_ANR = 2; 1197 static final int STATE_ANR = 3; 1198 1199 int mState; 1200 1201 static final int RESULT_DEFAULT = 0; 1202 1203 static final int RESULT_CRASH_DIALOG = 0; 1204 static final int RESULT_CRASH_KILL = 1; 1205 1206 static final int RESULT_EARLY_ANR_CONTINUE = 0; 1207 static final int RESULT_EARLY_ANR_KILL = 1; 1208 1209 static final int RESULT_ANR_DIALOG = 0; 1210 static final int RESULT_ANR_KILL = 1; 1211 static final int RESULT_ANR_WAIT = 1; 1212 1213 int mResult; 1214 1215 Process mGdbProcess; 1216 Thread mGdbThread; 1217 boolean mGotGdbPrint; 1218 1219 MyActivityController(String gdbPort) { 1220 mGdbPort = gdbPort; 1221 } 1222 1223 @Override 1224 public boolean activityResuming(String pkg) { 1225 synchronized (this) { 1226 System.out.println("** Activity resuming: " + pkg); 1227 } 1228 return true; 1229 } 1230 1231 @Override 1232 public boolean activityStarting(Intent intent, String pkg) { 1233 synchronized (this) { 1234 System.out.println("** Activity starting: " + pkg); 1235 } 1236 return true; 1237 } 1238 1239 @Override 1240 public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg, 1241 long timeMillis, String stackTrace) { 1242 synchronized (this) { 1243 System.out.println("** ERROR: PROCESS CRASHED"); 1244 System.out.println("processName: " + processName); 1245 System.out.println("processPid: " + pid); 1246 System.out.println("shortMsg: " + shortMsg); 1247 System.out.println("longMsg: " + longMsg); 1248 System.out.println("timeMillis: " + timeMillis); 1249 System.out.println("stack:"); 1250 System.out.print(stackTrace); 1251 System.out.println("#"); 1252 int result = waitControllerLocked(pid, STATE_CRASHED); 1253 return result == RESULT_CRASH_KILL ? false : true; 1254 } 1255 } 1256 1257 @Override 1258 public int appEarlyNotResponding(String processName, int pid, String annotation) { 1259 synchronized (this) { 1260 System.out.println("** ERROR: EARLY PROCESS NOT RESPONDING"); 1261 System.out.println("processName: " + processName); 1262 System.out.println("processPid: " + pid); 1263 System.out.println("annotation: " + annotation); 1264 int result = waitControllerLocked(pid, STATE_EARLY_ANR); 1265 if (result == RESULT_EARLY_ANR_KILL) return -1; 1266 return 0; 1267 } 1268 } 1269 1270 @Override 1271 public int appNotResponding(String processName, int pid, String processStats) { 1272 synchronized (this) { 1273 System.out.println("** ERROR: PROCESS NOT RESPONDING"); 1274 System.out.println("processName: " + processName); 1275 System.out.println("processPid: " + pid); 1276 System.out.println("processStats:"); 1277 System.out.print(processStats); 1278 System.out.println("#"); 1279 int result = waitControllerLocked(pid, STATE_ANR); 1280 if (result == RESULT_ANR_KILL) return -1; 1281 if (result == RESULT_ANR_WAIT) return 1; 1282 return 0; 1283 } 1284 } 1285 1286 @Override 1287 public int systemNotResponding(String message) { 1288 synchronized (this) { 1289 System.out.println("** ERROR: PROCESS NOT RESPONDING"); 1290 System.out.println("message: " + message); 1291 System.out.println("#"); 1292 System.out.println("Allowing system to die."); 1293 return -1; 1294 } 1295 } 1296 1297 void killGdbLocked() { 1298 mGotGdbPrint = false; 1299 if (mGdbProcess != null) { 1300 System.out.println("Stopping gdbserver"); 1301 mGdbProcess.destroy(); 1302 mGdbProcess = null; 1303 } 1304 if (mGdbThread != null) { 1305 mGdbThread.interrupt(); 1306 mGdbThread = null; 1307 } 1308 } 1309 1310 int waitControllerLocked(int pid, int state) { 1311 if (mGdbPort != null) { 1312 killGdbLocked(); 1313 1314 try { 1315 System.out.println("Starting gdbserver on port " + mGdbPort); 1316 System.out.println("Do the following:"); 1317 System.out.println(" adb forward tcp:" + mGdbPort + " tcp:" + mGdbPort); 1318 System.out.println(" gdbclient app_process :" + mGdbPort); 1319 1320 mGdbProcess = Runtime.getRuntime().exec(new String[] { 1321 "gdbserver", ":" + mGdbPort, "--attach", Integer.toString(pid) 1322 }); 1323 final InputStreamReader converter = new InputStreamReader( 1324 mGdbProcess.getInputStream()); 1325 mGdbThread = new Thread() { 1326 @Override 1327 public void run() { 1328 BufferedReader in = new BufferedReader(converter); 1329 String line; 1330 int count = 0; 1331 while (true) { 1332 synchronized (MyActivityController.this) { 1333 if (mGdbThread == null) { 1334 return; 1335 } 1336 if (count == 2) { 1337 mGotGdbPrint = true; 1338 MyActivityController.this.notifyAll(); 1339 } 1340 } 1341 try { 1342 line = in.readLine(); 1343 if (line == null) { 1344 return; 1345 } 1346 System.out.println("GDB: " + line); 1347 count++; 1348 } catch (IOException e) { 1349 return; 1350 } 1351 } 1352 } 1353 }; 1354 mGdbThread.start(); 1355 1356 // Stupid waiting for .5s. Doesn't matter if we end early. 1357 try { 1358 this.wait(500); 1359 } catch (InterruptedException e) { 1360 } 1361 1362 } catch (IOException e) { 1363 System.err.println("Failure starting gdbserver: " + e); 1364 killGdbLocked(); 1365 } 1366 } 1367 mState = state; 1368 System.out.println(""); 1369 printMessageForState(); 1370 1371 while (mState != STATE_NORMAL) { 1372 try { 1373 wait(); 1374 } catch (InterruptedException e) { 1375 } 1376 } 1377 1378 killGdbLocked(); 1379 1380 return mResult; 1381 } 1382 1383 void resumeController(int result) { 1384 synchronized (this) { 1385 mState = STATE_NORMAL; 1386 mResult = result; 1387 notifyAll(); 1388 } 1389 } 1390 1391 void printMessageForState() { 1392 switch (mState) { 1393 case STATE_NORMAL: 1394 System.out.println("Monitoring activity manager... available commands:"); 1395 break; 1396 case STATE_CRASHED: 1397 System.out.println("Waiting after crash... available commands:"); 1398 System.out.println("(c)ontinue: show crash dialog"); 1399 System.out.println("(k)ill: immediately kill app"); 1400 break; 1401 case STATE_EARLY_ANR: 1402 System.out.println("Waiting after early ANR... available commands:"); 1403 System.out.println("(c)ontinue: standard ANR processing"); 1404 System.out.println("(k)ill: immediately kill app"); 1405 break; 1406 case STATE_ANR: 1407 System.out.println("Waiting after ANR... available commands:"); 1408 System.out.println("(c)ontinue: show ANR dialog"); 1409 System.out.println("(k)ill: immediately kill app"); 1410 System.out.println("(w)ait: wait some more"); 1411 break; 1412 } 1413 System.out.println("(q)uit: finish monitoring"); 1414 } 1415 1416 void run() throws RemoteException { 1417 try { 1418 printMessageForState(); 1419 1420 mAm.setActivityController(this); 1421 mState = STATE_NORMAL; 1422 1423 InputStreamReader converter = new InputStreamReader(System.in); 1424 BufferedReader in = new BufferedReader(converter); 1425 String line; 1426 1427 while ((line = in.readLine()) != null) { 1428 boolean addNewline = true; 1429 if (line.length() <= 0) { 1430 addNewline = false; 1431 } else if ("q".equals(line) || "quit".equals(line)) { 1432 resumeController(RESULT_DEFAULT); 1433 break; 1434 } else if (mState == STATE_CRASHED) { 1435 if ("c".equals(line) || "continue".equals(line)) { 1436 resumeController(RESULT_CRASH_DIALOG); 1437 } else if ("k".equals(line) || "kill".equals(line)) { 1438 resumeController(RESULT_CRASH_KILL); 1439 } else { 1440 System.out.println("Invalid command: " + line); 1441 } 1442 } else if (mState == STATE_ANR) { 1443 if ("c".equals(line) || "continue".equals(line)) { 1444 resumeController(RESULT_ANR_DIALOG); 1445 } else if ("k".equals(line) || "kill".equals(line)) { 1446 resumeController(RESULT_ANR_KILL); 1447 } else if ("w".equals(line) || "wait".equals(line)) { 1448 resumeController(RESULT_ANR_WAIT); 1449 } else { 1450 System.out.println("Invalid command: " + line); 1451 } 1452 } else if (mState == STATE_EARLY_ANR) { 1453 if ("c".equals(line) || "continue".equals(line)) { 1454 resumeController(RESULT_EARLY_ANR_CONTINUE); 1455 } else if ("k".equals(line) || "kill".equals(line)) { 1456 resumeController(RESULT_EARLY_ANR_KILL); 1457 } else { 1458 System.out.println("Invalid command: " + line); 1459 } 1460 } else { 1461 System.out.println("Invalid command: " + line); 1462 } 1463 1464 synchronized (this) { 1465 if (addNewline) { 1466 System.out.println(""); 1467 } 1468 printMessageForState(); 1469 } 1470 } 1471 1472 } catch (IOException e) { 1473 e.printStackTrace(); 1474 } finally { 1475 mAm.setActivityController(null); 1476 } 1477 } 1478 } 1479 1480 private void runMonitor() throws Exception { 1481 String opt; 1482 String gdbPort = null; 1483 while ((opt=nextOption()) != null) { 1484 if (opt.equals("--gdb")) { 1485 gdbPort = nextArgRequired(); 1486 } else { 1487 System.err.println("Error: Unknown option: " + opt); 1488 return; 1489 } 1490 } 1491 1492 MyActivityController controller = new MyActivityController(gdbPort); 1493 controller.run(); 1494 } 1495 1496 private void runHang() throws Exception { 1497 String opt; 1498 boolean allowRestart = false; 1499 while ((opt=nextOption()) != null) { 1500 if (opt.equals("--allow-restart")) { 1501 allowRestart = true; 1502 } else { 1503 System.err.println("Error: Unknown option: " + opt); 1504 return; 1505 } 1506 } 1507 1508 System.out.println("Hanging the system..."); 1509 mAm.hang(new Binder(), allowRestart); 1510 } 1511 1512 private void runRestart() throws Exception { 1513 String opt; 1514 while ((opt=nextOption()) != null) { 1515 System.err.println("Error: Unknown option: " + opt); 1516 return; 1517 } 1518 1519 System.out.println("Restart the system..."); 1520 mAm.restart(); 1521 } 1522 1523 private void runIdleMaintenance() throws Exception { 1524 String opt; 1525 while ((opt=nextOption()) != null) { 1526 System.err.println("Error: Unknown option: " + opt); 1527 return; 1528 } 1529 1530 System.out.println("Performing idle maintenance..."); 1531 Intent intent = new Intent( 1532 "com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE"); 1533 mAm.broadcastIntent(null, intent, null, null, 0, null, null, null, 1534 android.app.AppOpsManager.OP_NONE, null, true, false, UserHandle.USER_ALL); 1535 } 1536 1537 private void runScreenCompat() throws Exception { 1538 String mode = nextArgRequired(); 1539 boolean enabled; 1540 if ("on".equals(mode)) { 1541 enabled = true; 1542 } else if ("off".equals(mode)) { 1543 enabled = false; 1544 } else { 1545 System.err.println("Error: enabled mode must be 'on' or 'off' at " + mode); 1546 return; 1547 } 1548 1549 String packageName = nextArgRequired(); 1550 do { 1551 try { 1552 mAm.setPackageScreenCompatMode(packageName, enabled 1553 ? ActivityManager.COMPAT_MODE_ENABLED 1554 : ActivityManager.COMPAT_MODE_DISABLED); 1555 } catch (RemoteException e) { 1556 } 1557 packageName = nextArg(); 1558 } while (packageName != null); 1559 } 1560 1561 private void runPackageImportance() throws Exception { 1562 String packageName = nextArgRequired(); 1563 try { 1564 int procState = mAm.getPackageProcessState(packageName, "com.android.shell"); 1565 System.out.println( 1566 ActivityManager.RunningAppProcessInfo.procStateToImportance(procState)); 1567 } catch (RemoteException e) { 1568 } 1569 } 1570 1571 private void runToUri(int flags) throws Exception { 1572 Intent intent = makeIntent(UserHandle.USER_CURRENT); 1573 System.out.println(intent.toUri(flags)); 1574 } 1575 1576 private class IntentReceiver extends IIntentReceiver.Stub { 1577 private boolean mFinished = false; 1578 1579 @Override 1580 public void performReceive(Intent intent, int resultCode, String data, Bundle extras, 1581 boolean ordered, boolean sticky, int sendingUser) { 1582 String line = "Broadcast completed: result=" + resultCode; 1583 if (data != null) line = line + ", data=\"" + data + "\""; 1584 if (extras != null) line = line + ", extras: " + extras; 1585 System.out.println(line); 1586 synchronized (this) { 1587 mFinished = true; 1588 notifyAll(); 1589 } 1590 } 1591 1592 public synchronized void waitForFinish() { 1593 try { 1594 while (!mFinished) wait(); 1595 } catch (InterruptedException e) { 1596 throw new IllegalStateException(e); 1597 } 1598 } 1599 } 1600 1601 private class InstrumentationWatcher extends IInstrumentationWatcher.Stub { 1602 private boolean mFinished = false; 1603 private boolean mRawMode = false; 1604 1605 /** 1606 * Set or reset "raw mode". In "raw mode", all bundles are dumped. In "pretty mode", 1607 * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that. 1608 * @param rawMode true for raw mode, false for pretty mode. 1609 */ 1610 public void setRawOutput(boolean rawMode) { 1611 mRawMode = rawMode; 1612 } 1613 1614 @Override 1615 public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) { 1616 synchronized (this) { 1617 // pretty printer mode? 1618 String pretty = null; 1619 if (!mRawMode && results != null) { 1620 pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 1621 } 1622 if (pretty != null) { 1623 System.out.print(pretty); 1624 } else { 1625 if (results != null) { 1626 for (String key : results.keySet()) { 1627 System.out.println( 1628 "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key)); 1629 } 1630 } 1631 System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode); 1632 } 1633 notifyAll(); 1634 } 1635 } 1636 1637 @Override 1638 public void instrumentationFinished(ComponentName name, int resultCode, 1639 Bundle results) { 1640 synchronized (this) { 1641 // pretty printer mode? 1642 String pretty = null; 1643 if (!mRawMode && results != null) { 1644 pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 1645 } 1646 if (pretty != null) { 1647 System.out.println(pretty); 1648 } else { 1649 if (results != null) { 1650 for (String key : results.keySet()) { 1651 System.out.println( 1652 "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key)); 1653 } 1654 } 1655 System.out.println("INSTRUMENTATION_CODE: " + resultCode); 1656 } 1657 mFinished = true; 1658 notifyAll(); 1659 } 1660 } 1661 1662 public boolean waitForFinish() { 1663 synchronized (this) { 1664 while (!mFinished) { 1665 try { 1666 if (!mAm.asBinder().pingBinder()) { 1667 return false; 1668 } 1669 wait(1000); 1670 } catch (InterruptedException e) { 1671 throw new IllegalStateException(e); 1672 } 1673 } 1674 } 1675 return true; 1676 } 1677 } 1678 1679 private void runStack() throws Exception { 1680 String op = nextArgRequired(); 1681 switch (op) { 1682 case "start": 1683 runStackStart(); 1684 break; 1685 case "movetask": 1686 runStackMoveTask(); 1687 break; 1688 case "resize": 1689 runStackResize(); 1690 break; 1691 case "resize-docked-stack": 1692 runStackResizeDocked(); 1693 break; 1694 case "positiontask": 1695 runStackPositionTask(); 1696 break; 1697 case "list": 1698 runStackList(); 1699 break; 1700 case "info": 1701 runStackInfo(); 1702 break; 1703 case "move-top-activity-to-pinned-stack": 1704 runMoveTopActivityToPinnedStack(); 1705 break; 1706 case "size-docked-stack-test": 1707 runStackSizeDockedStackTest(); 1708 break; 1709 default: 1710 showError("Error: unknown command '" + op + "'"); 1711 break; 1712 } 1713 } 1714 1715 private void runStackStart() throws Exception { 1716 String displayIdStr = nextArgRequired(); 1717 int displayId = Integer.valueOf(displayIdStr); 1718 Intent intent = makeIntent(UserHandle.USER_CURRENT); 1719 1720 try { 1721 IActivityContainer container = mAm.createStackOnDisplay(displayId); 1722 if (container != null) { 1723 container.startActivity(intent); 1724 } 1725 } catch (RemoteException e) { 1726 } 1727 } 1728 1729 private void runStackMoveTask() throws Exception { 1730 String taskIdStr = nextArgRequired(); 1731 int taskId = Integer.valueOf(taskIdStr); 1732 String stackIdStr = nextArgRequired(); 1733 int stackId = Integer.valueOf(stackIdStr); 1734 String toTopStr = nextArgRequired(); 1735 final boolean toTop; 1736 if ("true".equals(toTopStr)) { 1737 toTop = true; 1738 } else if ("false".equals(toTopStr)) { 1739 toTop = false; 1740 } else { 1741 System.err.println("Error: bad toTop arg: " + toTopStr); 1742 return; 1743 } 1744 1745 try { 1746 mAm.moveTaskToStack(taskId, stackId, toTop); 1747 } catch (RemoteException e) { 1748 } 1749 } 1750 1751 private void runStackResize() throws Exception { 1752 String stackIdStr = nextArgRequired(); 1753 int stackId = Integer.valueOf(stackIdStr); 1754 final Rect bounds = getBounds(); 1755 if (bounds == null) { 1756 System.err.println("Error: invalid input bounds"); 1757 return; 1758 } 1759 resizeStack(stackId, bounds, 0); 1760 } 1761 1762 private void runStackResizeDocked() throws Exception { 1763 final Rect bounds = getBounds(); 1764 final Rect taskBounds = getBounds(); 1765 if (bounds == null || taskBounds == null) { 1766 System.err.println("Error: invalid input bounds"); 1767 return; 1768 } 1769 try { 1770 mAm.resizeDockedStack(bounds, taskBounds, null, null, null); 1771 } catch (RemoteException e) { 1772 showError("Error: resizing docked stack " + e); 1773 } 1774 } 1775 1776 private void resizeStack(int stackId, Rect bounds, int delayMs) throws Exception { 1777 if (bounds == null) { 1778 showError("Error: invalid input bounds"); 1779 return; 1780 } 1781 1782 try { 1783 mAm.resizeStack(stackId, bounds, false); 1784 Thread.sleep(delayMs); 1785 } catch (RemoteException e) { 1786 showError("Error: resizing stack " + e); 1787 } catch (InterruptedException e) { 1788 } 1789 } 1790 1791 private void runStackPositionTask() throws Exception { 1792 String taskIdStr = nextArgRequired(); 1793 int taskId = Integer.valueOf(taskIdStr); 1794 String stackIdStr = nextArgRequired(); 1795 int stackId = Integer.valueOf(stackIdStr); 1796 String positionStr = nextArgRequired(); 1797 int position = Integer.valueOf(positionStr); 1798 1799 try { 1800 mAm.positionTaskInStack(taskId, stackId, position); 1801 } catch (RemoteException e) { 1802 } 1803 } 1804 1805 private void runStackList() throws Exception { 1806 try { 1807 List<StackInfo> stacks = mAm.getAllStackInfos(); 1808 for (StackInfo info : stacks) { 1809 System.out.println(info); 1810 } 1811 } catch (RemoteException e) { 1812 } 1813 } 1814 1815 private void runStackInfo() throws Exception { 1816 try { 1817 String stackIdStr = nextArgRequired(); 1818 int stackId = Integer.valueOf(stackIdStr); 1819 StackInfo info = mAm.getStackInfo(stackId); 1820 System.out.println(info); 1821 } catch (RemoteException e) { 1822 } 1823 } 1824 1825 private void runMoveTopActivityToPinnedStack() throws Exception { 1826 int stackId = Integer.valueOf(nextArgRequired()); 1827 final Rect bounds = getBounds(); 1828 if (bounds == null) { 1829 System.err.println("Error: invalid input bounds"); 1830 return; 1831 } 1832 1833 try { 1834 if (!mAm.moveTopActivityToPinnedStack(stackId, bounds)) { 1835 showError("Didn't move top activity to pinned stack."); 1836 } 1837 } catch (RemoteException e) { 1838 showError("Unable to move top activity: " + e); 1839 return; 1840 } 1841 } 1842 1843 private void runStackSizeDockedStackTest() throws Exception { 1844 final int stepSize = Integer.valueOf(nextArgRequired()); 1845 final String side = nextArgRequired(); 1846 final String delayStr = nextArg(); 1847 final int delayMs = (delayStr != null) ? Integer.valueOf(delayStr) : 0; 1848 1849 Rect bounds; 1850 try { 1851 StackInfo info = mAm.getStackInfo(DOCKED_STACK_ID); 1852 if (info == null) { 1853 showError("Docked stack doesn't exist"); 1854 return; 1855 } 1856 if (info.bounds == null) { 1857 showError("Docked stack doesn't have a bounds"); 1858 return; 1859 } 1860 bounds = info.bounds; 1861 } catch (RemoteException e) { 1862 showError("Unable to get docked stack info:" + e); 1863 return; 1864 } 1865 1866 final boolean horizontalGrowth = "l".equals(side) || "r".equals(side); 1867 final int changeSize = (horizontalGrowth ? bounds.width() : bounds.height()) / 2; 1868 int currentPoint; 1869 switch (side) { 1870 case "l": 1871 currentPoint = bounds.left; 1872 break; 1873 case "r": 1874 currentPoint = bounds.right; 1875 break; 1876 case "t": 1877 currentPoint = bounds.top; 1878 break; 1879 case "b": 1880 currentPoint = bounds.bottom; 1881 break; 1882 default: 1883 showError("Unknown growth side: " + side); 1884 return; 1885 } 1886 1887 final int startPoint = currentPoint; 1888 final int minPoint = currentPoint - changeSize; 1889 final int maxPoint = currentPoint + changeSize; 1890 1891 int maxChange; 1892 System.out.println("Shrinking docked stack side=" + side); 1893 while (currentPoint > minPoint) { 1894 maxChange = Math.min(stepSize, currentPoint - minPoint); 1895 currentPoint -= maxChange; 1896 setBoundsSide(bounds, side, currentPoint); 1897 resizeStack(DOCKED_STACK_ID, bounds, delayMs); 1898 } 1899 1900 System.out.println("Growing docked stack side=" + side); 1901 while (currentPoint < maxPoint) { 1902 maxChange = Math.min(stepSize, maxPoint - currentPoint); 1903 currentPoint += maxChange; 1904 setBoundsSide(bounds, side, currentPoint); 1905 resizeStack(DOCKED_STACK_ID, bounds, delayMs); 1906 } 1907 1908 System.out.println("Back to Original size side=" + side); 1909 while (currentPoint > startPoint) { 1910 maxChange = Math.min(stepSize, currentPoint - startPoint); 1911 currentPoint -= maxChange; 1912 setBoundsSide(bounds, side, currentPoint); 1913 resizeStack(DOCKED_STACK_ID, bounds, delayMs); 1914 } 1915 } 1916 1917 private void setBoundsSide(Rect bounds, String side, int value) { 1918 switch (side) { 1919 case "l": 1920 bounds.left = value; 1921 break; 1922 case "r": 1923 bounds.right = value; 1924 break; 1925 case "t": 1926 bounds.top = value; 1927 break; 1928 case "b": 1929 bounds.bottom = value; 1930 break; 1931 default: 1932 showError("Unknown set side: " + side); 1933 break; 1934 } 1935 } 1936 1937 private void runTask() throws Exception { 1938 String op = nextArgRequired(); 1939 if (op.equals("lock")) { 1940 runTaskLock(); 1941 } else if (op.equals("resizeable")) { 1942 runTaskResizeable(); 1943 } else if (op.equals("resize")) { 1944 runTaskResize(); 1945 } else if (op.equals("drag-task-test")) { 1946 runTaskDragTaskTest(); 1947 } else if (op.equals("size-task-test")) { 1948 runTaskSizeTaskTest(); 1949 } else { 1950 showError("Error: unknown command '" + op + "'"); 1951 return; 1952 } 1953 } 1954 1955 private void runTaskLock() throws Exception { 1956 String taskIdStr = nextArgRequired(); 1957 try { 1958 if (taskIdStr.equals("stop")) { 1959 mAm.stopLockTaskMode(); 1960 } else { 1961 int taskId = Integer.valueOf(taskIdStr); 1962 mAm.startLockTaskMode(taskId); 1963 } 1964 System.err.println("Activity manager is " + (mAm.isInLockTaskMode() ? "" : "not ") + 1965 "in lockTaskMode"); 1966 } catch (RemoteException e) { 1967 } 1968 } 1969 1970 private void runTaskResizeable() throws Exception { 1971 final String taskIdStr = nextArgRequired(); 1972 final int taskId = Integer.valueOf(taskIdStr); 1973 final String resizeableStr = nextArgRequired(); 1974 final boolean resizeable = Boolean.valueOf(resizeableStr); 1975 1976 try { 1977 mAm.setTaskResizeable(taskId, resizeable); 1978 } catch (RemoteException e) { 1979 } 1980 } 1981 1982 private void runTaskResize() throws Exception { 1983 final String taskIdStr = nextArgRequired(); 1984 final int taskId = Integer.valueOf(taskIdStr); 1985 final Rect bounds = getBounds(); 1986 if (bounds == null) { 1987 System.err.println("Error: invalid input bounds"); 1988 return; 1989 } 1990 taskResize(taskId, bounds, 0, false); 1991 } 1992 1993 private void taskResize(int taskId, Rect bounds, int delay_ms, boolean pretendUserResize) { 1994 try { 1995 final int resizeMode = pretendUserResize ? RESIZE_MODE_USER : RESIZE_MODE_SYSTEM; 1996 mAm.resizeTask(taskId, bounds, resizeMode); 1997 Thread.sleep(delay_ms); 1998 } catch (RemoteException e) { 1999 System.err.println("Error changing task bounds: " + e); 2000 } catch (InterruptedException e) { 2001 } 2002 } 2003 2004 private void runTaskDragTaskTest() { 2005 final int taskId = Integer.valueOf(nextArgRequired()); 2006 final int stepSize = Integer.valueOf(nextArgRequired()); 2007 final String delayStr = nextArg(); 2008 final int delay_ms = (delayStr != null) ? Integer.valueOf(delayStr) : 0; 2009 final StackInfo stackInfo; 2010 Rect taskBounds; 2011 try { 2012 stackInfo = mAm.getStackInfo(mAm.getFocusedStackId()); 2013 taskBounds = mAm.getTaskBounds(taskId); 2014 } catch (RemoteException e) { 2015 System.err.println("Error getting focus stack info or task bounds: " + e); 2016 return; 2017 } 2018 final Rect stackBounds = stackInfo.bounds; 2019 int travelRight = stackBounds.width() - taskBounds.width(); 2020 int travelLeft = -travelRight; 2021 int travelDown = stackBounds.height() - taskBounds.height(); 2022 int travelUp = -travelDown; 2023 int passes = 0; 2024 2025 // We do 2 passes to get back to the original location of the task. 2026 while (passes < 2) { 2027 // Move right 2028 System.out.println("Moving right..."); 2029 travelRight = moveTask(taskId, taskBounds, stackBounds, stepSize, 2030 travelRight, MOVING_FORWARD, MOVING_HORIZONTALLY, delay_ms); 2031 System.out.println("Still need to travel right by " + travelRight); 2032 2033 // Move down 2034 System.out.println("Moving down..."); 2035 travelDown = moveTask(taskId, taskBounds, stackBounds, stepSize, 2036 travelDown, MOVING_FORWARD, !MOVING_HORIZONTALLY, delay_ms); 2037 System.out.println("Still need to travel down by " + travelDown); 2038 2039 // Move left 2040 System.out.println("Moving left..."); 2041 travelLeft = moveTask(taskId, taskBounds, stackBounds, stepSize, 2042 travelLeft, !MOVING_FORWARD, MOVING_HORIZONTALLY, delay_ms); 2043 System.out.println("Still need to travel left by " + travelLeft); 2044 2045 // Move up 2046 System.out.println("Moving up..."); 2047 travelUp = moveTask(taskId, taskBounds, stackBounds, stepSize, 2048 travelUp, !MOVING_FORWARD, !MOVING_HORIZONTALLY, delay_ms); 2049 System.out.println("Still need to travel up by " + travelUp); 2050 2051 try { 2052 taskBounds = mAm.getTaskBounds(taskId); 2053 } catch (RemoteException e) { 2054 System.err.println("Error getting task bounds: " + e); 2055 return; 2056 } 2057 passes++; 2058 } 2059 } 2060 2061 private int moveTask(int taskId, Rect taskRect, Rect stackRect, int stepSize, 2062 int maxToTravel, boolean movingForward, boolean horizontal, int delay_ms) { 2063 int maxMove; 2064 if (movingForward) { 2065 while (maxToTravel > 0 2066 && ((horizontal && taskRect.right < stackRect.right) 2067 ||(!horizontal && taskRect.bottom < stackRect.bottom))) { 2068 if (horizontal) { 2069 maxMove = Math.min(stepSize, stackRect.right - taskRect.right); 2070 maxToTravel -= maxMove; 2071 taskRect.right += maxMove; 2072 taskRect.left += maxMove; 2073 } else { 2074 maxMove = Math.min(stepSize, stackRect.bottom - taskRect.bottom); 2075 maxToTravel -= maxMove; 2076 taskRect.top += maxMove; 2077 taskRect.bottom += maxMove; 2078 } 2079 taskResize(taskId, taskRect, delay_ms, false); 2080 } 2081 } else { 2082 while (maxToTravel < 0 2083 && ((horizontal && taskRect.left > stackRect.left) 2084 ||(!horizontal && taskRect.top > stackRect.top))) { 2085 if (horizontal) { 2086 maxMove = Math.min(stepSize, taskRect.left - stackRect.left); 2087 maxToTravel -= maxMove; 2088 taskRect.right -= maxMove; 2089 taskRect.left -= maxMove; 2090 } else { 2091 maxMove = Math.min(stepSize, taskRect.top - stackRect.top); 2092 maxToTravel -= maxMove; 2093 taskRect.top -= maxMove; 2094 taskRect.bottom -= maxMove; 2095 } 2096 taskResize(taskId, taskRect, delay_ms, false); 2097 } 2098 } 2099 // Return the remaining distance we didn't travel because we reached the target location. 2100 return maxToTravel; 2101 } 2102 2103 private void runTaskSizeTaskTest() { 2104 final int taskId = Integer.valueOf(nextArgRequired()); 2105 final int stepSize = Integer.valueOf(nextArgRequired()); 2106 final String delayStr = nextArg(); 2107 final int delay_ms = (delayStr != null) ? Integer.valueOf(delayStr) : 0; 2108 final StackInfo stackInfo; 2109 final Rect initialTaskBounds; 2110 try { 2111 stackInfo = mAm.getStackInfo(mAm.getFocusedStackId()); 2112 initialTaskBounds = mAm.getTaskBounds(taskId); 2113 } catch (RemoteException e) { 2114 System.err.println("Error getting focus stack info or task bounds: " + e); 2115 return; 2116 } 2117 final Rect stackBounds = stackInfo.bounds; 2118 stackBounds.inset(STACK_BOUNDS_INSET, STACK_BOUNDS_INSET); 2119 final Rect currentTaskBounds = new Rect(initialTaskBounds); 2120 2121 // Size by top-left 2122 System.out.println("Growing top-left"); 2123 do { 2124 currentTaskBounds.top -= getStepSize( 2125 currentTaskBounds.top, stackBounds.top, stepSize, GREATER_THAN_TARGET); 2126 2127 currentTaskBounds.left -= getStepSize( 2128 currentTaskBounds.left, stackBounds.left, stepSize, GREATER_THAN_TARGET); 2129 2130 taskResize(taskId, currentTaskBounds, delay_ms, true); 2131 } while (stackBounds.top < currentTaskBounds.top 2132 || stackBounds.left < currentTaskBounds.left); 2133 2134 // Back to original size 2135 System.out.println("Shrinking top-left"); 2136 do { 2137 currentTaskBounds.top += getStepSize( 2138 currentTaskBounds.top, initialTaskBounds.top, stepSize, !GREATER_THAN_TARGET); 2139 2140 currentTaskBounds.left += getStepSize( 2141 currentTaskBounds.left, initialTaskBounds.left, stepSize, !GREATER_THAN_TARGET); 2142 2143 taskResize(taskId, currentTaskBounds, delay_ms, true); 2144 } while (initialTaskBounds.top > currentTaskBounds.top 2145 || initialTaskBounds.left > currentTaskBounds.left); 2146 2147 // Size by top-right 2148 System.out.println("Growing top-right"); 2149 do { 2150 currentTaskBounds.top -= getStepSize( 2151 currentTaskBounds.top, stackBounds.top, stepSize, GREATER_THAN_TARGET); 2152 2153 currentTaskBounds.right += getStepSize( 2154 currentTaskBounds.right, stackBounds.right, stepSize, !GREATER_THAN_TARGET); 2155 2156 taskResize(taskId, currentTaskBounds, delay_ms, true); 2157 } while (stackBounds.top < currentTaskBounds.top 2158 || stackBounds.right > currentTaskBounds.right); 2159 2160 // Back to original size 2161 System.out.println("Shrinking top-right"); 2162 do { 2163 currentTaskBounds.top += getStepSize( 2164 currentTaskBounds.top, initialTaskBounds.top, stepSize, !GREATER_THAN_TARGET); 2165 2166 currentTaskBounds.right -= getStepSize(currentTaskBounds.right, initialTaskBounds.right, 2167 stepSize, GREATER_THAN_TARGET); 2168 2169 taskResize(taskId, currentTaskBounds, delay_ms, true); 2170 } while (initialTaskBounds.top > currentTaskBounds.top 2171 || initialTaskBounds.right < currentTaskBounds.right); 2172 2173 // Size by bottom-left 2174 System.out.println("Growing bottom-left"); 2175 do { 2176 currentTaskBounds.bottom += getStepSize( 2177 currentTaskBounds.bottom, stackBounds.bottom, stepSize, !GREATER_THAN_TARGET); 2178 2179 currentTaskBounds.left -= getStepSize( 2180 currentTaskBounds.left, stackBounds.left, stepSize, GREATER_THAN_TARGET); 2181 2182 taskResize(taskId, currentTaskBounds, delay_ms, true); 2183 } while (stackBounds.bottom > currentTaskBounds.bottom 2184 || stackBounds.left < currentTaskBounds.left); 2185 2186 // Back to original size 2187 System.out.println("Shrinking bottom-left"); 2188 do { 2189 currentTaskBounds.bottom -= getStepSize(currentTaskBounds.bottom, 2190 initialTaskBounds.bottom, stepSize, GREATER_THAN_TARGET); 2191 2192 currentTaskBounds.left += getStepSize( 2193 currentTaskBounds.left, initialTaskBounds.left, stepSize, !GREATER_THAN_TARGET); 2194 2195 taskResize(taskId, currentTaskBounds, delay_ms, true); 2196 } while (initialTaskBounds.bottom < currentTaskBounds.bottom 2197 || initialTaskBounds.left > currentTaskBounds.left); 2198 2199 // Size by bottom-right 2200 System.out.println("Growing bottom-right"); 2201 do { 2202 currentTaskBounds.bottom += getStepSize( 2203 currentTaskBounds.bottom, stackBounds.bottom, stepSize, !GREATER_THAN_TARGET); 2204 2205 currentTaskBounds.right += getStepSize( 2206 currentTaskBounds.right, stackBounds.right, stepSize, !GREATER_THAN_TARGET); 2207 2208 taskResize(taskId, currentTaskBounds, delay_ms, true); 2209 } while (stackBounds.bottom > currentTaskBounds.bottom 2210 || stackBounds.right > currentTaskBounds.right); 2211 2212 // Back to original size 2213 System.out.println("Shrinking bottom-right"); 2214 do { 2215 currentTaskBounds.bottom -= getStepSize(currentTaskBounds.bottom, 2216 initialTaskBounds.bottom, stepSize, GREATER_THAN_TARGET); 2217 2218 currentTaskBounds.right -= getStepSize(currentTaskBounds.right, initialTaskBounds.right, 2219 stepSize, GREATER_THAN_TARGET); 2220 2221 taskResize(taskId, currentTaskBounds, delay_ms, true); 2222 } while (initialTaskBounds.bottom < currentTaskBounds.bottom 2223 || initialTaskBounds.right < currentTaskBounds.right); 2224 } 2225 2226 private int getStepSize(int current, int target, int inStepSize, boolean greaterThanTarget) { 2227 int stepSize = 0; 2228 if (greaterThanTarget && target < current) { 2229 current -= inStepSize; 2230 stepSize = inStepSize; 2231 if (target > current) { 2232 stepSize -= (target - current); 2233 } 2234 } 2235 if (!greaterThanTarget && target > current) { 2236 current += inStepSize; 2237 stepSize = inStepSize; 2238 if (target < current) { 2239 stepSize += (current - target); 2240 } 2241 } 2242 return stepSize; 2243 } 2244 2245 private List<Configuration> getRecentConfigurations(int days) { 2246 IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( 2247 Context.USAGE_STATS_SERVICE)); 2248 final long now = System.currentTimeMillis(); 2249 final long nDaysAgo = now - (days * 24 * 60 * 60 * 1000); 2250 try { 2251 @SuppressWarnings("unchecked") 2252 ParceledListSlice<ConfigurationStats> configStatsSlice = usm.queryConfigurationStats( 2253 UsageStatsManager.INTERVAL_BEST, nDaysAgo, now, "com.android.shell"); 2254 if (configStatsSlice == null) { 2255 return Collections.emptyList(); 2256 } 2257 2258 final ArrayMap<Configuration, Integer> recentConfigs = new ArrayMap<>(); 2259 final List<ConfigurationStats> configStatsList = configStatsSlice.getList(); 2260 final int configStatsListSize = configStatsList.size(); 2261 for (int i = 0; i < configStatsListSize; i++) { 2262 final ConfigurationStats stats = configStatsList.get(i); 2263 final int indexOfKey = recentConfigs.indexOfKey(stats.getConfiguration()); 2264 if (indexOfKey < 0) { 2265 recentConfigs.put(stats.getConfiguration(), stats.getActivationCount()); 2266 } else { 2267 recentConfigs.setValueAt(indexOfKey, 2268 recentConfigs.valueAt(indexOfKey) + stats.getActivationCount()); 2269 } 2270 } 2271 2272 final Comparator<Configuration> comparator = new Comparator<Configuration>() { 2273 @Override 2274 public int compare(Configuration a, Configuration b) { 2275 return recentConfigs.get(b).compareTo(recentConfigs.get(a)); 2276 } 2277 }; 2278 2279 ArrayList<Configuration> configs = new ArrayList<>(recentConfigs.size()); 2280 configs.addAll(recentConfigs.keySet()); 2281 Collections.sort(configs, comparator); 2282 return configs; 2283 2284 } catch (RemoteException e) { 2285 return Collections.emptyList(); 2286 } 2287 } 2288 2289 private void runGetConfig() throws Exception { 2290 int days = 14; 2291 String option = nextOption(); 2292 if (option != null) { 2293 if (!option.equals("--days")) { 2294 throw new IllegalArgumentException("unrecognized option " + option); 2295 } 2296 2297 days = Integer.parseInt(nextArgRequired()); 2298 if (days <= 0) { 2299 throw new IllegalArgumentException("--days must be a positive integer"); 2300 } 2301 } 2302 2303 try { 2304 Configuration config = mAm.getConfiguration(); 2305 if (config == null) { 2306 System.err.println("Activity manager has no configuration"); 2307 return; 2308 } 2309 2310 System.out.println("config: " + Configuration.resourceQualifierString(config)); 2311 System.out.println("abi: " + TextUtils.join(",", Build.SUPPORTED_ABIS)); 2312 2313 final List<Configuration> recentConfigs = getRecentConfigurations(days); 2314 final int recentConfigSize = recentConfigs.size(); 2315 if (recentConfigSize > 0) { 2316 System.out.println("recentConfigs:"); 2317 } 2318 2319 for (int i = 0; i < recentConfigSize; i++) { 2320 System.out.println(" config: " + Configuration.resourceQualifierString( 2321 recentConfigs.get(i))); 2322 } 2323 2324 } catch (RemoteException e) { 2325 } 2326 } 2327 2328 private void runSuppressResizeConfigChanges() throws Exception { 2329 boolean suppress = Boolean.valueOf(nextArgRequired()); 2330 2331 try { 2332 mAm.suppressResizeConfigChanges(suppress); 2333 } catch (RemoteException e) { 2334 System.err.println("Error suppressing resize config changes: " + e); 2335 } 2336 } 2337 2338 private void runSetInactive() throws Exception { 2339 int userId = UserHandle.USER_CURRENT; 2340 2341 String opt; 2342 while ((opt=nextOption()) != null) { 2343 if (opt.equals("--user")) { 2344 userId = parseUserArg(nextArgRequired()); 2345 } else { 2346 System.err.println("Error: Unknown option: " + opt); 2347 return; 2348 } 2349 } 2350 String packageName = nextArgRequired(); 2351 String value = nextArgRequired(); 2352 2353 IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( 2354 Context.USAGE_STATS_SERVICE)); 2355 usm.setAppInactive(packageName, Boolean.parseBoolean(value), userId); 2356 } 2357 2358 private void runGetInactive() throws Exception { 2359 int userId = UserHandle.USER_CURRENT; 2360 2361 String opt; 2362 while ((opt=nextOption()) != null) { 2363 if (opt.equals("--user")) { 2364 userId = parseUserArg(nextArgRequired()); 2365 } else { 2366 System.err.println("Error: Unknown option: " + opt); 2367 return; 2368 } 2369 } 2370 String packageName = nextArgRequired(); 2371 2372 IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( 2373 Context.USAGE_STATS_SERVICE)); 2374 boolean isIdle = usm.isAppInactive(packageName, userId); 2375 System.out.println("Idle=" + isIdle); 2376 } 2377 2378 private void runSendTrimMemory() throws Exception { 2379 int userId = UserHandle.USER_CURRENT; 2380 String opt; 2381 while ((opt = nextOption()) != null) { 2382 if (opt.equals("--user")) { 2383 userId = parseUserArg(nextArgRequired()); 2384 if (userId == UserHandle.USER_ALL) { 2385 System.err.println("Error: Can't use user 'all'"); 2386 return; 2387 } 2388 } else { 2389 System.err.println("Error: Unknown option: " + opt); 2390 return; 2391 } 2392 } 2393 2394 String proc = nextArgRequired(); 2395 String levelArg = nextArgRequired(); 2396 int level; 2397 switch (levelArg) { 2398 case "HIDDEN": 2399 level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN; 2400 break; 2401 case "RUNNING_MODERATE": 2402 level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE; 2403 break; 2404 case "BACKGROUND": 2405 level = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; 2406 break; 2407 case "RUNNING_LOW": 2408 level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW; 2409 break; 2410 case "MODERATE": 2411 level = ComponentCallbacks2.TRIM_MEMORY_MODERATE; 2412 break; 2413 case "RUNNING_CRITICAL": 2414 level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL; 2415 break; 2416 case "COMPLETE": 2417 level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; 2418 break; 2419 default: 2420 System.err.println("Error: Unknown level option: " + levelArg); 2421 return; 2422 } 2423 if (!mAm.setProcessMemoryTrimLevel(proc, userId, level)) { 2424 System.err.println("Error: Failure to set the level - probably Unknown Process: " + 2425 proc); 2426 } 2427 } 2428 2429 private void runGetCurrentUser() throws Exception { 2430 UserInfo currentUser = Preconditions.checkNotNull(mAm.getCurrentUser(), 2431 "Current user not set"); 2432 System.out.println(currentUser.id); 2433 } 2434 2435 /** 2436 * Open the given file for sending into the system process. This verifies 2437 * with SELinux that the system will have access to the file. 2438 */ 2439 private static ParcelFileDescriptor openForSystemServer(File file, int mode) 2440 throws FileNotFoundException { 2441 final ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, mode); 2442 final String tcon = SELinux.getFileContext(file.getAbsolutePath()); 2443 if (!SELinux.checkSELinuxAccess("u:r:system_server:s0", tcon, "file", "read")) { 2444 throw new FileNotFoundException("System server has no access to file context " + tcon); 2445 } 2446 return fd; 2447 } 2448 2449 private Rect getBounds() { 2450 String leftStr = nextArgRequired(); 2451 int left = Integer.valueOf(leftStr); 2452 String topStr = nextArgRequired(); 2453 int top = Integer.valueOf(topStr); 2454 String rightStr = nextArgRequired(); 2455 int right = Integer.valueOf(rightStr); 2456 String bottomStr = nextArgRequired(); 2457 int bottom = Integer.valueOf(bottomStr); 2458 if (left < 0) { 2459 System.err.println("Error: bad left arg: " + leftStr); 2460 return null; 2461 } 2462 if (top < 0) { 2463 System.err.println("Error: bad top arg: " + topStr); 2464 return null; 2465 } 2466 if (right <= 0) { 2467 System.err.println("Error: bad right arg: " + rightStr); 2468 return null; 2469 } 2470 if (bottom <= 0) { 2471 System.err.println("Error: bad bottom arg: " + bottomStr); 2472 return null; 2473 } 2474 return new Rect(left, top, right, bottom); 2475 } 2476} 2477