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