1 /*
2  * Copyright (C) 2017 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.wm;
18 
19 import static android.os.Build.IS_USER;
20 import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
21 
22 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
23 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
24 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR;
25 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER;
26 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
27 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
28 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
29 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM;
30 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
31 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
32 
33 import android.content.res.Resources.NotFoundException;
34 import android.graphics.Color;
35 import android.graphics.Point;
36 import android.graphics.Rect;
37 import android.os.ParcelFileDescriptor;
38 import android.os.RemoteException;
39 import android.os.ShellCommand;
40 import android.os.UserHandle;
41 import android.provider.Settings;
42 import android.util.DisplayMetrics;
43 import android.util.Pair;
44 import android.util.TypedValue;
45 import android.view.Display;
46 import android.view.IWindow;
47 import android.view.IWindowManager;
48 import android.view.ViewDebug;
49 
50 import com.android.internal.os.ByteTransferPipe;
51 import com.android.internal.protolog.LegacyProtoLogImpl;
52 import com.android.internal.protolog.PerfettoProtoLogImpl;
53 import com.android.internal.protolog.common.IProtoLog;
54 import com.android.internal.protolog.common.ProtoLog;
55 import com.android.server.IoThread;
56 import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;
57 import com.android.server.wm.LetterboxConfiguration.LetterboxHorizontalReachabilityPosition;
58 import com.android.server.wm.LetterboxConfiguration.LetterboxVerticalReachabilityPosition;
59 
60 import java.io.IOException;
61 import java.io.PrintWriter;
62 import java.util.ArrayList;
63 import java.util.function.Consumer;
64 import java.util.regex.Matcher;
65 import java.util.regex.Pattern;
66 import java.util.zip.ZipEntry;
67 import java.util.zip.ZipOutputStream;
68 
69 /**
70  * ShellCommands for WindowManagerService.
71  *
72  * Use with {@code adb shell cmd window ...}.
73  */
74 public class WindowManagerShellCommand extends ShellCommand {
75 
76     // IPC interface to activity manager -- don't need to do additional security checks.
77     private final IWindowManager mInterface;
78 
79     // Internal service impl -- must perform security checks before touching.
80     private final WindowManagerService mInternal;
81     private final LetterboxConfiguration mLetterboxConfiguration;
82 
WindowManagerShellCommand(WindowManagerService service)83     public WindowManagerShellCommand(WindowManagerService service) {
84         mInterface = service;
85         mInternal = service;
86         mLetterboxConfiguration = service.mLetterboxConfiguration;
87     }
88 
89     @Override
onCommand(String cmd)90     public int onCommand(String cmd) {
91         if (cmd == null) {
92             return handleDefaultCommands(cmd);
93         }
94         final PrintWriter pw = getOutPrintWriter();
95         try {
96             switch (cmd) {
97                 case "size":
98                     return runDisplaySize(pw);
99                 case "density":
100                     return runDisplayDensity(pw);
101                 case "folded-area":
102                     return runDisplayFoldedArea(pw);
103                 case "scaling":
104                     return runDisplayScaling(pw);
105                 case "dismiss-keyguard":
106                     return runDismissKeyguard(pw);
107                 case "tracing":
108                     // XXX this should probably be changed to use openFileForSystem() to create
109                     // the output trace file, so the shell gets the correct semantics for where
110                     // trace files can be written.
111                     return mInternal.mWindowTracing.onShellCommand(this);
112                 case "logging":
113                     IProtoLog instance = ProtoLog.getSingleInstance();
114                     int result = 0;
115                     if (instance instanceof LegacyProtoLogImpl
116                             || instance instanceof PerfettoProtoLogImpl) {
117                         if (instance instanceof LegacyProtoLogImpl) {
118                             result = ((LegacyProtoLogImpl) instance).onShellCommand(this);
119                         } else {
120                             result = ((PerfettoProtoLogImpl) instance).onShellCommand(this);
121                         }
122                         if (result != 0) {
123                             pw.println("Not handled, please use "
124                                     + "`adb shell dumpsys activity service SystemUIService "
125                                     + "WMShell` if you are looking for ProtoLog in WMShell");
126                         }
127                     } else {
128                         result = -1;
129                         pw.println("ProtoLog impl doesn't support handling commands");
130                     }
131                     return result;
132                 case "user-rotation":
133                     return runDisplayUserRotation(pw);
134                 case "fixed-to-user-rotation":
135                     return runFixedToUserRotation(pw);
136                 case "set-ignore-orientation-request":
137                     return runSetIgnoreOrientationRequest(pw);
138                 case "get-ignore-orientation-request":
139                     return runGetIgnoreOrientationRequest(pw);
140                 case "dump-visible-window-views":
141                     return runDumpVisibleWindowViews(pw);
142                 case "set-letterbox-style":
143                     return runSetLetterboxStyle(pw);
144                 case "get-letterbox-style":
145                     return runGetLetterboxStyle(pw);
146                 case "reset-letterbox-style":
147                     return runResetLetterboxStyle(pw);
148                 case "set-sandbox-display-apis":
149                     return runSandboxDisplayApis(pw);
150                 case "set-multi-window-config":
151                     return runSetMultiWindowConfig();
152                 case "get-multi-window-config":
153                     return runGetMultiWindowConfig(pw);
154                 case "reset-multi-window-config":
155                     return runResetMultiWindowConfig();
156                 case "reset":
157                     return runReset(pw);
158                 case "disable-blur":
159                     return runSetBlurDisabled(pw);
160                 case "shell":
161                     return runWmShellCommand(pw);
162                 default:
163                     return handleDefaultCommands(cmd);
164             }
165         } catch (RemoteException e) {
166             pw.println("Remote exception: " + e);
167         }
168         return -1;
169     }
170 
getDisplayId(String opt)171     private int getDisplayId(String opt) {
172         int displayId = Display.DEFAULT_DISPLAY;
173         String option = "-d".equals(opt) ? opt : getNextOption();
174         if (option != null && "-d".equals(option)) {
175             try {
176                 displayId = Integer.parseInt(getNextArgRequired());
177             } catch (NumberFormatException e) {
178                 getErrPrintWriter().println("Error: bad number " + e);
179             } catch (IllegalArgumentException e) {
180                 getErrPrintWriter().println("Error: " + e);
181             }
182         }
183         return displayId;
184     }
185 
printInitialDisplaySize(PrintWriter pw , int displayId)186     private void printInitialDisplaySize(PrintWriter pw , int displayId) {
187         final Point initialSize = new Point();
188         final Point baseSize = new Point();
189 
190         try {
191             mInterface.getInitialDisplaySize(displayId, initialSize);
192             mInterface.getBaseDisplaySize(displayId, baseSize);
193             pw.println("Physical size: " + initialSize.x + "x" + initialSize.y);
194             if (!initialSize.equals(baseSize)) {
195                 pw.println("Override size: " + baseSize.x + "x" + baseSize.y);
196             }
197         } catch (RemoteException e) {
198             // Can't call getInitialDisplaySize() on IWindowManager or
199             // Can't call getBaseDisplaySize() on IWindowManager
200             pw.println("Remote exception: " + e);
201         }
202     }
203 
runDisplaySize(PrintWriter pw)204     private int runDisplaySize(PrintWriter pw) throws RemoteException {
205         String size = getNextArg();
206         int w, h;
207         final int displayId = getDisplayId(size);
208         if (size == null) {
209             printInitialDisplaySize(pw, displayId);
210             return 0;
211         } else if ("-d".equals(size)) {
212             printInitialDisplaySize(pw, displayId);
213             return 0;
214         } else if ("reset".equals(size)) {
215             w = h = -1;
216         } else {
217             int div = size.indexOf('x');
218             if (div <= 0 || div >= (size.length()-1)) {
219                 getErrPrintWriter().println("Error: bad size " + size);
220                 return -1;
221             }
222             String wstr = size.substring(0, div);
223             String hstr = size.substring(div+1);
224             try {
225                 w = parseDimension(wstr, displayId);
226                 h = parseDimension(hstr, displayId);
227             } catch (NumberFormatException e) {
228                 getErrPrintWriter().println("Error: bad number " + e);
229                 return -1;
230             }
231         }
232 
233         if (w >= 0 && h >= 0) {
234             mInterface.setForcedDisplaySize(displayId, w, h);
235         } else {
236             mInterface.clearForcedDisplaySize(displayId);
237         }
238         return 0;
239     }
240 
runSetBlurDisabled(PrintWriter pw)241     private int runSetBlurDisabled(PrintWriter pw) throws RemoteException {
242         String arg = getNextArg();
243         if (arg == null) {
244             pw.println("Blur supported on device: " + CROSS_WINDOW_BLUR_SUPPORTED);
245             pw.println("Blur enabled: " + mInternal.mBlurController.getBlurEnabled());
246             return 0;
247         }
248 
249         final boolean disableBlur;
250         switch (arg) {
251             case "true":
252             case "1":
253                 disableBlur = true;
254                 break;
255             case "false":
256             case "0":
257                 disableBlur = false;
258                 break;
259             default:
260                 getErrPrintWriter().println("Error: expected true, 1, false, 0, but got " + arg);
261                 return -1;
262         }
263 
264         Settings.Global.putInt(mInternal.mContext.getContentResolver(),
265                 Settings.Global.DISABLE_WINDOW_BLURS, disableBlur ? 1 : 0);
266 
267         return 0;
268     }
269 
printInitialDisplayDensity(PrintWriter pw , int displayId)270     private void printInitialDisplayDensity(PrintWriter pw , int displayId) {
271         try {
272             final int initialDensity = mInterface.getInitialDisplayDensity(displayId);
273             final int baseDensity = mInterface.getBaseDisplayDensity(displayId);
274             pw.println("Physical density: " + initialDensity);
275             if (initialDensity != baseDensity) {
276                 pw.println("Override density: " + baseDensity);
277             }
278         } catch (RemoteException e) {
279             // Can't call getInitialDisplayDensity() on IWindowManager or
280             // Can't call getBaseDisplayDensity() on IWindowManager
281             pw.println("Remote exception: " + e);
282         }
283     }
284 
runDisplayDensity(PrintWriter pw)285     private int runDisplayDensity(PrintWriter pw) throws RemoteException {
286         String densityStr = getNextArg();
287         String option = getNextOption();
288         String arg = getNextArg();
289         int density;
290         int displayId = Display.DEFAULT_DISPLAY;
291         if ("-d".equals(option) && arg != null) {
292             try {
293                 displayId = Integer.parseInt(arg);
294             } catch (NumberFormatException e) {
295                 getErrPrintWriter().println("Error: bad number " + e);
296             }
297         } else if ("-u".equals(option) && arg != null) {
298             displayId = mInterface.getDisplayIdByUniqueId(arg);
299             if (displayId == Display.INVALID_DISPLAY) {
300                 getErrPrintWriter().println("Error: the uniqueId is invalid ");
301                 return -1;
302             }
303         }
304 
305         if (densityStr == null) {
306             printInitialDisplayDensity(pw, displayId);
307             return 0;
308         } else if ("-d".equals(densityStr)) {
309             printInitialDisplayDensity(pw, displayId);
310             return 0;
311         } else if ("reset".equals(densityStr)) {
312             density = -1;
313         } else {
314             try {
315                 density = Integer.parseInt(densityStr);
316             } catch (NumberFormatException e) {
317                 getErrPrintWriter().println("Error: bad number " + e);
318                 return -1;
319             }
320             if (density < 72) {
321                 getErrPrintWriter().println("Error: density must be >= 72");
322                 return -1;
323             }
324         }
325 
326         if (density > 0) {
327             mInterface.setForcedDisplayDensityForUser(displayId, density,
328                     UserHandle.USER_CURRENT);
329         } else {
330             mInterface.clearForcedDisplayDensityForUser(displayId,
331                     UserHandle.USER_CURRENT);
332         }
333         return 0;
334     }
335 
printFoldedArea(PrintWriter pw)336     private void printFoldedArea(PrintWriter pw) {
337         final Rect foldedArea = mInternal.getFoldedArea();
338         if (foldedArea.isEmpty()) {
339             pw.println("Folded area: none");
340         } else {
341             pw.println("Folded area: " + foldedArea.left + "," + foldedArea.top + ","
342                     + foldedArea.right + "," + foldedArea.bottom);
343         }
344     }
345 
runDisplayFoldedArea(PrintWriter pw)346     private int runDisplayFoldedArea(PrintWriter pw) {
347         final String areaStr = getNextArg();
348         final Rect rect = new Rect();
349         if (areaStr == null) {
350             printFoldedArea(pw);
351             return 0;
352         } else if ("reset".equals(areaStr)) {
353             rect.setEmpty();
354         } else {
355             final Pattern flattenedPattern = Pattern.compile(
356                     "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)");
357             final Matcher matcher = flattenedPattern.matcher(areaStr);
358             if (!matcher.matches()) {
359                 getErrPrintWriter().println("Error: area should be LEFT,TOP,RIGHT,BOTTOM");
360                 return -1;
361             }
362             rect.set(Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2)),
363                     Integer.parseInt(matcher.group(3)), Integer.parseInt(matcher.group(4)));
364         }
365 
366         mInternal.setOverrideFoldedArea(rect);
367         return 0;
368     }
369 
runDisplayScaling(PrintWriter pw)370     private int runDisplayScaling(PrintWriter pw) throws RemoteException {
371         String scalingStr = getNextArgRequired();
372         if ("auto".equals(scalingStr)) {
373             mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr),
374                     DisplayContent.FORCE_SCALING_MODE_AUTO);
375         } else if ("off".equals(scalingStr)) {
376             mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr),
377                     DisplayContent.FORCE_SCALING_MODE_DISABLED);
378         } else {
379             getErrPrintWriter().println("Error: scaling must be 'auto' or 'off'");
380             return -1;
381         }
382         return 0;
383     }
384 
385     /**
386      * Override display size and metrics to reflect the DisplayArea of the calling activity.
387      */
runSandboxDisplayApis(PrintWriter pw)388     private int runSandboxDisplayApis(PrintWriter pw) throws RemoteException {
389         int displayId = Display.DEFAULT_DISPLAY;
390         String arg = getNextArgRequired();
391         if ("-d".equals(arg)) {
392             displayId = Integer.parseInt(getNextArgRequired());
393             arg = getNextArgRequired();
394         }
395 
396         final boolean sandboxDisplayApis;
397         switch (arg) {
398             case "true":
399             case "1":
400                 sandboxDisplayApis = true;
401                 break;
402             case "false":
403             case "0":
404                 sandboxDisplayApis = false;
405                 break;
406             default:
407                 getErrPrintWriter().println("Error: expecting true, 1, false, 0, but we "
408                         + "get " + arg);
409                 return -1;
410         }
411 
412         mInternal.setSandboxDisplayApis(displayId, sandboxDisplayApis);
413         return 0;
414     }
415 
runDismissKeyguard(PrintWriter pw)416     private int runDismissKeyguard(PrintWriter pw) throws RemoteException {
417         mInterface.dismissKeyguard(null /* callback */, null /* message */);
418         return 0;
419     }
420 
parseDimension(String s, int displayId)421     private int parseDimension(String s, int displayId) throws NumberFormatException {
422         if (s.endsWith("px")) {
423             return Integer.parseInt(s.substring(0, s.length() - 2));
424         }
425         if (s.endsWith("dp")) {
426             int density;
427             try {
428                 density = mInterface.getBaseDisplayDensity(displayId);
429             } catch (RemoteException e) {
430                 density = DisplayMetrics.DENSITY_DEFAULT;
431             }
432             return Integer.parseInt(s.substring(0, s.length() - 2)) * density /
433                     DisplayMetrics.DENSITY_DEFAULT;
434         }
435         return Integer.parseInt(s);
436     }
437 
runDisplayUserRotation(PrintWriter pw)438     private int runDisplayUserRotation(PrintWriter pw) {
439         int displayId = Display.DEFAULT_DISPLAY;
440         String arg = getNextArg();
441         if (arg == null) {
442             return printDisplayUserRotation(pw, displayId);
443         }
444 
445         if ("-d".equals(arg)) {
446             displayId = Integer.parseInt(getNextArgRequired());
447             arg = getNextArg();
448         }
449 
450         final String lockMode = arg;
451         if (lockMode == null) {
452             return printDisplayUserRotation(pw, displayId);
453         }
454 
455         if ("free".equals(lockMode)) {
456             mInternal.thawDisplayRotation(displayId,
457                     /* caller= */ "WindowManagerShellCommand#free");
458             return 0;
459         }
460 
461         if (!"lock".equals(lockMode)) {
462             getErrPrintWriter().println("Error: argument needs to be either -d, free or lock.");
463             return -1;
464         }
465 
466         arg = getNextArg();
467         try {
468             final int rotation =
469                     arg != null ? Integer.parseInt(arg) : -1 /* lock to current rotation */;
470             mInternal.freezeDisplayRotation(displayId, rotation,
471                     /* caller= */ "WindowManagerShellCommand#lock");
472             return 0;
473         } catch (IllegalArgumentException e) {
474             getErrPrintWriter().println("Error: " + e.getMessage());
475             return -1;
476         }
477     }
478 
printDisplayUserRotation(PrintWriter pw, int displayId)479     private int printDisplayUserRotation(PrintWriter pw, int displayId) {
480         final int displayUserRotation = mInternal.getDisplayUserRotation(displayId);
481         if (displayUserRotation < 0) {
482             getErrPrintWriter().println("Error: check logcat for more details.");
483             return -1;
484         }
485         if (!mInternal.isDisplayRotationFrozen(displayId)) {
486             pw.println("free");
487             return 0;
488         }
489         pw.print("lock ");
490         pw.println(displayUserRotation);
491         return 0;
492     }
493 
runFixedToUserRotation(PrintWriter pw)494     private int runFixedToUserRotation(PrintWriter pw) throws RemoteException {
495         int displayId = Display.DEFAULT_DISPLAY;
496         String arg = getNextArg();
497         if (arg == null) {
498             printFixedToUserRotation(pw, displayId);
499             return 0;
500         }
501 
502         if ("-d".equals(arg)) {
503             displayId = Integer.parseInt(getNextArgRequired());
504             arg = getNextArg();
505         }
506 
507         if (arg == null) {
508             return printFixedToUserRotation(pw, displayId);
509         }
510 
511         final int fixedToUserRotation;
512         switch (arg) {
513             case "enabled":
514                 fixedToUserRotation = IWindowManager.FIXED_TO_USER_ROTATION_ENABLED;
515                 break;
516             case "disabled":
517                 fixedToUserRotation = IWindowManager.FIXED_TO_USER_ROTATION_DISABLED;
518                 break;
519             case "default":
520                 fixedToUserRotation = IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT;
521                 break;
522             case "enabled_if_no_auto_rotation":
523                 fixedToUserRotation = IWindowManager.FIXED_TO_USER_ROTATION_IF_NO_AUTO_ROTATION;
524                 break;
525             default:
526                 getErrPrintWriter().println("Error: expecting enabled, disabled or default, but we "
527                         + "get " + arg);
528                 return -1;
529         }
530 
531         mInterface.setFixedToUserRotation(displayId, fixedToUserRotation);
532         return 0;
533     }
534 
printFixedToUserRotation(PrintWriter pw, int displayId)535     private int printFixedToUserRotation(PrintWriter pw, int displayId) {
536         int fixedToUserRotationMode = mInternal.getFixedToUserRotation(displayId);
537         switch (fixedToUserRotationMode) {
538             case IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT:
539                 pw.println("default");
540                 return 0;
541             case IWindowManager.FIXED_TO_USER_ROTATION_DISABLED:
542                 pw.println("disabled");
543                 return 0;
544             case IWindowManager.FIXED_TO_USER_ROTATION_IF_NO_AUTO_ROTATION:
545                 pw.println("enabled_if_no_auto_rotation");
546                 return 0;
547             case IWindowManager.FIXED_TO_USER_ROTATION_ENABLED:
548                 pw.println("enabled");
549                 return 0;
550             default:
551                 getErrPrintWriter().println("Error: check logcat for more details.");
552                 return -1;
553         }
554     }
555 
runSetIgnoreOrientationRequest(PrintWriter pw)556     private int runSetIgnoreOrientationRequest(PrintWriter pw) throws RemoteException {
557         int displayId = Display.DEFAULT_DISPLAY;
558         String arg = getNextArgRequired();
559         if ("-d".equals(arg)) {
560             displayId = Integer.parseInt(getNextArgRequired());
561             arg = getNextArgRequired();
562         }
563 
564         final boolean ignoreOrientationRequest;
565         switch (arg) {
566             case "true":
567             case "1":
568                 ignoreOrientationRequest = true;
569                 break;
570             case "false":
571             case "0":
572                 ignoreOrientationRequest = false;
573                 break;
574             default:
575                 getErrPrintWriter().println("Error: expecting true, 1, false, 0, but we "
576                         + "get " + arg);
577                 return -1;
578         }
579 
580         mInterface.setIgnoreOrientationRequest(displayId, ignoreOrientationRequest);
581         return 0;
582     }
583 
runGetIgnoreOrientationRequest(PrintWriter pw)584     private int runGetIgnoreOrientationRequest(PrintWriter pw) throws RemoteException {
585         int displayId = Display.DEFAULT_DISPLAY;
586         String arg = getNextArg();
587         if ("-d".equals(arg)) {
588             displayId = Integer.parseInt(getNextArgRequired());
589         }
590 
591         final boolean ignoreOrientationRequest = mInternal.getIgnoreOrientationRequest(displayId);
592         pw.println("ignoreOrientationRequest " + ignoreOrientationRequest
593                 + " for displayId=" + displayId);
594         return 0;
595     }
596 
dumpLocalWindowAsync(IWindow client, ParcelFileDescriptor pfd)597     private void dumpLocalWindowAsync(IWindow client, ParcelFileDescriptor pfd) {
598         // Make it asynchronous to avoid writer from being blocked
599         // by waiting for the buffer to be consumed in the same process.
600         IoThread.getExecutor().execute(() -> {
601             synchronized (mInternal.mGlobalLock) {
602                 try {
603                     client.executeCommand(ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null, pfd);
604                 } catch (Exception e) {
605                     // Ignore RemoteException for local call. Just print trace for other
606                     // exceptions caused by RC with tolerable low possibility.
607                     e.printStackTrace();
608                 }
609             }
610         });
611     }
612 
runDumpVisibleWindowViews(PrintWriter pw)613     private int runDumpVisibleWindowViews(PrintWriter pw) {
614         if (!mInternal.checkCallingPermission(android.Manifest.permission.DUMP,
615                 "runDumpVisibleWindowViews()")) {
616             throw new SecurityException("Requires DUMP permission");
617         }
618 
619         try (ZipOutputStream out = new ZipOutputStream(getRawOutputStream())) {
620             ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>();
621             synchronized (mInternal.mGlobalLock) {
622                 final RecentTasks recentTasks = mInternal.mAtmService.getRecentTasks();
623                 final int recentsComponentUid = recentTasks != null
624                         ? recentTasks.getRecentsComponentUid()
625                         : -1;
626                 // Request dump from all windows parallelly before writing to disk.
627                 mInternal.mRoot.forAllWindows(w -> {
628                     final boolean isRecents = (w.getUid() == recentsComponentUid);
629                     if (w.isVisible() || isRecents) {
630                         ByteTransferPipe pipe = null;
631                         try {
632                             pipe = new ByteTransferPipe();
633                             final ParcelFileDescriptor pfd = pipe.getWriteFd();
634                             if (w.isClientLocal()) {
635                                 dumpLocalWindowAsync(w.mClient, pfd);
636                             } else {
637                                 w.mClient.executeCommand(
638                                         ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null, pfd);
639                             }
640                             requestList.add(Pair.create(w.getName(), pipe));
641                         } catch (IOException | RemoteException e) {
642                             // Skip this window
643                             if (pipe != null) {
644                                 pipe.kill();
645                             }
646                         }
647                     }
648                 }, false /* traverseTopToBottom */);
649             }
650             for (Pair<String, ByteTransferPipe> entry : requestList) {
651                 byte[] data;
652                 try {
653                     data = entry.second.get();
654                 } catch (IOException e) {
655                     // Ignore this window
656                     continue;
657                 }
658                 out.putNextEntry(new ZipEntry(entry.first));
659                 out.write(data);
660             }
661         } catch (IOException e) {
662             pw.println("Error fetching dump " + e.getMessage());
663         }
664         return 0;
665     }
666 
runSetFixedOrientationLetterboxAspectRatio(PrintWriter pw)667     private int runSetFixedOrientationLetterboxAspectRatio(PrintWriter pw) throws RemoteException {
668         final float aspectRatio;
669         try {
670             String arg = getNextArgRequired();
671             aspectRatio = Float.parseFloat(arg);
672         } catch (NumberFormatException  e) {
673             getErrPrintWriter().println("Error: bad aspect ratio format " + e);
674             return -1;
675         } catch (IllegalArgumentException  e) {
676             getErrPrintWriter().println(
677                     "Error: aspect ratio should be provided as an argument " + e);
678             return -1;
679         }
680         synchronized (mInternal.mGlobalLock) {
681             mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(aspectRatio);
682         }
683         return 0;
684     }
685 
runSetDefaultMinAspectRatioForUnresizableApps(PrintWriter pw)686     private int runSetDefaultMinAspectRatioForUnresizableApps(PrintWriter pw)
687             throws RemoteException {
688         final float aspectRatio;
689         try {
690             String arg = getNextArgRequired();
691             aspectRatio = Float.parseFloat(arg);
692         } catch (NumberFormatException  e) {
693             getErrPrintWriter().println("Error: bad aspect ratio format " + e);
694             return -1;
695         } catch (IllegalArgumentException  e) {
696             getErrPrintWriter().println(
697                     "Error: aspect ratio should be provided as an argument " + e);
698             return -1;
699         }
700         synchronized (mInternal.mGlobalLock) {
701             mLetterboxConfiguration.setDefaultMinAspectRatioForUnresizableApps(aspectRatio);
702         }
703         return 0;
704     }
705 
runSetLetterboxActivityCornersRadius(PrintWriter pw)706     private int runSetLetterboxActivityCornersRadius(PrintWriter pw) throws RemoteException {
707         final int cornersRadius;
708         try {
709             String arg = getNextArgRequired();
710             cornersRadius = Integer.parseInt(arg);
711         } catch (NumberFormatException  e) {
712             getErrPrintWriter().println("Error: bad corners radius format " + e);
713             return -1;
714         } catch (IllegalArgumentException  e) {
715             getErrPrintWriter().println(
716                     "Error: corners radius should be provided as an argument " + e);
717             return -1;
718         }
719         synchronized (mInternal.mGlobalLock) {
720             mLetterboxConfiguration.setLetterboxActivityCornersRadius(cornersRadius);
721         }
722         return 0;
723     }
724 
runSetLetterboxBackgroundType(PrintWriter pw)725     private int runSetLetterboxBackgroundType(PrintWriter pw) throws RemoteException {
726         @LetterboxBackgroundType final int backgroundType;
727         try {
728             String arg = getNextArgRequired();
729             switch (arg) {
730                 case "solid_color":
731                     backgroundType = LETTERBOX_BACKGROUND_SOLID_COLOR;
732                     break;
733                 case "app_color_background":
734                     backgroundType = LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
735                     break;
736                 case "app_color_background_floating":
737                     backgroundType = LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
738                     break;
739                 case "wallpaper":
740                     backgroundType = LETTERBOX_BACKGROUND_WALLPAPER;
741                     break;
742                 default:
743                     getErrPrintWriter().println(
744                             "Error: 'solid_color', 'app_color_background' or "
745                             + "'wallpaper' should be provided as an argument");
746                     return -1;
747             }
748         } catch (IllegalArgumentException  e) {
749             getErrPrintWriter().println(
750                     "Error: 'solid_color', 'app_color_background' or "
751                         + "'wallpaper' should be provided as an argument" + e);
752             return -1;
753         }
754         synchronized (mInternal.mGlobalLock) {
755             mLetterboxConfiguration.setLetterboxBackgroundTypeOverride(backgroundType);
756         }
757         return 0;
758     }
759 
runSetLetterboxBackgroundColorResource(PrintWriter pw)760     private int runSetLetterboxBackgroundColorResource(PrintWriter pw) throws RemoteException {
761         final int colorId;
762         try {
763             String arg = getNextArgRequired();
764             colorId = mInternal.mContext.getResources()
765                     .getIdentifier(arg, "color", "com.android.internal");
766         } catch (NotFoundException e) {
767             getErrPrintWriter().println(
768                     "Error: color in '@android:color/resource_name' format should be provided as "
769                             + "an argument " + e);
770             return -1;
771         }
772         synchronized (mInternal.mGlobalLock) {
773             mLetterboxConfiguration.setLetterboxBackgroundColorResourceId(colorId);
774         }
775         return 0;
776     }
777 
runSetLetterboxBackgroundColor(PrintWriter pw)778     private int runSetLetterboxBackgroundColor(PrintWriter pw) throws RemoteException {
779         final Color color;
780         try {
781             String arg = getNextArgRequired();
782             color = Color.valueOf(Color.parseColor(arg));
783         } catch (IllegalArgumentException  e) {
784             getErrPrintWriter().println(
785                     "Error: color in #RRGGBB format should be provided as "
786                             + "an argument " + e);
787             return -1;
788         }
789         synchronized (mInternal.mGlobalLock) {
790             mLetterboxConfiguration.setLetterboxBackgroundColor(color);
791         }
792         return 0;
793     }
794 
runSetLetterboxBackgroundWallpaperBlurRadius(PrintWriter pw)795     private int runSetLetterboxBackgroundWallpaperBlurRadius(PrintWriter pw)
796             throws RemoteException {
797         final int radiusDp;
798         try {
799             String arg = getNextArgRequired();
800             radiusDp = Integer.parseInt(arg);
801         } catch (NumberFormatException  e) {
802             getErrPrintWriter().println("Error: blur radius format " + e);
803             return -1;
804         } catch (IllegalArgumentException  e) {
805             getErrPrintWriter().println(
806                     "Error: blur radius should be provided as an argument " + e);
807             return -1;
808         }
809         synchronized (mInternal.mGlobalLock) {
810             final int radiusPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
811                     radiusDp, mInternal.mContext.getResources().getDisplayMetrics());
812             mLetterboxConfiguration.setLetterboxBackgroundWallpaperBlurRadiusPx(radiusPx);
813         }
814         return 0;
815     }
816 
runSetLetterboxBackgroundWallpaperDarkScrimAlpha(PrintWriter pw)817     private int runSetLetterboxBackgroundWallpaperDarkScrimAlpha(PrintWriter pw)
818             throws RemoteException {
819         final float alpha;
820         try {
821             String arg = getNextArgRequired();
822             alpha = Float.parseFloat(arg);
823         } catch (NumberFormatException  e) {
824             getErrPrintWriter().println("Error: bad alpha format " + e);
825             return -1;
826         } catch (IllegalArgumentException  e) {
827             getErrPrintWriter().println(
828                     "Error: alpha should be provided as an argument " + e);
829             return -1;
830         }
831         synchronized (mInternal.mGlobalLock) {
832             mLetterboxConfiguration.setLetterboxBackgroundWallpaperDarkScrimAlpha(alpha);
833         }
834         return 0;
835     }
836 
runSetLetterboxHorizontalPositionMultiplier(PrintWriter pw)837     private int runSetLetterboxHorizontalPositionMultiplier(PrintWriter pw) throws RemoteException {
838         final float multiplier;
839         try {
840             String arg = getNextArgRequired();
841             multiplier = Float.parseFloat(arg);
842         } catch (NumberFormatException  e) {
843             getErrPrintWriter().println("Error: bad multiplier format " + e);
844             return -1;
845         } catch (IllegalArgumentException  e) {
846             getErrPrintWriter().println(
847                     "Error: multiplier should be provided as an argument " + e);
848             return -1;
849         }
850         synchronized (mInternal.mGlobalLock) {
851             try {
852                 mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(multiplier);
853             } catch (IllegalArgumentException  e) {
854                 getErrPrintWriter().println("Error: invalid multiplier value " + e);
855                 return -1;
856             }
857         }
858         return 0;
859     }
860 
runSetLetterboxVerticalPositionMultiplier(PrintWriter pw)861     private int runSetLetterboxVerticalPositionMultiplier(PrintWriter pw) throws RemoteException {
862         final float multiplier;
863         try {
864             String arg = getNextArgRequired();
865             multiplier = Float.parseFloat(arg);
866         } catch (NumberFormatException  e) {
867             getErrPrintWriter().println("Error: bad multiplier format " + e);
868             return -1;
869         } catch (IllegalArgumentException  e) {
870             getErrPrintWriter().println(
871                     "Error: multiplier should be provided as an argument " + e);
872             return -1;
873         }
874         synchronized (mInternal.mGlobalLock) {
875             try {
876                 mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(multiplier);
877             } catch (IllegalArgumentException  e) {
878                 getErrPrintWriter().println("Error: invalid multiplier value " + e);
879                 return -1;
880             }
881         }
882         return 0;
883     }
884 
runSetLetterboxDefaultPositionForHorizontalReachability(PrintWriter pw)885     private int runSetLetterboxDefaultPositionForHorizontalReachability(PrintWriter pw)
886             throws RemoteException {
887         @LetterboxHorizontalReachabilityPosition final int position;
888         try {
889             String arg = getNextArgRequired();
890             switch (arg) {
891                 case "left":
892                     position = LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
893                     break;
894                 case "center":
895                     position = LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
896                     break;
897                 case "right":
898                     position = LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
899                     break;
900                 default:
901                     getErrPrintWriter().println(
902                             "Error: 'left', 'center' or 'right' are expected as an argument");
903                     return -1;
904             }
905         } catch (IllegalArgumentException  e) {
906             getErrPrintWriter().println(
907                     "Error: 'left', 'center' or 'right' are expected as an argument" + e);
908             return -1;
909         }
910         synchronized (mInternal.mGlobalLock) {
911             mLetterboxConfiguration.setDefaultPositionForHorizontalReachability(position);
912         }
913         return 0;
914     }
915 
runSetLetterboxDefaultPositionForVerticalReachability(PrintWriter pw)916     private int runSetLetterboxDefaultPositionForVerticalReachability(PrintWriter pw)
917             throws RemoteException {
918         @LetterboxVerticalReachabilityPosition final int position;
919         try {
920             String arg = getNextArgRequired();
921             switch (arg) {
922                 case "top":
923                     position = LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
924                     break;
925                 case "center":
926                     position = LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
927                     break;
928                 case "bottom":
929                     position = LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM;
930                     break;
931                 default:
932                     getErrPrintWriter().println(
933                             "Error: 'top', 'center' or 'bottom' are expected as an argument");
934                     return -1;
935             }
936         } catch (IllegalArgumentException  e) {
937             getErrPrintWriter().println(
938                     "Error: 'top', 'center' or 'bottom' are expected as an argument" + e);
939             return -1;
940         }
941         synchronized (mInternal.mGlobalLock) {
942             mLetterboxConfiguration.setDefaultPositionForVerticalReachability(position);
943         }
944         return 0;
945     }
946 
runSetPersistentLetterboxPositionForHorizontalReachability(PrintWriter pw)947     private int runSetPersistentLetterboxPositionForHorizontalReachability(PrintWriter pw)
948             throws RemoteException {
949         @LetterboxHorizontalReachabilityPosition final int position;
950         try {
951             String arg = getNextArgRequired();
952             switch (arg) {
953                 case "left":
954                     position = LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
955                     break;
956                 case "center":
957                     position = LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
958                     break;
959                 case "right":
960                     position = LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
961                     break;
962                 default:
963                     getErrPrintWriter().println(
964                             "Error: 'left', 'center' or 'right' are expected as an argument");
965                     return -1;
966             }
967         } catch (IllegalArgumentException e) {
968             getErrPrintWriter().println(
969                     "Error: 'left', 'center' or 'right' are expected as an argument" + e);
970             return -1;
971         }
972         synchronized (mInternal.mGlobalLock) {
973             mLetterboxConfiguration.setPersistentLetterboxPositionForHorizontalReachability(
974                     false /* IsInBookMode */, position);
975         }
976         return 0;
977     }
978 
runSetPersistentLetterboxPositionForVerticalReachability(PrintWriter pw)979     private int runSetPersistentLetterboxPositionForVerticalReachability(PrintWriter pw)
980             throws RemoteException {
981         @LetterboxVerticalReachabilityPosition final int position;
982         try {
983             String arg = getNextArgRequired();
984             switch (arg) {
985                 case "top":
986                     position = LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
987                     break;
988                 case "center":
989                     position = LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
990                     break;
991                 case "bottom":
992                     position = LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM;
993                     break;
994                 default:
995                     getErrPrintWriter().println(
996                             "Error: 'top', 'center' or 'bottom' are expected as an argument");
997                     return -1;
998             }
999         } catch (IllegalArgumentException e) {
1000             getErrPrintWriter().println(
1001                     "Error: 'top', 'center' or 'bottom' are expected as an argument" + e);
1002             return -1;
1003         }
1004         synchronized (mInternal.mGlobalLock) {
1005             mLetterboxConfiguration.setPersistentLetterboxPositionForVerticalReachability(
1006                     false /* forTabletopMode */, position);
1007         }
1008         return 0;
1009     }
1010 
runSetBooleanFlag(PrintWriter pw, Consumer<Boolean> setter)1011     private int runSetBooleanFlag(PrintWriter pw, Consumer<Boolean> setter)
1012             throws RemoteException {
1013         String arg = getNextArg();
1014         if (arg == null) {
1015             getErrPrintWriter().println("Error: expected true, 1, false, 0, but got empty input.");
1016             return -1;
1017         }
1018         final boolean enabled;
1019         switch (arg) {
1020             case "true":
1021             case "1":
1022                 enabled = true;
1023                 break;
1024             case "false":
1025             case "0":
1026                 enabled = false;
1027                 break;
1028             default:
1029                 getErrPrintWriter().println("Error: expected true, 1, false, 0, but got " + arg);
1030                 return -1;
1031         }
1032 
1033         synchronized (mInternal.mGlobalLock) {
1034             setter.accept(enabled);
1035         }
1036         return 0;
1037     }
1038 
runSetLetterboxStyle(PrintWriter pw)1039     private int runSetLetterboxStyle(PrintWriter pw) throws RemoteException {
1040         if (peekNextArg() == null) {
1041             getErrPrintWriter().println("Error: No arguments provided.");
1042         }
1043         while (peekNextArg() != null) {
1044             String arg = getNextArg();
1045             switch (arg) {
1046                 case "--aspectRatio":
1047                     runSetFixedOrientationLetterboxAspectRatio(pw);
1048                     break;
1049                 case "--minAspectRatioForUnresizable":
1050                     runSetDefaultMinAspectRatioForUnresizableApps(pw);
1051                     break;
1052                 case "--cornerRadius":
1053                     runSetLetterboxActivityCornersRadius(pw);
1054                     break;
1055                 case "--backgroundType":
1056                     runSetLetterboxBackgroundType(pw);
1057                     break;
1058                 case "--backgroundColor":
1059                     runSetLetterboxBackgroundColor(pw);
1060                     break;
1061                 case "--backgroundColorResource":
1062                     runSetLetterboxBackgroundColorResource(pw);
1063                     break;
1064                 case "--wallpaperBlurRadius":
1065                     runSetLetterboxBackgroundWallpaperBlurRadius(pw);
1066                     break;
1067                 case "--wallpaperDarkScrimAlpha":
1068                     runSetLetterboxBackgroundWallpaperDarkScrimAlpha(pw);
1069                     break;
1070                 case "--horizontalPositionMultiplier":
1071                     runSetLetterboxHorizontalPositionMultiplier(pw);
1072                     break;
1073                 case "--verticalPositionMultiplier":
1074                     runSetLetterboxVerticalPositionMultiplier(pw);
1075                     break;
1076                 case "--isHorizontalReachabilityEnabled":
1077                     runSetBooleanFlag(pw, mLetterboxConfiguration
1078                             ::setIsHorizontalReachabilityEnabled);
1079                     break;
1080                 case "--isVerticalReachabilityEnabled":
1081                     runSetBooleanFlag(pw, mLetterboxConfiguration
1082                             ::setIsVerticalReachabilityEnabled);
1083                     break;
1084                 case "--isAutomaticReachabilityInBookModeEnabled":
1085                     runSetBooleanFlag(pw, mLetterboxConfiguration
1086                             ::setIsAutomaticReachabilityInBookModeEnabled);
1087                     break;
1088                 case "--defaultPositionForHorizontalReachability":
1089                     runSetLetterboxDefaultPositionForHorizontalReachability(pw);
1090                     break;
1091                 case "--defaultPositionForVerticalReachability":
1092                     runSetLetterboxDefaultPositionForVerticalReachability(pw);
1093                     break;
1094                 case "--persistentPositionForHorizontalReachability":
1095                     runSetPersistentLetterboxPositionForHorizontalReachability(pw);
1096                     break;
1097                 case "--persistentPositionForVerticalReachability":
1098                     runSetPersistentLetterboxPositionForVerticalReachability(pw);
1099                     break;
1100                 case "--isEducationEnabled":
1101                     runSetBooleanFlag(pw, mLetterboxConfiguration::setIsEducationEnabled);
1102                     break;
1103                 case "--isSplitScreenAspectRatioForUnresizableAppsEnabled":
1104                     runSetBooleanFlag(pw, mLetterboxConfiguration
1105                             ::setIsSplitScreenAspectRatioForUnresizableAppsEnabled);
1106                     break;
1107                 case "--isDisplayAspectRatioEnabledForFixedOrientationLetterbox":
1108                     runSetBooleanFlag(pw, mLetterboxConfiguration
1109                             ::setIsDisplayAspectRatioEnabledForFixedOrientationLetterbox);
1110                     break;
1111                 case "--isTranslucentLetterboxingEnabled":
1112                     runSetBooleanFlag(pw, mLetterboxConfiguration
1113                             ::setTranslucentLetterboxingOverrideEnabled);
1114                     break;
1115                 case "--isUserAppAspectRatioSettingsEnabled":
1116                     runSetBooleanFlag(pw, mLetterboxConfiguration
1117                             ::setUserAppAspectRatioSettingsOverrideEnabled);
1118                     break;
1119                 case "--isUserAppAspectRatioFullscreenEnabled":
1120                     runSetBooleanFlag(pw, mLetterboxConfiguration
1121                             ::setUserAppAspectRatioFullscreenOverrideEnabled);
1122                     break;
1123                 case "--isCameraCompatRefreshEnabled":
1124                     runSetBooleanFlag(pw, mLetterboxConfiguration::setCameraCompatRefreshEnabled);
1125                     break;
1126                 case "--isCameraCompatRefreshCycleThroughStopEnabled":
1127                     runSetBooleanFlag(pw,
1128                             mLetterboxConfiguration::setCameraCompatRefreshCycleThroughStopEnabled);
1129                     break;
1130                 default:
1131                     getErrPrintWriter().println(
1132                             "Error: Unrecognized letterbox style option: " + arg);
1133                     return -1;
1134             }
1135         }
1136         return 0;
1137     }
1138 
runResetLetterboxStyle(PrintWriter pw)1139     private int runResetLetterboxStyle(PrintWriter pw) throws RemoteException {
1140         if (peekNextArg() == null) {
1141             resetLetterboxStyle();
1142         }
1143         synchronized (mInternal.mGlobalLock) {
1144             while (peekNextArg() != null) {
1145                 String arg = getNextArg();
1146                 switch (arg) {
1147                     case "aspectRatio":
1148                         mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio();
1149                         break;
1150                     case "minAspectRatioForUnresizable":
1151                         mLetterboxConfiguration.resetDefaultMinAspectRatioForUnresizableApps();
1152                         break;
1153                     case "cornerRadius":
1154                         mLetterboxConfiguration.resetLetterboxActivityCornersRadius();
1155                         break;
1156                     case "backgroundType":
1157                         mLetterboxConfiguration.resetLetterboxBackgroundType();
1158                         break;
1159                     case "backgroundColor":
1160                         mLetterboxConfiguration.resetLetterboxBackgroundColor();
1161                         break;
1162                     case "wallpaperBlurRadius":
1163                         mLetterboxConfiguration.resetLetterboxBackgroundWallpaperBlurRadiusPx();
1164                         break;
1165                     case "wallpaperDarkScrimAlpha":
1166                         mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha();
1167                         break;
1168                     case "horizontalPositionMultiplier":
1169                         mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
1170                         break;
1171                     case "verticalPositionMultiplier":
1172                         mLetterboxConfiguration.resetLetterboxVerticalPositionMultiplier();
1173                         break;
1174                     case "isHorizontalReachabilityEnabled":
1175                         mLetterboxConfiguration.resetIsHorizontalReachabilityEnabled();
1176                         break;
1177                     case "isVerticalReachabilityEnabled":
1178                         mLetterboxConfiguration.resetIsVerticalReachabilityEnabled();
1179                         break;
1180                     case "defaultPositionForHorizontalReachability":
1181                         mLetterboxConfiguration.resetDefaultPositionForHorizontalReachability();
1182                         break;
1183                     case "defaultPositionForVerticalReachability":
1184                         mLetterboxConfiguration.resetDefaultPositionForVerticalReachability();
1185                         break;
1186                     case "persistentPositionForHorizontalReachability":
1187                         mLetterboxConfiguration
1188                                 .resetPersistentLetterboxPositionForHorizontalReachability();
1189                         break;
1190                     case "persistentPositionForVerticalReachability":
1191                         mLetterboxConfiguration
1192                                 .resetPersistentLetterboxPositionForVerticalReachability();
1193                         break;
1194                     case "isEducationEnabled":
1195                         mLetterboxConfiguration.resetIsEducationEnabled();
1196                         break;
1197                     case "isSplitScreenAspectRatioForUnresizableAppsEnabled":
1198                         mLetterboxConfiguration
1199                                 .resetIsSplitScreenAspectRatioForUnresizableAppsEnabled();
1200                         break;
1201                     case "IsDisplayAspectRatioEnabledForFixedOrientationLetterbox":
1202                         mLetterboxConfiguration
1203                                 .resetIsDisplayAspectRatioEnabledForFixedOrientationLetterbox();
1204                         break;
1205                     case "isTranslucentLetterboxingEnabled":
1206                         mLetterboxConfiguration.resetTranslucentLetterboxingEnabled();
1207                         break;
1208                     case "isUserAppAspectRatioSettingsEnabled":
1209                         mLetterboxConfiguration.resetUserAppAspectRatioSettingsEnabled();
1210                         break;
1211                     case "isUserAppAspectRatioFullscreenEnabled":
1212                         mLetterboxConfiguration.resetUserAppAspectRatioFullscreenEnabled();
1213                         break;
1214                     case "isCameraCompatRefreshEnabled":
1215                         mLetterboxConfiguration.resetCameraCompatRefreshEnabled();
1216                         break;
1217                     case "isCameraCompatRefreshCycleThroughStopEnabled":
1218                         mLetterboxConfiguration
1219                                 .resetCameraCompatRefreshCycleThroughStopEnabled();
1220                         break;
1221                     default:
1222                         getErrPrintWriter().println(
1223                                 "Error: Unrecognized letterbox style option: " + arg);
1224                         return -1;
1225                 }
1226             }
1227         }
1228         return 0;
1229     }
1230 
runSetMultiWindowConfig()1231     private int runSetMultiWindowConfig() {
1232         if (peekNextArg() == null) {
1233             getErrPrintWriter().println("Error: No arguments provided.");
1234         }
1235         int result = 0;
1236         while (peekNextArg() != null) {
1237             String arg = getNextArg();
1238             switch (arg) {
1239                 case "--supportsNonResizable":
1240                     result += runSetSupportsNonResizableMultiWindow();
1241                     break;
1242                 case "--respectsActivityMinWidthHeight":
1243                     result += runSetRespectsActivityMinWidthHeightMultiWindow();
1244                     break;
1245                 default:
1246                     getErrPrintWriter().println(
1247                             "Error: Unrecognized multi window option: " + arg);
1248                     return -1;
1249             }
1250         }
1251         return result == 0 ? 0 : -1;
1252     }
1253 
runSetSupportsNonResizableMultiWindow()1254     private int runSetSupportsNonResizableMultiWindow() {
1255         final String arg = getNextArg();
1256         if (!arg.equals("-1") && !arg.equals("0") && !arg.equals("1")) {
1257             getErrPrintWriter().println("Error: a config value of [-1, 0, 1] must be provided as"
1258                     + " an argument for supportsNonResizableMultiWindow");
1259             return -1;
1260         }
1261         final int configValue = Integer.parseInt(arg);
1262         synchronized (mInternal.mAtmService.mGlobalLock) {
1263             mInternal.mAtmService.mSupportsNonResizableMultiWindow = configValue;
1264         }
1265         return 0;
1266     }
1267 
runSetRespectsActivityMinWidthHeightMultiWindow()1268     private int runSetRespectsActivityMinWidthHeightMultiWindow() {
1269         final String arg = getNextArg();
1270         if (!arg.equals("-1") && !arg.equals("0") && !arg.equals("1")) {
1271             getErrPrintWriter().println("Error: a config value of [-1, 0, 1] must be provided as"
1272                     + " an argument for respectsActivityMinWidthHeightMultiWindow");
1273             return -1;
1274         }
1275         final int configValue = Integer.parseInt(arg);
1276         synchronized (mInternal.mAtmService.mGlobalLock) {
1277             mInternal.mAtmService.mRespectsActivityMinWidthHeightMultiWindow = configValue;
1278         }
1279         return 0;
1280     }
1281 
runGetMultiWindowConfig(PrintWriter pw)1282     private int runGetMultiWindowConfig(PrintWriter pw) {
1283         synchronized (mInternal.mAtmService.mGlobalLock) {
1284             pw.println("Supports non-resizable in multi window: "
1285                     + mInternal.mAtmService.mSupportsNonResizableMultiWindow);
1286             pw.println("Respects activity min width/height in multi window: "
1287                     + mInternal.mAtmService.mRespectsActivityMinWidthHeightMultiWindow);
1288         }
1289         return 0;
1290     }
1291 
runResetMultiWindowConfig()1292     private int runResetMultiWindowConfig() {
1293         final int supportsNonResizable = mInternal.mContext.getResources().getInteger(
1294                 com.android.internal.R.integer.config_supportsNonResizableMultiWindow);
1295         final int respectsActivityMinWidthHeight = mInternal.mContext.getResources().getInteger(
1296                 com.android.internal.R.integer.config_respectsActivityMinWidthHeightMultiWindow);
1297         synchronized (mInternal.mAtmService.mGlobalLock) {
1298             mInternal.mAtmService.mSupportsNonResizableMultiWindow = supportsNonResizable;
1299             mInternal.mAtmService.mRespectsActivityMinWidthHeightMultiWindow =
1300                     respectsActivityMinWidthHeight;
1301         }
1302         return 0;
1303     }
1304 
resetLetterboxStyle()1305     private void resetLetterboxStyle() {
1306         synchronized (mInternal.mGlobalLock) {
1307             mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio();
1308             mLetterboxConfiguration.resetDefaultMinAspectRatioForUnresizableApps();
1309             mLetterboxConfiguration.resetLetterboxActivityCornersRadius();
1310             mLetterboxConfiguration.resetLetterboxBackgroundType();
1311             mLetterboxConfiguration.resetLetterboxBackgroundColor();
1312             mLetterboxConfiguration.resetLetterboxBackgroundWallpaperBlurRadiusPx();
1313             mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha();
1314             mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
1315             mLetterboxConfiguration.resetLetterboxVerticalPositionMultiplier();
1316             mLetterboxConfiguration.resetIsHorizontalReachabilityEnabled();
1317             mLetterboxConfiguration.resetIsVerticalReachabilityEnabled();
1318             mLetterboxConfiguration.resetEnabledAutomaticReachabilityInBookMode();
1319             mLetterboxConfiguration.resetDefaultPositionForHorizontalReachability();
1320             mLetterboxConfiguration.resetDefaultPositionForVerticalReachability();
1321             mLetterboxConfiguration.resetPersistentLetterboxPositionForHorizontalReachability();
1322             mLetterboxConfiguration.resetPersistentLetterboxPositionForVerticalReachability();
1323             mLetterboxConfiguration.resetIsEducationEnabled();
1324             mLetterboxConfiguration.resetIsSplitScreenAspectRatioForUnresizableAppsEnabled();
1325             mLetterboxConfiguration.resetIsDisplayAspectRatioEnabledForFixedOrientationLetterbox();
1326             mLetterboxConfiguration.resetTranslucentLetterboxingEnabled();
1327             mLetterboxConfiguration.resetUserAppAspectRatioSettingsEnabled();
1328             mLetterboxConfiguration.resetUserAppAspectRatioFullscreenEnabled();
1329             mLetterboxConfiguration.resetCameraCompatRefreshEnabled();
1330             mLetterboxConfiguration.resetCameraCompatRefreshCycleThroughStopEnabled();
1331         }
1332     }
1333 
runGetLetterboxStyle(PrintWriter pw)1334     private int runGetLetterboxStyle(PrintWriter pw) throws RemoteException {
1335         synchronized (mInternal.mGlobalLock) {
1336             pw.println("Corner radius: "
1337                     + mLetterboxConfiguration.getLetterboxActivityCornersRadius());
1338             pw.println("Horizontal position multiplier: "
1339                     + mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier(
1340                             false /* isInBookMode */));
1341             pw.println("Vertical position multiplier: "
1342                     + mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier(
1343                             false /* isInTabletopMode */));
1344             pw.println("Horizontal position multiplier (book mode): "
1345                     + mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier(
1346                             true /* isInBookMode */));
1347             pw.println("Vertical position multiplier (tabletop mode): "
1348                     + mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier(
1349                             true /* isInTabletopMode */));
1350             pw.println("Horizontal position multiplier for reachability: "
1351                     + mLetterboxConfiguration.getHorizontalMultiplierForReachability(
1352                             false /* isInBookMode */));
1353             pw.println("Vertical position multiplier for reachability: "
1354                     + mLetterboxConfiguration.getVerticalMultiplierForReachability(
1355                             false /* isInTabletopMode */));
1356             pw.println("Aspect ratio: "
1357                     + mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio());
1358             pw.println("Default min aspect ratio for unresizable apps: "
1359                     + mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps());
1360             pw.println("Is horizontal reachability enabled: "
1361                     + mLetterboxConfiguration.getIsHorizontalReachabilityEnabled());
1362             pw.println("Is vertical reachability enabled: "
1363                     + mLetterboxConfiguration.getIsVerticalReachabilityEnabled());
1364             pw.println("Is automatic reachability in book mode enabled: "
1365                     + mLetterboxConfiguration.getIsAutomaticReachabilityInBookModeEnabled());
1366             pw.println("Default position for horizontal reachability: "
1367                     + LetterboxConfiguration.letterboxHorizontalReachabilityPositionToString(
1368                             mLetterboxConfiguration.getDefaultPositionForHorizontalReachability()));
1369             pw.println("Default position for vertical reachability: "
1370                     + LetterboxConfiguration.letterboxVerticalReachabilityPositionToString(
1371                     mLetterboxConfiguration.getDefaultPositionForVerticalReachability()));
1372             pw.println("Current position for horizontal reachability:"
1373                     + LetterboxConfiguration.letterboxHorizontalReachabilityPositionToString(
1374                     mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability(false)));
1375             pw.println("Current position for vertical reachability:"
1376                     + LetterboxConfiguration.letterboxVerticalReachabilityPositionToString(
1377                     mLetterboxConfiguration.getLetterboxPositionForVerticalReachability(false)));
1378             pw.println("Is education enabled: "
1379                     + mLetterboxConfiguration.getIsEducationEnabled());
1380             pw.println("Is using split screen aspect ratio as aspect ratio for unresizable apps: "
1381                     + mLetterboxConfiguration
1382                             .getIsSplitScreenAspectRatioForUnresizableAppsEnabled());
1383             pw.println("Is using display aspect ratio as aspect ratio for all letterboxed apps: "
1384                     + mLetterboxConfiguration
1385                             .getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox());
1386             pw.println("    Is activity \"refresh\" in camera compatibility treatment enabled: "
1387                     + mLetterboxConfiguration.isCameraCompatRefreshEnabled());
1388             pw.println("    Refresh using \"stopped -> resumed\" cycle: "
1389                     + mLetterboxConfiguration.isCameraCompatRefreshCycleThroughStopEnabled());
1390             pw.println("Background type: "
1391                     + LetterboxConfiguration.letterboxBackgroundTypeToString(
1392                             mLetterboxConfiguration.getLetterboxBackgroundType()));
1393             pw.println("    Background color: " + Integer.toHexString(
1394                     mLetterboxConfiguration.getLetterboxBackgroundColor().toArgb()));
1395             pw.println("    Wallpaper blur radius: "
1396                     + mLetterboxConfiguration.getLetterboxBackgroundWallpaperBlurRadiusPx());
1397             pw.println("    Wallpaper dark scrim alpha: "
1398                     + mLetterboxConfiguration.getLetterboxBackgroundWallpaperDarkScrimAlpha());
1399             pw.println("Is letterboxing for translucent activities enabled: "
1400                     + mLetterboxConfiguration.isTranslucentLetterboxingEnabled());
1401             pw.println("Is the user aspect ratio settings enabled: "
1402                     + mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled());
1403             pw.println("Is the fullscreen option in user aspect ratio settings enabled: "
1404                     + mLetterboxConfiguration.isUserAppAspectRatioFullscreenEnabled());
1405         }
1406         return 0;
1407     }
1408 
runWmShellCommand(PrintWriter pw)1409     private int runWmShellCommand(PrintWriter pw) {
1410         String arg = getNextArg();
1411 
1412         switch (arg) {
1413             case "tracing":
1414                 return runWmShellTracing(pw);
1415             case "help":
1416             default:
1417                 return runHelp(pw);
1418         }
1419     }
1420 
runHelp(PrintWriter pw)1421     private int runHelp(PrintWriter pw) {
1422         pw.println("Window Manager Shell commands:");
1423         pw.println("  help");
1424         pw.println("    Print this help text.");
1425         pw.println("  tracing <start/stop>");
1426         pw.println("    Start/stop shell transition tracing.");
1427 
1428         return 0;
1429     }
1430 
runWmShellTracing(PrintWriter pw)1431     private int runWmShellTracing(PrintWriter pw) {
1432         String arg = getNextArg();
1433 
1434         switch (arg) {
1435             case "start":
1436                 mInternal.mTransitionTracer.startTrace(pw);
1437                 break;
1438             case "stop":
1439                 mInternal.mTransitionTracer.stopTrace(pw);
1440                 break;
1441             case "save-for-bugreport":
1442                 mInternal.mTransitionTracer.saveForBugreport(pw);
1443                 break;
1444             default:
1445                 getErrPrintWriter()
1446                         .println("Error: expected 'start' or 'stop', but got '" + arg + "'");
1447                 return -1;
1448         }
1449 
1450         return 0;
1451     }
1452 
runReset(PrintWriter pw)1453     private int runReset(PrintWriter pw) throws RemoteException {
1454         int displayId = getDisplayId(getNextArg());
1455 
1456         // size
1457         mInterface.clearForcedDisplaySize(displayId);
1458 
1459         // density
1460         mInterface.clearForcedDisplayDensityForUser(displayId, UserHandle.USER_CURRENT);
1461 
1462         // folded-area
1463         mInternal.setOverrideFoldedArea(new Rect());
1464 
1465         // scaling
1466         mInterface.setForcedDisplayScalingMode(displayId, DisplayContent.FORCE_SCALING_MODE_AUTO);
1467 
1468         // user-rotation
1469         mInternal.thawDisplayRotation(displayId,
1470                 /* caller= */ "WindowManagerShellCommand#runReset");
1471 
1472         // fixed-to-user-rotation
1473         mInterface.setFixedToUserRotation(displayId, IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT);
1474 
1475         // set-ignore-orientation-request
1476         mInterface.setIgnoreOrientationRequest(displayId, false /* ignoreOrientationRequest */);
1477 
1478         // set-letterbox-style
1479         resetLetterboxStyle();
1480 
1481         // set-sandbox-display-apis
1482         mInternal.setSandboxDisplayApis(displayId, /* sandboxDisplayApis= */ true);
1483 
1484         // set-multi-window-config
1485         runResetMultiWindowConfig();
1486 
1487         pw.println("Reset all settings for displayId=" + displayId);
1488         return 0;
1489     }
1490 
1491     @Override
onHelp()1492     public void onHelp() {
1493         PrintWriter pw = getOutPrintWriter();
1494         pw.println("Window manager (window) commands:");
1495         pw.println("  help");
1496         pw.println("      Print this help text.");
1497         pw.println("  size [reset|WxH|WdpxHdp] [-d DISPLAY_ID]");
1498         pw.println("    Return or override display size.");
1499         pw.println("    width and height in pixels unless suffixed with 'dp'.");
1500         pw.println("  density [reset|DENSITY] [-d DISPLAY_ID] [-u UNIQUE_ID]");
1501         pw.println("    Return or override display density.");
1502         pw.println("  folded-area [reset|LEFT,TOP,RIGHT,BOTTOM]");
1503         pw.println("    Return or override folded area.");
1504         pw.println("  scaling [off|auto] [-d DISPLAY_ID]");
1505         pw.println("    Set display scaling mode.");
1506         pw.println("  dismiss-keyguard");
1507         pw.println("    Dismiss the keyguard, prompting user for auth if necessary.");
1508         pw.println("  disable-blur [true|1|false|0]");
1509         pw.println("  user-rotation [-d DISPLAY_ID] [free|lock] [rotation]");
1510         pw.println("    Print or set user rotation mode and user rotation.");
1511         pw.println("  dump-visible-window-views");
1512         pw.println("    Dumps the encoded view hierarchies of visible windows");
1513         pw.println("  fixed-to-user-rotation [-d DISPLAY_ID] [enabled|disabled|default");
1514         pw.println("      |enabled_if_no_auto_rotation]");
1515         pw.println("    Print or set rotating display for app requested orientation.");
1516         pw.println("  set-ignore-orientation-request [-d DISPLAY_ID] [true|1|false|0]");
1517         pw.println("  get-ignore-orientation-request [-d DISPLAY_ID] ");
1518         pw.println("    If app requested orientation should be ignored.");
1519         pw.println("  set-sandbox-display-apis [true|1|false|0]");
1520         pw.println("    Sets override of Display APIs getRealSize / getRealMetrics to reflect ");
1521         pw.println("    DisplayArea of the activity, or the window bounds if in letterbox or");
1522         pw.println("    Size Compat Mode.");
1523 
1524         printLetterboxHelp(pw);
1525         printMultiWindowConfigHelp(pw);
1526 
1527         pw.println("  reset [-d DISPLAY_ID]");
1528         pw.println("    Reset all override settings.");
1529         if (!IS_USER) {
1530             pw.println("  tracing (start | stop)");
1531             pw.println("    Start or stop window tracing.");
1532             pw.println("  logging (start | stop | enable | disable | enable-text | disable-text)");
1533             pw.println("    Logging settings.");
1534         }
1535     }
1536 
printLetterboxHelp(PrintWriter pw)1537     private void printLetterboxHelp(PrintWriter pw) {
1538         pw.println("  set-letterbox-style");
1539         pw.println("    Sets letterbox style using the following options:");
1540         pw.println("      --aspectRatio aspectRatio");
1541         pw.println("        Aspect ratio of letterbox for fixed orientation. If aspectRatio <= "
1542                 + LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO);
1543         pw.println("        both it and R.dimen.config_fixedOrientationLetterboxAspectRatio will");
1544         pw.println("        be ignored and framework implementation will determine aspect ratio.");
1545         pw.println("      --minAspectRatioForUnresizable aspectRatio");
1546         pw.println("        Default min aspect ratio for unresizable apps which is used when an");
1547         pw.println("        app is eligible for the size compat mode.  If aspectRatio <= "
1548                 + LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO);
1549         pw.println("        both it and R.dimen.config_fixedOrientationLetterboxAspectRatio will");
1550         pw.println("        be ignored and framework implementation will determine aspect ratio.");
1551         pw.println("      --cornerRadius radius");
1552         pw.println("        Corners radius (in pixels) for activities in the letterbox mode.");
1553         pw.println("        If radius < 0, both R.integer.config_letterboxActivityCornersRadius");
1554         pw.println("        and it will be ignored and corners of the activity won't be rounded.");
1555         pw.println("      --backgroundType [reset|solid_color|app_color_background");
1556         pw.println("          |app_color_background_floating|wallpaper]");
1557         pw.println("        Type of background used in the letterbox mode.");
1558         pw.println("      --backgroundColor color");
1559         pw.println("        Color of letterbox which is be used when letterbox background type");
1560         pw.println("        is 'solid-color'. Use (set)get-letterbox-style to check and control");
1561         pw.println("        letterbox background type. See Color#parseColor for allowed color");
1562         pw.println("        formats (#RRGGBB and some colors by name, e.g. magenta or olive).");
1563         pw.println("      --backgroundColorResource resource_name");
1564         pw.println("        Color resource name of letterbox background which is used when");
1565         pw.println("        background type is 'solid-color'. Use (set)get-letterbox-style to");
1566         pw.println("        check and control background type. Parameter is a color resource");
1567         pw.println("        name, for example, @android:color/system_accent2_50.");
1568         pw.println("      --wallpaperBlurRadius radius");
1569         pw.println("        Blur radius for 'wallpaper' letterbox background. If radius <= 0");
1570         pw.println("        both it and R.dimen.config_letterboxBackgroundWallpaperBlurRadius");
1571         pw.println("        are ignored and 0 is used.");
1572         pw.println("      --wallpaperDarkScrimAlpha alpha");
1573         pw.println("        Alpha of a black translucent scrim shown over 'wallpaper'");
1574         pw.println("        letterbox background. If alpha < 0 or >= 1 both it and");
1575         pw.println("        R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha are ignored");
1576         pw.println("        and 0.0 (transparent) is used instead.");
1577         pw.println("      --horizontalPositionMultiplier multiplier");
1578         pw.println("        Horizontal position of app window center. If multiplier < 0 or > 1,");
1579         pw.println("        both it and R.dimen.config_letterboxHorizontalPositionMultiplier");
1580         pw.println("        are ignored and central position (0.5) is used.");
1581         pw.println("      --verticalPositionMultiplier multiplier");
1582         pw.println("        Vertical position of app window center. If multiplier < 0 or > 1,");
1583         pw.println("        both it and R.dimen.config_letterboxVerticalPositionMultiplier");
1584         pw.println("        are ignored and central position (0.5) is used.");
1585         pw.println("      --isHorizontalReachabilityEnabled [true|1|false|0]");
1586         pw.println("        Whether horizontal reachability repositioning is allowed for ");
1587         pw.println("        letterboxed fullscreen apps in landscape device orientation.");
1588         pw.println("      --isVerticalReachabilityEnabled [true|1|false|0]");
1589         pw.println("        Whether vertical reachability repositioning is allowed for ");
1590         pw.println("        letterboxed fullscreen apps in portrait device orientation.");
1591         pw.println("      --defaultPositionForHorizontalReachability [left|center|right]");
1592         pw.println("        Default position of app window when horizontal reachability is.");
1593         pw.println("        enabled.");
1594         pw.println("      --defaultPositionForVerticalReachability [top|center|bottom]");
1595         pw.println("        Default position of app window when vertical reachability is.");
1596         pw.println("        enabled.");
1597         pw.println("      --persistentPositionForHorizontalReachability [left|center|right]");
1598         pw.println("        Persistent position of app window when horizontal reachability is.");
1599         pw.println("        enabled.");
1600         pw.println("      --persistentPositionForVerticalReachability [top|center|bottom]");
1601         pw.println("        Persistent position of app window when vertical reachability is.");
1602         pw.println("        enabled.");
1603         pw.println("      --isEducationEnabled [true|1|false|0]");
1604         pw.println("        Whether education is allowed for letterboxed fullscreen apps.");
1605         pw.println("      --isSplitScreenAspectRatioForUnresizableAppsEnabled [true|1|false|0]");
1606         pw.println("        Whether using split screen aspect ratio as a default aspect ratio for");
1607         pw.println("        unresizable apps.");
1608         pw.println("      --isTranslucentLetterboxingEnabled [true|1|false|0]");
1609         pw.println("        Whether letterboxing for translucent activities is enabled.");
1610         pw.println("      --isUserAppAspectRatioSettingsEnabled [true|1|false|0]");
1611         pw.println("        Whether user aspect ratio settings are enabled.");
1612         pw.println("      --isUserAppAspectRatioFullscreenEnabled [true|1|false|0]");
1613         pw.println("        Whether user aspect ratio fullscreen option is enabled.");
1614         pw.println("      --isCameraCompatRefreshEnabled [true|1|false|0]");
1615         pw.println("        Whether camera compatibility refresh is enabled.");
1616         pw.println("      --isCameraCompatRefreshCycleThroughStopEnabled [true|1|false|0]");
1617         pw.println("        Whether activity \"refresh\" in camera compatibility treatment should");
1618         pw.println("        happen using the \"stopped -> resumed\" cycle rather than");
1619         pw.println("        \"paused -> resumed\" cycle.");
1620         pw.println("  reset-letterbox-style [aspectRatio|cornerRadius|backgroundType");
1621         pw.println("      |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha");
1622         pw.println("      |horizontalPositionMultiplier|verticalPositionMultiplier");
1623         pw.println("      |isHorizontalReachabilityEnabled|isVerticalReachabilityEnabled");
1624         pw.println("      |isEducationEnabled|defaultPositionMultiplierForHorizontalReachability");
1625         pw.println("      |isTranslucentLetterboxingEnabled|isUserAppAspectRatioSettingsEnabled");
1626         pw.println("      |persistentPositionMultiplierForHorizontalReachability");
1627         pw.println("      |persistentPositionMultiplierForVerticalReachability");
1628         pw.println("      |defaultPositionMultiplierForVerticalReachability]");
1629         pw.println("    Resets overrides to default values for specified properties separated");
1630         pw.println("    by space, e.g. 'reset-letterbox-style aspectRatio cornerRadius'.");
1631         pw.println("    If no arguments provided, all values will be reset.");
1632         pw.println("  get-letterbox-style");
1633         pw.println("    Prints letterbox style configuration.");
1634     }
1635 
printMultiWindowConfigHelp(PrintWriter pw)1636     private void printMultiWindowConfigHelp(PrintWriter pw) {
1637         pw.println("  set-multi-window-config");
1638         pw.println("    Sets options to determine if activity should be shown in multi window:");
1639         pw.println("      --supportsNonResizable [configValue]");
1640         pw.println("        Whether the device supports non-resizable activity in multi window.");
1641         pw.println("        -1: The device doesn't support non-resizable in multi window.");
1642         pw.println("         0: The device supports non-resizable in multi window only if");
1643         pw.println("            this is a large screen device.");
1644         pw.println("         1: The device always supports non-resizable in multi window.");
1645         pw.println("      --respectsActivityMinWidthHeight [configValue]");
1646         pw.println("        Whether the device checks the activity min width/height to determine ");
1647         pw.println("        if it can be shown in multi window.");
1648         pw.println("        -1: The device ignores the activity min width/height when determining");
1649         pw.println("            if it can be shown in multi window.");
1650         pw.println("         0: If this is a small screen, the device compares the activity min");
1651         pw.println("            width/height with the min multi window modes dimensions");
1652         pw.println("            the device supports to determine if the activity can be shown in");
1653         pw.println("            multi window.");
1654         pw.println("         1: The device always compare the activity min width/height with the");
1655         pw.println("            min multi window dimensions the device supports to determine if");
1656         pw.println("            the activity can be shown in multi window.");
1657         pw.println("  get-multi-window-config");
1658         pw.println("    Prints values of the multi window config options.");
1659         pw.println("  reset-multi-window-config");
1660         pw.println("    Resets overrides to default values of the multi window config options.");
1661     }
1662 }
1663