blob: bf2d0df2bec324b924232c57456f8919798644b0 [file] [log] [blame]
Adrian Roos111aff92017-09-27 18:11:46 +02001/*
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
17package com.android.server.wm;
18
Vishnu Nairab250032017-11-21 07:32:43 -080019import static android.os.Build.IS_USER;
20
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080021import android.graphics.Point;
22import android.graphics.Rect;
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080023import android.os.RemoteException;
Adrian Roos111aff92017-09-27 18:11:46 +020024import android.os.ShellCommand;
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080025import android.os.UserHandle;
26import android.util.DisplayMetrics;
27import android.view.Display;
28import android.view.IWindowManager;
Garfield Tan90c90052018-10-08 12:29:41 -070029import android.view.Surface;
Adrian Roos111aff92017-09-27 18:11:46 +020030
31import java.io.PrintWriter;
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080032import java.util.regex.Matcher;
33import java.util.regex.Pattern;
Adrian Roos111aff92017-09-27 18:11:46 +020034
35/**
36 * ShellCommands for WindowManagerService.
37 *
38 * Use with {@code adb shell cmd window ...}.
39 */
40public class WindowManagerShellCommand extends ShellCommand {
41
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080042 // IPC interface to activity manager -- don't need to do additional security checks.
43 private final IWindowManager mInterface;
44
45 // Internal service impl -- must perform security checks before touching.
46 private final WindowManagerService mInternal;
Adrian Roos111aff92017-09-27 18:11:46 +020047
48 public WindowManagerShellCommand(WindowManagerService service) {
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080049 mInterface = service;
50 mInternal = service;
Adrian Roos111aff92017-09-27 18:11:46 +020051 }
52
53 @Override
54 public int onCommand(String cmd) {
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080055 if (cmd == null) {
56 return handleDefaultCommands(cmd);
Adrian Roos111aff92017-09-27 18:11:46 +020057 }
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080058 final PrintWriter pw = getOutPrintWriter();
59 try {
60 switch (cmd) {
61 case "size":
62 return runDisplaySize(pw);
63 case "density":
64 return runDisplayDensity(pw);
65 case "overscan":
66 return runDisplayOverscan(pw);
67 case "scaling":
68 return runDisplayScaling(pw);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080069 case "dismiss-keyguard":
70 return runDismissKeyguard(pw);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080071 case "tracing":
72 // XXX this should probably be changed to use openFileForSystem() to create
73 // the output trace file, so the shell gets the correct semantics for where
74 // trace files can be written.
75 return mInternal.mWindowTracing.onShellCommand(this,
76 getNextArgRequired());
Garfield Tan90c90052018-10-08 12:29:41 -070077 case "set-user-rotation":
78 return runSetDisplayUserRotation(pw);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080079 default:
80 return handleDefaultCommands(cmd);
81 }
82 } catch (RemoteException e) {
83 pw.println("Remote exception: " + e);
84 }
85 return -1;
86 }
87
Jeff Chang95aa5002018-09-06 16:34:10 +080088 private int getDisplayId(String opt) {
89 int displayId = Display.DEFAULT_DISPLAY;
90 String option = "-d".equals(opt) ? opt : getNextOption();
91 if (option != null && "-d".equals(option)) {
92 try {
93 displayId = Integer.parseInt(getNextArgRequired());
94 } catch (NumberFormatException e) {
95 getErrPrintWriter().println("Error: bad number " + e);
96 } catch (IllegalArgumentException e) {
97 getErrPrintWriter().println("Error: " + e);
98 }
99 }
100 return displayId;
101 }
102
103 private void printInitialDisplaySize(PrintWriter pw , int displayId) {
104 final Point initialSize = new Point();
105 final Point baseSize = new Point();
106
107 try {
108 mInterface.getInitialDisplaySize(displayId, initialSize);
109 mInterface.getBaseDisplaySize(displayId, baseSize);
110 pw.println("Physical size: " + initialSize.x + "x" + initialSize.y);
111 if (!initialSize.equals(baseSize)) {
112 pw.println("Override size: " + baseSize.x + "x" + baseSize.y);
113 }
114 } catch (RemoteException e) {
115 // Can't call getInitialDisplaySize() on IWindowManager or
116 // Can't call getBaseDisplaySize() on IWindowManager
117 pw.println("Remote exception: " + e);
118 }
119 }
120
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800121 private int runDisplaySize(PrintWriter pw) throws RemoteException {
122 String size = getNextArg();
123 int w, h;
Jeff Chang95aa5002018-09-06 16:34:10 +0800124 final int displayId = getDisplayId(size);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800125 if (size == null) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800126 printInitialDisplaySize(pw, displayId);
127 return 0;
128 } else if ("-d".equals(size)) {
129 printInitialDisplaySize(pw, displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800130 return 0;
131 } else if ("reset".equals(size)) {
132 w = h = -1;
133 } else {
134 int div = size.indexOf('x');
135 if (div <= 0 || div >= (size.length()-1)) {
136 getErrPrintWriter().println("Error: bad size " + size);
137 return -1;
138 }
139 String wstr = size.substring(0, div);
140 String hstr = size.substring(div+1);
141 try {
Jeff Chang95aa5002018-09-06 16:34:10 +0800142 w = parseDimension(wstr, displayId);
143 h = parseDimension(hstr, displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800144 } catch (NumberFormatException e) {
145 getErrPrintWriter().println("Error: bad number " + e);
146 return -1;
147 }
148 }
149
150 if (w >= 0 && h >= 0) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800151 mInterface.setForcedDisplaySize(displayId, w, h);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800152 } else {
Jeff Chang95aa5002018-09-06 16:34:10 +0800153 mInterface.clearForcedDisplaySize(displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800154 }
155 return 0;
156 }
157
Jeff Chang95aa5002018-09-06 16:34:10 +0800158 private void printInitialDisplayDensity(PrintWriter pw , int displayId) {
159 try {
160 final int initialDensity = mInterface.getInitialDisplayDensity(displayId);
161 final int baseDensity = mInterface.getBaseDisplayDensity(displayId);
162 pw.println("Physical density: " + initialDensity);
163 if (initialDensity != baseDensity) {
164 pw.println("Override density: " + baseDensity);
165 }
166 } catch (RemoteException e) {
167 // Can't call getInitialDisplayDensity() on IWindowManager or
168 // Can't call getBaseDisplayDensity() on IWindowManager
169 pw.println("Remote exception: " + e);
170 }
171 }
172
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800173 private int runDisplayDensity(PrintWriter pw) throws RemoteException {
174 String densityStr = getNextArg();
175 int density;
Jeff Chang95aa5002018-09-06 16:34:10 +0800176 final int displayId = getDisplayId(densityStr);
177
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800178 if (densityStr == null) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800179 printInitialDisplayDensity(pw, displayId);
180 return 0;
181 } else if ("-d".equals(densityStr)) {
182 printInitialDisplayDensity(pw, displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800183 return 0;
184 } else if ("reset".equals(densityStr)) {
185 density = -1;
186 } else {
187 try {
188 density = Integer.parseInt(densityStr);
189 } catch (NumberFormatException e) {
190 getErrPrintWriter().println("Error: bad number " + e);
191 return -1;
192 }
193 if (density < 72) {
194 getErrPrintWriter().println("Error: density must be >= 72");
195 return -1;
196 }
197 }
198
199 if (density > 0) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800200 mInterface.setForcedDisplayDensityForUser(displayId, density,
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800201 UserHandle.USER_CURRENT);
202 } else {
Jeff Chang95aa5002018-09-06 16:34:10 +0800203 mInterface.clearForcedDisplayDensityForUser(displayId,
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800204 UserHandle.USER_CURRENT);
205 }
206 return 0;
207 }
208
209 private int runDisplayOverscan(PrintWriter pw) throws RemoteException {
210 String overscanStr = getNextArgRequired();
211 Rect rect = new Rect();
Jeff Chang95aa5002018-09-06 16:34:10 +0800212 final int displayId = getDisplayId(overscanStr);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800213 if ("reset".equals(overscanStr)) {
214 rect.set(0, 0, 0, 0);
215 } else {
216 final Pattern FLATTENED_PATTERN = Pattern.compile(
217 "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)");
218 Matcher matcher = FLATTENED_PATTERN.matcher(overscanStr);
219 if (!matcher.matches()) {
220 getErrPrintWriter().println("Error: bad rectangle arg: " + overscanStr);
221 return -1;
222 }
223 rect.left = Integer.parseInt(matcher.group(1));
224 rect.top = Integer.parseInt(matcher.group(2));
225 rect.right = Integer.parseInt(matcher.group(3));
226 rect.bottom = Integer.parseInt(matcher.group(4));
227 }
228
Jeff Chang95aa5002018-09-06 16:34:10 +0800229 mInterface.setOverscan(displayId, rect.left, rect.top, rect.right, rect.bottom);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800230 return 0;
231 }
232
233 private int runDisplayScaling(PrintWriter pw) throws RemoteException {
234 String scalingStr = getNextArgRequired();
235 if ("auto".equals(scalingStr)) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800236 mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr), 0);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800237 } else if ("off".equals(scalingStr)) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800238 mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr), 1);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800239 } else {
240 getErrPrintWriter().println("Error: scaling must be 'auto' or 'off'");
241 return -1;
242 }
243 return 0;
244 }
245
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800246 private int runDismissKeyguard(PrintWriter pw) throws RemoteException {
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800247 mInterface.dismissKeyguard(null /* callback */, null /* message */);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800248 return 0;
249 }
250
Jeff Chang95aa5002018-09-06 16:34:10 +0800251 private int parseDimension(String s, int displayId) throws NumberFormatException {
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800252 if (s.endsWith("px")) {
253 return Integer.parseInt(s.substring(0, s.length() - 2));
254 }
255 if (s.endsWith("dp")) {
256 int density;
257 try {
Jeff Chang95aa5002018-09-06 16:34:10 +0800258 density = mInterface.getBaseDisplayDensity(displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800259 } catch (RemoteException e) {
260 density = DisplayMetrics.DENSITY_DEFAULT;
261 }
262 return Integer.parseInt(s.substring(0, s.length() - 2)) * density /
263 DisplayMetrics.DENSITY_DEFAULT;
264 }
265 return Integer.parseInt(s);
Adrian Roos111aff92017-09-27 18:11:46 +0200266 }
267
Garfield Tan90c90052018-10-08 12:29:41 -0700268 private int runSetDisplayUserRotation(PrintWriter pw) {
269 final String lockMode = getNextArgRequired();
270
271 int displayId = Display.DEFAULT_DISPLAY;
272 String arg = getNextArg();
273 if ("-d".equals(arg)) {
274 displayId = Integer.parseInt(getNextArgRequired());
275 arg = getNextArg();
276 }
277
278 if ("free".equals(lockMode)) {
279 mInternal.thawDisplayRotation(displayId);
280 return 0;
281 }
282
283 if (!lockMode.equals("lock")) {
284 getErrPrintWriter().println("Error: lock mode needs to be either free or lock.");
285 return -1;
286 }
287
288 try {
289 final int rotation = arg != null ? Integer.parseInt(arg) : Surface.ROTATION_0;
290 mInternal.freezeDisplayRotation(displayId, rotation);
291 return 0;
292 } catch (IllegalArgumentException e) {
293 getErrPrintWriter().println("Error: " + e.getMessage());
294 return -1;
295 }
296 }
297
Adrian Roos111aff92017-09-27 18:11:46 +0200298 @Override
299 public void onHelp() {
300 PrintWriter pw = getOutPrintWriter();
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800301 pw.println("Window manager (window) commands:");
Adrian Roos111aff92017-09-27 18:11:46 +0200302 pw.println(" help");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800303 pw.println(" Print this help text.");
Jeff Chang95aa5002018-09-06 16:34:10 +0800304 pw.println(" size [reset|WxH|WdpxHdp] [-d DISPLAY_ID]");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800305 pw.println(" Return or override display size.");
306 pw.println(" width and height in pixels unless suffixed with 'dp'.");
Jeff Chang95aa5002018-09-06 16:34:10 +0800307 pw.println(" density [reset|DENSITY] [-d DISPLAY_ID]");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800308 pw.println(" Return or override display density.");
Jeff Chang95aa5002018-09-06 16:34:10 +0800309 pw.println(" overscan [reset|LEFT,TOP,RIGHT,BOTTOM] [-d DISPLAY ID]");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800310 pw.println(" Set overscan area for display.");
Jeff Chang95aa5002018-09-06 16:34:10 +0800311 pw.println(" scaling [off|auto] [-d DISPLAY_ID]");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800312 pw.println(" Set display scaling mode.");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800313 pw.println(" dismiss-keyguard");
314 pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
Garfield Tan90c90052018-10-08 12:29:41 -0700315 pw.println(" set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
316 pw.println(" Set user rotation mode and user rotation.");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800317 if (!IS_USER) {
Vishnu Nairab250032017-11-21 07:32:43 -0800318 pw.println(" tracing (start | stop)");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800319 pw.println(" Start or stop window tracing.");
Vishnu Nairab250032017-11-21 07:32:43 -0800320 }
Adrian Roos111aff92017-09-27 18:11:46 +0200321 }
322}