• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.am;
18 
19 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
20 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
21 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
22 import static android.app.ActivityTaskManager.RESIZE_MODE_USER;
23 import static android.app.WaitResult.launchStateToString;
24 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
25 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
26 import static android.view.Display.INVALID_DISPLAY;
27 
28 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
29 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW;
30 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE;
31 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL;
32 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
33 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
34 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_COUNT;
35 import static com.android.server.am.LowMemDetector.ADJ_MEM_FACTOR_NOTHING;
36 
37 import android.app.Activity;
38 import android.app.ActivityManager;
39 import android.app.ActivityOptions;
40 import android.app.ActivityTaskManager;
41 import android.app.ActivityTaskManager.RootTaskInfo;
42 import android.app.AppGlobals;
43 import android.app.BroadcastOptions;
44 import android.app.IActivityController;
45 import android.app.IActivityManager;
46 import android.app.IActivityTaskManager;
47 import android.app.IStopUserCallback;
48 import android.app.IUidObserver;
49 import android.app.KeyguardManager;
50 import android.app.ProfilerInfo;
51 import android.app.RemoteServiceException.CrashedByAdbException;
52 import android.app.UserSwitchObserver;
53 import android.app.WaitResult;
54 import android.app.usage.AppStandbyInfo;
55 import android.app.usage.ConfigurationStats;
56 import android.app.usage.IUsageStatsManager;
57 import android.app.usage.UsageStatsManager;
58 import android.compat.Compatibility;
59 import android.content.ComponentCallbacks2;
60 import android.content.ComponentName;
61 import android.content.Context;
62 import android.content.DeviceConfigurationProto;
63 import android.content.GlobalConfigurationProto;
64 import android.content.IIntentReceiver;
65 import android.content.Intent;
66 import android.content.pm.ConfigurationInfo;
67 import android.content.pm.FeatureInfo;
68 import android.content.pm.IPackageManager;
69 import android.content.pm.PackageManager;
70 import android.content.pm.ParceledListSlice;
71 import android.content.pm.ResolveInfo;
72 import android.content.pm.SharedLibraryInfo;
73 import android.content.pm.UserInfo;
74 import android.content.res.AssetManager;
75 import android.content.res.Configuration;
76 import android.content.res.Resources;
77 import android.graphics.Rect;
78 import android.hardware.display.DisplayManager;
79 import android.opengl.GLES10;
80 import android.os.Binder;
81 import android.os.Build;
82 import android.os.Bundle;
83 import android.os.IProgressListener;
84 import android.os.ParcelFileDescriptor;
85 import android.os.RemoteCallback;
86 import android.os.RemoteCallback.OnResultListener;
87 import android.os.RemoteException;
88 import android.os.ServiceManager;
89 import android.os.ShellCommand;
90 import android.os.StrictMode;
91 import android.os.SystemClock;
92 import android.os.SystemProperties;
93 import android.os.Trace;
94 import android.os.UserHandle;
95 import android.os.UserManager;
96 import android.text.TextUtils;
97 import android.util.ArrayMap;
98 import android.util.ArraySet;
99 import android.util.DebugUtils;
100 import android.util.DisplayMetrics;
101 import android.util.proto.ProtoOutputStream;
102 import android.view.Display;
103 import android.window.SplashScreen;
104 
105 import com.android.internal.compat.CompatibilityChangeConfig;
106 import com.android.internal.util.MemInfoReader;
107 import com.android.server.am.LowMemDetector.MemFactor;
108 import com.android.server.compat.PlatformCompat;
109 import com.android.server.utils.Slogf;
110 
111 import dalvik.annotation.optimization.NeverCompile;
112 
113 import java.io.BufferedReader;
114 import java.io.IOException;
115 import java.io.InputStream;
116 import java.io.InputStreamReader;
117 import java.io.PrintWriter;
118 import java.net.URISyntaxException;
119 import java.time.Clock;
120 import java.time.LocalDateTime;
121 import java.time.format.DateTimeFormatter;
122 import java.util.ArrayList;
123 import java.util.Arrays;
124 import java.util.Collections;
125 import java.util.Comparator;
126 import java.util.HashSet;
127 import java.util.List;
128 import java.util.Locale;
129 import java.util.Set;
130 import java.util.concurrent.CountDownLatch;
131 import java.util.concurrent.TimeUnit;
132 
133 import javax.microedition.khronos.egl.EGL10;
134 import javax.microedition.khronos.egl.EGLConfig;
135 import javax.microedition.khronos.egl.EGLContext;
136 import javax.microedition.khronos.egl.EGLDisplay;
137 import javax.microedition.khronos.egl.EGLSurface;
138 
139 final class ActivityManagerShellCommand extends ShellCommand {
140 
141     static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerShellCommand" : TAG_AM;
142 
143 
144     public static final String NO_CLASS_ERROR_CODE = "Error type 3";
145 
146     private static final String SHELL_PACKAGE_NAME = "com.android.shell";
147 
148     private static final int USER_OPERATION_TIMEOUT_MS = 2 * 60 * 1000; // 2 minutes
149 
150     private static final DateTimeFormatter LOG_NAME_TIME_FORMATTER =
151             DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss", Locale.ROOT);
152 
153     // IPC interface to activity manager -- don't need to do additional security checks.
154     final IActivityManager mInterface;
155     final IActivityTaskManager mTaskInterface;
156 
157     // Internal service impl -- must perform security checks before touching.
158     final ActivityManagerService mInternal;
159 
160     // Convenience for interacting with package manager.
161     final IPackageManager mPm;
162 
163     private int mStartFlags = 0;
164     private boolean mWaitOption = false;
165     private boolean mStopOption = false;
166 
167     private int mRepeat = 0;
168     private int mUserId;
169     private String mReceiverPermission;
170 
171     private String mProfileFile;
172     private int mSamplingInterval;
173     private boolean mAutoStop;
174     private boolean mStreaming;   // Streaming the profiling output to a file.
175     private String mAgent;  // Agent to attach on startup.
176     private boolean mAttachAgentDuringBind;  // Whether agent should be attached late.
177     private int mDisplayId;
178     private int mWindowingMode;
179     private int mActivityType;
180     private int mTaskId;
181     private boolean mIsTaskOverlay;
182     private boolean mIsLockTask;
183     private boolean mAsync;
184     private BroadcastOptions mBroadcastOptions;
185     private boolean mShowSplashScreen;
186     private boolean mDismissKeyguard;
187 
188     final boolean mDumping;
189 
ActivityManagerShellCommand(ActivityManagerService service, boolean dumping)190     ActivityManagerShellCommand(ActivityManagerService service, boolean dumping) {
191         mInterface = service;
192         mTaskInterface = service.mActivityTaskManager;
193         mInternal = service;
194         mPm = AppGlobals.getPackageManager();
195         mDumping = dumping;
196     }
197 
198     @Override
onCommand(String cmd)199     public int onCommand(String cmd) {
200         if (cmd == null) {
201             return handleDefaultCommands(cmd);
202         }
203         final PrintWriter pw = getOutPrintWriter();
204         try {
205             switch (cmd) {
206                 case "start":
207                 case "start-activity":
208                     return runStartActivity(pw);
209                 case "startservice":
210                 case "start-service":
211                     return runStartService(pw, false);
212                 case "startforegroundservice":
213                 case "startfgservice":
214                 case "start-foreground-service":
215                 case "start-fg-service":
216                     return runStartService(pw, true);
217                 case "stopservice":
218                 case "stop-service":
219                     return runStopService(pw);
220                 case "broadcast":
221                     return runSendBroadcast(pw);
222                 case "compact":
223                     return runCompact(pw);
224                 case "instrument":
225                     getOutPrintWriter().println("Error: must be invoked through 'am instrument'.");
226                     return -1;
227                 case "trace-ipc":
228                     return runTraceIpc(pw);
229                 case "profile":
230                     return runProfile(pw);
231                 case "dumpheap":
232                     return runDumpHeap(pw);
233                 case "set-debug-app":
234                     return runSetDebugApp(pw);
235                 case "set-agent-app":
236                     return runSetAgentApp(pw);
237                 case "clear-debug-app":
238                     return runClearDebugApp(pw);
239                 case "set-watch-heap":
240                     return runSetWatchHeap(pw);
241                 case "clear-watch-heap":
242                     return runClearWatchHeap(pw);
243                 case "clear-exit-info":
244                     return runClearExitInfo(pw);
245                 case "bug-report":
246                     return runBugReport(pw);
247                 case "force-stop":
248                     return runForceStop(pw);
249                 case "stop-app":
250                     return runStopApp(pw);
251                 case "clear-recent-apps":
252                     return runClearRecentApps(pw);
253                 case "fgs-notification-rate-limit":
254                     return runFgsNotificationRateLimit(pw);
255                 case "crash":
256                     return runCrash(pw);
257                 case "kill":
258                     return runKill(pw);
259                 case "kill-all":
260                     return runKillAll(pw);
261                 case "make-uid-idle":
262                     return runMakeIdle(pw);
263                 case "monitor":
264                     return runMonitor(pw);
265                 case "watch-uids":
266                     return runWatchUids(pw);
267                 case "hang":
268                     return runHang(pw);
269                 case "restart":
270                     return runRestart(pw);
271                 case "idle-maintenance":
272                     return runIdleMaintenance(pw);
273                 case "screen-compat":
274                     return runScreenCompat(pw);
275                 case "package-importance":
276                     return runPackageImportance(pw);
277                 case "to-uri":
278                     return runToUri(pw, 0);
279                 case "to-intent-uri":
280                     return runToUri(pw, Intent.URI_INTENT_SCHEME);
281                 case "to-app-uri":
282                     return runToUri(pw, Intent.URI_ANDROID_APP_SCHEME);
283                 case "switch-user":
284                     return runSwitchUser(pw);
285                 case "get-current-user":
286                     return runGetCurrentUser(pw);
287                 case "start-user":
288                     return runStartUser(pw);
289                 case "unlock-user":
290                     return runUnlockUser(pw);
291                 case "stop-user":
292                     return runStopUser(pw);
293                 case "is-user-stopped":
294                     return runIsUserStopped(pw);
295                 case "get-started-user-state":
296                     return runGetStartedUserState(pw);
297                 case "track-associations":
298                     return runTrackAssociations(pw);
299                 case "untrack-associations":
300                     return runUntrackAssociations(pw);
301                 case "get-uid-state":
302                     return getUidState(pw);
303                 case "get-config":
304                     return runGetConfig(pw);
305                 case "suppress-resize-config-changes":
306                     return runSuppressResizeConfigChanges(pw);
307                 case "set-inactive":
308                     return runSetInactive(pw);
309                 case "get-inactive":
310                     return runGetInactive(pw);
311                 case "set-standby-bucket":
312                     return runSetStandbyBucket(pw);
313                 case "get-standby-bucket":
314                     return runGetStandbyBucket(pw);
315                 case "send-trim-memory":
316                     return runSendTrimMemory(pw);
317                 case "display":
318                     return runDisplay(pw);
319                 case "stack":
320                     return runStack(pw);
321                 case "task":
322                     return runTask(pw);
323                 case "write":
324                     return runWrite(pw);
325                 case "attach-agent":
326                     return runAttachAgent(pw);
327                 case "supports-multiwindow":
328                     return runSupportsMultiwindow(pw);
329                 case "supports-split-screen-multi-window":
330                     return runSupportsSplitScreenMultiwindow(pw);
331                 case "update-appinfo":
332                     return runUpdateApplicationInfo(pw);
333                 case "no-home-screen":
334                     return runNoHomeScreen(pw);
335                 case "wait-for-broadcast-idle":
336                     return runWaitForBroadcastIdle(pw);
337                 case "compat":
338                     return runCompat(pw);
339                 case "refresh-settings-cache":
340                     return runRefreshSettingsCache();
341                 case "memory-factor":
342                     return runMemoryFactor(pw);
343                 case "service-restart-backoff":
344                     return runServiceRestartBackoff(pw);
345                 case "get-isolated-pids":
346                     return runGetIsolatedProcesses(pw);
347                 case "set-stop-user-on-switch":
348                     return runSetStopUserOnSwitch(pw);
349                 case "set-bg-abusive-uids":
350                     return runSetBgAbusiveUids(pw);
351                 case "list-bg-exemptions-config":
352                     return runListBgExemptionsConfig(pw);
353                 default:
354                     return handleDefaultCommands(cmd);
355             }
356         } catch (RemoteException e) {
357             pw.println("Remote exception: " + e);
358         }
359         return -1;
360     }
361 
makeIntent(int defUser)362     private Intent makeIntent(int defUser) throws URISyntaxException {
363         mStartFlags = 0;
364         mWaitOption = false;
365         mStopOption = false;
366         mRepeat = 0;
367         mProfileFile = null;
368         mSamplingInterval = 0;
369         mAutoStop = false;
370         mStreaming = false;
371         mUserId = defUser;
372         mDisplayId = INVALID_DISPLAY;
373         mWindowingMode = WINDOWING_MODE_UNDEFINED;
374         mActivityType = ACTIVITY_TYPE_UNDEFINED;
375         mTaskId = INVALID_TASK_ID;
376         mIsTaskOverlay = false;
377         mIsLockTask = false;
378         mAsync = false;
379         mBroadcastOptions = null;
380 
381         return Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
382             @Override
383             public boolean handleOption(String opt, ShellCommand cmd) {
384                 if (opt.equals("-D")) {
385                     mStartFlags |= ActivityManager.START_FLAG_DEBUG;
386                 } else if (opt.equals("-N")) {
387                     mStartFlags |= ActivityManager.START_FLAG_NATIVE_DEBUGGING;
388                 } else if (opt.equals("-W")) {
389                     mWaitOption = true;
390                 } else if (opt.equals("-P")) {
391                     mProfileFile = getNextArgRequired();
392                     mAutoStop = true;
393                 } else if (opt.equals("--start-profiler")) {
394                     mProfileFile = getNextArgRequired();
395                     mAutoStop = false;
396                 } else if (opt.equals("--sampling")) {
397                     mSamplingInterval = Integer.parseInt(getNextArgRequired());
398                 } else if (opt.equals("--streaming")) {
399                     mStreaming = true;
400                 } else if (opt.equals("--attach-agent")) {
401                     if (mAgent != null) {
402                         cmd.getErrPrintWriter().println(
403                                 "Multiple --attach-agent(-bind) not supported");
404                         return false;
405                     }
406                     mAgent = getNextArgRequired();
407                     mAttachAgentDuringBind = false;
408                 } else if (opt.equals("--attach-agent-bind")) {
409                     if (mAgent != null) {
410                         cmd.getErrPrintWriter().println(
411                                 "Multiple --attach-agent(-bind) not supported");
412                         return false;
413                     }
414                     mAgent = getNextArgRequired();
415                     mAttachAgentDuringBind = true;
416                 } else if (opt.equals("-R")) {
417                     mRepeat = Integer.parseInt(getNextArgRequired());
418                 } else if (opt.equals("-S")) {
419                     mStopOption = true;
420                 } else if (opt.equals("--track-allocation")) {
421                     mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION;
422                 } else if (opt.equals("--user")) {
423                     mUserId = UserHandle.parseUserArg(getNextArgRequired());
424                 } else if (opt.equals("--receiver-permission")) {
425                     mReceiverPermission = getNextArgRequired();
426                 } else if (opt.equals("--display")) {
427                     mDisplayId = Integer.parseInt(getNextArgRequired());
428                 } else if (opt.equals("--windowingMode")) {
429                     mWindowingMode = Integer.parseInt(getNextArgRequired());
430                 } else if (opt.equals("--activityType")) {
431                     mActivityType = Integer.parseInt(getNextArgRequired());
432                 } else if (opt.equals("--task")) {
433                     mTaskId = Integer.parseInt(getNextArgRequired());
434                 } else if (opt.equals("--task-overlay")) {
435                     mIsTaskOverlay = true;
436                 } else if (opt.equals("--lock-task")) {
437                     mIsLockTask = true;
438                 } else if (opt.equals("--allow-background-activity-starts")) {
439                     if (mBroadcastOptions == null) {
440                         mBroadcastOptions = BroadcastOptions.makeBasic();
441                     }
442                     mBroadcastOptions.setBackgroundActivityStartsAllowed(true);
443                 } else if (opt.equals("--async")) {
444                     mAsync = true;
445                 } else if (opt.equals("--splashscreen-show-icon")) {
446                     mShowSplashScreen = true;
447                 } else if (opt.equals("--dismiss-keyguard")) {
448                     mDismissKeyguard = true;
449                 } else {
450                     return false;
451                 }
452                 return true;
453             }
454         });
455     }
456 
457     private class ProgressWaiter extends IProgressListener.Stub {
458         private final CountDownLatch mFinishedLatch = new CountDownLatch(1);
459 
460         @Override
461         public void onStarted(int id, Bundle extras) {}
462 
463         @Override
464         public void onProgress(int id, int progress, Bundle extras) {}
465 
466         @Override
467         public void onFinished(int id, Bundle extras) {
468             mFinishedLatch.countDown();
469         }
470 
471         public boolean waitForFinish(long timeoutMillis) {
472             try {
473                 return mFinishedLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
474             } catch (InterruptedException e) {
475                 System.err.println("Thread interrupted unexpectedly.");
476                 return false;
477             }
478         }
479     }
480 
481     int runStartActivity(PrintWriter pw) throws RemoteException {
482         Intent intent;
483         try {
484             intent = makeIntent(UserHandle.USER_CURRENT);
485         } catch (URISyntaxException e) {
486             throw new RuntimeException(e.getMessage(), e);
487         }
488 
489         if (mUserId == UserHandle.USER_ALL) {
490             getErrPrintWriter().println("Error: Can't start service with user 'all'");
491             return 1;
492         }
493 
494         String mimeType = intent.getType();
495         if (mimeType == null && intent.getData() != null
496                 && "content".equals(intent.getData().getScheme())) {
497             mimeType = mInterface.getProviderMimeType(intent.getData(), mUserId);
498         }
499 
500         do {
501             if (mStopOption) {
502                 String packageName;
503                 if (intent.getComponent() != null) {
504                     packageName = intent.getComponent().getPackageName();
505                 } else {
506                     // queryIntentActivities does not convert user id, so we convert it here first
507                     int userIdForQuery = mInternal.mUserController.handleIncomingUser(
508                             Binder.getCallingPid(), Binder.getCallingUid(), mUserId, false,
509                             ALLOW_NON_FULL, "ActivityManagerShellCommand", null);
510                     List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
511                             userIdForQuery).getList();
512                     if (activities == null || activities.size() <= 0) {
513                         getErrPrintWriter().println("Error: Intent does not match any activities: "
514                                 + intent);
515                         return 1;
516                     } else if (activities.size() > 1) {
517                         getErrPrintWriter().println(
518                                 "Error: Intent matches multiple activities; can't stop: "
519                                 + intent);
520                         return 1;
521                     }
522                     packageName = activities.get(0).activityInfo.packageName;
523                 }
524                 pw.println("Stopping: " + packageName);
525                 pw.flush();
526                 mInterface.forceStopPackage(packageName, mUserId);
527                 try {
528                     Thread.sleep(250);
529                 } catch (InterruptedException e) {
530                 }
531             }
532 
533             ProfilerInfo profilerInfo = null;
534 
535             if (mProfileFile != null || mAgent != null) {
536                 ParcelFileDescriptor fd = null;
537                 if (mProfileFile != null) {
538                     fd = openFileForSystem(mProfileFile, "w");
539                     if (fd == null) {
540                         return 1;
541                     }
542                 }
543                 profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop,
544                         mStreaming, mAgent, mAttachAgentDuringBind);
545             }
546 
547             pw.println("Starting: " + intent);
548             pw.flush();
549             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
550 
551             WaitResult result = null;
552             int res;
553             final long startTime = SystemClock.uptimeMillis();
554             ActivityOptions options = null;
555             if (mDisplayId != INVALID_DISPLAY) {
556                 options = ActivityOptions.makeBasic();
557                 options.setLaunchDisplayId(mDisplayId);
558             }
559             if (mWindowingMode != WINDOWING_MODE_UNDEFINED) {
560                 if (options == null) {
561                     options = ActivityOptions.makeBasic();
562                 }
563                 options.setLaunchWindowingMode(mWindowingMode);
564             }
565             if (mActivityType != ACTIVITY_TYPE_UNDEFINED) {
566                 if (options == null) {
567                     options = ActivityOptions.makeBasic();
568                 }
569                 options.setLaunchActivityType(mActivityType);
570             }
571             if (mTaskId != INVALID_TASK_ID) {
572                 if (options == null) {
573                     options = ActivityOptions.makeBasic();
574                 }
575                 options.setLaunchTaskId(mTaskId);
576 
577                 if (mIsTaskOverlay) {
578                     options.setTaskOverlay(true, true /* canResume */);
579                 }
580             }
581             if (mIsLockTask) {
582                 if (options == null) {
583                     options = ActivityOptions.makeBasic();
584                 }
585                 options.setLockTaskEnabled(true);
586             }
587             if (mShowSplashScreen) {
588                 if (options == null) {
589                     options = ActivityOptions.makeBasic();
590                 }
591                 options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
592             }
593             if (mDismissKeyguard) {
594                 if (options == null) {
595                     options = ActivityOptions.makeBasic();
596                 }
597                 options.setDismissKeyguard();
598             }
599             if (mWaitOption) {
600                 result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, null, intent,
601                         mimeType, null, null, 0, mStartFlags, profilerInfo,
602                         options != null ? options.toBundle() : null, mUserId);
603                 res = result.result;
604             } else {
605                 res = mInternal.startActivityAsUserWithFeature(null, SHELL_PACKAGE_NAME, null,
606                         intent, mimeType, null, null, 0, mStartFlags, profilerInfo,
607                         options != null ? options.toBundle() : null, mUserId);
608             }
609             final long endTime = SystemClock.uptimeMillis();
610             PrintWriter out = mWaitOption ? pw : getErrPrintWriter();
611             boolean launched = false;
612             switch (res) {
613                 case ActivityManager.START_SUCCESS:
614                     launched = true;
615                     break;
616                 case ActivityManager.START_SWITCHES_CANCELED:
617                     launched = true;
618                     out.println(
619                             "Warning: Activity not started because the "
620                                     + " current activity is being kept for the user.");
621                     break;
622                 case ActivityManager.START_DELIVERED_TO_TOP:
623                     launched = true;
624                     out.println(
625                             "Warning: Activity not started, intent has "
626                                     + "been delivered to currently running "
627                                     + "top-most instance.");
628                     break;
629                 case ActivityManager.START_RETURN_INTENT_TO_CALLER:
630                     launched = true;
631                     out.println(
632                             "Warning: Activity not started because intent "
633                                     + "should be handled by the caller");
634                     break;
635                 case ActivityManager.START_TASK_TO_FRONT:
636                     launched = true;
637                     out.println(
638                             "Warning: Activity not started, its current "
639                                     + "task has been brought to the front");
640                     break;
641                 case ActivityManager.START_INTENT_NOT_RESOLVED:
642                     out.println(
643                             "Error: Activity not started, unable to "
644                                     + "resolve " + intent.toString());
645                     break;
646                 case ActivityManager.START_CLASS_NOT_FOUND:
647                     out.println(NO_CLASS_ERROR_CODE);
648                     out.println("Error: Activity class " +
649                             intent.getComponent().toShortString()
650                             + " does not exist.");
651                     break;
652                 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
653                     out.println(
654                             "Error: Activity not started, you requested to "
655                                     + "both forward and receive its result");
656                     break;
657                 case ActivityManager.START_PERMISSION_DENIED:
658                     out.println(
659                             "Error: Activity not started, you do not "
660                                     + "have permission to access it.");
661                     break;
662                 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
663                     out.println(
664                             "Error: Activity not started, voice control not allowed for: "
665                                     + intent);
666                     break;
667                 case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
668                     out.println(
669                             "Error: Not allowed to start background user activity"
670                                     + " that shouldn't be displayed for all users.");
671                     break;
672                 default:
673                     out.println(
674                             "Error: Activity not started, unknown error code " + res);
675                     break;
676             }
677             out.flush();
678             if (mWaitOption && launched) {
679                 if (result == null) {
680                     result = new WaitResult();
681                     result.who = intent.getComponent();
682                 }
683                 pw.println("Status: " + (result.timeout ? "timeout" : "ok"));
684                 pw.println("LaunchState: " + launchStateToString(result.launchState));
685                 if (result.who != null) {
686                     pw.println("Activity: " + result.who.flattenToShortString());
687                 }
688                 if (result.totalTime >= 0) {
689                     pw.println("TotalTime: " + result.totalTime);
690                 }
691                 pw.println("WaitTime: " + (endTime-startTime));
692                 pw.println("Complete");
693                 pw.flush();
694             }
695             mRepeat--;
696             if (mRepeat > 0) {
697                 mTaskInterface.unhandledBack();
698             }
699         } while (mRepeat > 0);
700         return 0;
701     }
702 
703     int runStartService(PrintWriter pw, boolean asForeground) throws RemoteException {
704         final PrintWriter err = getErrPrintWriter();
705         Intent intent;
706         try {
707             intent = makeIntent(UserHandle.USER_CURRENT);
708         } catch (URISyntaxException e) {
709             throw new RuntimeException(e.getMessage(), e);
710         }
711         if (mUserId == UserHandle.USER_ALL) {
712             err.println("Error: Can't start activity with user 'all'");
713             return -1;
714         }
715         pw.println("Starting service: " + intent);
716         pw.flush();
717         ComponentName cn = mInterface.startService(null, intent, intent.getType(),
718                 asForeground, SHELL_PACKAGE_NAME, null, mUserId);
719         if (cn == null) {
720             err.println("Error: Not found; no service started.");
721             return -1;
722         } else if (cn.getPackageName().equals("!")) {
723             err.println("Error: Requires permission " + cn.getClassName());
724             return -1;
725         } else if (cn.getPackageName().equals("!!")) {
726             err.println("Error: " + cn.getClassName());
727             return -1;
728         } else if (cn.getPackageName().equals("?")) {
729             err.println("Error: " + cn.getClassName());
730             return -1;
731         }
732         return 0;
733     }
734 
735     int runStopService(PrintWriter pw) throws RemoteException {
736         final PrintWriter err = getErrPrintWriter();
737         Intent intent;
738         try {
739             intent = makeIntent(UserHandle.USER_CURRENT);
740         } catch (URISyntaxException e) {
741             throw new RuntimeException(e.getMessage(), e);
742         }
743         if (mUserId == UserHandle.USER_ALL) {
744             err.println("Error: Can't stop activity with user 'all'");
745             return -1;
746         }
747         pw.println("Stopping service: " + intent);
748         pw.flush();
749         int result = mInterface.stopService(null, intent, intent.getType(), mUserId);
750         if (result == 0) {
751             err.println("Service not stopped: was not running.");
752             return -1;
753         } else if (result == 1) {
754             err.println("Service stopped");
755             return -1;
756         } else if (result == -1) {
757             err.println("Error stopping service");
758             return -1;
759         }
760         return 0;
761     }
762 
763     final static class IntentReceiver extends IIntentReceiver.Stub {
764         private final PrintWriter mPw;
765         private boolean mFinished = false;
766 
767         IntentReceiver(PrintWriter pw) {
768             mPw = pw;
769         }
770 
771         @Override
772         public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
773                 boolean ordered, boolean sticky, int sendingUser) {
774             String line = "Broadcast completed: result=" + resultCode;
775             if (data != null) line = line + ", data=\"" + data + "\"";
776             if (extras != null) line = line + ", extras: " + extras;
777             mPw.println(line);
778             mPw.flush();
779             synchronized (this) {
780                 mFinished = true;
781                 notifyAll();
782             }
783         }
784 
785         public synchronized void waitForFinish() {
786             try {
787                 while (!mFinished) wait();
788             } catch (InterruptedException e) {
789                 throw new IllegalStateException(e);
790             }
791         }
792     }
793 
794     int runSendBroadcast(PrintWriter pw) throws RemoteException {
795         Intent intent;
796         try {
797             intent = makeIntent(UserHandle.USER_CURRENT);
798         } catch (URISyntaxException e) {
799             throw new RuntimeException(e.getMessage(), e);
800         }
801         intent.addFlags(Intent.FLAG_RECEIVER_FROM_SHELL);
802         IntentReceiver receiver = new IntentReceiver(pw);
803         String[] requiredPermissions = mReceiverPermission == null ? null
804                 : new String[] {mReceiverPermission};
805         pw.println("Broadcasting: " + intent);
806         pw.flush();
807         Bundle bundle = mBroadcastOptions == null ? null : mBroadcastOptions.toBundle();
808         mInterface.broadcastIntentWithFeature(null, null, intent, null, receiver, 0, null, null,
809                 requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE, bundle, true,
810                 false, mUserId);
811         if (!mAsync) {
812             receiver.waitForFinish();
813         }
814         return 0;
815     }
816 
817     int runTraceIpc(PrintWriter pw) throws RemoteException {
818         String op = getNextArgRequired();
819         if (op.equals("start")) {
820             return runTraceIpcStart(pw);
821         } else if (op.equals("stop")) {
822             return runTraceIpcStop(pw);
823         } else {
824             getErrPrintWriter().println("Error: unknown trace ipc command '" + op + "'");
825             return -1;
826         }
827     }
828 
829     int runTraceIpcStart(PrintWriter pw) throws RemoteException {
830         pw.println("Starting IPC tracing.");
831         pw.flush();
832         mInterface.startBinderTracking();
833         return 0;
834     }
835 
836     int runTraceIpcStop(PrintWriter pw) throws RemoteException {
837         final PrintWriter err = getErrPrintWriter();
838         String opt;
839         String filename = null;
840         while ((opt=getNextOption()) != null) {
841             if (opt.equals("--dump-file")) {
842                 filename = getNextArgRequired();
843             } else {
844                 err.println("Error: Unknown option: " + opt);
845                 return -1;
846             }
847         }
848         if (filename == null) {
849             err.println("Error: Specify filename to dump logs to.");
850             return -1;
851         }
852 
853         // Writes an error message to stderr on failure
854         ParcelFileDescriptor fd = openFileForSystem(filename, "w");
855         if (fd == null) {
856             return -1;
857         }
858 
859         if (!mInterface.stopBinderTrackingAndDump(fd)) {
860             err.println("STOP TRACE FAILED.");
861             return -1;
862         }
863 
864         pw.println("Stopped IPC tracing. Dumping logs to: " + filename);
865         return 0;
866     }
867 
868     static void removeWallOption() {
869         String props = SystemProperties.get("dalvik.vm.extra-opts");
870         if (props != null && props.contains("-Xprofile:wallclock")) {
871             props = props.replace("-Xprofile:wallclock", "");
872             props = props.trim();
873             SystemProperties.set("dalvik.vm.extra-opts", props);
874         }
875     }
876 
877     private int runProfile(PrintWriter pw) throws RemoteException {
878         final PrintWriter err = getErrPrintWriter();
879         String profileFile = null;
880         boolean start = false;
881         boolean wall = false;
882         int userId = UserHandle.USER_CURRENT;
883         int profileType = 0;
884         mSamplingInterval = 0;
885         mStreaming = false;
886 
887         String process = null;
888 
889         String cmd = getNextArgRequired();
890 
891         if ("start".equals(cmd)) {
892             start = true;
893             String opt;
894             while ((opt=getNextOption()) != null) {
895                 if (opt.equals("--user")) {
896                     userId = UserHandle.parseUserArg(getNextArgRequired());
897                 } else if (opt.equals("--wall")) {
898                     wall = true;
899                 } else if (opt.equals("--streaming")) {
900                     mStreaming = true;
901                 } else if (opt.equals("--sampling")) {
902                     mSamplingInterval = Integer.parseInt(getNextArgRequired());
903                 } else {
904                     err.println("Error: Unknown option: " + opt);
905                     return -1;
906                 }
907             }
908             process = getNextArgRequired();
909         } else if ("stop".equals(cmd)) {
910             String opt;
911             while ((opt=getNextOption()) != null) {
912                 if (opt.equals("--user")) {
913                     userId = UserHandle.parseUserArg(getNextArgRequired());
914                 } else {
915                     err.println("Error: Unknown option: " + opt);
916                     return -1;
917                 }
918             }
919             process = getNextArgRequired();
920         } else {
921             // Compatibility with old syntax: process is specified first.
922             process = cmd;
923             cmd = getNextArgRequired();
924             if ("start".equals(cmd)) {
925                 start = true;
926             } else if (!"stop".equals(cmd)) {
927                 throw new IllegalArgumentException("Profile command " + process + " not valid");
928             }
929         }
930 
931         if (userId == UserHandle.USER_ALL) {
932             err.println("Error: Can't profile with user 'all'");
933             return -1;
934         }
935 
936         ParcelFileDescriptor fd = null;
937         ProfilerInfo profilerInfo = null;
938 
939         if (start) {
940             profileFile = getNextArgRequired();
941             fd = openFileForSystem(profileFile, "w");
942             if (fd == null) {
943                 return -1;
944             }
945             profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming,
946                     null, false);
947         }
948 
949         try {
950             if (wall) {
951                 // XXX doesn't work -- this needs to be set before booting.
952                 String props = SystemProperties.get("dalvik.vm.extra-opts");
953                 if (props == null || !props.contains("-Xprofile:wallclock")) {
954                     props = props + " -Xprofile:wallclock";
955                     //SystemProperties.set("dalvik.vm.extra-opts", props);
956                 }
957             } else if (start) {
958                 //removeWallOption();
959             }
960             if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) {
961                 wall = false;
962                 err.println("PROFILE FAILED on process " + process);
963                 return -1;
964             }
965         } finally {
966             if (!wall) {
967                 //removeWallOption();
968             }
969         }
970         return 0;
971     }
972 
973     @NeverCompile
974     int runCompact(PrintWriter pw) {
975         String processName = getNextArgRequired();
976         String uid = getNextArgRequired();
977         String op = getNextArgRequired();
978         ProcessRecord app;
979         synchronized (mInternal.mProcLock) {
980             app = mInternal.getProcessRecordLocked(processName, Integer.parseInt(uid));
981         }
982         pw.println("Process record found pid: " + app.mPid);
983         if (op.equals("full")) {
984             pw.println("Executing full compaction for " + app.mPid);
985             synchronized (mInternal.mProcLock) {
986                 mInternal.mOomAdjuster.mCachedAppOptimizer.compactAppFull(app, true);
987             }
988             pw.println("Finished full compaction for " + app.mPid);
989         } else if (op.equals("some")) {
990             pw.println("Executing some compaction for " + app.mPid);
991             synchronized (mInternal.mProcLock) {
992                 mInternal.mOomAdjuster.mCachedAppOptimizer.compactAppSome(app, true);
993             }
994             pw.println("Finished some compaction for " + app.mPid);
995         } else {
996             getErrPrintWriter().println("Error: unknown compact command '" + op + "'");
997             return -1;
998         }
999 
1000         return 0;
1001     }
1002 
1003     int runDumpHeap(PrintWriter pw) throws RemoteException {
1004         final PrintWriter err = getErrPrintWriter();
1005         boolean managed = true;
1006         boolean mallocInfo = false;
1007         int userId = UserHandle.USER_CURRENT;
1008         boolean runGc = false;
1009 
1010         String opt;
1011         while ((opt=getNextOption()) != null) {
1012             if (opt.equals("--user")) {
1013                 userId = UserHandle.parseUserArg(getNextArgRequired());
1014                 if (userId == UserHandle.USER_ALL) {
1015                     err.println("Error: Can't dump heap with user 'all'");
1016                     return -1;
1017                 }
1018             } else if (opt.equals("-n")) {
1019                 managed = false;
1020             } else if (opt.equals("-g")) {
1021                 runGc = true;
1022             } else if (opt.equals("-m")) {
1023                 managed = false;
1024                 mallocInfo = true;
1025             } else {
1026                 err.println("Error: Unknown option: " + opt);
1027                 return -1;
1028             }
1029         }
1030         String process = getNextArgRequired();
1031         String heapFile = getNextArg();
1032         if (heapFile == null) {
1033             LocalDateTime localDateTime = LocalDateTime.now(Clock.systemDefaultZone());
1034             String logNameTimeString = LOG_NAME_TIME_FORMATTER.format(localDateTime);
1035             heapFile = "/data/local/tmp/heapdump-" + logNameTimeString + ".prof";
1036         }
1037 
1038         // Writes an error message to stderr on failure
1039         ParcelFileDescriptor fd = openFileForSystem(heapFile, "w");
1040         if (fd == null) {
1041             return -1;
1042         }
1043 
1044         pw.println("File: " + heapFile);
1045         pw.flush();
1046 
1047         final CountDownLatch latch = new CountDownLatch(1);
1048 
1049         final RemoteCallback finishCallback = new RemoteCallback(new OnResultListener() {
1050             @Override
1051             public void onResult(Bundle result) {
1052                 latch.countDown();
1053             }
1054         }, null);
1055 
1056         if (!mInterface.dumpHeap(process, userId, managed, mallocInfo, runGc, heapFile, fd,
1057                 finishCallback)) {
1058             err.println("HEAP DUMP FAILED on process " + process);
1059             return -1;
1060         }
1061         pw.println("Waiting for dump to finish...");
1062         pw.flush();
1063         try {
1064             latch.await();
1065         } catch (InterruptedException e) {
1066             err.println("Caught InterruptedException");
1067         }
1068 
1069         return 0;
1070     }
1071 
1072     int runSetDebugApp(PrintWriter pw) throws RemoteException {
1073         boolean wait = false;
1074         boolean persistent = false;
1075 
1076         String opt;
1077         while ((opt=getNextOption()) != null) {
1078             if (opt.equals("-w")) {
1079                 wait = true;
1080             } else if (opt.equals("--persistent")) {
1081                 persistent = true;
1082             } else {
1083                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1084                 return -1;
1085             }
1086         }
1087 
1088         String pkg = getNextArgRequired();
1089         mInterface.setDebugApp(pkg, wait, persistent);
1090         return 0;
1091     }
1092 
1093     int runSetAgentApp(PrintWriter pw) throws RemoteException {
1094         String pkg = getNextArgRequired();
1095         String agent = getNextArg();
1096         mInterface.setAgentApp(pkg, agent);
1097         return 0;
1098     }
1099 
1100     int runClearDebugApp(PrintWriter pw) throws RemoteException {
1101         mInterface.setDebugApp(null, false, true);
1102         return 0;
1103     }
1104 
1105     int runSetWatchHeap(PrintWriter pw) throws RemoteException {
1106         String proc = getNextArgRequired();
1107         String limit = getNextArgRequired();
1108         mInterface.setDumpHeapDebugLimit(proc, 0, Long.parseLong(limit), null);
1109         return 0;
1110     }
1111 
1112     int runClearWatchHeap(PrintWriter pw) throws RemoteException {
1113         String proc = getNextArgRequired();
1114         mInterface.setDumpHeapDebugLimit(proc, 0, -1, null);
1115         return 0;
1116     }
1117 
1118     int runClearExitInfo(PrintWriter pw) throws RemoteException {
1119         mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
1120                 "runClearExitInfo()");
1121         String opt;
1122         int userId = UserHandle.USER_CURRENT;
1123         String packageName = null;
1124         while ((opt = getNextOption()) != null) {
1125             if (opt.equals("--user")) {
1126                 userId = UserHandle.parseUserArg(getNextArgRequired());
1127             } else {
1128                 packageName = opt;
1129             }
1130         }
1131         if (userId == UserHandle.USER_CURRENT) {
1132             UserInfo user = mInterface.getCurrentUser();
1133             if (user == null) {
1134                 return -1;
1135             }
1136             userId = user.id;
1137         }
1138         mInternal.mProcessList.mAppExitInfoTracker.clearHistoryProcessExitInfo(packageName, userId);
1139         return 0;
1140     }
1141 
1142     int runBugReport(PrintWriter pw) throws RemoteException {
1143         String opt;
1144         boolean fullBugreport = true;
1145         while ((opt=getNextOption()) != null) {
1146             if (opt.equals("--progress")) {
1147                 fullBugreport = false;
1148                 mInterface.requestInteractiveBugReport();
1149             } else if (opt.equals("--telephony")) {
1150                 fullBugreport = false;
1151                 // no title and description specified
1152                 mInterface.requestTelephonyBugReport("" /* no title */, "" /* no descriptions */);
1153             } else {
1154                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1155                 return -1;
1156             }
1157         }
1158         if (fullBugreport) {
1159             mInterface.requestFullBugReport();
1160         }
1161         pw.println("Your lovely bug report is being created; please be patient.");
1162         return 0;
1163     }
1164 
1165     int runForceStop(PrintWriter pw) throws RemoteException {
1166         int userId = UserHandle.USER_ALL;
1167 
1168         String opt;
1169         while ((opt = getNextOption()) != null) {
1170             if (opt.equals("--user")) {
1171                 userId = UserHandle.parseUserArg(getNextArgRequired());
1172             } else {
1173                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1174                 return -1;
1175             }
1176         }
1177         mInterface.forceStopPackage(getNextArgRequired(), userId);
1178         return 0;
1179     }
1180 
1181     int runStopApp(PrintWriter pw) throws RemoteException {
1182         int userId = UserHandle.USER_SYSTEM;
1183 
1184         String opt;
1185         while ((opt = getNextOption()) != null) {
1186             if (opt.equals("--user")) {
1187                 userId = UserHandle.parseUserArg(getNextArgRequired());
1188             } else {
1189                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1190                 return -1;
1191             }
1192         }
1193         mInterface.stopAppForUser(getNextArgRequired(), userId);
1194         return 0;
1195     }
1196 
1197     int runClearRecentApps(PrintWriter pw) throws RemoteException {
1198         mTaskInterface.removeAllVisibleRecentTasks();
1199         return 0;
1200     }
1201 
1202     int runFgsNotificationRateLimit(PrintWriter pw) throws RemoteException {
1203         final String toggleValue = getNextArgRequired();
1204         final boolean enable;
1205         switch (toggleValue) {
1206             case "enable":
1207                 enable = true;
1208                 break;
1209             case "disable":
1210                 enable = false;
1211                 break;
1212             default:
1213                 throw new IllegalArgumentException(
1214                         "Argument must be either 'enable' or 'disable'");
1215         }
1216         mInterface.enableFgsNotificationRateLimit(enable);
1217         return 0;
1218     }
1219 
1220     int runCrash(PrintWriter pw) throws RemoteException {
1221         int userId = UserHandle.USER_ALL;
1222 
1223         String opt;
1224         while ((opt=getNextOption()) != null) {
1225             if (opt.equals("--user")) {
1226                 userId = UserHandle.parseUserArg(getNextArgRequired());
1227             } else {
1228                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1229                 return -1;
1230             }
1231         }
1232 
1233         int pid = -1;
1234         String packageName = null;
1235         final String arg = getNextArgRequired();
1236         // The argument is either a pid or a package name
1237         try {
1238             pid = Integer.parseInt(arg);
1239         } catch (NumberFormatException e) {
1240             packageName = arg;
1241         }
1242 
1243         int[] userIds = (userId == UserHandle.USER_ALL) ? mInternal.mUserController.getUserIds()
1244                 : new int[]{userId};
1245         for (int id : userIds) {
1246             if (mInternal.mUserController.hasUserRestriction(
1247                     UserManager.DISALLOW_DEBUGGING_FEATURES, id)) {
1248                 getOutPrintWriter().println(
1249                         "Shell does not have permission to crash packages for user " + id);
1250                 continue;
1251             }
1252             mInterface.crashApplicationWithType(-1, pid, packageName, id, "shell-induced crash",
1253                     false, CrashedByAdbException.TYPE_ID);
1254         }
1255         return 0;
1256     }
1257 
1258     int runKill(PrintWriter pw) throws RemoteException {
1259         int userId = UserHandle.USER_ALL;
1260 
1261         String opt;
1262         while ((opt=getNextOption()) != null) {
1263             if (opt.equals("--user")) {
1264                 userId = UserHandle.parseUserArg(getNextArgRequired());
1265             } else {
1266                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1267                 return -1;
1268             }
1269         }
1270         mInterface.killBackgroundProcesses(getNextArgRequired(), userId);
1271         return 0;
1272     }
1273 
1274     int runKillAll(PrintWriter pw) throws RemoteException {
1275         mInterface.killAllBackgroundProcesses();
1276         return 0;
1277     }
1278 
1279     int runMakeIdle(PrintWriter pw) throws RemoteException {
1280         int userId = UserHandle.USER_ALL;
1281 
1282         String opt;
1283         while ((opt = getNextOption()) != null) {
1284             if (opt.equals("--user")) {
1285                 userId = UserHandle.parseUserArg(getNextArgRequired());
1286             } else {
1287                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1288                 return -1;
1289             }
1290         }
1291         mInterface.makePackageIdle(getNextArgRequired(), userId);
1292         return 0;
1293     }
1294 
1295     static final class MyActivityController extends IActivityController.Stub {
1296         final IActivityManager mInterface;
1297         final PrintWriter mPw;
1298         final InputStream mInput;
1299         final String mGdbPort;
1300         final boolean mMonkey;
1301 
1302         static final int STATE_NORMAL = 0;
1303         static final int STATE_CRASHED = 1;
1304         static final int STATE_EARLY_ANR = 2;
1305         static final int STATE_ANR = 3;
1306 
1307         int mState;
1308 
1309         static final int RESULT_DEFAULT = 0;
1310 
1311         static final int RESULT_CRASH_DIALOG = 0;
1312         static final int RESULT_CRASH_KILL = 1;
1313 
1314         static final int RESULT_EARLY_ANR_CONTINUE = 0;
1315         static final int RESULT_EARLY_ANR_KILL = 1;
1316 
1317         static final int RESULT_ANR_DIALOG = 0;
1318         static final int RESULT_ANR_KILL = 1;
1319         static final int RESULT_ANR_WAIT = 2;
1320 
1321         int mResult;
1322 
1323         Process mGdbProcess;
1324         Thread mGdbThread;
1325         boolean mGotGdbPrint;
1326 
1327         MyActivityController(IActivityManager iam, PrintWriter pw, InputStream input,
1328                 String gdbPort, boolean monkey) {
1329             mInterface = iam;
1330             mPw = pw;
1331             mInput = input;
1332             mGdbPort = gdbPort;
1333             mMonkey = monkey;
1334         }
1335 
1336         @Override
1337         public boolean activityResuming(String pkg) {
1338             synchronized (this) {
1339                 mPw.println("** Activity resuming: " + pkg);
1340                 mPw.flush();
1341             }
1342             return true;
1343         }
1344 
1345         @Override
1346         public boolean activityStarting(Intent intent, String pkg) {
1347             synchronized (this) {
1348                 mPw.println("** Activity starting: " + pkg);
1349                 mPw.flush();
1350             }
1351             return true;
1352         }
1353 
1354         @Override
1355         public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
1356                 long timeMillis, String stackTrace) {
1357             synchronized (this) {
1358                 mPw.println("** ERROR: PROCESS CRASHED");
1359                 mPw.println("processName: " + processName);
1360                 mPw.println("processPid: " + pid);
1361                 mPw.println("shortMsg: " + shortMsg);
1362                 mPw.println("longMsg: " + longMsg);
1363                 mPw.println("timeMillis: " + timeMillis);
1364                 mPw.println("stack:");
1365                 mPw.print(stackTrace);
1366                 mPw.println("#");
1367                 mPw.flush();
1368                 int result = waitControllerLocked(pid, STATE_CRASHED);
1369                 return result == RESULT_CRASH_KILL ? false : true;
1370             }
1371         }
1372 
1373         @Override
1374         public int appEarlyNotResponding(String processName, int pid, String annotation) {
1375             synchronized (this) {
1376                 mPw.println("** ERROR: EARLY PROCESS NOT RESPONDING");
1377                 mPw.println("processName: " + processName);
1378                 mPw.println("processPid: " + pid);
1379                 mPw.println("annotation: " + annotation);
1380                 mPw.flush();
1381                 int result = waitControllerLocked(pid, STATE_EARLY_ANR);
1382                 if (result == RESULT_EARLY_ANR_KILL) return -1;
1383                 return 0;
1384             }
1385         }
1386 
1387         @Override
1388         public int appNotResponding(String processName, int pid, String processStats) {
1389             synchronized (this) {
1390                 mPw.println("** ERROR: PROCESS NOT RESPONDING");
1391                 mPw.println("processName: " + processName);
1392                 mPw.println("processPid: " + pid);
1393                 mPw.println("processStats:");
1394                 mPw.print(processStats);
1395                 mPw.println("#");
1396                 mPw.flush();
1397                 int result = waitControllerLocked(pid, STATE_ANR);
1398                 if (result == RESULT_ANR_KILL) return -1;
1399                 if (result == RESULT_ANR_WAIT) return 1;
1400                 return 0;
1401             }
1402         }
1403 
1404         @Override
1405         public int systemNotResponding(String message) {
1406             synchronized (this) {
1407                 mPw.println("** ERROR: PROCESS NOT RESPONDING");
1408                 mPw.println("message: " + message);
1409                 mPw.println("#");
1410                 mPw.println("Allowing system to die.");
1411                 mPw.flush();
1412                 return -1;
1413             }
1414         }
1415 
1416         void killGdbLocked() {
1417             mGotGdbPrint = false;
1418             if (mGdbProcess != null) {
1419                 mPw.println("Stopping gdbserver");
1420                 mPw.flush();
1421                 mGdbProcess.destroy();
1422                 mGdbProcess = null;
1423             }
1424             if (mGdbThread != null) {
1425                 mGdbThread.interrupt();
1426                 mGdbThread = null;
1427             }
1428         }
1429 
1430         int waitControllerLocked(int pid, int state) {
1431             if (mGdbPort != null) {
1432                 killGdbLocked();
1433 
1434                 try {
1435                     mPw.println("Starting gdbserver on port " + mGdbPort);
1436                     mPw.println("Do the following:");
1437                     mPw.println("  adb forward tcp:" + mGdbPort + " tcp:" + mGdbPort);
1438                     mPw.println("  gdbclient app_process :" + mGdbPort);
1439                     mPw.flush();
1440 
1441                     mGdbProcess = Runtime.getRuntime().exec(new String[] {
1442                             "gdbserver", ":" + mGdbPort, "--attach", Integer.toString(pid)
1443                     });
1444                     final InputStreamReader converter = new InputStreamReader(
1445                             mGdbProcess.getInputStream());
1446                     mGdbThread = new Thread() {
1447                         @Override
1448                         public void run() {
1449                             BufferedReader in = new BufferedReader(converter);
1450                             String line;
1451                             int count = 0;
1452                             while (true) {
1453                                 synchronized (MyActivityController.this) {
1454                                     if (mGdbThread == null) {
1455                                         return;
1456                                     }
1457                                     if (count == 2) {
1458                                         mGotGdbPrint = true;
1459                                         MyActivityController.this.notifyAll();
1460                                     }
1461                                 }
1462                                 try {
1463                                     line = in.readLine();
1464                                     if (line == null) {
1465                                         return;
1466                                     }
1467                                     mPw.println("GDB: " + line);
1468                                     mPw.flush();
1469                                     count++;
1470                                 } catch (IOException e) {
1471                                     return;
1472                                 }
1473                             }
1474                         }
1475                     };
1476                     mGdbThread.start();
1477 
1478                     // Stupid waiting for .5s.  Doesn't matter if we end early.
1479                     try {
1480                         this.wait(500);
1481                     } catch (InterruptedException e) {
1482                     }
1483 
1484                 } catch (IOException e) {
1485                     mPw.println("Failure starting gdbserver: " + e);
1486                     mPw.flush();
1487                     killGdbLocked();
1488                 }
1489             }
1490             mState = state;
1491             mPw.println("");
1492             printMessageForState();
1493             mPw.flush();
1494 
1495             while (mState != STATE_NORMAL) {
1496                 try {
1497                     wait();
1498                 } catch (InterruptedException e) {
1499                 }
1500             }
1501 
1502             killGdbLocked();
1503 
1504             return mResult;
1505         }
1506 
1507         void resumeController(int result) {
1508             synchronized (this) {
1509                 mState = STATE_NORMAL;
1510                 mResult = result;
1511                 notifyAll();
1512             }
1513         }
1514 
1515         void printMessageForState() {
1516             switch (mState) {
1517                 case STATE_NORMAL:
1518                     mPw.println("Monitoring activity manager...  available commands:");
1519                     break;
1520                 case STATE_CRASHED:
1521                     mPw.println("Waiting after crash...  available commands:");
1522                     mPw.println("(c)ontinue: show crash dialog");
1523                     mPw.println("(k)ill: immediately kill app");
1524                     break;
1525                 case STATE_EARLY_ANR:
1526                     mPw.println("Waiting after early ANR...  available commands:");
1527                     mPw.println("(c)ontinue: standard ANR processing");
1528                     mPw.println("(k)ill: immediately kill app");
1529                     break;
1530                 case STATE_ANR:
1531                     mPw.println("Waiting after ANR...  available commands:");
1532                     mPw.println("(c)ontinue: show ANR dialog");
1533                     mPw.println("(k)ill: immediately kill app");
1534                     mPw.println("(w)ait: wait some more");
1535                     break;
1536             }
1537             mPw.println("(q)uit: finish monitoring");
1538         }
1539 
1540         void run() throws RemoteException {
1541             try {
1542                 printMessageForState();
1543                 mPw.flush();
1544 
1545                 mInterface.setActivityController(this, mMonkey);
1546                 mState = STATE_NORMAL;
1547 
1548                 InputStreamReader converter = new InputStreamReader(mInput);
1549                 BufferedReader in = new BufferedReader(converter);
1550                 String line;
1551 
1552                 while ((line = in.readLine()) != null) {
1553                     boolean addNewline = true;
1554                     if (line.length() <= 0) {
1555                         addNewline = false;
1556                     } else if ("q".equals(line) || "quit".equals(line)) {
1557                         resumeController(RESULT_DEFAULT);
1558                         break;
1559                     } else if (mState == STATE_CRASHED) {
1560                         if ("c".equals(line) || "continue".equals(line)) {
1561                             resumeController(RESULT_CRASH_DIALOG);
1562                         } else if ("k".equals(line) || "kill".equals(line)) {
1563                             resumeController(RESULT_CRASH_KILL);
1564                         } else {
1565                             mPw.println("Invalid command: " + line);
1566                         }
1567                     } else if (mState == STATE_ANR) {
1568                         if ("c".equals(line) || "continue".equals(line)) {
1569                             resumeController(RESULT_ANR_DIALOG);
1570                         } else if ("k".equals(line) || "kill".equals(line)) {
1571                             resumeController(RESULT_ANR_KILL);
1572                         } else if ("w".equals(line) || "wait".equals(line)) {
1573                             resumeController(RESULT_ANR_WAIT);
1574                         } else {
1575                             mPw.println("Invalid command: " + line);
1576                         }
1577                     } else if (mState == STATE_EARLY_ANR) {
1578                         if ("c".equals(line) || "continue".equals(line)) {
1579                             resumeController(RESULT_EARLY_ANR_CONTINUE);
1580                         } else if ("k".equals(line) || "kill".equals(line)) {
1581                             resumeController(RESULT_EARLY_ANR_KILL);
1582                         } else {
1583                             mPw.println("Invalid command: " + line);
1584                         }
1585                     } else {
1586                         mPw.println("Invalid command: " + line);
1587                     }
1588 
1589                     synchronized (this) {
1590                         if (addNewline) {
1591                             mPw.println("");
1592                         }
1593                         printMessageForState();
1594                         mPw.flush();
1595                     }
1596                 }
1597 
1598             } catch (IOException e) {
1599                 e.printStackTrace(mPw);
1600                 mPw.flush();
1601             } finally {
1602                 mInterface.setActivityController(null, mMonkey);
1603             }
1604         }
1605     }
1606 
1607     int runMonitor(PrintWriter pw) throws RemoteException {
1608         String opt;
1609         String gdbPort = null;
1610         boolean monkey = false;
1611         while ((opt=getNextOption()) != null) {
1612             if (opt.equals("--gdb")) {
1613                 gdbPort = getNextArgRequired();
1614             } else if (opt.equals("-m")) {
1615                 monkey = true;
1616             } else {
1617                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1618                 return -1;
1619             }
1620         }
1621 
1622         MyActivityController controller = new MyActivityController(mInterface, pw,
1623                 getRawInputStream(), gdbPort, monkey);
1624         controller.run();
1625         return 0;
1626     }
1627 
1628     static final class MyUidObserver extends IUidObserver.Stub
1629             implements ActivityManagerService.OomAdjObserver {
1630         final IActivityManager mInterface;
1631         final ActivityManagerService mInternal;
1632         final PrintWriter mPw;
1633         final InputStream mInput;
1634         final int mUid;
1635 
1636         static final int STATE_NORMAL = 0;
1637 
1638         int mState;
1639 
1640         MyUidObserver(ActivityManagerService service, PrintWriter pw, InputStream input, int uid) {
1641             mInterface = service;
1642             mInternal = service;
1643             mPw = pw;
1644             mInput = input;
1645             mUid = uid;
1646         }
1647 
1648         @Override
1649         public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability)
1650                 throws RemoteException {
1651             synchronized (this) {
1652                 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
1653                 try {
1654                     mPw.print(uid);
1655                     mPw.print(" procstate ");
1656                     mPw.print(ProcessList.makeProcStateString(procState));
1657                     mPw.print(" seq ");
1658                     mPw.print(procStateSeq);
1659                     mPw.print(" capability ");
1660                     mPw.println(capability);
1661                     mPw.flush();
1662                 } finally {
1663                     StrictMode.setThreadPolicy(oldPolicy);
1664                 }
1665             }
1666         }
1667 
1668         @Override
1669         public void onUidGone(int uid, boolean disabled) throws RemoteException {
1670             synchronized (this) {
1671                 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
1672                 try {
1673                     mPw.print(uid);
1674                     mPw.print(" gone");
1675                     if (disabled) {
1676                         mPw.print(" disabled");
1677                     }
1678                     mPw.println();
1679                     mPw.flush();
1680                 } finally {
1681                     StrictMode.setThreadPolicy(oldPolicy);
1682                 }
1683             }
1684         }
1685 
1686         @Override
1687         public void onUidActive(int uid) throws RemoteException {
1688             synchronized (this) {
1689                 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
1690                 try {
1691                     mPw.print(uid);
1692                     mPw.println(" active");
1693                     mPw.flush();
1694                 } finally {
1695                     StrictMode.setThreadPolicy(oldPolicy);
1696                 }
1697             }
1698         }
1699 
1700         @Override
1701         public void onUidIdle(int uid, boolean disabled) throws RemoteException {
1702             synchronized (this) {
1703                 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
1704                 try {
1705                     mPw.print(uid);
1706                     mPw.print(" idle");
1707                     if (disabled) {
1708                         mPw.print(" disabled");
1709                     }
1710                     mPw.println();
1711                     mPw.flush();
1712                 } finally {
1713                     StrictMode.setThreadPolicy(oldPolicy);
1714                 }
1715             }
1716         }
1717 
1718         @Override
1719         public void onUidCachedChanged(int uid, boolean cached) throws RemoteException {
1720             synchronized (this) {
1721                 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
1722                 try {
1723                     mPw.print(uid);
1724                     mPw.println(cached ? " cached" : " uncached");
1725                     mPw.flush();
1726                 } finally {
1727                     StrictMode.setThreadPolicy(oldPolicy);
1728                 }
1729             }
1730         }
1731 
1732         @Override
1733         public void onUidProcAdjChanged(int uid) throws RemoteException {
1734         }
1735 
1736         @Override
1737         public void onOomAdjMessage(String msg) {
1738             synchronized (this) {
1739                 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
1740                 try {
1741                     mPw.print("# ");
1742                     mPw.println(msg);
1743                     mPw.flush();
1744                 } finally {
1745                     StrictMode.setThreadPolicy(oldPolicy);
1746                 }
1747             }
1748         }
1749 
1750         void printMessageForState() {
1751             switch (mState) {
1752                 case STATE_NORMAL:
1753                     mPw.println("Watching uid states...  available commands:");
1754                     break;
1755             }
1756             mPw.println("(q)uit: finish watching");
1757         }
1758 
1759         void run() throws RemoteException {
1760             try {
1761                 printMessageForState();
1762                 mPw.flush();
1763 
1764                 mInterface.registerUidObserver(this, ActivityManager.UID_OBSERVER_ACTIVE
1765                         | ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_PROCSTATE
1766                         | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_CACHED,
1767                         ActivityManager.PROCESS_STATE_UNKNOWN, null);
1768                 if (mUid >= 0) {
1769                     mInternal.setOomAdjObserver(mUid, this);
1770                 }
1771                 mState = STATE_NORMAL;
1772 
1773                 InputStreamReader converter = new InputStreamReader(mInput);
1774                 BufferedReader in = new BufferedReader(converter);
1775                 String line;
1776 
1777                 while ((line = in.readLine()) != null) {
1778                     boolean addNewline = true;
1779                     if (line.length() <= 0) {
1780                         addNewline = false;
1781                     } else if ("q".equals(line) || "quit".equals(line)) {
1782                         break;
1783                     } else {
1784                         mPw.println("Invalid command: " + line);
1785                     }
1786 
1787                     synchronized (this) {
1788                         if (addNewline) {
1789                             mPw.println("");
1790                         }
1791                         printMessageForState();
1792                         mPw.flush();
1793                     }
1794                 }
1795 
1796             } catch (IOException e) {
1797                 e.printStackTrace(mPw);
1798                 mPw.flush();
1799             } finally {
1800                 if (mUid >= 0) {
1801                     mInternal.clearOomAdjObserver();
1802                 }
1803                 mInterface.unregisterUidObserver(this);
1804             }
1805         }
1806     }
1807 
1808     int runWatchUids(PrintWriter pw) throws RemoteException {
1809         String opt;
1810         int uid = -1;
1811         while ((opt=getNextOption()) != null) {
1812             if (opt.equals("--oom")) {
1813                 uid = Integer.parseInt(getNextArgRequired());
1814             } else {
1815                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1816                 return -1;
1817 
1818             }
1819         }
1820 
1821         MyUidObserver controller = new MyUidObserver(mInternal, pw, getRawInputStream(), uid);
1822         controller.run();
1823         return 0;
1824     }
1825 
1826     int runHang(PrintWriter pw) throws RemoteException {
1827         String opt;
1828         boolean allowRestart = false;
1829         while ((opt=getNextOption()) != null) {
1830             if (opt.equals("--allow-restart")) {
1831                 allowRestart = true;
1832             } else {
1833                 getErrPrintWriter().println("Error: Unknown option: " + opt);
1834                 return -1;
1835             }
1836         }
1837 
1838         pw.println("Hanging the system...");
1839         pw.flush();
1840         try {
1841             mInterface.hang(getShellCallback().getShellCallbackBinder(), allowRestart);
1842         } catch (NullPointerException e) {
1843             pw.println("Hanging failed, since caller " + Binder.getCallingPid() +
1844                     " did not provide a ShellCallback!");
1845             pw.flush();
1846             return 1;
1847         }
1848         return 0;
1849     }
1850 
1851     int runRestart(PrintWriter pw) throws RemoteException {
1852         String opt;
1853         while ((opt=getNextOption()) != null) {
1854             getErrPrintWriter().println("Error: Unknown option: " + opt);
1855             return -1;
1856         }
1857 
1858         pw.println("Restart the system...");
1859         pw.flush();
1860         mInterface.restart();
1861         return 0;
1862     }
1863 
1864     int runIdleMaintenance(PrintWriter pw) throws RemoteException {
1865         String opt;
1866         while ((opt=getNextOption()) != null) {
1867             getErrPrintWriter().println("Error: Unknown option: " + opt);
1868             return -1;
1869         }
1870 
1871         pw.println("Performing idle maintenance...");
1872         mInterface.sendIdleJobTrigger();
1873         return 0;
1874     }
1875 
1876     int runScreenCompat(PrintWriter pw) throws RemoteException {
1877         String mode = getNextArgRequired();
1878         boolean enabled;
1879         if ("on".equals(mode)) {
1880             enabled = true;
1881         } else if ("off".equals(mode)) {
1882             enabled = false;
1883         } else {
1884             getErrPrintWriter().println("Error: enabled mode must be 'on' or 'off' at " + mode);
1885             return -1;
1886         }
1887 
1888         String packageName = getNextArgRequired();
1889         do {
1890             try {
1891                 mInterface.setPackageScreenCompatMode(packageName, enabled
1892                         ? ActivityManager.COMPAT_MODE_ENABLED
1893                         : ActivityManager.COMPAT_MODE_DISABLED);
1894             } catch (RemoteException e) {
1895             }
1896             packageName = getNextArg();
1897         } while (packageName != null);
1898         return 0;
1899     }
1900 
1901     int runPackageImportance(PrintWriter pw) throws RemoteException {
1902         String packageName = getNextArgRequired();
1903         int procState = mInterface.getPackageProcessState(packageName, "com.android.shell");
1904         pw.println(ActivityManager.RunningAppProcessInfo.procStateToImportance(procState));
1905         return 0;
1906     }
1907 
1908     int runToUri(PrintWriter pw, int flags) throws RemoteException {
1909         Intent intent;
1910         try {
1911             intent = makeIntent(UserHandle.USER_CURRENT);
1912         } catch (URISyntaxException e) {
1913             throw new RuntimeException(e.getMessage(), e);
1914         }
1915         pw.println(intent.toUri(flags));
1916         return 0;
1917     }
1918 
1919     private boolean switchUserAndWaitForComplete(int userId) throws RemoteException {
1920         UserInfo currentUser = mInterface.getCurrentUser();
1921         if (currentUser != null && userId == currentUser.id) {
1922             // Already switched to the correct user, exit early.
1923             return true;
1924         }
1925 
1926         // Register switch observer.
1927         final CountDownLatch switchLatch = new CountDownLatch(1);
1928         mInterface.registerUserSwitchObserver(
1929                 new UserSwitchObserver() {
1930                     @Override
1931                     public void onUserSwitchComplete(int newUserId) {
1932                         if (userId == newUserId) {
1933                             switchLatch.countDown();
1934                         }
1935                     }
1936                 }, ActivityManagerShellCommand.class.getName());
1937 
1938         // Switch.
1939         boolean switched = mInterface.switchUser(userId);
1940         if (!switched) {
1941             // Switching failed, don't wait for the user switch observer.
1942             return false;
1943         }
1944 
1945         // Wait.
1946         try {
1947             switched = switchLatch.await(USER_OPERATION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
1948         } catch (InterruptedException e) {
1949             getErrPrintWriter().println("Error: Thread interrupted unexpectedly.");
1950         }
1951 
1952         return switched;
1953     }
1954 
1955     int runSwitchUser(PrintWriter pw) throws RemoteException {
1956         UserManager userManager = mInternal.mContext.getSystemService(UserManager.class);
1957         final int userSwitchable = userManager.getUserSwitchability();
1958         if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
1959             getErrPrintWriter().println("Error: " + userSwitchable);
1960             return -1;
1961         }
1962         boolean wait = false;
1963         String opt;
1964         while ((opt = getNextOption()) != null) {
1965             if ("-w".equals(opt)) {
1966                 wait = true;
1967             } else {
1968                 getErrPrintWriter().println("Error: unknown option: " + opt);
1969                 return -1;
1970             }
1971         }
1972 
1973         int userId = Integer.parseInt(getNextArgRequired());
1974         boolean switched;
1975         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "shell_runSwitchUser");
1976         try {
1977             if (wait) {
1978                 switched = switchUserAndWaitForComplete(userId);
1979             } else {
1980                 switched = mInterface.switchUser(userId);
1981             }
1982             if (switched) {
1983                 return 0;
1984             } else {
1985                 pw.printf("Error: Failed to switch to user %d\n", userId);
1986                 return 1;
1987             }
1988         } finally {
1989             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1990         }
1991     }
1992 
1993     int runGetCurrentUser(PrintWriter pw) throws RemoteException {
1994         int userId = mInterface.getCurrentUserId();
1995         if (userId == UserHandle.USER_NULL) {
1996             throw new IllegalStateException("Current user not set");
1997         }
1998         pw.println(userId);
1999         return 0;
2000     }
2001 
2002     int runStartUser(PrintWriter pw) throws RemoteException {
2003         boolean wait = false;
2004         String opt;
2005         while ((opt = getNextOption()) != null) {
2006             if ("-w".equals(opt)) {
2007                 wait = true;
2008             } else {
2009                 getErrPrintWriter().println("Error: unknown option: " + opt);
2010                 return -1;
2011             }
2012         }
2013         int userId = Integer.parseInt(getNextArgRequired());
2014 
2015         final ProgressWaiter waiter = wait ? new ProgressWaiter() : null;
2016         boolean success = mInterface.startUserInBackgroundWithListener(userId, waiter);
2017         if (wait && success) {
2018             success = waiter.waitForFinish(USER_OPERATION_TIMEOUT_MS);
2019         }
2020 
2021         if (success) {
2022             pw.println("Success: user started");
2023         } else {
2024             getErrPrintWriter().println("Error: could not start user");
2025         }
2026         return 0;
2027     }
2028 
2029     int runUnlockUser(PrintWriter pw) throws RemoteException {
2030         int userId = Integer.parseInt(getNextArgRequired());
2031 
2032         /*
2033          * Originally this command required two more parameters: the hardware
2034          * authentication token and secret needed to unlock the user.  However,
2035          * unlockUser() no longer takes a token parameter at all, and there
2036          * isn't really any way for callers of this shell command to get the
2037          * secret if one is needed (i.e., when the user has an LSKF), given that
2038          * the secret must be a cryptographic key derived from the user's
2039          * synthetic password.  I.e. the secret is *not* the LSKF here, but
2040          * rather an intermediate value several steps down the chain.
2041          *
2042          * As such, the only supported use for this command is unlocking a user
2043          * who doesn't have an LSKF, with empty or unspecified token and secret.
2044          *
2045          * To preserve previous behavior, an exclamation mark ("!") is also
2046          * accepted for these values; it means the same as an empty string.
2047          */
2048         String token = getNextArg();
2049         if (!TextUtils.isEmpty(token) && !"!".equals(token)) {
2050             getErrPrintWriter().println("Error: token parameter not supported");
2051             return -1;
2052         }
2053         String secret = getNextArg();
2054         if (!TextUtils.isEmpty(secret) && !"!".equals(secret)) {
2055             getErrPrintWriter().println("Error: secret parameter not supported");
2056             return -1;
2057         }
2058 
2059         boolean success = mInterface.unlockUser(userId, null, null, null);
2060         if (success) {
2061             pw.println("Success: user unlocked");
2062         } else {
2063             // TODO(b/218389026): we can reach here even if the user's storage
2064             // was successfully unlocked.
2065             getErrPrintWriter().println("Error: could not unlock user");
2066         }
2067         return 0;
2068     }
2069 
2070     static final class StopUserCallback extends IStopUserCallback.Stub {
2071         private boolean mFinished = false;
2072 
2073         public synchronized void waitForFinish() {
2074             try {
2075                 while (!mFinished) wait();
2076             } catch (InterruptedException e) {
2077                 throw new IllegalStateException(e);
2078             }
2079         }
2080 
2081         @Override
2082         public synchronized void userStopped(int userId) {
2083             mFinished = true;
2084             notifyAll();
2085         }
2086 
2087         @Override
2088         public synchronized void userStopAborted(int userId) {
2089             mFinished = true;
2090             notifyAll();
2091         }
2092     }
2093 
2094     int runStopUser(PrintWriter pw) throws RemoteException {
2095         boolean wait = false;
2096         boolean force = false;
2097         String opt;
2098         while ((opt = getNextOption()) != null) {
2099             if ("-w".equals(opt)) {
2100                 wait = true;
2101             } else if ("-f".equals(opt)) {
2102                 force = true;
2103             } else {
2104                 getErrPrintWriter().println("Error: unknown option: " + opt);
2105                 return -1;
2106             }
2107         }
2108         int user = Integer.parseInt(getNextArgRequired());
2109         StopUserCallback callback = wait ? new StopUserCallback() : null;
2110 
2111         int res = mInterface.stopUser(user, force, callback);
2112         if (res != ActivityManager.USER_OP_SUCCESS) {
2113             String txt = "";
2114             switch (res) {
2115                 case ActivityManager.USER_OP_IS_CURRENT:
2116                     txt = " (Can't stop current user)";
2117                     break;
2118                 case ActivityManager.USER_OP_UNKNOWN_USER:
2119                     txt = " (Unknown user " + user + ")";
2120                     break;
2121                 case ActivityManager.USER_OP_ERROR_IS_SYSTEM:
2122                     txt = " (System user cannot be stopped)";
2123                     break;
2124                 case ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP:
2125                     txt = " (Can't stop user " + user
2126                             + " - one of its related users can't be stopped)";
2127                     break;
2128             }
2129             getErrPrintWriter().println("Switch failed: " + res + txt);
2130             return -1;
2131         } else if (callback != null) {
2132             callback.waitForFinish();
2133         }
2134         return 0;
2135     }
2136 
2137     int runIsUserStopped(PrintWriter pw) {
2138         int userId = UserHandle.parseUserArg(getNextArgRequired());
2139         boolean stopped = mInternal.isUserStopped(userId);
2140         pw.println(stopped);
2141         return 0;
2142     }
2143 
2144     int runGetStartedUserState(PrintWriter pw) throws RemoteException {
2145         mInternal.enforceCallingPermission(android.Manifest.permission.DUMP,
2146                 "runGetStartedUserState()");
2147         final int userId = Integer.parseInt(getNextArgRequired());
2148         try {
2149             pw.println(mInternal.getStartedUserState(userId));
2150         } catch (NullPointerException e) {
2151             pw.println("User is not started: " + userId);
2152         }
2153         return 0;
2154     }
2155 
2156     int runTrackAssociations(PrintWriter pw) {
2157         mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
2158                 "runTrackAssociations()");
2159         synchronized (mInternal) {
2160             if (!mInternal.mTrackingAssociations) {
2161                 mInternal.mTrackingAssociations = true;
2162                 pw.println("Association tracking started.");
2163             } else {
2164                 pw.println("Association tracking already enabled.");
2165             }
2166         }
2167         return 0;
2168     }
2169 
2170     int runUntrackAssociations(PrintWriter pw) {
2171         mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
2172                 "runUntrackAssociations()");
2173         synchronized (mInternal) {
2174             if (mInternal.mTrackingAssociations) {
2175                 mInternal.mTrackingAssociations = false;
2176                 mInternal.mAssociations.clear();
2177                 pw.println("Association tracking stopped.");
2178             } else {
2179                 pw.println("Association tracking not running.");
2180             }
2181         }
2182         return 0;
2183     }
2184 
2185     int getUidState(PrintWriter pw) throws RemoteException {
2186         mInternal.enforceCallingPermission(android.Manifest.permission.DUMP,
2187                 "getUidState()");
2188         int state = mInternal.getUidState(Integer.parseInt(getNextArgRequired()));
2189         pw.print(state);
2190         pw.print(" (");
2191         pw.printf(DebugUtils.valueToString(ActivityManager.class, "PROCESS_STATE_", state));
2192         pw.println(")");
2193         return 0;
2194     }
2195 
2196     private List<Configuration> getRecentConfigurations(int days) {
2197         IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
2198                 Context.USAGE_STATS_SERVICE));
2199         final long now = System.currentTimeMillis();
2200         final long nDaysAgo = now - (days * 24 * 60 * 60 * 1000);
2201         try {
2202             @SuppressWarnings("unchecked")
2203             ParceledListSlice<ConfigurationStats> configStatsSlice = usm.queryConfigurationStats(
2204                     UsageStatsManager.INTERVAL_BEST, nDaysAgo, now, "com.android.shell");
2205             if (configStatsSlice == null) {
2206                 return Collections.emptyList();
2207             }
2208 
2209             final ArrayMap<Configuration, Integer> recentConfigs = new ArrayMap<>();
2210             final List<ConfigurationStats> configStatsList = configStatsSlice.getList();
2211             final int configStatsListSize = configStatsList.size();
2212             for (int i = 0; i < configStatsListSize; i++) {
2213                 final ConfigurationStats stats = configStatsList.get(i);
2214                 final int indexOfKey = recentConfigs.indexOfKey(stats.getConfiguration());
2215                 if (indexOfKey < 0) {
2216                     recentConfigs.put(stats.getConfiguration(), stats.getActivationCount());
2217                 } else {
2218                     recentConfigs.setValueAt(indexOfKey,
2219                             recentConfigs.valueAt(indexOfKey) + stats.getActivationCount());
2220                 }
2221             }
2222 
2223             final Comparator<Configuration> comparator = new Comparator<Configuration>() {
2224                 @Override
2225                 public int compare(Configuration a, Configuration b) {
2226                     return recentConfigs.get(b).compareTo(recentConfigs.get(a));
2227                 }
2228             };
2229 
2230             ArrayList<Configuration> configs = new ArrayList<>(recentConfigs.size());
2231             configs.addAll(recentConfigs.keySet());
2232             Collections.sort(configs, comparator);
2233             return configs;
2234 
2235         } catch (RemoteException e) {
2236             return Collections.emptyList();
2237         }
2238     }
2239 
2240     /**
2241      * Adds all supported GL extensions for a provided EGLConfig to a set by creating an EGLContext
2242      * and EGLSurface and querying extensions.
2243      *
2244      * @param egl An EGL API object
2245      * @param display An EGLDisplay to create a context and surface with
2246      * @param config The EGLConfig to get the extensions for
2247      * @param surfaceSize eglCreatePbufferSurface generic parameters
2248      * @param contextAttribs eglCreateContext generic parameters
2249      * @param glExtensions A Set<String> to add GL extensions to
2250      */
2251     private static void addExtensionsForConfig(
2252             EGL10 egl,
2253             EGLDisplay display,
2254             EGLConfig config,
2255             int[] surfaceSize,
2256             int[] contextAttribs,
2257             Set<String> glExtensions) {
2258         // Create a context.
2259         EGLContext context =
2260                 egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, contextAttribs);
2261         // No-op if we can't create a context.
2262         if (context == EGL10.EGL_NO_CONTEXT) {
2263             return;
2264         }
2265 
2266         // Create a surface.
2267         EGLSurface surface = egl.eglCreatePbufferSurface(display, config, surfaceSize);
2268         if (surface == EGL10.EGL_NO_SURFACE) {
2269             egl.eglDestroyContext(display, context);
2270             return;
2271         }
2272 
2273         // Update the current surface and context.
2274         egl.eglMakeCurrent(display, surface, surface, context);
2275 
2276         // Get the list of extensions.
2277         String extensionList = GLES10.glGetString(GLES10.GL_EXTENSIONS);
2278         if (!TextUtils.isEmpty(extensionList)) {
2279             // The list of extensions comes from the driver separated by spaces.
2280             // Split them apart and add them into a Set for deduping purposes.
2281             for (String extension : extensionList.split(" ")) {
2282                 glExtensions.add(extension);
2283             }
2284         }
2285 
2286         // Tear down the context and surface for this config.
2287         egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
2288         egl.eglDestroySurface(display, surface);
2289         egl.eglDestroyContext(display, context);
2290     }
2291 
2292 
2293     Set<String> getGlExtensionsFromDriver() {
2294         Set<String> glExtensions = new HashSet<>();
2295 
2296         // Get the EGL implementation.
2297         EGL10 egl = (EGL10) EGLContext.getEGL();
2298         if (egl == null) {
2299             getErrPrintWriter().println("Warning: couldn't get EGL");
2300             return glExtensions;
2301         }
2302 
2303         // Get the default display and initialize it.
2304         EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
2305         int[] version = new int[2];
2306         egl.eglInitialize(display, version);
2307 
2308         // Call getConfigs() in order to find out how many there are.
2309         int[] numConfigs = new int[1];
2310         if (!egl.eglGetConfigs(display, null, 0, numConfigs)) {
2311             getErrPrintWriter().println("Warning: couldn't get EGL config count");
2312             return glExtensions;
2313         }
2314 
2315         // Allocate space for all configs and ask again.
2316         EGLConfig[] configs = new EGLConfig[numConfigs[0]];
2317         if (!egl.eglGetConfigs(display, configs, numConfigs[0], numConfigs)) {
2318             getErrPrintWriter().println("Warning: couldn't get EGL configs");
2319             return glExtensions;
2320         }
2321 
2322         // Allocate surface size parameters outside of the main loop to cut down
2323         // on GC thrashing.  1x1 is enough since we are only using it to get at
2324         // the list of extensions.
2325         int[] surfaceSize =
2326                 new int[] {
2327                         EGL10.EGL_WIDTH, 1,
2328                         EGL10.EGL_HEIGHT, 1,
2329                         EGL10.EGL_NONE
2330                 };
2331 
2332         // For when we need to create a GLES2.0 context.
2333         final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
2334         int[] gles2 = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
2335 
2336         // For getting return values from eglGetConfigAttrib
2337         int[] attrib = new int[1];
2338 
2339         for (int i = 0; i < numConfigs[0]; i++) {
2340             // Get caveat for this config in order to skip slow (i.e. software) configs.
2341             egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_CONFIG_CAVEAT, attrib);
2342             if (attrib[0] == EGL10.EGL_SLOW_CONFIG) {
2343                 continue;
2344             }
2345 
2346             // If the config does not support pbuffers we cannot do an eglMakeCurrent
2347             // on it in addExtensionsForConfig(), so skip it here. Attempting to make
2348             // it current with a pbuffer will result in an EGL_BAD_MATCH error
2349             egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_SURFACE_TYPE, attrib);
2350             if ((attrib[0] & EGL10.EGL_PBUFFER_BIT) == 0) {
2351                 continue;
2352             }
2353 
2354             final int EGL_OPENGL_ES_BIT = 0x0001;
2355             final int EGL_OPENGL_ES2_BIT = 0x0004;
2356             egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_RENDERABLE_TYPE, attrib);
2357             if ((attrib[0] & EGL_OPENGL_ES_BIT) != 0) {
2358                 addExtensionsForConfig(egl, display, configs[i], surfaceSize, null, glExtensions);
2359             }
2360             if ((attrib[0] & EGL_OPENGL_ES2_BIT) != 0) {
2361                 addExtensionsForConfig(egl, display, configs[i], surfaceSize, gles2, glExtensions);
2362             }
2363         }
2364 
2365         // Release all EGL resources.
2366         egl.eglTerminate(display);
2367 
2368         return glExtensions;
2369     }
2370 
2371     private void writeDeviceConfig(ProtoOutputStream protoOutputStream, long fieldId,
2372             PrintWriter pw, Configuration config, DisplayMetrics displayMetrics) {
2373         long token = -1;
2374         if (protoOutputStream != null) {
2375             token = protoOutputStream.start(fieldId);
2376             protoOutputStream.write(DeviceConfigurationProto.STABLE_SCREEN_WIDTH_PX,
2377                     displayMetrics.widthPixels);
2378             protoOutputStream.write(DeviceConfigurationProto.STABLE_SCREEN_HEIGHT_PX,
2379                     displayMetrics.heightPixels);
2380             protoOutputStream.write(DeviceConfigurationProto.STABLE_DENSITY_DPI,
2381                     DisplayMetrics.DENSITY_DEVICE_STABLE);
2382         }
2383         if (pw != null) {
2384             pw.print("stable-width-px: "); pw.println(displayMetrics.widthPixels);
2385             pw.print("stable-height-px: "); pw.println(displayMetrics.heightPixels);
2386             pw.print("stable-density-dpi: "); pw.println(DisplayMetrics.DENSITY_DEVICE_STABLE);
2387         }
2388 
2389         MemInfoReader memreader = new MemInfoReader();
2390         memreader.readMemInfo();
2391         KeyguardManager kgm = mInternal.mContext.getSystemService(KeyguardManager.class);
2392         if (protoOutputStream != null) {
2393             protoOutputStream.write(DeviceConfigurationProto.TOTAL_RAM, memreader.getTotalSize());
2394             protoOutputStream.write(DeviceConfigurationProto.LOW_RAM,
2395                     ActivityManager.isLowRamDeviceStatic());
2396             protoOutputStream.write(DeviceConfigurationProto.MAX_CORES,
2397                     Runtime.getRuntime().availableProcessors());
2398             protoOutputStream.write(DeviceConfigurationProto.HAS_SECURE_SCREEN_LOCK,
2399                     kgm.isDeviceSecure());
2400         }
2401         if (pw != null) {
2402             pw.print("total-ram: "); pw.println(memreader.getTotalSize());
2403             pw.print("low-ram: "); pw.println(ActivityManager.isLowRamDeviceStatic());
2404             pw.print("max-cores: "); pw.println(Runtime.getRuntime().availableProcessors());
2405             pw.print("has-secure-screen-lock: "); pw.println(kgm.isDeviceSecure());
2406         }
2407 
2408         ConfigurationInfo configInfo = null;
2409         try {
2410             configInfo = mTaskInterface.getDeviceConfigurationInfo();
2411         } catch (RemoteException e) {
2412             throw e.rethrowFromSystemServer();
2413         }
2414         if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) {
2415             if (protoOutputStream != null) {
2416                 protoOutputStream.write(DeviceConfigurationProto.OPENGL_VERSION,
2417                         configInfo.reqGlEsVersion);
2418             }
2419             if (pw != null) {
2420                 pw.print("opengl-version: 0x");
2421                 pw.println(Integer.toHexString(configInfo.reqGlEsVersion));
2422             }
2423         }
2424 
2425         Set<String> glExtensionsSet = getGlExtensionsFromDriver();
2426         String[] glExtensions = new String[glExtensionsSet.size()];
2427         glExtensions = glExtensionsSet.toArray(glExtensions);
2428         Arrays.sort(glExtensions);
2429         for (int i = 0; i < glExtensions.length; i++) {
2430             if (protoOutputStream != null) {
2431                 protoOutputStream.write(DeviceConfigurationProto.OPENGL_EXTENSIONS,
2432                         glExtensions[i]);
2433             }
2434             if (pw != null) {
2435                 pw.print("opengl-extensions: "); pw.println(glExtensions[i]);
2436             }
2437 
2438         }
2439 
2440         PackageManager pm = mInternal.mContext.getPackageManager();
2441         List<SharedLibraryInfo> slibs = pm.getSharedLibraries(0);
2442         Collections.sort(slibs, Comparator.comparing(SharedLibraryInfo::getName));
2443         for (int i = 0; i < slibs.size(); i++) {
2444             if (protoOutputStream != null) {
2445                 protoOutputStream.write(DeviceConfigurationProto.SHARED_LIBRARIES,
2446                         slibs.get(i).getName());
2447             }
2448             if (pw != null) {
2449                 pw.print("shared-libraries: "); pw.println(slibs.get(i).getName());
2450             }
2451         }
2452 
2453         FeatureInfo[] features = pm.getSystemAvailableFeatures();
2454         Arrays.sort(features, (o1, o2) -> {
2455             if (o1.name == o2.name) return 0;
2456             if (o1.name == null) return -1;
2457             if (o2.name == null) return 1;
2458             return o1.name.compareTo(o2.name);
2459         });
2460 
2461         for (int i = 0; i < features.length; i++) {
2462             if (features[i].name != null) {
2463                 if (protoOutputStream != null) {
2464                     protoOutputStream.write(DeviceConfigurationProto.FEATURES, features[i].name);
2465                 }
2466                 if (pw != null) {
2467                     pw.print("features: "); pw.println(features[i].name);
2468                 }
2469             }
2470         }
2471 
2472         if (protoOutputStream != null) {
2473             protoOutputStream.end(token);
2474         }
2475     }
2476 
2477     int runGetConfig(PrintWriter pw) throws RemoteException {
2478         int days = -1;
2479         int displayId = Display.DEFAULT_DISPLAY;
2480         boolean asProto = false;
2481         boolean inclDevice = false;
2482 
2483         String opt;
2484         while ((opt = getNextOption()) != null) {
2485             if (opt.equals("--days")) {
2486                 days = Integer.parseInt(getNextArgRequired());
2487                 if (days <= 0) {
2488                     throw new IllegalArgumentException("--days must be a positive integer");
2489                 }
2490             } else if (opt.equals("--proto")) {
2491                 asProto = true;
2492             } else if (opt.equals("--device")) {
2493                 inclDevice = true;
2494             } else if (opt.equals("--display")) {
2495                 displayId = Integer.parseInt(getNextArgRequired());
2496                 if (displayId < 0) {
2497                     throw new IllegalArgumentException("--display must be a non-negative integer");
2498                 }
2499             } else {
2500                 getErrPrintWriter().println("Error: Unknown option: " + opt);
2501                 return -1;
2502             }
2503         }
2504 
2505         Configuration config = mInterface.getConfiguration();
2506         if (config == null) {
2507             getErrPrintWriter().println("Activity manager has no configuration");
2508             return -1;
2509         }
2510 
2511         DisplayManager dm = mInternal.mContext.getSystemService(DisplayManager.class);
2512         Display display = dm.getDisplay(displayId);
2513 
2514         if (display == null) {
2515             getErrPrintWriter().println("Error: Display does not exist: " + displayId);
2516             return -1;
2517         }
2518 
2519         DisplayMetrics metrics = new DisplayMetrics();
2520         display.getMetrics(metrics);
2521 
2522         if (asProto) {
2523             final ProtoOutputStream proto = new ProtoOutputStream(getOutFileDescriptor());
2524             config.writeResConfigToProto(proto, GlobalConfigurationProto.RESOURCES, metrics);
2525             if (inclDevice) {
2526                 writeDeviceConfig(proto, GlobalConfigurationProto.DEVICE, null, config, metrics);
2527             }
2528             proto.flush();
2529         } else {
2530             pw.println("config: " + Configuration.resourceQualifierString(config, metrics));
2531             pw.println("abi: " + TextUtils.join(",", Build.SUPPORTED_ABIS));
2532             if (inclDevice) {
2533                 writeDeviceConfig(null, -1, pw, config, metrics);
2534             }
2535 
2536             if (days >= 0) {
2537                 final List<Configuration> recentConfigs = getRecentConfigurations(days);
2538                 final int recentConfigSize = recentConfigs.size();
2539                 if (recentConfigSize > 0) {
2540                     pw.println("recentConfigs:");
2541                     for (int i = 0; i < recentConfigSize; i++) {
2542                         pw.println("  config: " + Configuration.resourceQualifierString(
2543                                 recentConfigs.get(i)));
2544                     }
2545                 }
2546             }
2547 
2548         }
2549         return 0;
2550     }
2551 
2552     int runSuppressResizeConfigChanges(PrintWriter pw) throws RemoteException {
2553         boolean suppress = Boolean.valueOf(getNextArgRequired());
2554         mTaskInterface.suppressResizeConfigChanges(suppress);
2555         return 0;
2556     }
2557 
2558     int runSetInactive(PrintWriter pw) throws RemoteException {
2559         int userId = UserHandle.USER_CURRENT;
2560 
2561         String opt;
2562         while ((opt=getNextOption()) != null) {
2563             if (opt.equals("--user")) {
2564                 userId = UserHandle.parseUserArg(getNextArgRequired());
2565             } else {
2566                 getErrPrintWriter().println("Error: Unknown option: " + opt);
2567                 return -1;
2568             }
2569         }
2570         String packageName = getNextArgRequired();
2571         String value = getNextArgRequired();
2572 
2573         IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
2574                 Context.USAGE_STATS_SERVICE));
2575         usm.setAppInactive(packageName, Boolean.parseBoolean(value), userId);
2576         return 0;
2577     }
2578 
2579     private int bucketNameToBucketValue(String name) {
2580         String lower = name.toLowerCase();
2581         if (lower.startsWith("ac")) {
2582             return UsageStatsManager.STANDBY_BUCKET_ACTIVE;
2583         } else if (lower.startsWith("wo")) {
2584             return UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
2585         } else if (lower.startsWith("fr")) {
2586             return UsageStatsManager.STANDBY_BUCKET_FREQUENT;
2587         } else if (lower.startsWith("ra")) {
2588             return UsageStatsManager.STANDBY_BUCKET_RARE;
2589         } else if (lower.startsWith("re")) {
2590             return UsageStatsManager.STANDBY_BUCKET_RESTRICTED;
2591         } else if (lower.startsWith("ne")) {
2592             return UsageStatsManager.STANDBY_BUCKET_NEVER;
2593         } else {
2594             try {
2595                 int bucket = Integer.parseInt(lower);
2596                 return bucket;
2597             } catch (NumberFormatException nfe) {
2598                 getErrPrintWriter().println("Error: Unknown bucket: " + name);
2599             }
2600         }
2601         return -1;
2602     }
2603 
2604     int runSetStandbyBucket(PrintWriter pw) throws RemoteException {
2605         int userId = UserHandle.USER_CURRENT;
2606 
2607         String opt;
2608         while ((opt=getNextOption()) != null) {
2609             if (opt.equals("--user")) {
2610                 userId = UserHandle.parseUserArg(getNextArgRequired());
2611             } else {
2612                 getErrPrintWriter().println("Error: Unknown option: " + opt);
2613                 return -1;
2614             }
2615         }
2616         String packageName = getNextArgRequired();
2617         String value = getNextArgRequired();
2618         int bucket = bucketNameToBucketValue(value);
2619         if (bucket < 0) return -1;
2620         boolean multiple = peekNextArg() != null;
2621 
2622 
2623         IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
2624                 Context.USAGE_STATS_SERVICE));
2625         if (!multiple) {
2626             usm.setAppStandbyBucket(packageName, bucketNameToBucketValue(value), userId);
2627         } else {
2628             ArrayList<AppStandbyInfo> bucketInfoList = new ArrayList<>();
2629             bucketInfoList.add(new AppStandbyInfo(packageName, bucket));
2630             while ((packageName = getNextArg()) != null) {
2631                 value = getNextArgRequired();
2632                 bucket = bucketNameToBucketValue(value);
2633                 if (bucket < 0) continue;
2634                 bucketInfoList.add(new AppStandbyInfo(packageName, bucket));
2635             }
2636             ParceledListSlice<AppStandbyInfo> slice = new ParceledListSlice<>(bucketInfoList);
2637             usm.setAppStandbyBuckets(slice, userId);
2638         }
2639         return 0;
2640     }
2641 
2642     int runGetStandbyBucket(PrintWriter pw) throws RemoteException {
2643         int userId = UserHandle.USER_CURRENT;
2644 
2645         String opt;
2646         while ((opt=getNextOption()) != null) {
2647             if (opt.equals("--user")) {
2648                 userId = UserHandle.parseUserArg(getNextArgRequired());
2649             } else {
2650                 getErrPrintWriter().println("Error: Unknown option: " + opt);
2651                 return -1;
2652             }
2653         }
2654         String packageName = getNextArg();
2655 
2656         IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
2657                 Context.USAGE_STATS_SERVICE));
2658         if (packageName != null) {
2659             int bucket = usm.getAppStandbyBucket(packageName, null, userId);
2660             pw.println(bucket);
2661         } else {
2662             ParceledListSlice<AppStandbyInfo> buckets = usm.getAppStandbyBuckets(
2663                     SHELL_PACKAGE_NAME, userId);
2664             for (AppStandbyInfo bucketInfo : buckets.getList()) {
2665                 pw.print(bucketInfo.mPackageName); pw.print(": ");
2666                 pw.println(bucketInfo.mStandbyBucket);
2667             }
2668         }
2669         return 0;
2670     }
2671 
2672     int runGetInactive(PrintWriter pw) throws RemoteException {
2673         int userId = UserHandle.USER_CURRENT;
2674 
2675         String opt;
2676         while ((opt=getNextOption()) != null) {
2677             if (opt.equals("--user")) {
2678                 userId = UserHandle.parseUserArg(getNextArgRequired());
2679             } else {
2680                 getErrPrintWriter().println("Error: Unknown option: " + opt);
2681                 return -1;
2682             }
2683         }
2684         String packageName = getNextArgRequired();
2685 
2686         IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
2687                 Context.USAGE_STATS_SERVICE));
2688         boolean isIdle = usm.isAppInactive(packageName, userId, SHELL_PACKAGE_NAME);
2689         pw.println("Idle=" + isIdle);
2690         return 0;
2691     }
2692 
2693     int runSendTrimMemory(PrintWriter pw) throws RemoteException {
2694         int userId = UserHandle.USER_CURRENT;
2695         String opt;
2696         while ((opt = getNextOption()) != null) {
2697             if (opt.equals("--user")) {
2698                 userId = UserHandle.parseUserArg(getNextArgRequired());
2699                 if (userId == UserHandle.USER_ALL) {
2700                     getErrPrintWriter().println("Error: Can't use user 'all'");
2701                     return -1;
2702                 }
2703             } else {
2704                 getErrPrintWriter().println("Error: Unknown option: " + opt);
2705                 return -1;
2706             }
2707         }
2708 
2709         String proc = getNextArgRequired();
2710         String levelArg = getNextArgRequired();
2711         int level;
2712         switch (levelArg) {
2713             case "HIDDEN":
2714                 level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
2715                 break;
2716             case "RUNNING_MODERATE":
2717                 level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
2718                 break;
2719             case "BACKGROUND":
2720                 level = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
2721                 break;
2722             case "RUNNING_LOW":
2723                 level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
2724                 break;
2725             case "MODERATE":
2726                 level = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
2727                 break;
2728             case "RUNNING_CRITICAL":
2729                 level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
2730                 break;
2731             case "COMPLETE":
2732                 level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
2733                 break;
2734             default:
2735                 try {
2736                     level = Integer.parseInt(levelArg);
2737                 } catch (NumberFormatException e) {
2738                     getErrPrintWriter().println("Error: Unknown level option: " + levelArg);
2739                     return -1;
2740                 }
2741         }
2742         if (!mInterface.setProcessMemoryTrimLevel(proc, userId, level)) {
2743             getErrPrintWriter().println("Unknown error: failed to set trim level");
2744             return -1;
2745         }
2746         return 0;
2747     }
2748 
2749     int runDisplay(PrintWriter pw) throws RemoteException {
2750         String op = getNextArgRequired();
2751         switch (op) {
2752             case "move-stack":
2753                 return runDisplayMoveStack(pw);
2754             default:
2755                 getErrPrintWriter().println("Error: unknown command '" + op + "'");
2756                 return -1;
2757         }
2758     }
2759 
2760     int runStack(PrintWriter pw) throws RemoteException {
2761         String op = getNextArgRequired();
2762         switch (op) {
2763             case "move-task":
2764                 return runStackMoveTask(pw);
2765             case "list":
2766                 return runStackList(pw);
2767             case "info":
2768                 return runRootTaskInfo(pw);
2769             case "remove":
2770                 return runRootTaskRemove(pw);
2771             default:
2772                 getErrPrintWriter().println("Error: unknown command '" + op + "'");
2773                 return -1;
2774         }
2775     }
2776 
2777 
2778     private Rect getBounds() {
2779         String leftStr = getNextArgRequired();
2780         int left = Integer.parseInt(leftStr);
2781         String topStr = getNextArgRequired();
2782         int top = Integer.parseInt(topStr);
2783         String rightStr = getNextArgRequired();
2784         int right = Integer.parseInt(rightStr);
2785         String bottomStr = getNextArgRequired();
2786         int bottom = Integer.parseInt(bottomStr);
2787         if (left < 0) {
2788             getErrPrintWriter().println("Error: bad left arg: " + leftStr);
2789             return null;
2790         }
2791         if (top < 0) {
2792             getErrPrintWriter().println("Error: bad top arg: " + topStr);
2793             return null;
2794         }
2795         if (right <= 0) {
2796             getErrPrintWriter().println("Error: bad right arg: " + rightStr);
2797             return null;
2798         }
2799         if (bottom <= 0) {
2800             getErrPrintWriter().println("Error: bad bottom arg: " + bottomStr);
2801             return null;
2802         }
2803         return new Rect(left, top, right, bottom);
2804     }
2805 
2806     int runDisplayMoveStack(PrintWriter pw) throws RemoteException {
2807         String rootTaskIdStr = getNextArgRequired();
2808         int rootTaskId = Integer.parseInt(rootTaskIdStr);
2809         String displayIdStr = getNextArgRequired();
2810         int displayId = Integer.parseInt(displayIdStr);
2811         mTaskInterface.moveRootTaskToDisplay(rootTaskId, displayId);
2812         return 0;
2813     }
2814 
2815     int runStackMoveTask(PrintWriter pw) throws RemoteException {
2816         String taskIdStr = getNextArgRequired();
2817         int taskId = Integer.parseInt(taskIdStr);
2818         String rootTaskIdStr = getNextArgRequired();
2819         int rootTaskId = Integer.parseInt(rootTaskIdStr);
2820         String toTopStr = getNextArgRequired();
2821         final boolean toTop;
2822         if ("true".equals(toTopStr)) {
2823             toTop = true;
2824         } else if ("false".equals(toTopStr)) {
2825             toTop = false;
2826         } else {
2827             getErrPrintWriter().println("Error: bad toTop arg: " + toTopStr);
2828             return -1;
2829         }
2830 
2831         mTaskInterface.moveTaskToRootTask(taskId, rootTaskId, toTop);
2832         return 0;
2833     }
2834 
2835     int runStackList(PrintWriter pw) throws RemoteException {
2836         List<RootTaskInfo> tasks = mTaskInterface.getAllRootTaskInfos();
2837         for (RootTaskInfo info : tasks) {
2838             pw.println(info);
2839         }
2840         return 0;
2841     }
2842 
2843     int runRootTaskInfo(PrintWriter pw) throws RemoteException {
2844         int windowingMode = Integer.parseInt(getNextArgRequired());
2845         int activityType = Integer.parseInt(getNextArgRequired());
2846         RootTaskInfo info = mTaskInterface.getRootTaskInfo(windowingMode, activityType);
2847         pw.println(info);
2848         return 0;
2849     }
2850 
2851     int runRootTaskRemove(PrintWriter pw) throws RemoteException {
2852         String taskIdStr = getNextArgRequired();
2853         int taskId = Integer.parseInt(taskIdStr);
2854         mTaskInterface.removeTask(taskId);
2855         return 0;
2856     }
2857 
2858     int runTask(PrintWriter pw) throws RemoteException {
2859         String op = getNextArgRequired();
2860         if (op.equals("lock")) {
2861             return runTaskLock(pw);
2862         } else if (op.equals("resizeable")) {
2863             return runTaskResizeable(pw);
2864         } else if (op.equals("resize")) {
2865             return runTaskResize(pw);
2866         } else if (op.equals("focus")) {
2867             return runTaskFocus(pw);
2868         } else {
2869             getErrPrintWriter().println("Error: unknown command '" + op + "'");
2870             return -1;
2871         }
2872     }
2873 
2874     int runTaskLock(PrintWriter pw) throws RemoteException {
2875         String taskIdStr = getNextArgRequired();
2876         if (taskIdStr.equals("stop")) {
2877             mTaskInterface.stopSystemLockTaskMode();
2878         } else {
2879             int taskId = Integer.parseInt(taskIdStr);
2880             mTaskInterface.startSystemLockTaskMode(taskId);
2881         }
2882         pw.println("Activity manager is " + (mTaskInterface.isInLockTaskMode() ? "" : "not ") +
2883                 "in lockTaskMode");
2884         return 0;
2885     }
2886 
2887     int runTaskResizeable(PrintWriter pw) throws RemoteException {
2888         final String taskIdStr = getNextArgRequired();
2889         final int taskId = Integer.parseInt(taskIdStr);
2890         final String resizeableStr = getNextArgRequired();
2891         final int resizeableMode = Integer.parseInt(resizeableStr);
2892         mTaskInterface.setTaskResizeable(taskId, resizeableMode);
2893         return 0;
2894     }
2895 
2896     int runTaskResize(PrintWriter pw) throws RemoteException {
2897         final String taskIdStr = getNextArgRequired();
2898         final int taskId = Integer.parseInt(taskIdStr);
2899         final Rect bounds = getBounds();
2900         if (bounds == null) {
2901             getErrPrintWriter().println("Error: invalid input bounds");
2902             return -1;
2903         }
2904         taskResize(taskId, bounds, 0, false);
2905         return 0;
2906     }
2907 
2908     void taskResize(int taskId, Rect bounds, int delay_ms, boolean pretendUserResize)
2909             throws RemoteException {
2910         final int resizeMode = pretendUserResize ? RESIZE_MODE_USER : RESIZE_MODE_SYSTEM;
2911         mTaskInterface.resizeTask(taskId, bounds, resizeMode);
2912         try {
2913             Thread.sleep(delay_ms);
2914         } catch (InterruptedException e) {
2915         }
2916     }
2917 
2918     int moveTask(int taskId, Rect taskRect, Rect stackRect, int stepSize,
2919             int maxToTravel, boolean movingForward, boolean horizontal, int delay_ms)
2920             throws RemoteException {
2921         int maxMove;
2922         if (movingForward) {
2923             while (maxToTravel > 0
2924                     && ((horizontal && taskRect.right < stackRect.right)
2925                     ||(!horizontal && taskRect.bottom < stackRect.bottom))) {
2926                 if (horizontal) {
2927                     maxMove = Math.min(stepSize, stackRect.right - taskRect.right);
2928                     maxToTravel -= maxMove;
2929                     taskRect.right += maxMove;
2930                     taskRect.left += maxMove;
2931                 } else {
2932                     maxMove = Math.min(stepSize, stackRect.bottom - taskRect.bottom);
2933                     maxToTravel -= maxMove;
2934                     taskRect.top += maxMove;
2935                     taskRect.bottom += maxMove;
2936                 }
2937                 taskResize(taskId, taskRect, delay_ms, false);
2938             }
2939         } else {
2940             while (maxToTravel < 0
2941                     && ((horizontal && taskRect.left > stackRect.left)
2942                     ||(!horizontal && taskRect.top > stackRect.top))) {
2943                 if (horizontal) {
2944                     maxMove = Math.min(stepSize, taskRect.left - stackRect.left);
2945                     maxToTravel -= maxMove;
2946                     taskRect.right -= maxMove;
2947                     taskRect.left -= maxMove;
2948                 } else {
2949                     maxMove = Math.min(stepSize, taskRect.top - stackRect.top);
2950                     maxToTravel -= maxMove;
2951                     taskRect.top -= maxMove;
2952                     taskRect.bottom -= maxMove;
2953                 }
2954                 taskResize(taskId, taskRect, delay_ms, false);
2955             }
2956         }
2957         // Return the remaining distance we didn't travel because we reached the target location.
2958         return maxToTravel;
2959     }
2960 
2961     int getStepSize(int current, int target, int inStepSize, boolean greaterThanTarget) {
2962         int stepSize = 0;
2963         if (greaterThanTarget && target < current) {
2964             current -= inStepSize;
2965             stepSize = inStepSize;
2966             if (target > current) {
2967                 stepSize -= (target - current);
2968             }
2969         }
2970         if (!greaterThanTarget && target > current) {
2971             current += inStepSize;
2972             stepSize = inStepSize;
2973             if (target < current) {
2974                 stepSize += (current - target);
2975             }
2976         }
2977         return stepSize;
2978     }
2979 
2980     int runTaskFocus(PrintWriter pw) throws RemoteException {
2981         final int taskId = Integer.parseInt(getNextArgRequired());
2982         pw.println("Setting focus to task " + taskId);
2983         mTaskInterface.setFocusedTask(taskId);
2984         return 0;
2985     }
2986 
2987     int runWrite(PrintWriter pw) {
2988         mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
2989                 "registerUidObserver()");
2990         mInternal.mAtmInternal.flushRecentTasks();
2991         pw.println("All tasks persisted.");
2992         return 0;
2993     }
2994 
2995     int runAttachAgent(PrintWriter pw) {
2996         // TODO: revisit the permissions required for attaching agents
2997         mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
2998                 "attach-agent");
2999         String process = getNextArgRequired();
3000         String agent = getNextArgRequired();
3001         String opt;
3002         if ((opt = getNextArg()) != null) {
3003             pw.println("Error: Unknown option: " + opt);
3004             return -1;
3005         }
3006         mInternal.attachAgent(process, agent);
3007         return 0;
3008     }
3009 
3010     int runSupportsMultiwindow(PrintWriter pw) throws RemoteException {
3011         final Resources res = getResources(pw);
3012         if (res == null) {
3013             return -1;
3014         }
3015         pw.println(ActivityTaskManager.supportsMultiWindow(mInternal.mContext));
3016         return 0;
3017     }
3018 
3019     int runSupportsSplitScreenMultiwindow(PrintWriter pw) throws RemoteException {
3020         final Resources res = getResources(pw);
3021         if (res == null) {
3022             return -1;
3023         }
3024         pw.println(ActivityTaskManager.supportsSplitScreenMultiWindow(mInternal.mContext));
3025         return 0;
3026     }
3027 
3028     int runUpdateApplicationInfo(PrintWriter pw) throws RemoteException {
3029         int userid = UserHandle.parseUserArg(getNextArgRequired());
3030         ArrayList<String> packages = new ArrayList<>();
3031         packages.add(getNextArgRequired());
3032         String packageName;
3033         while ((packageName = getNextArg()) != null) {
3034             packages.add(packageName);
3035         }
3036         mInternal.scheduleApplicationInfoChanged(packages, userid);
3037         pw.println("Packages updated with most recent ApplicationInfos.");
3038         return 0;
3039     }
3040 
3041     int runNoHomeScreen(PrintWriter pw) throws RemoteException {
3042         final Resources res = getResources(pw);
3043         if (res == null) {
3044             return -1;
3045         }
3046         pw.println(res.getBoolean(com.android.internal.R.bool.config_noHomeScreen));
3047         return 0;
3048     }
3049 
3050     int runWaitForBroadcastIdle(PrintWriter pw) throws RemoteException {
3051         mInternal.waitForBroadcastIdle(pw);
3052         return 0;
3053     }
3054 
3055     int runRefreshSettingsCache() throws RemoteException {
3056         mInternal.refreshSettingsCache();
3057         return 0;
3058     }
3059 
3060     private int runCompat(PrintWriter pw) throws RemoteException {
3061         final PlatformCompat platformCompat = (PlatformCompat)
3062                 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
3063         String toggleValue = getNextArgRequired();
3064         boolean killPackage = !"--no-kill".equals(getNextOption());
3065         boolean toggleAll = false;
3066         int targetSdkVersion = -1;
3067         long changeId = -1;
3068 
3069         if (toggleValue.endsWith("-all")) {
3070             toggleValue = toggleValue.substring(0, toggleValue.lastIndexOf("-all"));
3071             toggleAll = true;
3072             if (!toggleValue.equals("reset")) {
3073                 try {
3074                     targetSdkVersion = Integer.parseInt(getNextArgRequired());
3075                 } catch (NumberFormatException e) {
3076                     pw.println("Invalid targetSdkVersion!");
3077                     return -1;
3078                 }
3079             }
3080         } else {
3081             String changeIdString = getNextArgRequired();
3082             try {
3083                 changeId = Long.parseLong(changeIdString);
3084             } catch (NumberFormatException e) {
3085                 changeId = platformCompat.lookupChangeId(changeIdString);
3086             }
3087             if (changeId == -1) {
3088                 pw.println("Unknown or invalid change: '" + changeIdString + "'.");
3089                 return -1;
3090             }
3091         }
3092         String packageName = getNextArgRequired();
3093         if (!toggleAll && !platformCompat.isKnownChangeId(changeId)) {
3094             pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it"
3095                     + " could have no effect.");
3096         }
3097         ArraySet<Long> enabled = new ArraySet<>();
3098         ArraySet<Long> disabled = new ArraySet<>();
3099         try {
3100             switch (toggleValue) {
3101                 case "enable":
3102                     if (toggleAll) {
3103                         int numChanges = platformCompat.enableTargetSdkChanges(packageName,
3104                                                                                targetSdkVersion);
3105                         if (numChanges == 0) {
3106                             pw.println("No changes were enabled.");
3107                             return -1;
3108                         }
3109                         pw.println("Enabled " + numChanges + " changes gated by targetSdkVersion "
3110                                 + targetSdkVersion + " for " + packageName + ".");
3111                     } else {
3112                         enabled.add(changeId);
3113                         CompatibilityChangeConfig overrides =
3114                                 new CompatibilityChangeConfig(
3115                                         new Compatibility.ChangeConfig(enabled, disabled));
3116                         if (killPackage) {
3117                             platformCompat.setOverrides(overrides, packageName);
3118                         } else {
3119                             platformCompat.setOverridesForTest(overrides, packageName);
3120                         }
3121                         pw.println("Enabled change " + changeId + " for " + packageName + ".");
3122                     }
3123                     return 0;
3124                 case "disable":
3125                     if (toggleAll) {
3126                         int numChanges = platformCompat.disableTargetSdkChanges(packageName,
3127                                                                                 targetSdkVersion);
3128                         if (numChanges == 0) {
3129                             pw.println("No changes were disabled.");
3130                             return -1;
3131                         }
3132                         pw.println("Disabled " + numChanges + " changes gated by targetSdkVersion "
3133                                 + targetSdkVersion + " for " + packageName + ".");
3134                     } else {
3135                         disabled.add(changeId);
3136                         CompatibilityChangeConfig overrides =
3137                                 new CompatibilityChangeConfig(
3138                                         new Compatibility.ChangeConfig(enabled, disabled));
3139                         if (killPackage) {
3140                             platformCompat.setOverrides(overrides, packageName);
3141                         } else {
3142                             platformCompat.setOverridesForTest(overrides, packageName);
3143                         }
3144                         pw.println("Disabled change " + changeId + " for " + packageName + ".");
3145                     }
3146                     return 0;
3147                 case "reset":
3148                     if (toggleAll) {
3149                         if (killPackage) {
3150                             platformCompat.clearOverrides(packageName);
3151                         } else {
3152                             platformCompat.clearOverridesForTest(packageName);
3153                         }
3154                         pw.println("Reset all changes for " + packageName + " to default value.");
3155                         return 0;
3156                     }
3157                     boolean existed;
3158                     if (killPackage) {
3159                         existed = platformCompat.clearOverride(changeId, packageName);
3160                     } else {
3161                         existed = platformCompat.clearOverrideForTest(changeId, packageName);
3162                     }
3163                     if (existed) {
3164                         pw.println("Reset change " + changeId + " for " + packageName
3165                                 + " to default value.");
3166                     } else {
3167                         pw.println("No override exists for changeId " + changeId + ".");
3168                     }
3169                     return 0;
3170                 default:
3171                     pw.println("Invalid toggle value: '" + toggleValue + "'.");
3172             }
3173         } catch (SecurityException e) {
3174             pw.println(e.getMessage());
3175         }
3176         return -1;
3177     }
3178 
3179     private int runSetMemoryFactor(PrintWriter pw) throws RemoteException {
3180         final String levelArg = getNextArgRequired();
3181         @MemFactor int level = ADJ_MEM_FACTOR_NOTHING;
3182         switch (levelArg) {
3183             case "NORMAL":
3184                 level = ADJ_MEM_FACTOR_NORMAL;
3185                 break;
3186             case "MODERATE":
3187                 level = ADJ_MEM_FACTOR_MODERATE;
3188                 break;
3189             case "LOW":
3190                 level = ADJ_MEM_FACTOR_LOW;
3191                 break;
3192             case "CRITICAL":
3193                 level = ADJ_MEM_FACTOR_CRITICAL;
3194                 break;
3195             default:
3196                 try {
3197                     level = Integer.parseInt(levelArg);
3198                 } catch (NumberFormatException e) {
3199                 }
3200                 if (level < ADJ_MEM_FACTOR_NORMAL || level > ADJ_MEM_FACTOR_CRITICAL) {
3201                     getErrPrintWriter().println("Error: Unknown level option: " + levelArg);
3202                     return -1;
3203                 }
3204         }
3205         mInternal.setMemFactorOverride(level);
3206         return 0;
3207     }
3208 
3209     private int runShowMemoryFactor(PrintWriter pw) throws RemoteException {
3210         final @MemFactor int level = mInternal.getMemoryTrimLevel();
3211         switch (level) {
3212             case ADJ_MEM_FACTOR_NOTHING:
3213                 pw.println("<UNKNOWN>");
3214                 break;
3215             case ADJ_MEM_FACTOR_NORMAL:
3216                 pw.println("NORMAL");
3217                 break;
3218             case ADJ_MEM_FACTOR_MODERATE:
3219                 pw.println("MODERATE");
3220                 break;
3221             case ADJ_MEM_FACTOR_LOW:
3222                 pw.println("LOW");
3223                 break;
3224             case ADJ_MEM_FACTOR_CRITICAL:
3225                 pw.println("CRITICAL");
3226                 break;
3227         }
3228         pw.flush();
3229         return 0;
3230     }
3231 
3232     private int runResetMemoryFactor(PrintWriter pw) throws RemoteException {
3233         mInternal.setMemFactorOverride(ADJ_MEM_FACTOR_NOTHING);
3234         return 0;
3235     }
3236 
3237     private int runMemoryFactor(PrintWriter pw) throws RemoteException {
3238         mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
3239                 "runMemoryFactor()");
3240 
3241         final String op = getNextArgRequired();
3242         switch (op) {
3243             case "set":
3244                 return runSetMemoryFactor(pw);
3245             case "show":
3246                 return runShowMemoryFactor(pw);
3247             case "reset":
3248                 return runResetMemoryFactor(pw);
3249             default:
3250                 getErrPrintWriter().println("Error: unknown command '" + op + "'");
3251                 return -1;
3252         }
3253     }
3254 
3255     private int runServiceRestartBackoff(PrintWriter pw) throws RemoteException {
3256         mInternal.enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3257                 "runServiceRestartBackoff()");
3258 
3259         final String opt = getNextArgRequired();
3260         switch (opt) {
3261             case "enable":
3262                 mInternal.setServiceRestartBackoffEnabled(getNextArgRequired(), true, "shell");
3263                 return 0;
3264             case "disable":
3265                 mInternal.setServiceRestartBackoffEnabled(getNextArgRequired(), false, "shell");
3266                 return 0;
3267             case "show":
3268                 pw.println(mInternal.isServiceRestartBackoffEnabled(getNextArgRequired())
3269                         ? "enabled" : "disabled");
3270                 return 0;
3271             default:
3272                 getErrPrintWriter().println("Error: unknown command '" + opt + "'");
3273                 return -1;
3274         }
3275     }
3276 
3277     private int runGetIsolatedProcesses(PrintWriter pw) throws RemoteException {
3278         mInternal.enforceCallingPermission(android.Manifest.permission.DUMP,
3279                 "getIsolatedProcesses()");
3280         final List<Integer> result = mInternal.mInternal.getIsolatedProcesses(
3281                 Integer.parseInt(getNextArgRequired()));
3282         pw.print("[");
3283         if (result != null) {
3284             for (int i = 0, size = result.size(); i < size; i++) {
3285                 if (i > 0) {
3286                     pw.print(", ");
3287                 }
3288                 pw.print(result.get(i));
3289             }
3290         }
3291         pw.println("]");
3292         return 0;
3293     }
3294 
3295     private int runSetStopUserOnSwitch(PrintWriter pw) throws RemoteException {
3296         mInternal.enforceCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
3297                 "setStopUserOnSwitch()");
3298         String arg = getNextArg();
3299         if (arg == null) {
3300             Slogf.i(TAG, "setStopUserOnSwitch(): resetting to default value");
3301             mInternal.setStopUserOnSwitch(ActivityManager.STOP_USER_ON_SWITCH_DEFAULT);
3302             pw.println("Reset to default value");
3303             return 0;
3304         }
3305 
3306         boolean stop = Boolean.parseBoolean(arg);
3307         int value = stop
3308                 ? ActivityManager.STOP_USER_ON_SWITCH_TRUE
3309                 : ActivityManager.STOP_USER_ON_SWITCH_FALSE;
3310 
3311         Slogf.i(TAG, "runSetStopUserOnSwitch(): setting to %d (%b)", value, stop);
3312         mInternal.setStopUserOnSwitch(value);
3313         pw.println("Set to " + stop);
3314 
3315         return 0;
3316     }
3317 
3318     // TODO(b/203105544) STOPSHIP - For debugging only, to be removed before shipping.
3319     private int runSetBgAbusiveUids(PrintWriter pw) throws RemoteException {
3320         final String arg = getNextArg();
3321         final AppBatteryTracker batteryTracker =
3322                 mInternal.mAppRestrictionController.getAppStateTracker(AppBatteryTracker.class);
3323         if (batteryTracker == null) {
3324             getErrPrintWriter().println("Unable to get bg battery tracker");
3325             return -1;
3326         }
3327         if (arg == null) {
3328             batteryTracker.clearDebugUidPercentage();
3329             return 0;
3330         }
3331         String[] pairs = arg.split(",");
3332         int[] uids = new int[pairs.length];
3333         double[][] values = new double[pairs.length][];
3334         try {
3335             for (int i = 0; i < pairs.length; i++) {
3336                 String[] pair = pairs[i].split("=");
3337                 if (pair.length != 2) {
3338                     getErrPrintWriter().println("Malformed input");
3339                     return -1;
3340                 }
3341                 uids[i] = Integer.parseInt(pair[0]);
3342                 final String[] vals = pair[1].split(":");
3343                 if (vals.length != BATTERY_USAGE_COUNT) {
3344                     getErrPrintWriter().println("Malformed input");
3345                     return -1;
3346                 }
3347                 values[i] = new double[vals.length];
3348                 for (int j = 0; j < vals.length; j++) {
3349                     values[i][j] = Double.parseDouble(vals[j]);
3350                 }
3351             }
3352         } catch (NumberFormatException e) {
3353             getErrPrintWriter().println("Malformed input");
3354             return -1;
3355         }
3356         batteryTracker.setDebugUidPercentage(uids, values);
3357         return 0;
3358     }
3359 
3360     private int runListBgExemptionsConfig(PrintWriter pw) throws RemoteException {
3361         final ArraySet<String> sysConfigs = mInternal.mAppRestrictionController
3362                 .mBgRestrictionExemptioFromSysConfig;
3363         if (sysConfigs != null) {
3364             for (int i = 0, size = sysConfigs.size(); i < size; i++) {
3365                 pw.print(sysConfigs.valueAt(i));
3366                 pw.print(' ');
3367             }
3368             pw.println();
3369         }
3370         return 0;
3371     }
3372 
3373     private Resources getResources(PrintWriter pw) throws RemoteException {
3374         // system resources does not contain all the device configuration, construct it manually.
3375         Configuration config = mInterface.getConfiguration();
3376         if (config == null) {
3377             pw.println("Error: Activity manager has no configuration");
3378             return null;
3379         }
3380 
3381         final DisplayMetrics metrics = new DisplayMetrics();
3382         metrics.setToDefaults();
3383 
3384         return new Resources(AssetManager.getSystem(), metrics, config);
3385     }
3386 
3387     @Override
3388     public void onHelp() {
3389         PrintWriter pw = getOutPrintWriter();
3390         dumpHelp(pw, mDumping);
3391     }
3392 
3393     @NeverCompile // Avoid size overhead of debugging code.
3394     static void dumpHelp(PrintWriter pw, boolean dumping) {
3395         if (dumping) {
3396             pw.println("Activity manager dump options:");
3397             pw.println("  [-a] [-c] [-p PACKAGE] [-h] [WHAT] ...");
3398             pw.println("  WHAT may be one of:");
3399             pw.println("    a[ctivities]: activity stack state");
3400             pw.println("    r[recents]: recent activities state");
3401             pw.println("    b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state");
3402             pw.println("    broadcast-stats [PACKAGE_NAME]: aggregated broadcast statistics");
3403             pw.println("    i[ntents] [PACKAGE_NAME]: pending intent state");
3404             pw.println("    p[rocesses] [PACKAGE_NAME]: process state");
3405             pw.println("    o[om]: out of memory management");
3406             pw.println("    perm[issions]: URI permission grant state");
3407             pw.println("    prov[iders] [COMP_SPEC ...]: content provider state");
3408             pw.println("    provider [COMP_SPEC]: provider client-side state");
3409             pw.println("    s[ervices] [COMP_SPEC ...]: service state");
3410             pw.println("    allowed-associations: current package association restrictions");
3411             pw.println("    as[sociations]: tracked app associations");
3412             pw.println("    exit-info [PACKAGE_NAME]: historical process exit information");
3413             pw.println("    lmk: stats on low memory killer");
3414             pw.println("    lru: raw LRU process list");
3415             pw.println("    binder-proxies: stats on binder objects and IPCs");
3416             pw.println("    settings: currently applied config settings");
3417             pw.println("    service [COMP_SPEC]: service client-side state");
3418             pw.println("    package [PACKAGE_NAME]: all state related to given package");
3419             pw.println("    all: dump all activities");
3420             pw.println("    top: dump the top activity");
3421             pw.println("  WHAT may also be a COMP_SPEC to dump activities.");
3422             pw.println("  COMP_SPEC may be a component name (com.foo/.myApp),");
3423             pw.println("    a partial substring in a component name, a");
3424             pw.println("    hex object identifier.");
3425             pw.println("  -a: include all available server state.");
3426             pw.println("  -c: include client state.");
3427             pw.println("  -p: limit output to given package.");
3428             pw.println("  --checkin: output checkin format, resetting data.");
3429             pw.println("  --C: output checkin format, not resetting data.");
3430             pw.println("  --proto: output dump in protocol buffer format.");
3431             pw.printf("  %s: dump just the DUMPABLE-related state of an activity. Use the %s "
3432                     + "option to list the supported DUMPABLEs\n", Activity.DUMP_ARG_DUMP_DUMPABLE,
3433                     Activity.DUMP_ARG_LIST_DUMPABLES);
3434             pw.printf("  %s: show the available dumpables in an activity\n",
3435                     Activity.DUMP_ARG_LIST_DUMPABLES);
3436         } else {
3437             pw.println("Activity manager (activity) commands:");
3438             pw.println("  help");
3439             pw.println("      Print this help text.");
3440             pw.println("  start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]");
3441             pw.println("          [--sampling INTERVAL] [--streaming] [-R COUNT] [-S]");
3442             pw.println("          [--track-allocation] [--user <USER_ID> | current] <INTENT>");
3443             pw.println("      Start an Activity.  Options are:");
3444             pw.println("      -D: enable debugging");
3445             pw.println("      -N: enable native debugging");
3446             pw.println("      -W: wait for launch to complete");
3447             pw.println("      --start-profiler <FILE>: start profiler and send results to <FILE>");
3448             pw.println("      --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
3449             pw.println("          between samples (use with --start-profiler)");
3450             pw.println("      --streaming: stream the profiling output to the specified file");
3451             pw.println("          (use with --start-profiler)");
3452             pw.println("      -P <FILE>: like above, but profiling stops when app goes idle");
3453             pw.println("      --attach-agent <agent>: attach the given agent before binding");
3454             pw.println("      --attach-agent-bind <agent>: attach the given agent during binding");
3455             pw.println("      -R: repeat the activity launch <COUNT> times.  Prior to each repeat,");
3456             pw.println("          the top activity will be finished.");
3457             pw.println("      -S: force stop the target app before starting the activity");
3458             pw.println("      --track-allocation: enable tracking of object allocations");
3459             pw.println("      --user <USER_ID> | current: Specify which user to run as; if not");
3460             pw.println("          specified then run as the current user.");
3461             pw.println("      --windowingMode <WINDOWING_MODE>: The windowing mode to launch the activity into.");
3462             pw.println("      --activityType <ACTIVITY_TYPE>: The activity type to launch the activity as.");
3463             pw.println("      --display <DISPLAY_ID>: The display to launch the activity into.");
3464             pw.println("      --splashscreen-icon: Show the splash screen icon on launch.");
3465             pw.println("  start-service [--user <USER_ID> | current] <INTENT>");
3466             pw.println("      Start a Service.  Options are:");
3467             pw.println("      --user <USER_ID> | current: Specify which user to run as; if not");
3468             pw.println("          specified then run as the current user.");
3469             pw.println("  start-foreground-service [--user <USER_ID> | current] <INTENT>");
3470             pw.println("      Start a foreground Service.  Options are:");
3471             pw.println("      --user <USER_ID> | current: Specify which user to run as; if not");
3472             pw.println("          specified then run as the current user.");
3473             pw.println("  stop-service [--user <USER_ID> | current] <INTENT>");
3474             pw.println("      Stop a Service.  Options are:");
3475             pw.println("      --user <USER_ID> | current: Specify which user to run as; if not");
3476             pw.println("          specified then run as the current user.");
3477             pw.println("  broadcast [--user <USER_ID> | all | current]");
3478             pw.println("          [--receiver-permission <PERMISSION>]");
3479             pw.println("          [--allow-background-activity-starts]");
3480             pw.println("          [--async] <INTENT>");
3481             pw.println("      Send a broadcast Intent.  Options are:");
3482             pw.println("      --user <USER_ID> | all | current: Specify which user to send to; if not");
3483             pw.println("          specified then send to all users.");
3484             pw.println("      --receiver-permission <PERMISSION>: Require receiver to hold permission.");
3485             pw.println("      --allow-background-activity-starts: The receiver may start activities");
3486             pw.println("          even if in the background.");
3487             pw.println("      --async: Send without waiting for the completion of the receiver.");
3488             pw.println("  compact <process_name> <Package UID> [some|full]");
3489             pw.println("      Force process compaction.");
3490             pw.println("      some: execute file compaction.");
3491             pw.println("      full: execute anon + file compaction.");
3492             pw.println("  instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]");
3493             pw.println("          [--user <USER_ID> | current]");
3494             pw.println("          [--no-hidden-api-checks [--no-test-api-access]]");
3495             pw.println("          [--no-isolated-storage]");
3496             pw.println("          [--no-window-animation] [--abi <ABI>] <COMPONENT>");
3497             pw.println("      Start an Instrumentation.  Typically this target <COMPONENT> is in the");
3498             pw.println("      form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there");
3499             pw.println("      is only one instrumentation.  Options are:");
3500             pw.println("      -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with");
3501             pw.println("          [-e perf true] to generate raw output for performance measurements.");
3502             pw.println("      -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a");
3503             pw.println("          common form is [-e <testrunner_flag> <value>[,<value>...]].");
3504             pw.println("      -p <FILE>: write profiling data to <FILE>");
3505             pw.println("      -m: Write output as protobuf to stdout (machine readable)");
3506             pw.println("      -f <Optional PATH/TO/FILE>: Write output as protobuf to a file (machine");
3507             pw.println("          readable). If path is not specified, default directory and file name will");
3508             pw.println("          be used: /sdcard/instrument-logs/log-yyyyMMdd-hhmmss-SSS.instrumentation_data_proto");
3509             pw.println("      -w: wait for instrumentation to finish before returning.  Required for");
3510             pw.println("          test runners.");
3511             pw.println("      --user <USER_ID> | current: Specify user instrumentation runs in;");
3512             pw.println("          current user if not specified.");
3513             pw.println("      --no-hidden-api-checks: disable restrictions on use of hidden API.");
3514             pw.println("      --no-test-api-access: do not allow access to test APIs, if hidden");
3515             pw.println("          API checks are enabled.");
3516             pw.println("      --no-isolated-storage: don't use isolated storage sandbox and ");
3517             pw.println("          mount full external storage");
3518             pw.println("      --no-window-animation: turn off window animations while running.");
3519             pw.println("      --abi <ABI>: Launch the instrumented process with the selected ABI.");
3520             pw.println("          This assumes that the process supports the selected ABI.");
3521             pw.println("  trace-ipc [start|stop] [--dump-file <FILE>]");
3522             pw.println("      Trace IPC transactions.");
3523             pw.println("      start: start tracing IPC transactions.");
3524             pw.println("      stop: stop tracing IPC transactions and dump the results to file.");
3525             pw.println("      --dump-file <FILE>: Specify the file the trace should be dumped to.");
3526             pw.println("  profile start [--user <USER_ID> current]");
3527             pw.println("          [--sampling INTERVAL | --streaming] <PROCESS> <FILE>");
3528             pw.println("      Start profiler on a process.  The given <PROCESS> argument");
3529             pw.println("        may be either a process name or pid.  Options are:");
3530             pw.println("      --user <USER_ID> | current: When supplying a process name,");
3531             pw.println("          specify user of process to profile; uses current user if not");
3532             pw.println("          specified.");
3533             pw.println("      --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
3534             pw.println("          between samples.");
3535             pw.println("      --streaming: stream the profiling output to the specified file.");
3536             pw.println("  profile stop [--user <USER_ID> current] <PROCESS>");
3537             pw.println("      Stop profiler on a process.  The given <PROCESS> argument");
3538             pw.println("        may be either a process name or pid.  Options are:");
3539             pw.println("      --user <USER_ID> | current: When supplying a process name,");
3540             pw.println("          specify user of process to profile; uses current user if not");
3541             pw.println("          specified.");
3542             pw.println("  dumpheap [--user <USER_ID> current] [-n] [-g] <PROCESS> <FILE>");
3543             pw.println("      Dump the heap of a process.  The given <PROCESS> argument may");
3544             pw.println("        be either a process name or pid.  Options are:");
3545             pw.println("      -n: dump native heap instead of managed heap");
3546             pw.println("      -g: force GC before dumping the heap");
3547             pw.println("      --user <USER_ID> | current: When supplying a process name,");
3548             pw.println("          specify user of process to dump; uses current user if not specified.");
3549             pw.println("  set-debug-app [-w] [--persistent] <PACKAGE>");
3550             pw.println("      Set application <PACKAGE> to debug.  Options are:");
3551             pw.println("      -w: wait for debugger when application starts");
3552             pw.println("      --persistent: retain this value");
3553             pw.println("  clear-debug-app");
3554             pw.println("      Clear the previously set-debug-app.");
3555             pw.println("  set-watch-heap <PROCESS> <MEM-LIMIT>");
3556             pw.println("      Start monitoring pss size of <PROCESS>, if it is at or");
3557             pw.println("      above <HEAP-LIMIT> then a heap dump is collected for the user to report.");
3558             pw.println("  clear-watch-heap");
3559             pw.println("      Clear the previously set-watch-heap.");
3560             pw.println("  clear-exit-info [--user <USER_ID> | all | current] [package]");
3561             pw.println("      Clear the process exit-info for given package");
3562             pw.println("  bug-report [--progress | --telephony]");
3563             pw.println("      Request bug report generation; will launch a notification");
3564             pw.println("        when done to select where it should be delivered. Options are:");
3565             pw.println("     --progress: will launch a notification right away to show its progress.");
3566             pw.println("     --telephony: will dump only telephony sections.");
3567             pw.println("  fgs-notification-rate-limit {enable | disable}");
3568             pw.println("     Enable/disable rate limit on FGS notification deferral policy.");
3569             pw.println("  force-stop [--user <USER_ID> | all | current] <PACKAGE>");
3570             pw.println("      Completely stop the given application package.");
3571             pw.println("  stop-app [--user <USER_ID> | all | current] <PACKAGE>");
3572             pw.println("      Stop an app and all of its services.  Unlike `force-stop` this does");
3573             pw.println("      not cancel the app's scheduled alarms and jobs.");
3574             pw.println("  crash [--user <USER_ID>] <PACKAGE|PID>");
3575             pw.println("      Induce a VM crash in the specified package or process");
3576             pw.println("  kill [--user <USER_ID> | all | current] <PACKAGE>");
3577             pw.println("      Kill all background processes associated with the given application.");
3578             pw.println("  kill-all");
3579             pw.println("      Kill all processes that are safe to kill (cached, etc).");
3580             pw.println("  make-uid-idle [--user <USER_ID> | all | current] <PACKAGE>");
3581             pw.println("      If the given application's uid is in the background and waiting to");
3582             pw.println("      become idle (not allowing background services), do that now.");
3583             pw.println("  monitor [--gdb <port>]");
3584             pw.println("      Start monitoring for crashes or ANRs.");
3585             pw.println("      --gdb: start gdbserv on the given port at crash/ANR");
3586             pw.println("  watch-uids [--oom <uid>]");
3587             pw.println("      Start watching for and reporting uid state changes.");
3588             pw.println("      --oom: specify a uid for which to report detailed change messages.");
3589             pw.println("  hang [--allow-restart]");
3590             pw.println("      Hang the system.");
3591             pw.println("      --allow-restart: allow watchdog to perform normal system restart");
3592             pw.println("  restart");
3593             pw.println("      Restart the user-space system.");
3594             pw.println("  idle-maintenance");
3595             pw.println("      Perform idle maintenance now.");
3596             pw.println("  screen-compat [on|off] <PACKAGE>");
3597             pw.println("      Control screen compatibility mode of <PACKAGE>.");
3598             pw.println("  package-importance <PACKAGE>");
3599             pw.println("      Print current importance of <PACKAGE>.");
3600             pw.println("  to-uri [INTENT]");
3601             pw.println("      Print the given Intent specification as a URI.");
3602             pw.println("  to-intent-uri [INTENT]");
3603             pw.println("      Print the given Intent specification as an intent: URI.");
3604             pw.println("  to-app-uri [INTENT]");
3605             pw.println("      Print the given Intent specification as an android-app: URI.");
3606             pw.println("  switch-user <USER_ID>");
3607             pw.println("      Switch to put USER_ID in the foreground, starting");
3608             pw.println("      execution of that user if it is currently stopped.");
3609             pw.println("  get-current-user");
3610             pw.println("      Returns id of the current foreground user.");
3611             pw.println("  start-user [-w] <USER_ID>");
3612             pw.println("      Start USER_ID in background if it is currently stopped;");
3613             pw.println("      use switch-user if you want to start the user in foreground.");
3614             pw.println("      -w: wait for start-user to complete and the user to be unlocked.");
3615             pw.println("  unlock-user <USER_ID>");
3616             pw.println("      Unlock the given user.  This will only work if the user doesn't");
3617             pw.println("      have an LSKF (PIN/pattern/password).");
3618             pw.println("  stop-user [-w] [-f] <USER_ID>");
3619             pw.println("      Stop execution of USER_ID, not allowing it to run any");
3620             pw.println("      code until a later explicit start or switch to it.");
3621             pw.println("      -w: wait for stop-user to complete.");
3622             pw.println("      -f: force stop even if there are related users that cannot be stopped.");
3623             pw.println("  is-user-stopped <USER_ID>");
3624             pw.println("      Returns whether <USER_ID> has been stopped or not.");
3625             pw.println("  get-started-user-state <USER_ID>");
3626             pw.println("      Gets the current state of the given started user.");
3627             pw.println("  track-associations");
3628             pw.println("      Enable association tracking.");
3629             pw.println("  untrack-associations");
3630             pw.println("      Disable and clear association tracking.");
3631             pw.println("  get-uid-state <UID>");
3632             pw.println("      Gets the process state of an app given its <UID>.");
3633             pw.println("  attach-agent <PROCESS> <FILE>");
3634             pw.println("    Attach an agent to the specified <PROCESS>, which may be either a process name or a PID.");
3635             pw.println("  get-config [--days N] [--device] [--proto] [--display <DISPLAY_ID>]");
3636             pw.println("      Retrieve the configuration and any recent configurations of the device.");
3637             pw.println("      --days: also return last N days of configurations that have been seen.");
3638             pw.println("      --device: also output global device configuration info.");
3639             pw.println("      --proto: return result as a proto; does not include --days info.");
3640             pw.println("      --display: Specify for which display to run the command; if not ");
3641             pw.println("          specified then run for the default display.");
3642             pw.println("  supports-multiwindow");
3643             pw.println("      Returns true if the device supports multiwindow.");
3644             pw.println("  supports-split-screen-multi-window");
3645             pw.println("      Returns true if the device supports split screen multiwindow.");
3646             pw.println("  suppress-resize-config-changes <true|false>");
3647             pw.println("      Suppresses configuration changes due to user resizing an activity/task.");
3648             pw.println("  set-inactive [--user <USER_ID>] <PACKAGE> true|false");
3649             pw.println("      Sets the inactive state of an app.");
3650             pw.println("  get-inactive [--user <USER_ID>] <PACKAGE>");
3651             pw.println("      Returns the inactive state of an app.");
3652             pw.println("  set-standby-bucket [--user <USER_ID>] <PACKAGE> active|working_set|frequent|rare|restricted");
3653             pw.println("      Puts an app in the standby bucket.");
3654             pw.println("  get-standby-bucket [--user <USER_ID>] <PACKAGE>");
3655             pw.println("      Returns the standby bucket of an app.");
3656             pw.println("  send-trim-memory [--user <USER_ID>] <PROCESS>");
3657             pw.println("          [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]");
3658             pw.println("      Send a memory trim event to a <PROCESS>.  May also supply a raw trim int level.");
3659             pw.println("  display [COMMAND] [...]: sub-commands for operating on displays.");
3660             pw.println("       move-stack <STACK_ID> <DISPLAY_ID>");
3661             pw.println("           Move <STACK_ID> from its current display to <DISPLAY_ID>.");
3662             pw.println("  stack [COMMAND] [...]: sub-commands for operating on activity stacks.");
3663             pw.println("       move-task <TASK_ID> <STACK_ID> [true|false]");
3664             pw.println("           Move <TASK_ID> from its current stack to the top (true) or");
3665             pw.println("           bottom (false) of <STACK_ID>.");
3666             pw.println("       list");
3667             pw.println("           List all of the activity stacks and their sizes.");
3668             pw.println("       info <WINDOWING_MODE> <ACTIVITY_TYPE>");
3669             pw.println("           Display the information about activity stack in <WINDOWING_MODE> and <ACTIVITY_TYPE>.");
3670             pw.println("       remove <STACK_ID>");
3671             pw.println("           Remove stack <STACK_ID>.");
3672             pw.println("  task [COMMAND] [...]: sub-commands for operating on activity tasks.");
3673             pw.println("       lock <TASK_ID>");
3674             pw.println("           Bring <TASK_ID> to the front and don't allow other tasks to run.");
3675             pw.println("       lock stop");
3676             pw.println("           End the current task lock.");
3677             pw.println("       resizeable <TASK_ID> [0|1|2|3]");
3678             pw.println("           Change resizeable mode of <TASK_ID> to one of the following:");
3679             pw.println("           0: unresizeable");
3680             pw.println("           1: crop_windows");
3681             pw.println("           2: resizeable");
3682             pw.println("           3: resizeable_and_pipable");
3683             pw.println("       resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>");
3684             pw.println("           Makes sure <TASK_ID> is in a stack with the specified bounds.");
3685             pw.println("           Forces the task to be resizeable and creates a stack if no existing stack");
3686             pw.println("           has the specified bounds.");
3687             pw.println("  update-appinfo <USER_ID> <PACKAGE_NAME> [<PACKAGE_NAME>...]");
3688             pw.println("      Update the ApplicationInfo objects of the listed packages for <USER_ID>");
3689             pw.println("      without restarting any processes.");
3690             pw.println("  write");
3691             pw.println("      Write all pending state to storage.");
3692             pw.println("  compat [COMMAND] [...]: sub-commands for toggling app-compat changes.");
3693             pw.println("         enable|disable [--no-kill] <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
3694             pw.println("            Toggles a change either by id or by name for <PACKAGE_NAME>.");
3695             pw.println("            It kills <PACKAGE_NAME> (to allow the toggle to take effect) unless --no-kill is provided.");
3696             pw.println("         reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
3697             pw.println("            Toggles a change either by id or by name for <PACKAGE_NAME>.");
3698             pw.println("            It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
3699             pw.println("         enable-all|disable-all <targetSdkVersion> <PACKAGE_NAME>");
3700             pw.println("            Toggles all changes that are gated by <targetSdkVersion>.");
3701             pw.println("         reset-all [--no-kill] <PACKAGE_NAME>");
3702             pw.println("            Removes all existing overrides for all changes for ");
3703             pw.println("            <PACKAGE_NAME> (back to default behaviour).");
3704             pw.println("            It kills <PACKAGE_NAME> (to allow the toggle to take effect) unless --no-kill is provided.");
3705             pw.println("  memory-factor [command] [...]: sub-commands for overriding memory pressure factor");
3706             pw.println("         set <NORMAL|MODERATE|LOW|CRITICAL>");
3707             pw.println("            Overrides memory pressure factor. May also supply a raw int level");
3708             pw.println("         show");
3709             pw.println("            Shows the existing memory pressure factor");
3710             pw.println("         reset");
3711             pw.println("            Removes existing override for memory pressure factor");
3712             pw.println("  service-restart-backoff <COMMAND> [...]: sub-commands to toggle service restart backoff policy.");
3713             pw.println("         enable|disable <PACKAGE_NAME>");
3714             pw.println("            Toggles the restart backoff policy on/off for <PACKAGE_NAME>.");
3715             pw.println("         show <PACKAGE_NAME>");
3716             pw.println("            Shows the restart backoff policy state for <PACKAGE_NAME>.");
3717             pw.println("  get-isolated-pids <UID>");
3718             pw.println("         Get the PIDs of isolated processes with packages in this <UID>");
3719             pw.println("  set-stop-user-on-switch [true|false]");
3720             pw.println("         Sets whether the current user (and its profiles) should be stopped"
3721                     + " when switching to a different user.");
3722             pw.println("         Without arguments, it resets to the value defined by platform.");
3723             pw.println("  set-bg-abusive-uids [uid=percentage][,uid=percentage...]");
3724             pw.println("         Force setting the battery usage of the given UID.");
3725             pw.println();
3726             Intent.printIntentArgsHelp(pw, "");
3727         }
3728     }
3729 }
3730