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