blob: 6e0ccfd5d2db848477e620e8515679ca0b61d391 [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;
23import android.os.ParcelFileDescriptor;
24import android.os.RemoteException;
Adrian Roos111aff92017-09-27 18:11:46 +020025import android.os.ShellCommand;
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080026import android.os.UserHandle;
27import android.util.DisplayMetrics;
28import android.view.Display;
29import android.view.IWindowManager;
Adrian Roos111aff92017-09-27 18:11:46 +020030
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080031import java.io.BufferedReader;
32import java.io.IOException;
33import java.io.InputStream;
34import java.io.InputStreamReader;
Adrian Roos111aff92017-09-27 18:11:46 +020035import java.io.PrintWriter;
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080036import java.util.regex.Matcher;
37import java.util.regex.Pattern;
Adrian Roos111aff92017-09-27 18:11:46 +020038
39/**
40 * ShellCommands for WindowManagerService.
41 *
42 * Use with {@code adb shell cmd window ...}.
43 */
44public class WindowManagerShellCommand extends ShellCommand {
45
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080046 // IPC interface to activity manager -- don't need to do additional security checks.
47 private final IWindowManager mInterface;
48
49 // Internal service impl -- must perform security checks before touching.
50 private final WindowManagerService mInternal;
Adrian Roos111aff92017-09-27 18:11:46 +020051
52 public WindowManagerShellCommand(WindowManagerService service) {
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080053 mInterface = service;
54 mInternal = service;
Adrian Roos111aff92017-09-27 18:11:46 +020055 }
56
57 @Override
58 public int onCommand(String cmd) {
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080059 if (cmd == null) {
60 return handleDefaultCommands(cmd);
Adrian Roos111aff92017-09-27 18:11:46 +020061 }
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080062 final PrintWriter pw = getOutPrintWriter();
63 try {
64 switch (cmd) {
65 case "size":
66 return runDisplaySize(pw);
67 case "density":
68 return runDisplayDensity(pw);
69 case "overscan":
70 return runDisplayOverscan(pw);
71 case "scaling":
72 return runDisplayScaling(pw);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080073 case "dismiss-keyguard":
74 return runDismissKeyguard(pw);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -080075 case "tracing":
76 // XXX this should probably be changed to use openFileForSystem() to create
77 // the output trace file, so the shell gets the correct semantics for where
78 // trace files can be written.
79 return mInternal.mWindowTracing.onShellCommand(this,
80 getNextArgRequired());
81 default:
82 return handleDefaultCommands(cmd);
83 }
84 } catch (RemoteException e) {
85 pw.println("Remote exception: " + e);
86 }
87 return -1;
88 }
89
90 private int runDisplaySize(PrintWriter pw) throws RemoteException {
91 String size = getNextArg();
92 int w, h;
93 if (size == null) {
94 Point initialSize = new Point();
95 Point baseSize = new Point();
96 try {
97 mInterface.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);
98 mInterface.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize);
99 pw.println("Physical size: " + initialSize.x + "x" + initialSize.y);
100 if (!initialSize.equals(baseSize)) {
101 pw.println("Override size: " + baseSize.x + "x" + baseSize.y);
102 }
103 } catch (RemoteException e) {
104 }
105 return 0;
106 } else if ("reset".equals(size)) {
107 w = h = -1;
108 } else {
109 int div = size.indexOf('x');
110 if (div <= 0 || div >= (size.length()-1)) {
111 getErrPrintWriter().println("Error: bad size " + size);
112 return -1;
113 }
114 String wstr = size.substring(0, div);
115 String hstr = size.substring(div+1);
116 try {
117 w = parseDimension(wstr);
118 h = parseDimension(hstr);
119 } catch (NumberFormatException e) {
120 getErrPrintWriter().println("Error: bad number " + e);
121 return -1;
122 }
123 }
124
125 if (w >= 0 && h >= 0) {
126 // TODO(multidisplay): For now Configuration only applies to main screen.
127 mInterface.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h);
128 } else {
129 mInterface.clearForcedDisplaySize(Display.DEFAULT_DISPLAY);
130 }
131 return 0;
132 }
133
134 private int runDisplayDensity(PrintWriter pw) throws RemoteException {
135 String densityStr = getNextArg();
136 int density;
137 if (densityStr == null) {
138 try {
139 int initialDensity = mInterface.getInitialDisplayDensity(Display.DEFAULT_DISPLAY);
140 int baseDensity = mInterface.getBaseDisplayDensity(Display.DEFAULT_DISPLAY);
141 pw.println("Physical density: " + initialDensity);
142 if (initialDensity != baseDensity) {
143 pw.println("Override density: " + baseDensity);
144 }
145 } catch (RemoteException e) {
146 }
147 return 0;
148 } else if ("reset".equals(densityStr)) {
149 density = -1;
150 } else {
151 try {
152 density = Integer.parseInt(densityStr);
153 } catch (NumberFormatException e) {
154 getErrPrintWriter().println("Error: bad number " + e);
155 return -1;
156 }
157 if (density < 72) {
158 getErrPrintWriter().println("Error: density must be >= 72");
159 return -1;
160 }
161 }
162
163 if (density > 0) {
164 // TODO(multidisplay): For now Configuration only applies to main screen.
165 mInterface.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, density,
166 UserHandle.USER_CURRENT);
167 } else {
168 mInterface.clearForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY,
169 UserHandle.USER_CURRENT);
170 }
171 return 0;
172 }
173
174 private int runDisplayOverscan(PrintWriter pw) throws RemoteException {
175 String overscanStr = getNextArgRequired();
176 Rect rect = new Rect();
177 if ("reset".equals(overscanStr)) {
178 rect.set(0, 0, 0, 0);
179 } else {
180 final Pattern FLATTENED_PATTERN = Pattern.compile(
181 "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)");
182 Matcher matcher = FLATTENED_PATTERN.matcher(overscanStr);
183 if (!matcher.matches()) {
184 getErrPrintWriter().println("Error: bad rectangle arg: " + overscanStr);
185 return -1;
186 }
187 rect.left = Integer.parseInt(matcher.group(1));
188 rect.top = Integer.parseInt(matcher.group(2));
189 rect.right = Integer.parseInt(matcher.group(3));
190 rect.bottom = Integer.parseInt(matcher.group(4));
191 }
192
193 mInterface.setOverscan(Display.DEFAULT_DISPLAY, rect.left, rect.top, rect.right,
194 rect.bottom);
195 return 0;
196 }
197
198 private int runDisplayScaling(PrintWriter pw) throws RemoteException {
199 String scalingStr = getNextArgRequired();
200 if ("auto".equals(scalingStr)) {
201 mInterface.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 0);
202 } else if ("off".equals(scalingStr)) {
203 mInterface.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 1);
204 } else {
205 getErrPrintWriter().println("Error: scaling must be 'auto' or 'off'");
206 return -1;
207 }
208 return 0;
209 }
210
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800211 private int runDismissKeyguard(PrintWriter pw) throws RemoteException {
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800212 mInterface.dismissKeyguard(null /* callback */, null /* message */);
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800213 return 0;
214 }
215
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800216 private int parseDimension(String s) throws NumberFormatException {
217 if (s.endsWith("px")) {
218 return Integer.parseInt(s.substring(0, s.length() - 2));
219 }
220 if (s.endsWith("dp")) {
221 int density;
222 try {
223 density = mInterface.getBaseDisplayDensity(Display.DEFAULT_DISPLAY);
224 } catch (RemoteException e) {
225 density = DisplayMetrics.DENSITY_DEFAULT;
226 }
227 return Integer.parseInt(s.substring(0, s.length() - 2)) * density /
228 DisplayMetrics.DENSITY_DEFAULT;
229 }
230 return Integer.parseInt(s);
Adrian Roos111aff92017-09-27 18:11:46 +0200231 }
232
233 @Override
234 public void onHelp() {
235 PrintWriter pw = getOutPrintWriter();
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800236 pw.println("Window manager (window) commands:");
Adrian Roos111aff92017-09-27 18:11:46 +0200237 pw.println(" help");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800238 pw.println(" Print this help text.");
239 pw.println(" size [reset|WxH|WdpxHdp]");
240 pw.println(" Return or override display size.");
241 pw.println(" width and height in pixels unless suffixed with 'dp'.");
242 pw.println(" density [reset|DENSITY]");
243 pw.println(" Return or override display density.");
244 pw.println(" overscan [reset|LEFT,TOP,RIGHT,BOTTOM]");
245 pw.println(" Set overscan area for display.");
246 pw.println(" scaling [off|auto]");
247 pw.println(" Set display scaling mode.");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800248 pw.println(" dismiss-keyguard");
249 pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800250 if (!IS_USER) {
Vishnu Nairab250032017-11-21 07:32:43 -0800251 pw.println(" tracing (start | stop)");
Dianne Hackborn5c3296a2017-12-13 17:52:26 -0800252 pw.println(" Start or stop window tracing.");
Vishnu Nairab250032017-11-21 07:32:43 -0800253 }
Adrian Roos111aff92017-09-27 18:11:46 +0200254 }
255}