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 17 package com.android.server.am; 18 19 import android.app.ActivityManager; 20 import android.app.ActivityOptions; 21 import android.app.AppGlobals; 22 import android.app.IActivityController; 23 import android.app.IActivityManager; 24 import android.app.IStopUserCallback; 25 import android.app.IUidObserver; 26 import android.app.KeyguardManager; 27 import android.app.ProfilerInfo; 28 import android.app.WaitResult; 29 import android.app.usage.AppStandbyInfo; 30 import android.app.usage.ConfigurationStats; 31 import android.app.usage.IUsageStatsManager; 32 import android.app.usage.UsageStatsManager; 33 import android.content.ComponentCallbacks2; 34 import android.content.ComponentName; 35 import android.content.Context; 36 import android.content.DeviceConfigurationProto; 37 import android.content.GlobalConfigurationProto; 38 import android.content.IIntentReceiver; 39 import android.content.Intent; 40 import android.content.pm.ConfigurationInfo; 41 import android.content.pm.FeatureInfo; 42 import android.content.pm.IPackageManager; 43 import android.content.pm.PackageManager; 44 import android.content.pm.ParceledListSlice; 45 import android.content.pm.ResolveInfo; 46 import android.content.pm.SharedLibraryInfo; 47 import android.content.pm.UserInfo; 48 import android.content.res.AssetManager; 49 import android.content.res.Configuration; 50 import android.content.res.Resources; 51 import android.graphics.Point; 52 import android.graphics.Rect; 53 import android.hardware.display.DisplayManager; 54 import android.opengl.GLES10; 55 import android.os.Binder; 56 import android.os.Build; 57 import android.os.Bundle; 58 import android.os.ParcelFileDescriptor; 59 import android.os.RemoteException; 60 import android.os.ServiceManager; 61 import android.os.ShellCommand; 62 import android.os.StrictMode; 63 import android.os.SystemClock; 64 import android.os.SystemProperties; 65 import android.os.UserHandle; 66 import android.os.UserManager; 67 import android.text.TextUtils; 68 import android.util.ArrayMap; 69 import android.util.DebugUtils; 70 import android.util.DisplayMetrics; 71 import android.util.proto.ProtoOutputStream; 72 import android.view.Display; 73 74 import com.android.internal.util.HexDump; 75 import com.android.internal.util.MemInfoReader; 76 import com.android.internal.util.Preconditions; 77 78 import java.io.BufferedReader; 79 import java.io.File; 80 import java.io.IOException; 81 import java.io.InputStream; 82 import java.io.InputStreamReader; 83 import java.io.PrintWriter; 84 import java.net.URISyntaxException; 85 import java.util.ArrayList; 86 import java.util.Arrays; 87 import java.util.Collections; 88 import java.util.Comparator; 89 import java.util.HashSet; 90 import java.util.List; 91 import java.util.Set; 92 93 import javax.microedition.khronos.egl.EGL10; 94 import javax.microedition.khronos.egl.EGLConfig; 95 import javax.microedition.khronos.egl.EGLContext; 96 import javax.microedition.khronos.egl.EGLDisplay; 97 import javax.microedition.khronos.egl.EGLSurface; 98 99 import static android.app.ActivityManager.RESIZE_MODE_SYSTEM; 100 import static android.app.ActivityManager.RESIZE_MODE_USER; 101 import static android.app.ActivityManager.StackId.INVALID_STACK_ID; 102 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 103 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 104 import static android.view.Display.INVALID_DISPLAY; 105 106 import static com.android.server.am.TaskRecord.INVALID_TASK_ID; 107 108 final class ActivityManagerShellCommand extends ShellCommand { 109 public static final String NO_CLASS_ERROR_CODE = "Error type 3"; 110 private static final String SHELL_PACKAGE_NAME = "com.android.shell"; 111 112 // IPC interface to activity manager -- don't need to do additional security checks. 113 final IActivityManager mInterface; 114 115 // Internal service impl -- must perform security checks before touching. 116 final ActivityManagerService mInternal; 117 118 // Convenience for interacting with package manager. 119 final IPackageManager mPm; 120 121 private int mStartFlags = 0; 122 private boolean mWaitOption = false; 123 private boolean mStopOption = false; 124 125 private int mRepeat = 0; 126 private int mUserId; 127 private String mReceiverPermission; 128 129 private String mProfileFile; 130 private int mSamplingInterval; 131 private boolean mAutoStop; 132 private boolean mStreaming; // Streaming the profiling output to a file. 133 private String mAgent; // Agent to attach on startup. 134 private boolean mAttachAgentDuringBind; // Whether agent should be attached late. 135 private int mDisplayId; 136 private int mWindowingMode; 137 private int mActivityType; 138 private int mTaskId; 139 private boolean mIsTaskOverlay; 140 private boolean mIsLockTask; 141 142 final boolean mDumping; 143 144 ActivityManagerShellCommand(ActivityManagerService service, boolean dumping) { 145 mInterface = service; 146 mInternal = service; 147 mPm = AppGlobals.getPackageManager(); 148 mDumping = dumping; 149 } 150 151 @Override 152 public int onCommand(String cmd) { 153 if (cmd == null) { 154 return handleDefaultCommands(cmd); 155 } 156 final PrintWriter pw = getOutPrintWriter(); 157 try { 158 switch (cmd) { 159 case "start": 160 case "start-activity": 161 return runStartActivity(pw); 162 case "startservice": 163 case "start-service": 164 return runStartService(pw, false); 165 case "startforegroundservice": 166 case "startfgservice": 167 case "start-foreground-service": 168 case "start-fg-service": 169 return runStartService(pw, true); 170 case "stopservice": 171 case "stop-service": 172 return runStopService(pw); 173 case "broadcast": 174 return runSendBroadcast(pw); 175 case "instrument": 176 getOutPrintWriter().println("Error: must be invoked through 'am instrument'."); 177 return -1; 178 case "trace-ipc": 179 return runTraceIpc(pw); 180 case "profile": 181 return runProfile(pw); 182 case "dumpheap": 183 return runDumpHeap(pw); 184 case "set-debug-app": 185 return runSetDebugApp(pw); 186 case "set-agent-app": 187 return runSetAgentApp(pw); 188 case "clear-debug-app": 189 return runClearDebugApp(pw); 190 case "set-watch-heap": 191 return runSetWatchHeap(pw); 192 case "clear-watch-heap": 193 return runClearWatchHeap(pw); 194 case "bug-report": 195 return runBugReport(pw); 196 case "force-stop": 197 return runForceStop(pw); 198 case "crash": 199 return runCrash(pw); 200 case "kill": 201 return runKill(pw); 202 case "kill-all": 203 return runKillAll(pw); 204 case "make-uid-idle": 205 return runMakeIdle(pw); 206 case "monitor": 207 return runMonitor(pw); 208 case "watch-uids": 209 return runWatchUids(pw); 210 case "hang": 211 return runHang(pw); 212 case "restart": 213 return runRestart(pw); 214 case "idle-maintenance": 215 return runIdleMaintenance(pw); 216 case "screen-compat": 217 return runScreenCompat(pw); 218 case "package-importance": 219 return runPackageImportance(pw); 220 case "to-uri": 221 return runToUri(pw, 0); 222 case "to-intent-uri": 223 return runToUri(pw, Intent.URI_INTENT_SCHEME); 224 case "to-app-uri": 225 return runToUri(pw, Intent.URI_ANDROID_APP_SCHEME); 226 case "switch-user": 227 return runSwitchUser(pw); 228 case "get-current-user": 229 return runGetCurrentUser(pw); 230 case "start-user": 231 return runStartUser(pw); 232 case "unlock-user": 233 return runUnlockUser(pw); 234 case "stop-user": 235 return runStopUser(pw); 236 case "is-user-stopped": 237 return runIsUserStopped(pw); 238 case "get-started-user-state": 239 return runGetStartedUserState(pw); 240 case "track-associations": 241 return runTrackAssociations(pw); 242 case "untrack-associations": 243 return runUntrackAssociations(pw); 244 case "get-uid-state": 245 return getUidState(pw); 246 case "get-config": 247 return runGetConfig(pw); 248 case "suppress-resize-config-changes": 249 return runSuppressResizeConfigChanges(pw); 250 case "set-inactive": 251 return runSetInactive(pw); 252 case "get-inactive": 253 return runGetInactive(pw); 254 case "set-standby-bucket": 255 return runSetStandbyBucket(pw); 256 case "get-standby-bucket": 257 return runGetStandbyBucket(pw); 258 case "send-trim-memory": 259 return runSendTrimMemory(pw); 260 case "display": 261 return runDisplay(pw); 262 case "stack": 263 return runStack(pw); 264 case "task": 265 return runTask(pw); 266 case "write": 267 return runWrite(pw); 268 case "attach-agent": 269 return runAttachAgent(pw); 270 case "supports-multiwindow": 271 return runSupportsMultiwindow(pw); 272 case "supports-split-screen-multi-window": 273 return runSupportsSplitScreenMultiwindow(pw); 274 case "update-appinfo": 275 return runUpdateApplicationInfo(pw); 276 case "no-home-screen": 277 return runNoHomeScreen(pw); 278 case "wait-for-broadcast-idle": 279 return runWaitForBroadcastIdle(pw); 280 default: 281 return handleDefaultCommands(cmd); 282 } 283 } catch (RemoteException e) { 284 pw.println("Remote exception: " + e); 285 } 286 return -1; 287 } 288 289 private Intent makeIntent(int defUser) throws URISyntaxException { 290 mStartFlags = 0; 291 mWaitOption = false; 292 mStopOption = false; 293 mRepeat = 0; 294 mProfileFile = null; 295 mSamplingInterval = 0; 296 mAutoStop = false; 297 mStreaming = false; 298 mUserId = defUser; 299 mDisplayId = INVALID_DISPLAY; 300 mWindowingMode = WINDOWING_MODE_UNDEFINED; 301 mActivityType = ACTIVITY_TYPE_UNDEFINED; 302 mTaskId = INVALID_TASK_ID; 303 mIsTaskOverlay = false; 304 mIsLockTask = false; 305 306 return Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() { 307 @Override 308 public boolean handleOption(String opt, ShellCommand cmd) { 309 if (opt.equals("-D")) { 310 mStartFlags |= ActivityManager.START_FLAG_DEBUG; 311 } else if (opt.equals("-N")) { 312 mStartFlags |= ActivityManager.START_FLAG_NATIVE_DEBUGGING; 313 } else if (opt.equals("-W")) { 314 mWaitOption = true; 315 } else if (opt.equals("-P")) { 316 mProfileFile = getNextArgRequired(); 317 mAutoStop = true; 318 } else if (opt.equals("--start-profiler")) { 319 mProfileFile = getNextArgRequired(); 320 mAutoStop = false; 321 } else if (opt.equals("--sampling")) { 322 mSamplingInterval = Integer.parseInt(getNextArgRequired()); 323 } else if (opt.equals("--streaming")) { 324 mStreaming = true; 325 } else if (opt.equals("--attach-agent")) { 326 if (mAgent != null) { 327 cmd.getErrPrintWriter().println( 328 "Multiple --attach-agent(-bind) not supported"); 329 return false; 330 } 331 mAgent = getNextArgRequired(); 332 mAttachAgentDuringBind = false; 333 } else if (opt.equals("--attach-agent-bind")) { 334 if (mAgent != null) { 335 cmd.getErrPrintWriter().println( 336 "Multiple --attach-agent(-bind) not supported"); 337 return false; 338 } 339 mAgent = getNextArgRequired(); 340 mAttachAgentDuringBind = true; 341 } else if (opt.equals("-R")) { 342 mRepeat = Integer.parseInt(getNextArgRequired()); 343 } else if (opt.equals("-S")) { 344 mStopOption = true; 345 } else if (opt.equals("--track-allocation")) { 346 mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION; 347 } else if (opt.equals("--user")) { 348 mUserId = UserHandle.parseUserArg(getNextArgRequired()); 349 } else if (opt.equals("--receiver-permission")) { 350 mReceiverPermission = getNextArgRequired(); 351 } else if (opt.equals("--display")) { 352 mDisplayId = Integer.parseInt(getNextArgRequired()); 353 } else if (opt.equals("--windowingMode")) { 354 mWindowingMode = Integer.parseInt(getNextArgRequired()); 355 } else if (opt.equals("--activityType")) { 356 mActivityType = Integer.parseInt(getNextArgRequired()); 357 } else if (opt.equals("--task")) { 358 mTaskId = Integer.parseInt(getNextArgRequired()); 359 } else if (opt.equals("--task-overlay")) { 360 mIsTaskOverlay = true; 361 } else if (opt.equals("--lock-task")) { 362 mIsLockTask = true; 363 } else { 364 return false; 365 } 366 return true; 367 } 368 }); 369 } 370 371 int runStartActivity(PrintWriter pw) throws RemoteException { 372 Intent intent; 373 try { 374 intent = makeIntent(UserHandle.USER_CURRENT); 375 } catch (URISyntaxException e) { 376 throw new RuntimeException(e.getMessage(), e); 377 } 378 379 if (mUserId == UserHandle.USER_ALL) { 380 getErrPrintWriter().println("Error: Can't start service with user 'all'"); 381 return 1; 382 } 383 384 String mimeType = intent.getType(); 385 if (mimeType == null && intent.getData() != null 386 && "content".equals(intent.getData().getScheme())) { 387 mimeType = mInterface.getProviderMimeType(intent.getData(), mUserId); 388 } 389 390 do { 391 if (mStopOption) { 392 String packageName; 393 if (intent.getComponent() != null) { 394 packageName = intent.getComponent().getPackageName(); 395 } else { 396 List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0, 397 mUserId).getList(); 398 if (activities == null || activities.size() <= 0) { 399 getErrPrintWriter().println("Error: Intent does not match any activities: " 400 + intent); 401 return 1; 402 } else if (activities.size() > 1) { 403 getErrPrintWriter().println( 404 "Error: Intent matches multiple activities; can't stop: " 405 + intent); 406 return 1; 407 } 408 packageName = activities.get(0).activityInfo.packageName; 409 } 410 pw.println("Stopping: " + packageName); 411 pw.flush(); 412 mInterface.forceStopPackage(packageName, mUserId); 413 try { 414 Thread.sleep(250); 415 } catch (InterruptedException e) { 416 } 417 } 418 419 ProfilerInfo profilerInfo = null; 420 421 if (mProfileFile != null || mAgent != null) { 422 ParcelFileDescriptor fd = null; 423 if (mProfileFile != null) { 424 fd = openFileForSystem(mProfileFile, "w"); 425 if (fd == null) { 426 return 1; 427 } 428 } 429 profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop, 430 mStreaming, mAgent, mAttachAgentDuringBind); 431 } 432 433 pw.println("Starting: " + intent); 434 pw.flush(); 435 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 436 437 WaitResult result = null; 438 int res; 439 final long startTime = SystemClock.uptimeMillis(); 440 ActivityOptions options = null; 441 if (mDisplayId != INVALID_DISPLAY) { 442 options = ActivityOptions.makeBasic(); 443 options.setLaunchDisplayId(mDisplayId); 444 } 445 if (mWindowingMode != WINDOWING_MODE_UNDEFINED) { 446 if (options == null) { 447 options = ActivityOptions.makeBasic(); 448 } 449 options.setLaunchWindowingMode(mWindowingMode); 450 } 451 if (mActivityType != ACTIVITY_TYPE_UNDEFINED) { 452 if (options == null) { 453 options = ActivityOptions.makeBasic(); 454 } 455 options.setLaunchActivityType(mActivityType); 456 } 457 if (mTaskId != INVALID_TASK_ID) { 458 if (options == null) { 459 options = ActivityOptions.makeBasic(); 460 } 461 options.setLaunchTaskId(mTaskId); 462 463 if (mIsTaskOverlay) { 464 options.setTaskOverlay(true, true /* canResume */); 465 } 466 } 467 if (mIsLockTask) { 468 if (options == null) { 469 options = ActivityOptions.makeBasic(); 470 } 471 options.setLockTaskEnabled(true); 472 } 473 if (mWaitOption) { 474 result = mInterface.startActivityAndWait(null, null, intent, mimeType, 475 null, null, 0, mStartFlags, profilerInfo, 476 options != null ? options.toBundle() : null, mUserId); 477 res = result.result; 478 } else { 479 res = mInterface.startActivityAsUser(null, null, intent, mimeType, 480 null, null, 0, mStartFlags, profilerInfo, 481 options != null ? options.toBundle() : null, mUserId); 482 } 483 final long endTime = SystemClock.uptimeMillis(); 484 PrintWriter out = mWaitOption ? pw : getErrPrintWriter(); 485 boolean launched = false; 486 switch (res) { 487 case ActivityManager.START_SUCCESS: 488 launched = true; 489 break; 490 case ActivityManager.START_SWITCHES_CANCELED: 491 launched = true; 492 out.println( 493 "Warning: Activity not started because the " 494 + " current activity is being kept for the user."); 495 break; 496 case ActivityManager.START_DELIVERED_TO_TOP: 497 launched = true; 498 out.println( 499 "Warning: Activity not started, intent has " 500 + "been delivered to currently running " 501 + "top-most instance."); 502 break; 503 case ActivityManager.START_RETURN_INTENT_TO_CALLER: 504 launched = true; 505 out.println( 506 "Warning: Activity not started because intent " 507 + "should be handled by the caller"); 508 break; 509 case ActivityManager.START_TASK_TO_FRONT: 510 launched = true; 511 out.println( 512 "Warning: Activity not started, its current " 513 + "task has been brought to the front"); 514 break; 515 case ActivityManager.START_INTENT_NOT_RESOLVED: 516 out.println( 517 "Error: Activity not started, unable to " 518 + "resolve " + intent.toString()); 519 break; 520 case ActivityManager.START_CLASS_NOT_FOUND: 521 out.println(NO_CLASS_ERROR_CODE); 522 out.println("Error: Activity class " + 523 intent.getComponent().toShortString() 524 + " does not exist."); 525 break; 526 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: 527 out.println( 528 "Error: Activity not started, you requested to " 529 + "both forward and receive its result"); 530 break; 531 case ActivityManager.START_PERMISSION_DENIED: 532 out.println( 533 "Error: Activity not started, you do not " 534 + "have permission to access it."); 535 break; 536 case ActivityManager.START_NOT_VOICE_COMPATIBLE: 537 out.println( 538 "Error: Activity not started, voice control not allowed for: " 539 + intent); 540 break; 541 case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY: 542 out.println( 543 "Error: Not allowed to start background user activity" 544 + " that shouldn't be displayed for all users."); 545 break; 546 default: 547 out.println( 548 "Error: Activity not started, unknown error code " + res); 549 break; 550 } 551 out.flush(); 552 if (mWaitOption && launched) { 553 if (result == null) { 554 result = new WaitResult(); 555 result.who = intent.getComponent(); 556 } 557 pw.println("Status: " + (result.timeout ? "timeout" : "ok")); 558 if (result.who != null) { 559 pw.println("Activity: " + result.who.flattenToShortString()); 560 } 561 if (result.thisTime >= 0) { 562 pw.println("ThisTime: " + result.thisTime); 563 } 564 if (result.totalTime >= 0) { 565 pw.println("TotalTime: " + result.totalTime); 566 } 567 pw.println("WaitTime: " + (endTime-startTime)); 568 pw.println("Complete"); 569 pw.flush(); 570 } 571 mRepeat--; 572 if (mRepeat > 0) { 573 mInterface.unhandledBack(); 574 } 575 } while (mRepeat > 0); 576 return 0; 577 } 578 579 int runStartService(PrintWriter pw, boolean asForeground) throws RemoteException { 580 final PrintWriter err = getErrPrintWriter(); 581 Intent intent; 582 try { 583 intent = makeIntent(UserHandle.USER_CURRENT); 584 } catch (URISyntaxException e) { 585 throw new RuntimeException(e.getMessage(), e); 586 } 587 if (mUserId == UserHandle.USER_ALL) { 588 err.println("Error: Can't start activity with user 'all'"); 589 return -1; 590 } 591 pw.println("Starting service: " + intent); 592 pw.flush(); 593 ComponentName cn = mInterface.startService(null, intent, intent.getType(), 594 asForeground, SHELL_PACKAGE_NAME, mUserId); 595 if (cn == null) { 596 err.println("Error: Not found; no service started."); 597 return -1; 598 } else if (cn.getPackageName().equals("!")) { 599 err.println("Error: Requires permission " + cn.getClassName()); 600 return -1; 601 } else if (cn.getPackageName().equals("!!")) { 602 err.println("Error: " + cn.getClassName()); 603 return -1; 604 } else if (cn.getPackageName().equals("?")) { 605 err.println("Error: " + cn.getClassName()); 606 return -1; 607 } 608 return 0; 609 } 610 611 int runStopService(PrintWriter pw) throws RemoteException { 612 final PrintWriter err = getErrPrintWriter(); 613 Intent intent; 614 try { 615 intent = makeIntent(UserHandle.USER_CURRENT); 616 } catch (URISyntaxException e) { 617 throw new RuntimeException(e.getMessage(), e); 618 } 619 if (mUserId == UserHandle.USER_ALL) { 620 err.println("Error: Can't stop activity with user 'all'"); 621 return -1; 622 } 623 pw.println("Stopping service: " + intent); 624 pw.flush(); 625 int result = mInterface.stopService(null, intent, intent.getType(), mUserId); 626 if (result == 0) { 627 err.println("Service not stopped: was not running."); 628 return -1; 629 } else if (result == 1) { 630 err.println("Service stopped"); 631 return -1; 632 } else if (result == -1) { 633 err.println("Error stopping service"); 634 return -1; 635 } 636 return 0; 637 } 638 639 final static class IntentReceiver extends IIntentReceiver.Stub { 640 private final PrintWriter mPw; 641 private boolean mFinished = false; 642 643 IntentReceiver(PrintWriter pw) { 644 mPw = pw; 645 } 646 647 @Override 648 public void performReceive(Intent intent, int resultCode, String data, Bundle extras, 649 boolean ordered, boolean sticky, int sendingUser) { 650 String line = "Broadcast completed: result=" + resultCode; 651 if (data != null) line = line + ", data=\"" + data + "\""; 652 if (extras != null) line = line + ", extras: " + extras; 653 mPw.println(line); 654 mPw.flush(); 655 synchronized (this) { 656 mFinished = true; 657 notifyAll(); 658 } 659 } 660 661 public synchronized void waitForFinish() { 662 try { 663 while (!mFinished) wait(); 664 } catch (InterruptedException e) { 665 throw new IllegalStateException(e); 666 } 667 } 668 } 669 670 int runSendBroadcast(PrintWriter pw) throws RemoteException { 671 Intent intent; 672 try { 673 intent = makeIntent(UserHandle.USER_CURRENT); 674 } catch (URISyntaxException e) { 675 throw new RuntimeException(e.getMessage(), e); 676 } 677 intent.addFlags(Intent.FLAG_RECEIVER_FROM_SHELL); 678 IntentReceiver receiver = new IntentReceiver(pw); 679 String[] requiredPermissions = mReceiverPermission == null ? null 680 : new String[] {mReceiverPermission}; 681 pw.println("Broadcasting: " + intent); 682 pw.flush(); 683 mInterface.broadcastIntent(null, intent, null, receiver, 0, null, null, requiredPermissions, 684 android.app.AppOpsManager.OP_NONE, null, true, false, mUserId); 685 receiver.waitForFinish(); 686 return 0; 687 } 688 689 int runTraceIpc(PrintWriter pw) throws RemoteException { 690 String op = getNextArgRequired(); 691 if (op.equals("start")) { 692 return runTraceIpcStart(pw); 693 } else if (op.equals("stop")) { 694 return runTraceIpcStop(pw); 695 } else { 696 getErrPrintWriter().println("Error: unknown trace ipc command '" + op + "'"); 697 return -1; 698 } 699 } 700 701 int runTraceIpcStart(PrintWriter pw) throws RemoteException { 702 pw.println("Starting IPC tracing."); 703 pw.flush(); 704 mInterface.startBinderTracking(); 705 return 0; 706 } 707 708 int runTraceIpcStop(PrintWriter pw) throws RemoteException { 709 final PrintWriter err = getErrPrintWriter(); 710 String opt; 711 String filename = null; 712 while ((opt=getNextOption()) != null) { 713 if (opt.equals("--dump-file")) { 714 filename = getNextArgRequired(); 715 } else { 716 err.println("Error: Unknown option: " + opt); 717 return -1; 718 } 719 } 720 if (filename == null) { 721 err.println("Error: Specify filename to dump logs to."); 722 return -1; 723 } 724 725 File file = new File(filename); 726 file.delete(); 727 ParcelFileDescriptor fd = openFileForSystem(filename, "w"); 728 if (fd == null) { 729 return -1; 730 } 731 732 ; 733 if (!mInterface.stopBinderTrackingAndDump(fd)) { 734 err.println("STOP TRACE FAILED."); 735 return -1; 736 } 737 738 pw.println("Stopped IPC tracing. Dumping logs to: " + filename); 739 return 0; 740 } 741 742 static void removeWallOption() { 743 String props = SystemProperties.get("dalvik.vm.extra-opts"); 744 if (props != null && props.contains("-Xprofile:wallclock")) { 745 props = props.replace("-Xprofile:wallclock", ""); 746 props = props.trim(); 747 SystemProperties.set("dalvik.vm.extra-opts", props); 748 } 749 } 750 751 private int runProfile(PrintWriter pw) throws RemoteException { 752 final PrintWriter err = getErrPrintWriter(); 753 String profileFile = null; 754 boolean start = false; 755 boolean wall = false; 756 int userId = UserHandle.USER_CURRENT; 757 int profileType = 0; 758 mSamplingInterval = 0; 759 mStreaming = false; 760 761 String process = null; 762 763 String cmd = getNextArgRequired(); 764 765 if ("start".equals(cmd)) { 766 start = true; 767 String opt; 768 while ((opt=getNextOption()) != null) { 769 if (opt.equals("--user")) { 770 userId = UserHandle.parseUserArg(getNextArgRequired()); 771 } else if (opt.equals("--wall")) { 772 wall = true; 773 } else if (opt.equals("--streaming")) { 774 mStreaming = true; 775 } else if (opt.equals("--sampling")) { 776 mSamplingInterval = Integer.parseInt(getNextArgRequired()); 777 } else { 778 err.println("Error: Unknown option: " + opt); 779 return -1; 780 } 781 } 782 process = getNextArgRequired(); 783 } else if ("stop".equals(cmd)) { 784 String opt; 785 while ((opt=getNextOption()) != null) { 786 if (opt.equals("--user")) { 787 userId = UserHandle.parseUserArg(getNextArgRequired()); 788 } else { 789 err.println("Error: Unknown option: " + opt); 790 return -1; 791 } 792 } 793 process = getNextArg(); 794 } else { 795 // Compatibility with old syntax: process is specified first. 796 process = cmd; 797 cmd = getNextArgRequired(); 798 if ("start".equals(cmd)) { 799 start = true; 800 } else if (!"stop".equals(cmd)) { 801 throw new IllegalArgumentException("Profile command " + process + " not valid"); 802 } 803 } 804 805 if (userId == UserHandle.USER_ALL) { 806 err.println("Error: Can't profile with user 'all'"); 807 return -1; 808 } 809 810 ParcelFileDescriptor fd = null; 811 ProfilerInfo profilerInfo = null; 812 813 if (start) { 814 profileFile = getNextArgRequired(); 815 fd = openFileForSystem(profileFile, "w"); 816 if (fd == null) { 817 return -1; 818 } 819 profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming, 820 null, false); 821 } 822 823 try { 824 if (wall) { 825 // XXX doesn't work -- this needs to be set before booting. 826 String props = SystemProperties.get("dalvik.vm.extra-opts"); 827 if (props == null || !props.contains("-Xprofile:wallclock")) { 828 props = props + " -Xprofile:wallclock"; 829 //SystemProperties.set("dalvik.vm.extra-opts", props); 830 } 831 } else if (start) { 832 //removeWallOption(); 833 } 834 if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) { 835 wall = false; 836 err.println("PROFILE FAILED on process " + process); 837 return -1; 838 } 839 } finally { 840 if (!wall) { 841 //removeWallOption(); 842 } 843 } 844 return 0; 845 } 846 847 int runDumpHeap(PrintWriter pw) throws RemoteException { 848 final PrintWriter err = getErrPrintWriter(); 849 boolean managed = true; 850 boolean mallocInfo = false; 851 int userId = UserHandle.USER_CURRENT; 852 boolean runGc = false; 853 854 String opt; 855 while ((opt=getNextOption()) != null) { 856 if (opt.equals("--user")) { 857 userId = UserHandle.parseUserArg(getNextArgRequired()); 858 if (userId == UserHandle.USER_ALL) { 859 err.println("Error: Can't dump heap with user 'all'"); 860 return -1; 861 } 862 } else if (opt.equals("-n")) { 863 managed = false; 864 } else if (opt.equals("-g")) { 865 runGc = true; 866 } else if (opt.equals("-m")) { 867 managed = false; 868 mallocInfo = true; 869 } else { 870 err.println("Error: Unknown option: " + opt); 871 return -1; 872 } 873 } 874 String process = getNextArgRequired(); 875 String heapFile = getNextArgRequired(); 876 877 File file = new File(heapFile); 878 file.delete(); 879 ParcelFileDescriptor fd = openFileForSystem(heapFile, "w"); 880 if (fd == null) { 881 return -1; 882 } 883 884 if (!mInterface.dumpHeap(process, userId, managed, mallocInfo, runGc, heapFile, fd)) { 885 err.println("HEAP DUMP FAILED on process " + process); 886 return -1; 887 } 888 return 0; 889 } 890 891 int runSetDebugApp(PrintWriter pw) throws RemoteException { 892 boolean wait = false; 893 boolean persistent = false; 894 895 String opt; 896 while ((opt=getNextOption()) != null) { 897 if (opt.equals("-w")) { 898 wait = true; 899 } else if (opt.equals("--persistent")) { 900 persistent = true; 901 } else { 902 getErrPrintWriter().println("Error: Unknown option: " + opt); 903 return -1; 904 } 905 } 906 907 String pkg = getNextArgRequired(); 908 mInterface.setDebugApp(pkg, wait, persistent); 909 return 0; 910 } 911 912 int runSetAgentApp(PrintWriter pw) throws RemoteException { 913 String pkg = getNextArgRequired(); 914 String agent = getNextArg(); 915 mInterface.setAgentApp(pkg, agent); 916 return 0; 917 } 918 919 int runClearDebugApp(PrintWriter pw) throws RemoteException { 920 mInterface.setDebugApp(null, false, true); 921 return 0; 922 } 923 924 int runSetWatchHeap(PrintWriter pw) throws RemoteException { 925 String proc = getNextArgRequired(); 926 String limit = getNextArgRequired(); 927 mInterface.setDumpHeapDebugLimit(proc, 0, Long.parseLong(limit), null); 928 return 0; 929 } 930 931 int runClearWatchHeap(PrintWriter pw) throws RemoteException { 932 String proc = getNextArgRequired(); 933 mInterface.setDumpHeapDebugLimit(proc, 0, -1, null); 934 return 0; 935 } 936 937 int runBugReport(PrintWriter pw) throws RemoteException { 938 String opt; 939 int bugreportType = ActivityManager.BUGREPORT_OPTION_FULL; 940 while ((opt=getNextOption()) != null) { 941 if (opt.equals("--progress")) { 942 bugreportType = ActivityManager.BUGREPORT_OPTION_INTERACTIVE; 943 } else if (opt.equals("--telephony")) { 944 bugreportType = ActivityManager.BUGREPORT_OPTION_TELEPHONY; 945 } else { 946 getErrPrintWriter().println("Error: Unknown option: " + opt); 947 return -1; 948 } 949 } 950 mInterface.requestBugReport(bugreportType); 951 pw.println("Your lovely bug report is being created; please be patient."); 952 return 0; 953 } 954 955 int runForceStop(PrintWriter pw) throws RemoteException { 956 int userId = UserHandle.USER_ALL; 957 958 String opt; 959 while ((opt = getNextOption()) != null) { 960 if (opt.equals("--user")) { 961 userId = UserHandle.parseUserArg(getNextArgRequired()); 962 } else { 963 getErrPrintWriter().println("Error: Unknown option: " + opt); 964 return -1; 965 } 966 } 967 mInterface.forceStopPackage(getNextArgRequired(), userId); 968 return 0; 969 } 970 971 int runCrash(PrintWriter pw) throws RemoteException { 972 int userId = UserHandle.USER_ALL; 973 974 String opt; 975 while ((opt=getNextOption()) != null) { 976 if (opt.equals("--user")) { 977 userId = UserHandle.parseUserArg(getNextArgRequired()); 978 } else { 979 getErrPrintWriter().println("Error: Unknown option: " + opt); 980 return -1; 981 } 982 } 983 984 int pid = -1; 985 String packageName = null; 986 final String arg = getNextArgRequired(); 987 // The argument is either a pid or a package name 988 try { 989 pid = Integer.parseInt(arg); 990 } catch (NumberFormatException e) { 991 packageName = arg; 992 } 993 mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash"); 994 return 0; 995 } 996 997 int runKill(PrintWriter pw) throws RemoteException { 998 int userId = UserHandle.USER_ALL; 999 1000 String opt; 1001 while ((opt=getNextOption()) != null) { 1002 if (opt.equals("--user")) { 1003 userId = UserHandle.parseUserArg(getNextArgRequired()); 1004 } else { 1005 getErrPrintWriter().println("Error: Unknown option: " + opt); 1006 return -1; 1007 } 1008 } 1009 mInterface.killBackgroundProcesses(getNextArgRequired(), userId); 1010 return 0; 1011 } 1012 1013 int runKillAll(PrintWriter pw) throws RemoteException { 1014 mInterface.killAllBackgroundProcesses(); 1015 return 0; 1016 } 1017 1018 int runMakeIdle(PrintWriter pw) throws RemoteException { 1019 int userId = UserHandle.USER_ALL; 1020 1021 String opt; 1022 while ((opt = getNextOption()) != null) { 1023 if (opt.equals("--user")) { 1024 userId = UserHandle.parseUserArg(getNextArgRequired()); 1025 } else { 1026 getErrPrintWriter().println("Error: Unknown option: " + opt); 1027 return -1; 1028 } 1029 } 1030 mInterface.makePackageIdle(getNextArgRequired(), userId); 1031 return 0; 1032 } 1033 1034 static final class MyActivityController extends IActivityController.Stub { 1035 final IActivityManager mInterface; 1036 final PrintWriter mPw; 1037 final InputStream mInput; 1038 final String mGdbPort; 1039 final boolean mMonkey; 1040 1041 static final int STATE_NORMAL = 0; 1042 static final int STATE_CRASHED = 1; 1043 static final int STATE_EARLY_ANR = 2; 1044 static final int STATE_ANR = 3; 1045 1046 int mState; 1047 1048 static final int RESULT_DEFAULT = 0; 1049 1050 static final int RESULT_CRASH_DIALOG = 0; 1051 static final int RESULT_CRASH_KILL = 1; 1052 1053 static final int RESULT_EARLY_ANR_CONTINUE = 0; 1054 static final int RESULT_EARLY_ANR_KILL = 1; 1055 1056 static final int RESULT_ANR_DIALOG = 0; 1057 static final int RESULT_ANR_KILL = 1; 1058 static final int RESULT_ANR_WAIT = 1; 1059 1060 int mResult; 1061 1062 Process mGdbProcess; 1063 Thread mGdbThread; 1064 boolean mGotGdbPrint; 1065 1066 MyActivityController(IActivityManager iam, PrintWriter pw, InputStream input, 1067 String gdbPort, boolean monkey) { 1068 mInterface = iam; 1069 mPw = pw; 1070 mInput = input; 1071 mGdbPort = gdbPort; 1072 mMonkey = monkey; 1073 } 1074 1075 @Override 1076 public boolean activityResuming(String pkg) { 1077 synchronized (this) { 1078 mPw.println("** Activity resuming: " + pkg); 1079 mPw.flush(); 1080 } 1081 return true; 1082 } 1083 1084 @Override 1085 public boolean activityStarting(Intent intent, String pkg) { 1086 synchronized (this) { 1087 mPw.println("** Activity starting: " + pkg); 1088 mPw.flush(); 1089 } 1090 return true; 1091 } 1092 1093 @Override 1094 public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg, 1095 long timeMillis, String stackTrace) { 1096 synchronized (this) { 1097 mPw.println("** ERROR: PROCESS CRASHED"); 1098 mPw.println("processName: " + processName); 1099 mPw.println("processPid: " + pid); 1100 mPw.println("shortMsg: " + shortMsg); 1101 mPw.println("longMsg: " + longMsg); 1102 mPw.println("timeMillis: " + timeMillis); 1103 mPw.println("stack:"); 1104 mPw.print(stackTrace); 1105 mPw.println("#"); 1106 mPw.flush(); 1107 int result = waitControllerLocked(pid, STATE_CRASHED); 1108 return result == RESULT_CRASH_KILL ? false : true; 1109 } 1110 } 1111 1112 @Override 1113 public int appEarlyNotResponding(String processName, int pid, String annotation) { 1114 synchronized (this) { 1115 mPw.println("** ERROR: EARLY PROCESS NOT RESPONDING"); 1116 mPw.println("processName: " + processName); 1117 mPw.println("processPid: " + pid); 1118 mPw.println("annotation: " + annotation); 1119 mPw.flush(); 1120 int result = waitControllerLocked(pid, STATE_EARLY_ANR); 1121 if (result == RESULT_EARLY_ANR_KILL) return -1; 1122 return 0; 1123 } 1124 } 1125 1126 @Override 1127 public int appNotResponding(String processName, int pid, String processStats) { 1128 synchronized (this) { 1129 mPw.println("** ERROR: PROCESS NOT RESPONDING"); 1130 mPw.println("processName: " + processName); 1131 mPw.println("processPid: " + pid); 1132 mPw.println("processStats:"); 1133 mPw.print(processStats); 1134 mPw.println("#"); 1135 mPw.flush(); 1136 int result = waitControllerLocked(pid, STATE_ANR); 1137 if (result == RESULT_ANR_KILL) return -1; 1138 if (result == RESULT_ANR_WAIT) return 1; 1139 return 0; 1140 } 1141 } 1142 1143 @Override 1144 public int systemNotResponding(String message) { 1145 synchronized (this) { 1146 mPw.println("** ERROR: PROCESS NOT RESPONDING"); 1147 mPw.println("message: " + message); 1148 mPw.println("#"); 1149 mPw.println("Allowing system to die."); 1150 mPw.flush(); 1151 return -1; 1152 } 1153 } 1154 1155 void killGdbLocked() { 1156 mGotGdbPrint = false; 1157 if (mGdbProcess != null) { 1158 mPw.println("Stopping gdbserver"); 1159 mPw.flush(); 1160 mGdbProcess.destroy(); 1161 mGdbProcess = null; 1162 } 1163 if (mGdbThread != null) { 1164 mGdbThread.interrupt(); 1165 mGdbThread = null; 1166 } 1167 } 1168 1169 int waitControllerLocked(int pid, int state) { 1170 if (mGdbPort != null) { 1171 killGdbLocked(); 1172 1173 try { 1174 mPw.println("Starting gdbserver on port " + mGdbPort); 1175 mPw.println("Do the following:"); 1176 mPw.println(" adb forward tcp:" + mGdbPort + " tcp:" + mGdbPort); 1177 mPw.println(" gdbclient app_process :" + mGdbPort); 1178 mPw.flush(); 1179 1180 mGdbProcess = Runtime.getRuntime().exec(new String[] { 1181 "gdbserver", ":" + mGdbPort, "--attach", Integer.toString(pid) 1182 }); 1183 final InputStreamReader converter = new InputStreamReader( 1184 mGdbProcess.getInputStream()); 1185 mGdbThread = new Thread() { 1186 @Override 1187 public void run() { 1188 BufferedReader in = new BufferedReader(converter); 1189 String line; 1190 int count = 0; 1191 while (true) { 1192 synchronized (MyActivityController.this) { 1193 if (mGdbThread == null) { 1194 return; 1195 } 1196 if (count == 2) { 1197 mGotGdbPrint = true; 1198 MyActivityController.this.notifyAll(); 1199 } 1200 } 1201 try { 1202 line = in.readLine(); 1203 if (line == null) { 1204 return; 1205 } 1206 mPw.println("GDB: " + line); 1207 mPw.flush(); 1208 count++; 1209 } catch (IOException e) { 1210 return; 1211 } 1212 } 1213 } 1214 }; 1215 mGdbThread.start(); 1216 1217 // Stupid waiting for .5s. Doesn't matter if we end early. 1218 try { 1219 this.wait(500); 1220 } catch (InterruptedException e) { 1221 } 1222 1223 } catch (IOException e) { 1224 mPw.println("Failure starting gdbserver: " + e); 1225 mPw.flush(); 1226 killGdbLocked(); 1227 } 1228 } 1229 mState = state; 1230 mPw.println(""); 1231 printMessageForState(); 1232 mPw.flush(); 1233 1234 while (mState != STATE_NORMAL) { 1235 try { 1236 wait(); 1237 } catch (InterruptedException e) { 1238 } 1239 } 1240 1241 killGdbLocked(); 1242 1243 return mResult; 1244 } 1245 1246 void resumeController(int result) { 1247 synchronized (this) { 1248 mState = STATE_NORMAL; 1249 mResult = result; 1250 notifyAll(); 1251 } 1252 } 1253 1254 void printMessageForState() { 1255 switch (mState) { 1256 case STATE_NORMAL: 1257 mPw.println("Monitoring activity manager... available commands:"); 1258 break; 1259 case STATE_CRASHED: 1260 mPw.println("Waiting after crash... available commands:"); 1261 mPw.println("(c)ontinue: show crash dialog"); 1262 mPw.println("(k)ill: immediately kill app"); 1263 break; 1264 case STATE_EARLY_ANR: 1265 mPw.println("Waiting after early ANR... available commands:"); 1266 mPw.println("(c)ontinue: standard ANR processing"); 1267 mPw.println("(k)ill: immediately kill app"); 1268 break; 1269 case STATE_ANR: 1270 mPw.println("Waiting after ANR... available commands:"); 1271 mPw.println("(c)ontinue: show ANR dialog"); 1272 mPw.println("(k)ill: immediately kill app"); 1273 mPw.println("(w)ait: wait some more"); 1274 break; 1275 } 1276 mPw.println("(q)uit: finish monitoring"); 1277 } 1278 1279 void run() throws RemoteException { 1280 try { 1281 printMessageForState(); 1282 mPw.flush(); 1283 1284 mInterface.setActivityController(this, mMonkey); 1285 mState = STATE_NORMAL; 1286 1287 InputStreamReader converter = new InputStreamReader(mInput); 1288 BufferedReader in = new BufferedReader(converter); 1289 String line; 1290 1291 while ((line = in.readLine()) != null) { 1292 boolean addNewline = true; 1293 if (line.length() <= 0) { 1294 addNewline = false; 1295 } else if ("q".equals(line) || "quit".equals(line)) { 1296 resumeController(RESULT_DEFAULT); 1297 break; 1298 } else if (mState == STATE_CRASHED) { 1299 if ("c".equals(line) || "continue".equals(line)) { 1300 resumeController(RESULT_CRASH_DIALOG); 1301 } else if ("k".equals(line) || "kill".equals(line)) { 1302 resumeController(RESULT_CRASH_KILL); 1303 } else { 1304 mPw.println("Invalid command: " + line); 1305 } 1306 } else if (mState == STATE_ANR) { 1307 if ("c".equals(line) || "continue".equals(line)) { 1308 resumeController(RESULT_ANR_DIALOG); 1309 } else if ("k".equals(line) || "kill".equals(line)) { 1310 resumeController(RESULT_ANR_KILL); 1311 } else if ("w".equals(line) || "wait".equals(line)) { 1312 resumeController(RESULT_ANR_WAIT); 1313 } else { 1314 mPw.println("Invalid command: " + line); 1315 } 1316 } else if (mState == STATE_EARLY_ANR) { 1317 if ("c".equals(line) || "continue".equals(line)) { 1318 resumeController(RESULT_EARLY_ANR_CONTINUE); 1319 } else if ("k".equals(line) || "kill".equals(line)) { 1320 resumeController(RESULT_EARLY_ANR_KILL); 1321 } else { 1322 mPw.println("Invalid command: " + line); 1323 } 1324 } else { 1325 mPw.println("Invalid command: " + line); 1326 } 1327 1328 synchronized (this) { 1329 if (addNewline) { 1330 mPw.println(""); 1331 } 1332 printMessageForState(); 1333 mPw.flush(); 1334 } 1335 } 1336 1337 } catch (IOException e) { 1338 e.printStackTrace(mPw); 1339 mPw.flush(); 1340 } finally { 1341 mInterface.setActivityController(null, mMonkey); 1342 } 1343 } 1344 } 1345 1346 int runMonitor(PrintWriter pw) throws RemoteException { 1347 String opt; 1348 String gdbPort = null; 1349 boolean monkey = false; 1350 while ((opt=getNextOption()) != null) { 1351 if (opt.equals("--gdb")) { 1352 gdbPort = getNextArgRequired(); 1353 } else if (opt.equals("-m")) { 1354 monkey = true; 1355 } else { 1356 getErrPrintWriter().println("Error: Unknown option: " + opt); 1357 return -1; 1358 } 1359 } 1360 1361 MyActivityController controller = new MyActivityController(mInterface, pw, 1362 getRawInputStream(), gdbPort, monkey); 1363 controller.run(); 1364 return 0; 1365 } 1366 1367 static final class MyUidObserver extends IUidObserver.Stub 1368 implements ActivityManagerService.OomAdjObserver { 1369 final IActivityManager mInterface; 1370 final ActivityManagerService mInternal; 1371 final PrintWriter mPw; 1372 final InputStream mInput; 1373 final int mUid; 1374 1375 static final int STATE_NORMAL = 0; 1376 1377 int mState; 1378 1379 MyUidObserver(ActivityManagerService service, PrintWriter pw, InputStream input, int uid) { 1380 mInterface = service; 1381 mInternal = service; 1382 mPw = pw; 1383 mInput = input; 1384 mUid = uid; 1385 } 1386 1387 @Override 1388 public void onUidStateChanged(int uid, int procState, long procStateSeq) throws RemoteException { 1389 synchronized (this) { 1390 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 1391 try { 1392 mPw.print(uid); 1393 mPw.print(" procstate "); 1394 mPw.print(ProcessList.makeProcStateString(procState)); 1395 mPw.print(" seq "); 1396 mPw.println(procStateSeq); 1397 mPw.flush(); 1398 } finally { 1399 StrictMode.setThreadPolicy(oldPolicy); 1400 } 1401 } 1402 } 1403 1404 @Override 1405 public void onUidGone(int uid, boolean disabled) throws RemoteException { 1406 synchronized (this) { 1407 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 1408 try { 1409 mPw.print(uid); 1410 mPw.print(" gone"); 1411 if (disabled) { 1412 mPw.print(" disabled"); 1413 } 1414 mPw.println(); 1415 mPw.flush(); 1416 } finally { 1417 StrictMode.setThreadPolicy(oldPolicy); 1418 } 1419 } 1420 } 1421 1422 @Override 1423 public void onUidActive(int uid) throws RemoteException { 1424 synchronized (this) { 1425 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 1426 try { 1427 mPw.print(uid); 1428 mPw.println(" active"); 1429 mPw.flush(); 1430 } finally { 1431 StrictMode.setThreadPolicy(oldPolicy); 1432 } 1433 } 1434 } 1435 1436 @Override 1437 public void onUidIdle(int uid, boolean disabled) throws RemoteException { 1438 synchronized (this) { 1439 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 1440 try { 1441 mPw.print(uid); 1442 mPw.print(" idle"); 1443 if (disabled) { 1444 mPw.print(" disabled"); 1445 } 1446 mPw.println(); 1447 mPw.flush(); 1448 } finally { 1449 StrictMode.setThreadPolicy(oldPolicy); 1450 } 1451 } 1452 } 1453 1454 @Override 1455 public void onUidCachedChanged(int uid, boolean cached) throws RemoteException { 1456 synchronized (this) { 1457 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 1458 try { 1459 mPw.print(uid); 1460 mPw.println(cached ? " cached" : " uncached"); 1461 mPw.flush(); 1462 } finally { 1463 StrictMode.setThreadPolicy(oldPolicy); 1464 } 1465 } 1466 } 1467 1468 @Override 1469 public void onOomAdjMessage(String msg) { 1470 synchronized (this) { 1471 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 1472 try { 1473 mPw.print("# "); 1474 mPw.println(msg); 1475 mPw.flush(); 1476 } finally { 1477 StrictMode.setThreadPolicy(oldPolicy); 1478 } 1479 } 1480 } 1481 1482 void printMessageForState() { 1483 switch (mState) { 1484 case STATE_NORMAL: 1485 mPw.println("Watching uid states... available commands:"); 1486 break; 1487 } 1488 mPw.println("(q)uit: finish watching"); 1489 } 1490 1491 void run() throws RemoteException { 1492 try { 1493 printMessageForState(); 1494 mPw.flush(); 1495 1496 mInterface.registerUidObserver(this, ActivityManager.UID_OBSERVER_ACTIVE 1497 | ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_PROCSTATE 1498 | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_CACHED, 1499 ActivityManager.PROCESS_STATE_UNKNOWN, null); 1500 if (mUid >= 0) { 1501 mInternal.setOomAdjObserver(mUid, this); 1502 } 1503 mState = STATE_NORMAL; 1504 1505 InputStreamReader converter = new InputStreamReader(mInput); 1506 BufferedReader in = new BufferedReader(converter); 1507 String line; 1508 1509 while ((line = in.readLine()) != null) { 1510 boolean addNewline = true; 1511 if (line.length() <= 0) { 1512 addNewline = false; 1513 } else if ("q".equals(line) || "quit".equals(line)) { 1514 break; 1515 } else { 1516 mPw.println("Invalid command: " + line); 1517 } 1518 1519 synchronized (this) { 1520 if (addNewline) { 1521 mPw.println(""); 1522 } 1523 printMessageForState(); 1524 mPw.flush(); 1525 } 1526 } 1527 1528 } catch (IOException e) { 1529 e.printStackTrace(mPw); 1530 mPw.flush(); 1531 } finally { 1532 if (mUid >= 0) { 1533 mInternal.clearOomAdjObserver(); 1534 } 1535 mInterface.unregisterUidObserver(this); 1536 } 1537 } 1538 } 1539 1540 int runWatchUids(PrintWriter pw) throws RemoteException { 1541 String opt; 1542 int uid = -1; 1543 while ((opt=getNextOption()) != null) { 1544 if (opt.equals("--oom")) { 1545 uid = Integer.parseInt(getNextArgRequired()); 1546 } else { 1547 getErrPrintWriter().println("Error: Unknown option: " + opt); 1548 return -1; 1549 1550 } 1551 } 1552 1553 MyUidObserver controller = new MyUidObserver(mInternal, pw, getRawInputStream(), uid); 1554 controller.run(); 1555 return 0; 1556 } 1557 1558 int runHang(PrintWriter pw) throws RemoteException { 1559 String opt; 1560 boolean allowRestart = false; 1561 while ((opt=getNextOption()) != null) { 1562 if (opt.equals("--allow-restart")) { 1563 allowRestart = true; 1564 } else { 1565 getErrPrintWriter().println("Error: Unknown option: " + opt); 1566 return -1; 1567 } 1568 } 1569 1570 pw.println("Hanging the system..."); 1571 pw.flush(); 1572 mInterface.hang(new Binder(), allowRestart); 1573 return 0; 1574 } 1575 1576 int runRestart(PrintWriter pw) throws RemoteException { 1577 String opt; 1578 while ((opt=getNextOption()) != null) { 1579 getErrPrintWriter().println("Error: Unknown option: " + opt); 1580 return -1; 1581 } 1582 1583 pw.println("Restart the system..."); 1584 pw.flush(); 1585 mInterface.restart(); 1586 return 0; 1587 } 1588 1589 int runIdleMaintenance(PrintWriter pw) throws RemoteException { 1590 String opt; 1591 while ((opt=getNextOption()) != null) { 1592 getErrPrintWriter().println("Error: Unknown option: " + opt); 1593 return -1; 1594 } 1595 1596 pw.println("Performing idle maintenance..."); 1597 mInterface.sendIdleJobTrigger(); 1598 return 0; 1599 } 1600 1601 int runScreenCompat(PrintWriter pw) throws RemoteException { 1602 String mode = getNextArgRequired(); 1603 boolean enabled; 1604 if ("on".equals(mode)) { 1605 enabled = true; 1606 } else if ("off".equals(mode)) { 1607 enabled = false; 1608 } else { 1609 getErrPrintWriter().println("Error: enabled mode must be 'on' or 'off' at " + mode); 1610 return -1; 1611 } 1612 1613 String packageName = getNextArgRequired(); 1614 do { 1615 try { 1616 mInterface.setPackageScreenCompatMode(packageName, enabled 1617 ? ActivityManager.COMPAT_MODE_ENABLED 1618 : ActivityManager.COMPAT_MODE_DISABLED); 1619 } catch (RemoteException e) { 1620 } 1621 packageName = getNextArg(); 1622 } while (packageName != null); 1623 return 0; 1624 } 1625 1626 int runPackageImportance(PrintWriter pw) throws RemoteException { 1627 String packageName = getNextArgRequired(); 1628 int procState = mInterface.getPackageProcessState(packageName, "com.android.shell"); 1629 pw.println(ActivityManager.RunningAppProcessInfo.procStateToImportance(procState)); 1630 return 0; 1631 } 1632 1633 int runToUri(PrintWriter pw, int flags) throws RemoteException { 1634 Intent intent; 1635 try { 1636 intent = makeIntent(UserHandle.USER_CURRENT); 1637 } catch (URISyntaxException e) { 1638 throw new RuntimeException(e.getMessage(), e); 1639 } 1640 pw.println(intent.toUri(flags)); 1641 return 0; 1642 } 1643 1644 int runSwitchUser(PrintWriter pw) throws RemoteException { 1645 UserManager userManager = mInternal.mContext.getSystemService(UserManager.class); 1646 if (!userManager.canSwitchUsers()) { 1647 getErrPrintWriter().println("Error: disallowed switching user"); 1648 return -1; 1649 } 1650 String user = getNextArgRequired(); 1651 mInterface.switchUser(Integer.parseInt(user)); 1652 return 0; 1653 } 1654 1655 int runGetCurrentUser(PrintWriter pw) throws RemoteException { 1656 UserInfo currentUser = Preconditions.checkNotNull(mInterface.getCurrentUser(), 1657 "Current user not set"); 1658 pw.println(currentUser.id); 1659 return 0; 1660 } 1661 1662 int runStartUser(PrintWriter pw) throws RemoteException { 1663 String user = getNextArgRequired(); 1664 boolean success = mInterface.startUserInBackground(Integer.parseInt(user)); 1665 if (success) { 1666 pw.println("Success: user started"); 1667 } else { 1668 getErrPrintWriter().println("Error: could not start user"); 1669 } 1670 return 0; 1671 } 1672 1673 private static byte[] argToBytes(String arg) { 1674 if (arg.equals("!")) { 1675 return null; 1676 } else { 1677 return HexDump.hexStringToByteArray(arg); 1678 } 1679 } 1680 1681 int runUnlockUser(PrintWriter pw) throws RemoteException { 1682 int userId = Integer.parseInt(getNextArgRequired()); 1683 byte[] token = argToBytes(getNextArgRequired()); 1684 byte[] secret = argToBytes(getNextArgRequired()); 1685 boolean success = mInterface.unlockUser(userId, token, secret, null); 1686 if (success) { 1687 pw.println("Success: user unlocked"); 1688 } else { 1689 getErrPrintWriter().println("Error: could not unlock user"); 1690 } 1691 return 0; 1692 } 1693 1694 static final class StopUserCallback extends IStopUserCallback.Stub { 1695 private boolean mFinished = false; 1696 1697 public synchronized void waitForFinish() { 1698 try { 1699 while (!mFinished) wait(); 1700 } catch (InterruptedException e) { 1701 throw new IllegalStateException(e); 1702 } 1703 } 1704 1705 @Override 1706 public synchronized void userStopped(int userId) { 1707 mFinished = true; 1708 notifyAll(); 1709 } 1710 1711 @Override 1712 public synchronized void userStopAborted(int userId) { 1713 mFinished = true; 1714 notifyAll(); 1715 } 1716 } 1717 1718 int runStopUser(PrintWriter pw) throws RemoteException { 1719 boolean wait = false; 1720 boolean force = false; 1721 String opt; 1722 while ((opt = getNextOption()) != null) { 1723 if ("-w".equals(opt)) { 1724 wait = true; 1725 } else if ("-f".equals(opt)) { 1726 force = true; 1727 } else { 1728 getErrPrintWriter().println("Error: unknown option: " + opt); 1729 return -1; 1730 } 1731 } 1732 int user = Integer.parseInt(getNextArgRequired()); 1733 StopUserCallback callback = wait ? new StopUserCallback() : null; 1734 1735 int res = mInterface.stopUser(user, force, callback); 1736 if (res != ActivityManager.USER_OP_SUCCESS) { 1737 String txt = ""; 1738 switch (res) { 1739 case ActivityManager.USER_OP_IS_CURRENT: 1740 txt = " (Can't stop current user)"; 1741 break; 1742 case ActivityManager.USER_OP_UNKNOWN_USER: 1743 txt = " (Unknown user " + user + ")"; 1744 break; 1745 case ActivityManager.USER_OP_ERROR_IS_SYSTEM: 1746 txt = " (System user cannot be stopped)"; 1747 break; 1748 case ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP: 1749 txt = " (Can't stop user " + user 1750 + " - one of its related users can't be stopped)"; 1751 break; 1752 } 1753 getErrPrintWriter().println("Switch failed: " + res + txt); 1754 return -1; 1755 } else if (callback != null) { 1756 callback.waitForFinish(); 1757 } 1758 return 0; 1759 } 1760 1761 int runIsUserStopped(PrintWriter pw) { 1762 int userId = UserHandle.parseUserArg(getNextArgRequired()); 1763 boolean stopped = mInternal.isUserStopped(userId); 1764 pw.println(stopped); 1765 return 0; 1766 } 1767 1768 int runGetStartedUserState(PrintWriter pw) throws RemoteException { 1769 mInternal.enforceCallingPermission(android.Manifest.permission.DUMP, 1770 "runGetStartedUserState()"); 1771 final int userId = Integer.parseInt(getNextArgRequired()); 1772 try { 1773 pw.println(mInternal.getStartedUserState(userId)); 1774 } catch (NullPointerException e) { 1775 pw.println("User is not started: " + userId); 1776 } 1777 return 0; 1778 } 1779 1780 int runTrackAssociations(PrintWriter pw) { 1781 mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, 1782 "registerUidObserver()"); 1783 synchronized (mInternal) { 1784 if (!mInternal.mTrackingAssociations) { 1785 mInternal.mTrackingAssociations = true; 1786 pw.println("Association tracking started."); 1787 } else { 1788 pw.println("Association tracking already enabled."); 1789 } 1790 } 1791 return 0; 1792 } 1793 1794 int runUntrackAssociations(PrintWriter pw) { 1795 mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, 1796 "registerUidObserver()"); 1797 synchronized (mInternal) { 1798 if (mInternal.mTrackingAssociations) { 1799 mInternal.mTrackingAssociations = false; 1800 mInternal.mAssociations.clear(); 1801 pw.println("Association tracking stopped."); 1802 } else { 1803 pw.println("Association tracking not running."); 1804 } 1805 } 1806 return 0; 1807 } 1808 1809 int getUidState(PrintWriter pw) throws RemoteException { 1810 mInternal.enforceCallingPermission(android.Manifest.permission.DUMP, 1811 "getUidState()"); 1812 int state = mInternal.getUidState(Integer.parseInt(getNextArgRequired())); 1813 pw.print(state); 1814 pw.print(" ("); 1815 pw.printf(DebugUtils.valueToString(ActivityManager.class, "PROCESS_STATE_", state)); 1816 pw.println(")"); 1817 return 0; 1818 } 1819 1820 private List<Configuration> getRecentConfigurations(int days) { 1821 IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( 1822 Context.USAGE_STATS_SERVICE)); 1823 final long now = System.currentTimeMillis(); 1824 final long nDaysAgo = now - (days * 24 * 60 * 60 * 1000); 1825 try { 1826 @SuppressWarnings("unchecked") 1827 ParceledListSlice<ConfigurationStats> configStatsSlice = usm.queryConfigurationStats( 1828 UsageStatsManager.INTERVAL_BEST, nDaysAgo, now, "com.android.shell"); 1829 if (configStatsSlice == null) { 1830 return Collections.emptyList(); 1831 } 1832 1833 final ArrayMap<Configuration, Integer> recentConfigs = new ArrayMap<>(); 1834 final List<ConfigurationStats> configStatsList = configStatsSlice.getList(); 1835 final int configStatsListSize = configStatsList.size(); 1836 for (int i = 0; i < configStatsListSize; i++) { 1837 final ConfigurationStats stats = configStatsList.get(i); 1838 final int indexOfKey = recentConfigs.indexOfKey(stats.getConfiguration()); 1839 if (indexOfKey < 0) { 1840 recentConfigs.put(stats.getConfiguration(), stats.getActivationCount()); 1841 } else { 1842 recentConfigs.setValueAt(indexOfKey, 1843 recentConfigs.valueAt(indexOfKey) + stats.getActivationCount()); 1844 } 1845 } 1846 1847 final Comparator<Configuration> comparator = new Comparator<Configuration>() { 1848 @Override 1849 public int compare(Configuration a, Configuration b) { 1850 return recentConfigs.get(b).compareTo(recentConfigs.get(a)); 1851 } 1852 }; 1853 1854 ArrayList<Configuration> configs = new ArrayList<>(recentConfigs.size()); 1855 configs.addAll(recentConfigs.keySet()); 1856 Collections.sort(configs, comparator); 1857 return configs; 1858 1859 } catch (RemoteException e) { 1860 return Collections.emptyList(); 1861 } 1862 } 1863 1864 /** 1865 * Adds all supported GL extensions for a provided EGLConfig to a set by creating an EGLContext 1866 * and EGLSurface and querying extensions. 1867 * 1868 * @param egl An EGL API object 1869 * @param display An EGLDisplay to create a context and surface with 1870 * @param config The EGLConfig to get the extensions for 1871 * @param surfaceSize eglCreatePbufferSurface generic parameters 1872 * @param contextAttribs eglCreateContext generic parameters 1873 * @param glExtensions A Set<String> to add GL extensions to 1874 */ 1875 private static void addExtensionsForConfig( 1876 EGL10 egl, 1877 EGLDisplay display, 1878 EGLConfig config, 1879 int[] surfaceSize, 1880 int[] contextAttribs, 1881 Set<String> glExtensions) { 1882 // Create a context. 1883 EGLContext context = 1884 egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, contextAttribs); 1885 // No-op if we can't create a context. 1886 if (context == EGL10.EGL_NO_CONTEXT) { 1887 return; 1888 } 1889 1890 // Create a surface. 1891 EGLSurface surface = egl.eglCreatePbufferSurface(display, config, surfaceSize); 1892 if (surface == EGL10.EGL_NO_SURFACE) { 1893 egl.eglDestroyContext(display, context); 1894 return; 1895 } 1896 1897 // Update the current surface and context. 1898 egl.eglMakeCurrent(display, surface, surface, context); 1899 1900 // Get the list of extensions. 1901 String extensionList = GLES10.glGetString(GLES10.GL_EXTENSIONS); 1902 if (!TextUtils.isEmpty(extensionList)) { 1903 // The list of extensions comes from the driver separated by spaces. 1904 // Split them apart and add them into a Set for deduping purposes. 1905 for (String extension : extensionList.split(" ")) { 1906 glExtensions.add(extension); 1907 } 1908 } 1909 1910 // Tear down the context and surface for this config. 1911 egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 1912 egl.eglDestroySurface(display, surface); 1913 egl.eglDestroyContext(display, context); 1914 } 1915 1916 1917 Set<String> getGlExtensionsFromDriver() { 1918 Set<String> glExtensions = new HashSet<>(); 1919 1920 // Get the EGL implementation. 1921 EGL10 egl = (EGL10) EGLContext.getEGL(); 1922 if (egl == null) { 1923 getErrPrintWriter().println("Warning: couldn't get EGL"); 1924 return glExtensions; 1925 } 1926 1927 // Get the default display and initialize it. 1928 EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 1929 int[] version = new int[2]; 1930 egl.eglInitialize(display, version); 1931 1932 // Call getConfigs() in order to find out how many there are. 1933 int[] numConfigs = new int[1]; 1934 if (!egl.eglGetConfigs(display, null, 0, numConfigs)) { 1935 getErrPrintWriter().println("Warning: couldn't get EGL config count"); 1936 return glExtensions; 1937 } 1938 1939 // Allocate space for all configs and ask again. 1940 EGLConfig[] configs = new EGLConfig[numConfigs[0]]; 1941 if (!egl.eglGetConfigs(display, configs, numConfigs[0], numConfigs)) { 1942 getErrPrintWriter().println("Warning: couldn't get EGL configs"); 1943 return glExtensions; 1944 } 1945 1946 // Allocate surface size parameters outside of the main loop to cut down 1947 // on GC thrashing. 1x1 is enough since we are only using it to get at 1948 // the list of extensions. 1949 int[] surfaceSize = 1950 new int[] { 1951 EGL10.EGL_WIDTH, 1, 1952 EGL10.EGL_HEIGHT, 1, 1953 EGL10.EGL_NONE 1954 }; 1955 1956 // For when we need to create a GLES2.0 context. 1957 final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 1958 int[] gles2 = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE}; 1959 1960 // For getting return values from eglGetConfigAttrib 1961 int[] attrib = new int[1]; 1962 1963 for (int i = 0; i < numConfigs[0]; i++) { 1964 // Get caveat for this config in order to skip slow (i.e. software) configs. 1965 egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_CONFIG_CAVEAT, attrib); 1966 if (attrib[0] == EGL10.EGL_SLOW_CONFIG) { 1967 continue; 1968 } 1969 1970 // If the config does not support pbuffers we cannot do an eglMakeCurrent 1971 // on it in addExtensionsForConfig(), so skip it here. Attempting to make 1972 // it current with a pbuffer will result in an EGL_BAD_MATCH error 1973 egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_SURFACE_TYPE, attrib); 1974 if ((attrib[0] & EGL10.EGL_PBUFFER_BIT) == 0) { 1975 continue; 1976 } 1977 1978 final int EGL_OPENGL_ES_BIT = 0x0001; 1979 final int EGL_OPENGL_ES2_BIT = 0x0004; 1980 egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_RENDERABLE_TYPE, attrib); 1981 if ((attrib[0] & EGL_OPENGL_ES_BIT) != 0) { 1982 addExtensionsForConfig(egl, display, configs[i], surfaceSize, null, glExtensions); 1983 } 1984 if ((attrib[0] & EGL_OPENGL_ES2_BIT) != 0) { 1985 addExtensionsForConfig(egl, display, configs[i], surfaceSize, gles2, glExtensions); 1986 } 1987 } 1988 1989 // Release all EGL resources. 1990 egl.eglTerminate(display); 1991 1992 return glExtensions; 1993 } 1994 1995 private void writeDeviceConfig(ProtoOutputStream protoOutputStream, long fieldId, 1996 PrintWriter pw, Configuration config, DisplayManager dm) { 1997 Point stableSize = dm.getStableDisplaySize(); 1998 long token = -1; 1999 if (protoOutputStream != null) { 2000 token = protoOutputStream.start(fieldId); 2001 protoOutputStream.write(DeviceConfigurationProto.STABLE_SCREEN_WIDTH_PX, stableSize.x); 2002 protoOutputStream.write(DeviceConfigurationProto.STABLE_SCREEN_HEIGHT_PX, stableSize.y); 2003 protoOutputStream.write(DeviceConfigurationProto.STABLE_DENSITY_DPI, 2004 DisplayMetrics.DENSITY_DEVICE_STABLE); 2005 } 2006 if (pw != null) { 2007 pw.print("stable-width-px: "); pw.println(stableSize.x); 2008 pw.print("stable-height-px: "); pw.println(stableSize.y); 2009 pw.print("stable-density-dpi: "); pw.println(DisplayMetrics.DENSITY_DEVICE_STABLE); 2010 } 2011 2012 MemInfoReader memreader = new MemInfoReader(); 2013 memreader.readMemInfo(); 2014 KeyguardManager kgm = mInternal.mContext.getSystemService(KeyguardManager.class); 2015 if (protoOutputStream != null) { 2016 protoOutputStream.write(DeviceConfigurationProto.TOTAL_RAM, memreader.getTotalSize()); 2017 protoOutputStream.write(DeviceConfigurationProto.LOW_RAM, 2018 ActivityManager.isLowRamDeviceStatic()); 2019 protoOutputStream.write(DeviceConfigurationProto.MAX_CORES, 2020 Runtime.getRuntime().availableProcessors()); 2021 protoOutputStream.write(DeviceConfigurationProto.HAS_SECURE_SCREEN_LOCK, 2022 kgm.isDeviceSecure()); 2023 } 2024 if (pw != null) { 2025 pw.print("total-ram: "); pw.println(memreader.getTotalSize()); 2026 pw.print("low-ram: "); pw.println(ActivityManager.isLowRamDeviceStatic()); 2027 pw.print("max-cores: "); pw.println(Runtime.getRuntime().availableProcessors()); 2028 pw.print("has-secure-screen-lock: "); pw.println(kgm.isDeviceSecure()); 2029 } 2030 2031 ConfigurationInfo configInfo = mInternal.getDeviceConfigurationInfo(); 2032 if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) { 2033 if (protoOutputStream != null) { 2034 protoOutputStream.write(DeviceConfigurationProto.OPENGL_VERSION, 2035 configInfo.reqGlEsVersion); 2036 } 2037 if (pw != null) { 2038 pw.print("opengl-version: 0x"); 2039 pw.println(Integer.toHexString(configInfo.reqGlEsVersion)); 2040 } 2041 } 2042 2043 Set<String> glExtensionsSet = getGlExtensionsFromDriver(); 2044 String[] glExtensions = new String[glExtensionsSet.size()]; 2045 glExtensions = glExtensionsSet.toArray(glExtensions); 2046 Arrays.sort(glExtensions); 2047 for (int i = 0; i < glExtensions.length; i++) { 2048 if (protoOutputStream != null) { 2049 protoOutputStream.write(DeviceConfigurationProto.OPENGL_EXTENSIONS, 2050 glExtensions[i]); 2051 } 2052 if (pw != null) { 2053 pw.print("opengl-extensions: "); pw.println(glExtensions[i]); 2054 } 2055 2056 } 2057 2058 PackageManager pm = mInternal.mContext.getPackageManager(); 2059 List<SharedLibraryInfo> slibs = pm.getSharedLibraries(0); 2060 Collections.sort(slibs, Comparator.comparing(SharedLibraryInfo::getName)); 2061 for (int i = 0; i < slibs.size(); i++) { 2062 if (protoOutputStream != null) { 2063 protoOutputStream.write(DeviceConfigurationProto.SHARED_LIBRARIES, 2064 slibs.get(i).getName()); 2065 } 2066 if (pw != null) { 2067 pw.print("shared-libraries: "); pw.println(slibs.get(i).getName()); 2068 } 2069 } 2070 2071 FeatureInfo[] features = pm.getSystemAvailableFeatures(); 2072 Arrays.sort(features, (o1, o2) -> 2073 (o1.name == o2.name ? 0 : (o1.name == null ? -1 : o1.name.compareTo(o2.name)))); 2074 for (int i = 0; i < features.length; i++) { 2075 if (features[i].name != null) { 2076 if (protoOutputStream != null) { 2077 protoOutputStream.write(DeviceConfigurationProto.FEATURES, features[i].name); 2078 } 2079 if (pw != null) { 2080 pw.print("features: "); pw.println(features[i].name); 2081 } 2082 } 2083 } 2084 2085 if (protoOutputStream != null) { 2086 protoOutputStream.end(token); 2087 } 2088 } 2089 2090 int runGetConfig(PrintWriter pw) throws RemoteException { 2091 int days = -1; 2092 boolean asProto = false; 2093 boolean inclDevice = false; 2094 2095 String opt; 2096 while ((opt=getNextOption()) != null) { 2097 if (opt.equals("--days")) { 2098 days = Integer.parseInt(getNextArgRequired()); 2099 if (days <= 0) { 2100 throw new IllegalArgumentException("--days must be a positive integer"); 2101 } 2102 } else if (opt.equals("--proto")) { 2103 asProto = true; 2104 } else if (opt.equals("--device")) { 2105 inclDevice = true; 2106 } else { 2107 getErrPrintWriter().println("Error: Unknown option: " + opt); 2108 return -1; 2109 } 2110 } 2111 2112 Configuration config = mInterface.getConfiguration(); 2113 if (config == null) { 2114 getErrPrintWriter().println("Activity manager has no configuration"); 2115 return -1; 2116 } 2117 2118 DisplayManager dm = mInternal.mContext.getSystemService(DisplayManager.class); 2119 Display display = dm.getDisplay(Display.DEFAULT_DISPLAY); 2120 DisplayMetrics metrics = new DisplayMetrics(); 2121 display.getMetrics(metrics); 2122 2123 if (asProto) { 2124 final ProtoOutputStream proto = new ProtoOutputStream(getOutFileDescriptor()); 2125 config.writeResConfigToProto(proto, GlobalConfigurationProto.RESOURCES, metrics); 2126 if (inclDevice) { 2127 writeDeviceConfig(proto, GlobalConfigurationProto.DEVICE, null, config, dm); 2128 } 2129 proto.flush(); 2130 2131 } else { 2132 pw.println("config: " + Configuration.resourceQualifierString(config, metrics)); 2133 pw.println("abi: " + TextUtils.join(",", Build.SUPPORTED_ABIS)); 2134 if (inclDevice) { 2135 writeDeviceConfig(null, -1, pw, config, dm); 2136 } 2137 2138 if (days >= 0) { 2139 final List<Configuration> recentConfigs = getRecentConfigurations(days); 2140 final int recentConfigSize = recentConfigs.size(); 2141 if (recentConfigSize > 0) { 2142 pw.println("recentConfigs:"); 2143 for (int i = 0; i < recentConfigSize; i++) { 2144 pw.println(" config: " + Configuration.resourceQualifierString( 2145 recentConfigs.get(i))); 2146 } 2147 } 2148 } 2149 2150 } 2151 return 0; 2152 } 2153 2154 int runSuppressResizeConfigChanges(PrintWriter pw) throws RemoteException { 2155 boolean suppress = Boolean.valueOf(getNextArgRequired()); 2156 mInterface.suppressResizeConfigChanges(suppress); 2157 return 0; 2158 } 2159 2160 int runSetInactive(PrintWriter pw) throws RemoteException { 2161 int userId = UserHandle.USER_CURRENT; 2162 2163 String opt; 2164 while ((opt=getNextOption()) != null) { 2165 if (opt.equals("--user")) { 2166 userId = UserHandle.parseUserArg(getNextArgRequired()); 2167 } else { 2168 getErrPrintWriter().println("Error: Unknown option: " + opt); 2169 return -1; 2170 } 2171 } 2172 String packageName = getNextArgRequired(); 2173 String value = getNextArgRequired(); 2174 2175 IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( 2176 Context.USAGE_STATS_SERVICE)); 2177 usm.setAppInactive(packageName, Boolean.parseBoolean(value), userId); 2178 return 0; 2179 } 2180 2181 private int bucketNameToBucketValue(String name) { 2182 String lower = name.toLowerCase(); 2183 if (lower.startsWith("ac")) { 2184 return UsageStatsManager.STANDBY_BUCKET_ACTIVE; 2185 } else if (lower.startsWith("wo")) { 2186 return UsageStatsManager.STANDBY_BUCKET_WORKING_SET; 2187 } else if (lower.startsWith("fr")) { 2188 return UsageStatsManager.STANDBY_BUCKET_FREQUENT; 2189 } else if (lower.startsWith("ra")) { 2190 return UsageStatsManager.STANDBY_BUCKET_RARE; 2191 } else if (lower.startsWith("ne")) { 2192 return UsageStatsManager.STANDBY_BUCKET_NEVER; 2193 } else { 2194 try { 2195 int bucket = Integer.parseInt(lower); 2196 return bucket; 2197 } catch (NumberFormatException nfe) { 2198 getErrPrintWriter().println("Error: Unknown bucket: " + name); 2199 } 2200 } 2201 return -1; 2202 } 2203 2204 int runSetStandbyBucket(PrintWriter pw) throws RemoteException { 2205 int userId = UserHandle.USER_CURRENT; 2206 2207 String opt; 2208 while ((opt=getNextOption()) != null) { 2209 if (opt.equals("--user")) { 2210 userId = UserHandle.parseUserArg(getNextArgRequired()); 2211 } else { 2212 getErrPrintWriter().println("Error: Unknown option: " + opt); 2213 return -1; 2214 } 2215 } 2216 String packageName = getNextArgRequired(); 2217 String value = getNextArgRequired(); 2218 int bucket = bucketNameToBucketValue(value); 2219 if (bucket < 0) return -1; 2220 boolean multiple = peekNextArg() != null; 2221 2222 2223 IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( 2224 Context.USAGE_STATS_SERVICE)); 2225 if (!multiple) { 2226 usm.setAppStandbyBucket(packageName, bucketNameToBucketValue(value), userId); 2227 } else { 2228 ArrayList<AppStandbyInfo> bucketInfoList = new ArrayList<>(); 2229 bucketInfoList.add(new AppStandbyInfo(packageName, bucket)); 2230 while ((packageName = getNextArg()) != null) { 2231 value = getNextArgRequired(); 2232 bucket = bucketNameToBucketValue(value); 2233 if (bucket < 0) continue; 2234 bucketInfoList.add(new AppStandbyInfo(packageName, bucket)); 2235 } 2236 ParceledListSlice<AppStandbyInfo> slice = new ParceledListSlice<>(bucketInfoList); 2237 usm.setAppStandbyBuckets(slice, userId); 2238 } 2239 return 0; 2240 } 2241 2242 int runGetStandbyBucket(PrintWriter pw) throws RemoteException { 2243 int userId = UserHandle.USER_CURRENT; 2244 2245 String opt; 2246 while ((opt=getNextOption()) != null) { 2247 if (opt.equals("--user")) { 2248 userId = UserHandle.parseUserArg(getNextArgRequired()); 2249 } else { 2250 getErrPrintWriter().println("Error: Unknown option: " + opt); 2251 return -1; 2252 } 2253 } 2254 String packageName = getNextArg(); 2255 2256 IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( 2257 Context.USAGE_STATS_SERVICE)); 2258 if (packageName != null) { 2259 int bucket = usm.getAppStandbyBucket(packageName, null, userId); 2260 pw.println(bucket); 2261 } else { 2262 ParceledListSlice<AppStandbyInfo> buckets = usm.getAppStandbyBuckets( 2263 SHELL_PACKAGE_NAME, userId); 2264 for (AppStandbyInfo bucketInfo : buckets.getList()) { 2265 pw.print(bucketInfo.mPackageName); pw.print(": "); 2266 pw.println(bucketInfo.mStandbyBucket); 2267 } 2268 } 2269 return 0; 2270 } 2271 2272 int runGetInactive(PrintWriter pw) throws RemoteException { 2273 int userId = UserHandle.USER_CURRENT; 2274 2275 String opt; 2276 while ((opt=getNextOption()) != null) { 2277 if (opt.equals("--user")) { 2278 userId = UserHandle.parseUserArg(getNextArgRequired()); 2279 } else { 2280 getErrPrintWriter().println("Error: Unknown option: " + opt); 2281 return -1; 2282 } 2283 } 2284 String packageName = getNextArgRequired(); 2285 2286 IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( 2287 Context.USAGE_STATS_SERVICE)); 2288 boolean isIdle = usm.isAppInactive(packageName, userId); 2289 pw.println("Idle=" + isIdle); 2290 return 0; 2291 } 2292 2293 int runSendTrimMemory(PrintWriter pw) throws RemoteException { 2294 int userId = UserHandle.USER_CURRENT; 2295 String opt; 2296 while ((opt = getNextOption()) != null) { 2297 if (opt.equals("--user")) { 2298 userId = UserHandle.parseUserArg(getNextArgRequired()); 2299 if (userId == UserHandle.USER_ALL) { 2300 getErrPrintWriter().println("Error: Can't use user 'all'"); 2301 return -1; 2302 } 2303 } else { 2304 getErrPrintWriter().println("Error: Unknown option: " + opt); 2305 return -1; 2306 } 2307 } 2308 2309 String proc = getNextArgRequired(); 2310 String levelArg = getNextArgRequired(); 2311 int level; 2312 switch (levelArg) { 2313 case "HIDDEN": 2314 level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN; 2315 break; 2316 case "RUNNING_MODERATE": 2317 level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE; 2318 break; 2319 case "BACKGROUND": 2320 level = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; 2321 break; 2322 case "RUNNING_LOW": 2323 level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW; 2324 break; 2325 case "MODERATE": 2326 level = ComponentCallbacks2.TRIM_MEMORY_MODERATE; 2327 break; 2328 case "RUNNING_CRITICAL": 2329 level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL; 2330 break; 2331 case "COMPLETE": 2332 level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; 2333 break; 2334 default: 2335 try { 2336 level = Integer.parseInt(levelArg); 2337 } catch (NumberFormatException e) { 2338 getErrPrintWriter().println("Error: Unknown level option: " + levelArg); 2339 return -1; 2340 } 2341 } 2342 if (!mInterface.setProcessMemoryTrimLevel(proc, userId, level)) { 2343 getErrPrintWriter().println("Unknown error: failed to set trim level"); 2344 return -1; 2345 } 2346 return 0; 2347 } 2348 2349 int runDisplay(PrintWriter pw) throws RemoteException { 2350 String op = getNextArgRequired(); 2351 switch (op) { 2352 case "move-stack": 2353 return runDisplayMoveStack(pw); 2354 default: 2355 getErrPrintWriter().println("Error: unknown command '" + op + "'"); 2356 return -1; 2357 } 2358 } 2359 2360 int runStack(PrintWriter pw) throws RemoteException { 2361 String op = getNextArgRequired(); 2362 switch (op) { 2363 case "start": 2364 return runStackStart(pw); 2365 case "move-task": 2366 return runStackMoveTask(pw); 2367 case "resize": 2368 return runStackResize(pw); 2369 case "resize-animated": 2370 return runStackResizeAnimated(pw); 2371 case "resize-docked-stack": 2372 return runStackResizeDocked(pw); 2373 case "positiontask": 2374 return runStackPositionTask(pw); 2375 case "list": 2376 return runStackList(pw); 2377 case "info": 2378 return runStackInfo(pw); 2379 case "move-top-activity-to-pinned-stack": 2380 return runMoveTopActivityToPinnedStack(pw); 2381 case "remove": 2382 return runStackRemove(pw); 2383 default: 2384 getErrPrintWriter().println("Error: unknown command '" + op + "'"); 2385 return -1; 2386 } 2387 } 2388 2389 2390 private Rect getBounds() { 2391 String leftStr = getNextArgRequired(); 2392 int left = Integer.parseInt(leftStr); 2393 String topStr = getNextArgRequired(); 2394 int top = Integer.parseInt(topStr); 2395 String rightStr = getNextArgRequired(); 2396 int right = Integer.parseInt(rightStr); 2397 String bottomStr = getNextArgRequired(); 2398 int bottom = Integer.parseInt(bottomStr); 2399 if (left < 0) { 2400 getErrPrintWriter().println("Error: bad left arg: " + leftStr); 2401 return null; 2402 } 2403 if (top < 0) { 2404 getErrPrintWriter().println("Error: bad top arg: " + topStr); 2405 return null; 2406 } 2407 if (right <= 0) { 2408 getErrPrintWriter().println("Error: bad right arg: " + rightStr); 2409 return null; 2410 } 2411 if (bottom <= 0) { 2412 getErrPrintWriter().println("Error: bad bottom arg: " + bottomStr); 2413 return null; 2414 } 2415 return new Rect(left, top, right, bottom); 2416 } 2417 2418 int runDisplayMoveStack(PrintWriter pw) throws RemoteException { 2419 String stackIdStr = getNextArgRequired(); 2420 int stackId = Integer.parseInt(stackIdStr); 2421 String displayIdStr = getNextArgRequired(); 2422 int displayId = Integer.parseInt(displayIdStr); 2423 mInterface.moveStackToDisplay(stackId, displayId); 2424 return 0; 2425 } 2426 2427 int runStackStart(PrintWriter pw) throws RemoteException { 2428 String displayIdStr = getNextArgRequired(); 2429 int displayId = Integer.parseInt(displayIdStr); 2430 Intent intent; 2431 try { 2432 intent = makeIntent(UserHandle.USER_CURRENT); 2433 } catch (URISyntaxException e) { 2434 throw new RuntimeException(e.getMessage(), e); 2435 } 2436 2437 final int stackId = mInterface.createStackOnDisplay(displayId); 2438 if (stackId != INVALID_STACK_ID) { 2439 // TODO: Need proper support if this is used by test... 2440 // container.startActivity(intent); 2441 // ActivityOptions options = ActivityOptions.makeBasic(); 2442 // options.setLaunchDisplayId(displayId); 2443 // options.setLaunchStackId(stackId); 2444 // mInterface.startAct 2445 // mInterface.startActivityAsUser(null, null, intent, mimeType, 2446 // null, null, 0, mStartFlags, profilerInfo, 2447 // options != null ? options.toBundle() : null, mUserId); 2448 } 2449 return 0; 2450 } 2451 2452 int runStackMoveTask(PrintWriter pw) throws RemoteException { 2453 String taskIdStr = getNextArgRequired(); 2454 int taskId = Integer.parseInt(taskIdStr); 2455 String stackIdStr = getNextArgRequired(); 2456 int stackId = Integer.parseInt(stackIdStr); 2457 String toTopStr = getNextArgRequired(); 2458 final boolean toTop; 2459 if ("true".equals(toTopStr)) { 2460 toTop = true; 2461 } else if ("false".equals(toTopStr)) { 2462 toTop = false; 2463 } else { 2464 getErrPrintWriter().println("Error: bad toTop arg: " + toTopStr); 2465 return -1; 2466 } 2467 2468 mInterface.moveTaskToStack(taskId, stackId, toTop); 2469 return 0; 2470 } 2471 2472 int runStackResize(PrintWriter pw) throws RemoteException { 2473 String stackIdStr = getNextArgRequired(); 2474 int stackId = Integer.parseInt(stackIdStr); 2475 final Rect bounds = getBounds(); 2476 if (bounds == null) { 2477 getErrPrintWriter().println("Error: invalid input bounds"); 2478 return -1; 2479 } 2480 return resizeStack(stackId, bounds, 0); 2481 } 2482 2483 int runStackResizeAnimated(PrintWriter pw) throws RemoteException { 2484 String stackIdStr = getNextArgRequired(); 2485 int stackId = Integer.parseInt(stackIdStr); 2486 final Rect bounds; 2487 if ("null".equals(peekNextArg())) { 2488 bounds = null; 2489 } else { 2490 bounds = getBounds(); 2491 if (bounds == null) { 2492 getErrPrintWriter().println("Error: invalid input bounds"); 2493 return -1; 2494 } 2495 } 2496 return resizeStackUnchecked(stackId, bounds, 0, true); 2497 } 2498 2499 int resizeStackUnchecked(int stackId, Rect bounds, int delayMs, boolean animate) 2500 throws RemoteException { 2501 try { 2502 mInterface.resizeStack(stackId, bounds, false, false, animate, -1); 2503 Thread.sleep(delayMs); 2504 } catch (InterruptedException e) { 2505 } 2506 return 0; 2507 } 2508 2509 int runStackResizeDocked(PrintWriter pw) throws RemoteException { 2510 final Rect bounds = getBounds(); 2511 final Rect taskBounds = getBounds(); 2512 if (bounds == null || taskBounds == null) { 2513 getErrPrintWriter().println("Error: invalid input bounds"); 2514 return -1; 2515 } 2516 mInterface.resizeDockedStack(bounds, taskBounds, null, null, null); 2517 return 0; 2518 } 2519 2520 int resizeStack(int stackId, Rect bounds, int delayMs) throws RemoteException { 2521 if (bounds == null) { 2522 getErrPrintWriter().println("Error: invalid input bounds"); 2523 return -1; 2524 } 2525 return resizeStackUnchecked(stackId, bounds, delayMs, false); 2526 } 2527 2528 int runStackPositionTask(PrintWriter pw) throws RemoteException { 2529 String taskIdStr = getNextArgRequired(); 2530 int taskId = Integer.parseInt(taskIdStr); 2531 String stackIdStr = getNextArgRequired(); 2532 int stackId = Integer.parseInt(stackIdStr); 2533 String positionStr = getNextArgRequired(); 2534 int position = Integer.parseInt(positionStr); 2535 2536 mInterface.positionTaskInStack(taskId, stackId, position); 2537 return 0; 2538 } 2539 2540 int runStackList(PrintWriter pw) throws RemoteException { 2541 List<ActivityManager.StackInfo> stacks = mInterface.getAllStackInfos(); 2542 for (ActivityManager.StackInfo info : stacks) { 2543 pw.println(info); 2544 } 2545 return 0; 2546 } 2547 2548 int runStackInfo(PrintWriter pw) throws RemoteException { 2549 int windowingMode = Integer.parseInt(getNextArgRequired()); 2550 int activityType = Integer.parseInt(getNextArgRequired()); 2551 ActivityManager.StackInfo info = mInterface.getStackInfo(windowingMode, activityType); 2552 pw.println(info); 2553 return 0; 2554 } 2555 2556 int runStackRemove(PrintWriter pw) throws RemoteException { 2557 String stackIdStr = getNextArgRequired(); 2558 int stackId = Integer.parseInt(stackIdStr); 2559 mInterface.removeStack(stackId); 2560 return 0; 2561 } 2562 2563 int runMoveTopActivityToPinnedStack(PrintWriter pw) throws RemoteException { 2564 int stackId = Integer.parseInt(getNextArgRequired()); 2565 final Rect bounds = getBounds(); 2566 if (bounds == null) { 2567 getErrPrintWriter().println("Error: invalid input bounds"); 2568 return -1; 2569 } 2570 2571 if (!mInterface.moveTopActivityToPinnedStack(stackId, bounds)) { 2572 getErrPrintWriter().println("Didn't move top activity to pinned stack."); 2573 return -1; 2574 } 2575 return 0; 2576 } 2577 2578 void setBoundsSide(Rect bounds, String side, int value) { 2579 switch (side) { 2580 case "l": 2581 bounds.left = value; 2582 break; 2583 case "r": 2584 bounds.right = value; 2585 break; 2586 case "t": 2587 bounds.top = value; 2588 break; 2589 case "b": 2590 bounds.bottom = value; 2591 break; 2592 default: 2593 getErrPrintWriter().println("Unknown set side: " + side); 2594 break; 2595 } 2596 } 2597 2598 int runTask(PrintWriter pw) throws RemoteException { 2599 String op = getNextArgRequired(); 2600 if (op.equals("lock")) { 2601 return runTaskLock(pw); 2602 } else if (op.equals("resizeable")) { 2603 return runTaskResizeable(pw); 2604 } else if (op.equals("resize")) { 2605 return runTaskResize(pw); 2606 } else if (op.equals("focus")) { 2607 return runTaskFocus(pw); 2608 } else { 2609 getErrPrintWriter().println("Error: unknown command '" + op + "'"); 2610 return -1; 2611 } 2612 } 2613 2614 int runTaskLock(PrintWriter pw) throws RemoteException { 2615 String taskIdStr = getNextArgRequired(); 2616 if (taskIdStr.equals("stop")) { 2617 mInterface.stopSystemLockTaskMode(); 2618 } else { 2619 int taskId = Integer.parseInt(taskIdStr); 2620 mInterface.startSystemLockTaskMode(taskId); 2621 } 2622 pw.println("Activity manager is " + (mInterface.isInLockTaskMode() ? "" : "not ") + 2623 "in lockTaskMode"); 2624 return 0; 2625 } 2626 2627 int runTaskResizeable(PrintWriter pw) throws RemoteException { 2628 final String taskIdStr = getNextArgRequired(); 2629 final int taskId = Integer.parseInt(taskIdStr); 2630 final String resizeableStr = getNextArgRequired(); 2631 final int resizeableMode = Integer.parseInt(resizeableStr); 2632 mInterface.setTaskResizeable(taskId, resizeableMode); 2633 return 0; 2634 } 2635 2636 int runTaskResize(PrintWriter pw) throws RemoteException { 2637 final String taskIdStr = getNextArgRequired(); 2638 final int taskId = Integer.parseInt(taskIdStr); 2639 final Rect bounds = getBounds(); 2640 if (bounds == null) { 2641 getErrPrintWriter().println("Error: invalid input bounds"); 2642 return -1; 2643 } 2644 taskResize(taskId, bounds, 0, false); 2645 return 0; 2646 } 2647 2648 void taskResize(int taskId, Rect bounds, int delay_ms, boolean pretendUserResize) 2649 throws RemoteException { 2650 final int resizeMode = pretendUserResize ? RESIZE_MODE_USER : RESIZE_MODE_SYSTEM; 2651 mInterface.resizeTask(taskId, bounds, resizeMode); 2652 try { 2653 Thread.sleep(delay_ms); 2654 } catch (InterruptedException e) { 2655 } 2656 } 2657 2658 int moveTask(int taskId, Rect taskRect, Rect stackRect, int stepSize, 2659 int maxToTravel, boolean movingForward, boolean horizontal, int delay_ms) 2660 throws RemoteException { 2661 int maxMove; 2662 if (movingForward) { 2663 while (maxToTravel > 0 2664 && ((horizontal && taskRect.right < stackRect.right) 2665 ||(!horizontal && taskRect.bottom < stackRect.bottom))) { 2666 if (horizontal) { 2667 maxMove = Math.min(stepSize, stackRect.right - taskRect.right); 2668 maxToTravel -= maxMove; 2669 taskRect.right += maxMove; 2670 taskRect.left += maxMove; 2671 } else { 2672 maxMove = Math.min(stepSize, stackRect.bottom - taskRect.bottom); 2673 maxToTravel -= maxMove; 2674 taskRect.top += maxMove; 2675 taskRect.bottom += maxMove; 2676 } 2677 taskResize(taskId, taskRect, delay_ms, false); 2678 } 2679 } else { 2680 while (maxToTravel < 0 2681 && ((horizontal && taskRect.left > stackRect.left) 2682 ||(!horizontal && taskRect.top > stackRect.top))) { 2683 if (horizontal) { 2684 maxMove = Math.min(stepSize, taskRect.left - stackRect.left); 2685 maxToTravel -= maxMove; 2686 taskRect.right -= maxMove; 2687 taskRect.left -= maxMove; 2688 } else { 2689 maxMove = Math.min(stepSize, taskRect.top - stackRect.top); 2690 maxToTravel -= maxMove; 2691 taskRect.top -= maxMove; 2692 taskRect.bottom -= maxMove; 2693 } 2694 taskResize(taskId, taskRect, delay_ms, false); 2695 } 2696 } 2697 // Return the remaining distance we didn't travel because we reached the target location. 2698 return maxToTravel; 2699 } 2700 2701 int getStepSize(int current, int target, int inStepSize, boolean greaterThanTarget) { 2702 int stepSize = 0; 2703 if (greaterThanTarget && target < current) { 2704 current -= inStepSize; 2705 stepSize = inStepSize; 2706 if (target > current) { 2707 stepSize -= (target - current); 2708 } 2709 } 2710 if (!greaterThanTarget && target > current) { 2711 current += inStepSize; 2712 stepSize = inStepSize; 2713 if (target < current) { 2714 stepSize += (current - target); 2715 } 2716 } 2717 return stepSize; 2718 } 2719 2720 int runTaskFocus(PrintWriter pw) throws RemoteException { 2721 final int taskId = Integer.parseInt(getNextArgRequired()); 2722 pw.println("Setting focus to task " + taskId); 2723 mInterface.setFocusedTask(taskId); 2724 return 0; 2725 } 2726 2727 int runWrite(PrintWriter pw) { 2728 mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, 2729 "registerUidObserver()"); 2730 mInternal.getRecentTasks().flush(); 2731 pw.println("All tasks persisted."); 2732 return 0; 2733 } 2734 2735 int runAttachAgent(PrintWriter pw) { 2736 // TODO: revisit the permissions required for attaching agents 2737 mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, 2738 "attach-agent"); 2739 String process = getNextArgRequired(); 2740 String agent = getNextArgRequired(); 2741 String opt; 2742 if ((opt = getNextArg()) != null) { 2743 pw.println("Error: Unknown option: " + opt); 2744 return -1; 2745 } 2746 mInternal.attachAgent(process, agent); 2747 return 0; 2748 } 2749 2750 int runSupportsMultiwindow(PrintWriter pw) throws RemoteException { 2751 final Resources res = getResources(pw); 2752 if (res == null) { 2753 return -1; 2754 } 2755 pw.println(ActivityManager.supportsMultiWindow(mInternal.mContext)); 2756 return 0; 2757 } 2758 2759 int runSupportsSplitScreenMultiwindow(PrintWriter pw) throws RemoteException { 2760 final Resources res = getResources(pw); 2761 if (res == null) { 2762 return -1; 2763 } 2764 pw.println(ActivityManager.supportsSplitScreenMultiWindow(mInternal.mContext)); 2765 return 0; 2766 } 2767 2768 int runUpdateApplicationInfo(PrintWriter pw) throws RemoteException { 2769 int userid = UserHandle.parseUserArg(getNextArgRequired()); 2770 ArrayList<String> packages = new ArrayList<>(); 2771 packages.add(getNextArgRequired()); 2772 String packageName; 2773 while ((packageName = getNextArg()) != null) { 2774 packages.add(packageName); 2775 } 2776 mInternal.scheduleApplicationInfoChanged(packages, userid); 2777 pw.println("Packages updated with most recent ApplicationInfos."); 2778 return 0; 2779 } 2780 2781 int runNoHomeScreen(PrintWriter pw) throws RemoteException { 2782 final Resources res = getResources(pw); 2783 if (res == null) { 2784 return -1; 2785 } 2786 pw.println(res.getBoolean(com.android.internal.R.bool.config_noHomeScreen)); 2787 return 0; 2788 } 2789 2790 int runWaitForBroadcastIdle(PrintWriter pw) throws RemoteException { 2791 mInternal.waitForBroadcastIdle(pw); 2792 return 0; 2793 } 2794 2795 private Resources getResources(PrintWriter pw) throws RemoteException { 2796 // system resources does not contain all the device configuration, construct it manually. 2797 Configuration config = mInterface.getConfiguration(); 2798 if (config == null) { 2799 pw.println("Error: Activity manager has no configuration"); 2800 return null; 2801 } 2802 2803 final DisplayMetrics metrics = new DisplayMetrics(); 2804 metrics.setToDefaults(); 2805 2806 return new Resources(AssetManager.getSystem(), metrics, config); 2807 } 2808 2809 @Override 2810 public void onHelp() { 2811 PrintWriter pw = getOutPrintWriter(); 2812 dumpHelp(pw, mDumping); 2813 } 2814 2815 static void dumpHelp(PrintWriter pw, boolean dumping) { 2816 if (dumping) { 2817 pw.println("Activity manager dump options:"); 2818 pw.println(" [-a] [-c] [-p PACKAGE] [-h] [WHAT] ..."); 2819 pw.println(" WHAT may be one of:"); 2820 pw.println(" a[ctivities]: activity stack state"); 2821 pw.println(" r[recents]: recent activities state"); 2822 pw.println(" b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state"); 2823 pw.println(" broadcast-stats [PACKAGE_NAME]: aggregated broadcast statistics"); 2824 pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state"); 2825 pw.println(" p[rocesses] [PACKAGE_NAME]: process state"); 2826 pw.println(" o[om]: out of memory management"); 2827 pw.println(" perm[issions]: URI permission grant state"); 2828 pw.println(" prov[iders] [COMP_SPEC ...]: content provider state"); 2829 pw.println(" provider [COMP_SPEC]: provider client-side state"); 2830 pw.println(" s[ervices] [COMP_SPEC ...]: service state"); 2831 pw.println(" as[sociations]: tracked app associations"); 2832 pw.println(" settings: currently applied config settings"); 2833 pw.println(" service [COMP_SPEC]: service client-side state"); 2834 pw.println(" package [PACKAGE_NAME]: all state related to given package"); 2835 pw.println(" all: dump all activities"); 2836 pw.println(" top: dump the top activity"); 2837 pw.println(" WHAT may also be a COMP_SPEC to dump activities."); 2838 pw.println(" COMP_SPEC may be a component name (com.foo/.myApp),"); 2839 pw.println(" a partial substring in a component name, a"); 2840 pw.println(" hex object identifier."); 2841 pw.println(" -a: include all available server state."); 2842 pw.println(" -c: include client state."); 2843 pw.println(" -p: limit output to given package."); 2844 pw.println(" --checkin: output checkin format, resetting data."); 2845 pw.println(" --C: output checkin format, not resetting data."); 2846 pw.println(" --proto: output dump in protocol buffer format."); 2847 } else { 2848 pw.println("Activity manager (activity) commands:"); 2849 pw.println(" help"); 2850 pw.println(" Print this help text."); 2851 pw.println(" start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]"); 2852 pw.println(" [--sampling INTERVAL] [--streaming] [-R COUNT] [-S]"); 2853 pw.println(" [--track-allocation] [--user <USER_ID> | current] <INTENT>"); 2854 pw.println(" Start an Activity. Options are:"); 2855 pw.println(" -D: enable debugging"); 2856 pw.println(" -N: enable native debugging"); 2857 pw.println(" -W: wait for launch to complete"); 2858 pw.println(" --start-profiler <FILE>: start profiler and send results to <FILE>"); 2859 pw.println(" --sampling INTERVAL: use sample profiling with INTERVAL microseconds"); 2860 pw.println(" between samples (use with --start-profiler)"); 2861 pw.println(" --streaming: stream the profiling output to the specified file"); 2862 pw.println(" (use with --start-profiler)"); 2863 pw.println(" -P <FILE>: like above, but profiling stops when app goes idle"); 2864 pw.println(" --attach-agent <agent>: attach the given agent before binding"); 2865 pw.println(" --attach-agent-bind <agent>: attach the given agent during binding"); 2866 pw.println(" -R: repeat the activity launch <COUNT> times. Prior to each repeat,"); 2867 pw.println(" the top activity will be finished."); 2868 pw.println(" -S: force stop the target app before starting the activity"); 2869 pw.println(" --track-allocation: enable tracking of object allocations"); 2870 pw.println(" --user <USER_ID> | current: Specify which user to run as; if not"); 2871 pw.println(" specified then run as the current user."); 2872 pw.println(" --windowingMode <WINDOWING_MODE>: The windowing mode to launch the activity into."); 2873 pw.println(" --activityType <ACTIVITY_TYPE>: The activity type to launch the activity as."); 2874 pw.println(" start-service [--user <USER_ID> | current] <INTENT>"); 2875 pw.println(" Start a Service. Options are:"); 2876 pw.println(" --user <USER_ID> | current: Specify which user to run as; if not"); 2877 pw.println(" specified then run as the current user."); 2878 pw.println(" start-foreground-service [--user <USER_ID> | current] <INTENT>"); 2879 pw.println(" Start a foreground Service. Options are:"); 2880 pw.println(" --user <USER_ID> | current: Specify which user to run as; if not"); 2881 pw.println(" specified then run as the current user."); 2882 pw.println(" stop-service [--user <USER_ID> | current] <INTENT>"); 2883 pw.println(" Stop a Service. Options are:"); 2884 pw.println(" --user <USER_ID> | current: Specify which user to run as; if not"); 2885 pw.println(" specified then run as the current user."); 2886 pw.println(" broadcast [--user <USER_ID> | all | current] <INTENT>"); 2887 pw.println(" Send a broadcast Intent. Options are:"); 2888 pw.println(" --user <USER_ID> | all | current: Specify which user to send to; if not"); 2889 pw.println(" specified then send to all users."); 2890 pw.println(" --receiver-permission <PERMISSION>: Require receiver to hold permission."); 2891 pw.println(" instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]"); 2892 pw.println(" [--user <USER_ID> | current] [--no-hidden-api-checks]"); 2893 pw.println(" [--no-window-animation] [--abi <ABI>] <COMPONENT>"); 2894 pw.println(" Start an Instrumentation. Typically this target <COMPONENT> is in the"); 2895 pw.println(" form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there"); 2896 pw.println(" is only one instrumentation. Options are:"); 2897 pw.println(" -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with"); 2898 pw.println(" [-e perf true] to generate raw output for performance measurements."); 2899 pw.println(" -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a"); 2900 pw.println(" common form is [-e <testrunner_flag> <value>[,<value>...]]."); 2901 pw.println(" -p <FILE>: write profiling data to <FILE>"); 2902 pw.println(" -m: Write output as protobuf to stdout (machine readable)"); 2903 pw.println(" -f <Optional PATH/TO/FILE>: Write output as protobuf to a file (machine"); 2904 pw.println(" readable). If path is not specified, default directory and file name will"); 2905 pw.println(" be used: /sdcard/instrument-logs/log-yyyyMMdd-hhmmss-SSS.instrumentation_data_proto"); 2906 pw.println(" -w: wait for instrumentation to finish before returning. Required for"); 2907 pw.println(" test runners."); 2908 pw.println(" --user <USER_ID> | current: Specify user instrumentation runs in;"); 2909 pw.println(" current user if not specified."); 2910 pw.println(" --no-hidden-api-checks: disable restrictions on use of hidden API."); 2911 pw.println(" --no-window-animation: turn off window animations while running."); 2912 pw.println(" --abi <ABI>: Launch the instrumented process with the selected ABI."); 2913 pw.println(" This assumes that the process supports the selected ABI."); 2914 pw.println(" trace-ipc [start|stop] [--dump-file <FILE>]"); 2915 pw.println(" Trace IPC transactions."); 2916 pw.println(" start: start tracing IPC transactions."); 2917 pw.println(" stop: stop tracing IPC transactions and dump the results to file."); 2918 pw.println(" --dump-file <FILE>: Specify the file the trace should be dumped to."); 2919 pw.println(" profile [start|stop] [--user <USER_ID> current] [--sampling INTERVAL]"); 2920 pw.println(" [--streaming] <PROCESS> <FILE>"); 2921 pw.println(" Start and stop profiler on a process. The given <PROCESS> argument"); 2922 pw.println(" may be either a process name or pid. Options are:"); 2923 pw.println(" --user <USER_ID> | current: When supplying a process name,"); 2924 pw.println(" specify user of process to profile; uses current user if not specified."); 2925 pw.println(" --sampling INTERVAL: use sample profiling with INTERVAL microseconds"); 2926 pw.println(" between samples"); 2927 pw.println(" --streaming: stream the profiling output to the specified file"); 2928 pw.println(" dumpheap [--user <USER_ID> current] [-n] [-g] <PROCESS> <FILE>"); 2929 pw.println(" Dump the heap of a process. The given <PROCESS> argument may"); 2930 pw.println(" be either a process name or pid. Options are:"); 2931 pw.println(" -n: dump native heap instead of managed heap"); 2932 pw.println(" -g: force GC before dumping the heap"); 2933 pw.println(" --user <USER_ID> | current: When supplying a process name,"); 2934 pw.println(" specify user of process to dump; uses current user if not specified."); 2935 pw.println(" set-debug-app [-w] [--persistent] <PACKAGE>"); 2936 pw.println(" Set application <PACKAGE> to debug. Options are:"); 2937 pw.println(" -w: wait for debugger when application starts"); 2938 pw.println(" --persistent: retain this value"); 2939 pw.println(" clear-debug-app"); 2940 pw.println(" Clear the previously set-debug-app."); 2941 pw.println(" set-watch-heap <PROCESS> <MEM-LIMIT>"); 2942 pw.println(" Start monitoring pss size of <PROCESS>, if it is at or"); 2943 pw.println(" above <HEAP-LIMIT> then a heap dump is collected for the user to report."); 2944 pw.println(" clear-watch-heap"); 2945 pw.println(" Clear the previously set-watch-heap."); 2946 pw.println(" bug-report [--progress | --telephony]"); 2947 pw.println(" Request bug report generation; will launch a notification"); 2948 pw.println(" when done to select where it should be delivered. Options are:"); 2949 pw.println(" --progress: will launch a notification right away to show its progress."); 2950 pw.println(" --telephony: will dump only telephony sections."); 2951 pw.println(" force-stop [--user <USER_ID> | all | current] <PACKAGE>"); 2952 pw.println(" Completely stop the given application package."); 2953 pw.println(" crash [--user <USER_ID>] <PACKAGE|PID>"); 2954 pw.println(" Induce a VM crash in the specified package or process"); 2955 pw.println(" kill [--user <USER_ID> | all | current] <PACKAGE>"); 2956 pw.println(" Kill all background processes associated with the given application."); 2957 pw.println(" kill-all"); 2958 pw.println(" Kill all processes that are safe to kill (cached, etc)."); 2959 pw.println(" make-uid-idle [--user <USER_ID> | all | current] <PACKAGE>"); 2960 pw.println(" If the given application's uid is in the background and waiting to"); 2961 pw.println(" become idle (not allowing background services), do that now."); 2962 pw.println(" monitor [--gdb <port>]"); 2963 pw.println(" Start monitoring for crashes or ANRs."); 2964 pw.println(" --gdb: start gdbserv on the given port at crash/ANR"); 2965 pw.println(" watch-uids [--oom <uid>]"); 2966 pw.println(" Start watching for and reporting uid state changes."); 2967 pw.println(" --oom: specify a uid for which to report detailed change messages."); 2968 pw.println(" hang [--allow-restart]"); 2969 pw.println(" Hang the system."); 2970 pw.println(" --allow-restart: allow watchdog to perform normal system restart"); 2971 pw.println(" restart"); 2972 pw.println(" Restart the user-space system."); 2973 pw.println(" idle-maintenance"); 2974 pw.println(" Perform idle maintenance now."); 2975 pw.println(" screen-compat [on|off] <PACKAGE>"); 2976 pw.println(" Control screen compatibility mode of <PACKAGE>."); 2977 pw.println(" package-importance <PACKAGE>"); 2978 pw.println(" Print current importance of <PACKAGE>."); 2979 pw.println(" to-uri [INTENT]"); 2980 pw.println(" Print the given Intent specification as a URI."); 2981 pw.println(" to-intent-uri [INTENT]"); 2982 pw.println(" Print the given Intent specification as an intent: URI."); 2983 pw.println(" to-app-uri [INTENT]"); 2984 pw.println(" Print the given Intent specification as an android-app: URI."); 2985 pw.println(" switch-user <USER_ID>"); 2986 pw.println(" Switch to put USER_ID in the foreground, starting"); 2987 pw.println(" execution of that user if it is currently stopped."); 2988 pw.println(" get-current-user"); 2989 pw.println(" Returns id of the current foreground user."); 2990 pw.println(" start-user <USER_ID>"); 2991 pw.println(" Start USER_ID in background if it is currently stopped;"); 2992 pw.println(" use switch-user if you want to start the user in foreground"); 2993 pw.println(" unlock-user <USER_ID> [TOKEN_HEX]"); 2994 pw.println(" Attempt to unlock the given user using the given authorization token."); 2995 pw.println(" stop-user [-w] [-f] <USER_ID>"); 2996 pw.println(" Stop execution of USER_ID, not allowing it to run any"); 2997 pw.println(" code until a later explicit start or switch to it."); 2998 pw.println(" -w: wait for stop-user to complete."); 2999 pw.println(" -f: force stop even if there are related users that cannot be stopped."); 3000 pw.println(" is-user-stopped <USER_ID>"); 3001 pw.println(" Returns whether <USER_ID> has been stopped or not."); 3002 pw.println(" get-started-user-state <USER_ID>"); 3003 pw.println(" Gets the current state of the given started user."); 3004 pw.println(" track-associations"); 3005 pw.println(" Enable association tracking."); 3006 pw.println(" untrack-associations"); 3007 pw.println(" Disable and clear association tracking."); 3008 pw.println(" get-uid-state <UID>"); 3009 pw.println(" Gets the process state of an app given its <UID>."); 3010 pw.println(" attach-agent <PROCESS> <FILE>"); 3011 pw.println(" Attach an agent to the specified <PROCESS>, which may be either a process name or a PID."); 3012 pw.println(" get-config [--days N] [--device] [--proto]"); 3013 pw.println(" Retrieve the configuration and any recent configurations of the device."); 3014 pw.println(" --days: also return last N days of configurations that have been seen."); 3015 pw.println(" --device: also output global device configuration info."); 3016 pw.println(" --proto: return result as a proto; does not include --days info."); 3017 pw.println(" supports-multiwindow"); 3018 pw.println(" Returns true if the device supports multiwindow."); 3019 pw.println(" supports-split-screen-multi-window"); 3020 pw.println(" Returns true if the device supports split screen multiwindow."); 3021 pw.println(" suppress-resize-config-changes <true|false>"); 3022 pw.println(" Suppresses configuration changes due to user resizing an activity/task."); 3023 pw.println(" set-inactive [--user <USER_ID>] <PACKAGE> true|false"); 3024 pw.println(" Sets the inactive state of an app."); 3025 pw.println(" get-inactive [--user <USER_ID>] <PACKAGE>"); 3026 pw.println(" Returns the inactive state of an app."); 3027 pw.println(" set-standby-bucket [--user <USER_ID>] <PACKAGE> active|working_set|frequent|rare"); 3028 pw.println(" Puts an app in the standby bucket."); 3029 pw.println(" get-standby-bucket [--user <USER_ID>] <PACKAGE>"); 3030 pw.println(" Returns the standby bucket of an app."); 3031 pw.println(" send-trim-memory [--user <USER_ID>] <PROCESS>"); 3032 pw.println(" [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]"); 3033 pw.println(" Send a memory trim event to a <PROCESS>. May also supply a raw trim int level."); 3034 pw.println(" display [COMMAND] [...]: sub-commands for operating on displays."); 3035 pw.println(" move-stack <STACK_ID> <DISPLAY_ID>"); 3036 pw.println(" Move <STACK_ID> from its current display to <DISPLAY_ID>."); 3037 pw.println(" stack [COMMAND] [...]: sub-commands for operating on activity stacks."); 3038 pw.println(" start <DISPLAY_ID> <INTENT>"); 3039 pw.println(" Start a new activity on <DISPLAY_ID> using <INTENT>"); 3040 pw.println(" move-task <TASK_ID> <STACK_ID> [true|false]"); 3041 pw.println(" Move <TASK_ID> from its current stack to the top (true) or"); 3042 pw.println(" bottom (false) of <STACK_ID>."); 3043 pw.println(" resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>"); 3044 pw.println(" Change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>."); 3045 pw.println(" resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>"); 3046 pw.println(" Same as resize, but allow animation."); 3047 pw.println(" resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]"); 3048 pw.println(" Change docked stack to <LEFT,TOP,RIGHT,BOTTOM>"); 3049 pw.println(" and supplying temporary different task bounds indicated by"); 3050 pw.println(" <TASK_LEFT,TOP,RIGHT,BOTTOM>"); 3051 pw.println(" move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>"); 3052 pw.println(" Moves the top activity from"); 3053 pw.println(" <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the"); 3054 pw.println(" bounds of the pinned stack."); 3055 pw.println(" positiontask <TASK_ID> <STACK_ID> <POSITION>"); 3056 pw.println(" Place <TASK_ID> in <STACK_ID> at <POSITION>"); 3057 pw.println(" list"); 3058 pw.println(" List all of the activity stacks and their sizes."); 3059 pw.println(" info <WINDOWING_MODE> <ACTIVITY_TYPE>"); 3060 pw.println(" Display the information about activity stack in <WINDOWING_MODE> and <ACTIVITY_TYPE>."); 3061 pw.println(" remove <STACK_ID>"); 3062 pw.println(" Remove stack <STACK_ID>."); 3063 pw.println(" task [COMMAND] [...]: sub-commands for operating on activity tasks."); 3064 pw.println(" lock <TASK_ID>"); 3065 pw.println(" Bring <TASK_ID> to the front and don't allow other tasks to run."); 3066 pw.println(" lock stop"); 3067 pw.println(" End the current task lock."); 3068 pw.println(" resizeable <TASK_ID> [0|1|2|3]"); 3069 pw.println(" Change resizeable mode of <TASK_ID> to one of the following:"); 3070 pw.println(" 0: unresizeable"); 3071 pw.println(" 1: crop_windows"); 3072 pw.println(" 2: resizeable"); 3073 pw.println(" 3: resizeable_and_pipable"); 3074 pw.println(" resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>"); 3075 pw.println(" Makes sure <TASK_ID> is in a stack with the specified bounds."); 3076 pw.println(" Forces the task to be resizeable and creates a stack if no existing stack"); 3077 pw.println(" has the specified bounds."); 3078 pw.println(" update-appinfo <USER_ID> <PACKAGE_NAME> [<PACKAGE_NAME>...]"); 3079 pw.println(" Update the ApplicationInfo objects of the listed packages for <USER_ID>"); 3080 pw.println(" without restarting any processes."); 3081 pw.println(" write"); 3082 pw.println(" Write all pending state to storage."); 3083 pw.println(); 3084 Intent.printIntentArgsHelp(pw, ""); 3085 } 3086 } 3087 } 3088