Home | History | Annotate | Download | only in am
      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