blob: 831418b4b2b42135dd09a65be3b17db4648c2520 [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;
Adrian Roos111aff92017-09-27 18:11:46 +020029
30import java.io.PrintWriter;
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080031import java.util.regex.Matcher;
32import java.util.regex.Pattern;
Adrian Roos111aff92017-09-27 18:11:46 +020033
34/**
35 * ShellCommands for WindowManagerService.
36 *
37 * Use with {@code adb shell cmd window ...}.
38 */
39public class WindowManagerShellCommand extends ShellCommand {
40
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080041 // IPC interface to activity manager -- don't need to do additional security checks.
42 private final IWindowManager mInterface;
43
44 // Internal service impl -- must perform security checks before touching.
45 private final WindowManagerService mInternal;
Adrian Roos111aff92017-09-27 18:11:46 +020046
47 public WindowManagerShellCommand(WindowManagerService service) {
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080048 mInterface = service;
49 mInternal = service;
Adrian Roos111aff92017-09-27 18:11:46 +020050 }
51
52 @Override
53 public int onCommand(String cmd) {
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080054 if (cmd == null) {
55 return handleDefaultCommands(cmd);
Adrian Roos111aff92017-09-27 18:11:46 +020056 }
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080057 final PrintWriter pw = getOutPrintWriter();
58 try {
59 switch (cmd) {
60 case "size":
61 return runDisplaySize(pw);
62 case "density":
63 return runDisplayDensity(pw);
64 case "overscan":
65 return runDisplayOverscan(pw);
66 case "scaling":
67 return runDisplayScaling(pw);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080068 case "dismiss-keyguard":
69 return runDismissKeyguard(pw);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080070 case "tracing":
71 // XXX this should probably be changed to use openFileForSystem() to create
72 // the output trace file, so the shell gets the correct semantics for where
73 // trace files can be written.
74 return mInternal.mWindowTracing.onShellCommand(this,
75 getNextArgRequired());
76 default:
77 return handleDefaultCommands(cmd);
78 }
79 } catch (RemoteException e) {
80 pw.println("Remote exception: " + e);
81 }
82 return -1;
83 }
84
Jeff Chang95aa5002018-09-06 16:34:10 +080085 private int getDisplayId(String opt) {
86 int displayId = Display.DEFAULT_DISPLAY;
87 String option = "-d".equals(opt) ? opt : getNextOption();
88 if (option != null && "-d".equals(option)) {
89 try {
90 displayId = Integer.parseInt(getNextArgRequired());
91 } catch (NumberFormatException e) {
92 getErrPrintWriter().println("Error: bad number " + e);
93 } catch (IllegalArgumentException e) {
94 getErrPrintWriter().println("Error: " + e);
95 }
96 }
97 return displayId;
98 }
99
100 private void printInitialDisplaySize(PrintWriter pw , int displayId) {
101 final Point initialSize = new Point();
102 final Point baseSize = new Point();
103
104 try {
105 mInterface.getInitialDisplaySize(displayId, initialSize);
106 mInterface.getBaseDisplaySize(displayId, baseSize);
107 pw.println("Physical size: " + initialSize.x + "x" + initialSize.y);
108 if (!initialSize.equals(baseSize)) {
109 pw.println("Override size: " + baseSize.x + "x" + baseSize.y);
110 }
111 } catch (RemoteException e) {
112 // Can't call getInitialDisplaySize() on IWindowManager or
113 // Can't call getBaseDisplaySize() on IWindowManager
114 pw.println("Remote exception: " + e);
115 }
116 }
117
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800118 private int runDisplaySize(PrintWriter pw) throws RemoteException {
119 String size = getNextArg();
120 int w, h;
Jeff Chang95aa5002018-09-06 16:34:10 +0800121 final int displayId = getDisplayId(size);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800122 if (size == null) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800123 printInitialDisplaySize(pw, displayId);
124 return 0;
125 } else if ("-d".equals(size)) {
126 printInitialDisplaySize(pw, displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800127 return 0;
128 } else if ("reset".equals(size)) {
129 w = h = -1;
130 } else {
131 int div = size.indexOf('x');
132 if (div <= 0 || div >= (size.length()-1)) {
133 getErrPrintWriter().println("Error: bad size " + size);
134 return -1;
135 }
136 String wstr = size.substring(0, div);
137 String hstr = size.substring(div+1);
138 try {
Jeff Chang95aa5002018-09-06 16:34:10 +0800139 w = parseDimension(wstr, displayId);
140 h = parseDimension(hstr, displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800141 } catch (NumberFormatException e) {
142 getErrPrintWriter().println("Error: bad number " + e);
143 return -1;
144 }
145 }
146
147 if (w >= 0 && h >= 0) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800148 mInterface.setForcedDisplaySize(displayId, w, h);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800149 } else {
Jeff Chang95aa5002018-09-06 16:34:10 +0800150 mInterface.clearForcedDisplaySize(displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800151 }
152 return 0;
153 }
154
Jeff Chang95aa5002018-09-06 16:34:10 +0800155 private void printInitialDisplayDensity(PrintWriter pw , int displayId) {
156 try {
157 final int initialDensity = mInterface.getInitialDisplayDensity(displayId);
158 final int baseDensity = mInterface.getBaseDisplayDensity(displayId);
159 pw.println("Physical density: " + initialDensity);
160 if (initialDensity != baseDensity) {
161 pw.println("Override density: " + baseDensity);
162 }
163 } catch (RemoteException e) {
164 // Can't call getInitialDisplayDensity() on IWindowManager or
165 // Can't call getBaseDisplayDensity() on IWindowManager
166 pw.println("Remote exception: " + e);
167 }
168 }
169
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800170 private int runDisplayDensity(PrintWriter pw) throws RemoteException {
171 String densityStr = getNextArg();
172 int density;
Jeff Chang95aa5002018-09-06 16:34:10 +0800173 final int displayId = getDisplayId(densityStr);
174
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800175 if (densityStr == null) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800176 printInitialDisplayDensity(pw, displayId);
177 return 0;
178 } else if ("-d".equals(densityStr)) {
179 printInitialDisplayDensity(pw, displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800180 return 0;
181 } else if ("reset".equals(densityStr)) {
182 density = -1;
183 } else {
184 try {
185 density = Integer.parseInt(densityStr);
186 } catch (NumberFormatException e) {
187 getErrPrintWriter().println("Error: bad number " + e);
188 return -1;
189 }
190 if (density < 72) {
191 getErrPrintWriter().println("Error: density must be >= 72");
192 return -1;
193 }
194 }
195
196 if (density > 0) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800197 mInterface.setForcedDisplayDensityForUser(displayId, density,
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800198 UserHandle.USER_CURRENT);
199 } else {
Jeff Chang95aa5002018-09-06 16:34:10 +0800200 mInterface.clearForcedDisplayDensityForUser(displayId,
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800201 UserHandle.USER_CURRENT);
202 }
203 return 0;
204 }
205
206 private int runDisplayOverscan(PrintWriter pw) throws RemoteException {
207 String overscanStr = getNextArgRequired();
208 Rect rect = new Rect();
Jeff Chang95aa5002018-09-06 16:34:10 +0800209 final int displayId = getDisplayId(overscanStr);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800210 if ("reset".equals(overscanStr)) {
211 rect.set(0, 0, 0, 0);
212 } else {
213 final Pattern FLATTENED_PATTERN = Pattern.compile(
214 "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)");
215 Matcher matcher = FLATTENED_PATTERN.matcher(overscanStr);
216 if (!matcher.matches()) {
217 getErrPrintWriter().println("Error: bad rectangle arg: " + overscanStr);
218 return -1;
219 }
220 rect.left = Integer.parseInt(matcher.group(1));
221 rect.top = Integer.parseInt(matcher.group(2));
222 rect.right = Integer.parseInt(matcher.group(3));
223 rect.bottom = Integer.parseInt(matcher.group(4));
224 }
225
Jeff Chang95aa5002018-09-06 16:34:10 +0800226 mInterface.setOverscan(displayId, rect.left, rect.top, rect.right, rect.bottom);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800227 return 0;
228 }
229
230 private int runDisplayScaling(PrintWriter pw) throws RemoteException {
231 String scalingStr = getNextArgRequired();
232 if ("auto".equals(scalingStr)) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800233 mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr), 0);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800234 } else if ("off".equals(scalingStr)) {
Jeff Chang95aa5002018-09-06 16:34:10 +0800235 mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr), 1);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800236 } else {
237 getErrPrintWriter().println("Error: scaling must be 'auto' or 'off'");
238 return -1;
239 }
240 return 0;
241 }
242
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800243 private int runDismissKeyguard(PrintWriter pw) throws RemoteException {
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800244 mInterface.dismissKeyguard(null /* callback */, null /* message */);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800245 return 0;
246 }
247
Jeff Chang95aa5002018-09-06 16:34:10 +0800248 private int parseDimension(String s, int displayId) throws NumberFormatException {
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800249 if (s.endsWith("px")) {
250 return Integer.parseInt(s.substring(0, s.length() - 2));
251 }
252 if (s.endsWith("dp")) {
253 int density;
254 try {
Jeff Chang95aa5002018-09-06 16:34:10 +0800255 density = mInterface.getBaseDisplayDensity(displayId);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800256 } catch (RemoteException e) {
257 density = DisplayMetrics.DENSITY_DEFAULT;
258 }
259 return Integer.parseInt(s.substring(0, s.length() - 2)) * density /
260 DisplayMetrics.DENSITY_DEFAULT;
261 }
262 return Integer.parseInt(s);
Adrian Roos111aff92017-09-27 18:11:46 +0200263 }
264
265 @Override
266 public void onHelp() {
267 PrintWriter pw = getOutPrintWriter();
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800268 pw.println("Window manager (window) commands:");
Adrian Roos111aff92017-09-27 18:11:46 +0200269 pw.println(" help");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800270 pw.println(" Print this help text.");
Jeff Chang95aa5002018-09-06 16:34:10 +0800271 pw.println(" size [reset|WxH|WdpxHdp] [-d DISPLAY_ID]");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800272 pw.println(" Return or override display size.");
273 pw.println(" width and height in pixels unless suffixed with 'dp'.");
Jeff Chang95aa5002018-09-06 16:34:10 +0800274 pw.println(" density [reset|DENSITY] [-d DISPLAY_ID]");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800275 pw.println(" Return or override display density.");
Jeff Chang95aa5002018-09-06 16:34:10 +0800276 pw.println(" overscan [reset|LEFT,TOP,RIGHT,BOTTOM] [-d DISPLAY ID]");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800277 pw.println(" Set overscan area for display.");
Jeff Chang95aa5002018-09-06 16:34:10 +0800278 pw.println(" scaling [off|auto] [-d DISPLAY_ID]");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800279 pw.println(" Set display scaling mode.");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800280 pw.println(" dismiss-keyguard");
281 pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800282 if (!IS_USER) {
Vishnu Nairab250032017-11-21 07:32:43 -0800283 pw.println(" tracing (start | stop)");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800284 pw.println(" Start or stop window tracing.");
Vishnu Nairab250032017-11-21 07:32:43 -0800285 }
Adrian Roos111aff92017-09-27 18:11:46 +0200286 }
287}