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