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