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