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