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