Wm.java revision f5ad42f4324bfb7aa28f0967e2fcc89f55d6e91f
1/* 2** 3** Copyright 2013, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18 19package com.android.commands.wm; 20 21import android.content.Context; 22import android.graphics.Point; 23import android.graphics.Rect; 24import android.os.RemoteException; 25import android.os.ServiceManager; 26import android.util.AndroidException; 27import android.util.DisplayMetrics; 28import android.view.Display; 29import android.view.IWindowManager; 30import com.android.internal.os.BaseCommand; 31 32import java.io.PrintStream; 33import java.util.regex.Matcher; 34import java.util.regex.Pattern; 35 36public class Wm extends BaseCommand { 37 38 private IWindowManager mWm; 39 40 /** 41 * Command-line entry point. 42 * 43 * @param args The command-line arguments 44 */ 45 public static void main(String[] args) { 46 (new Wm()).run(args); 47 } 48 49 @Override 50 public void onShowUsage(PrintStream out) { 51 out.println( 52 "usage: wm [subcommand] [options]\n" + 53 " wm size [reset|WxH|WdpxHdp]\n" + 54 " wm density [reset|DENSITY]\n" + 55 " wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" + 56 " wm scaling [off|auto]\n" + 57 " wm screen-capture [userId] [true|false]\n" + 58 "\n" + 59 "wm size: return or override display size.\n" + 60 " width and height in pixels unless suffixed with 'dp'.\n" + 61 "\n" + 62 "wm density: override display density.\n" + 63 "\n" + 64 "wm overscan: set overscan area for display.\n" + 65 "\n" + 66 "wm scaling: set display scaling mode.\n" + 67 "\n" + 68 "wm screen-capture: enable/disable screen capture.\n" 69 ); 70 } 71 72 @Override 73 public void onRun() throws Exception { 74 mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService( 75 Context.WINDOW_SERVICE)); 76 if (mWm == null) { 77 System.err.println(NO_SYSTEM_ERROR_CODE); 78 throw new AndroidException("Can't connect to window manager; is the system running?"); 79 } 80 81 String op = nextArgRequired(); 82 83 if (op.equals("size")) { 84 runDisplaySize(); 85 } else if (op.equals("density")) { 86 runDisplayDensity(); 87 } else if (op.equals("overscan")) { 88 runDisplayOverscan(); 89 } else if (op.equals("scaling")) { 90 runDisplayScaling(); 91 } else if (op.equals("screen-capture")) { 92 runSetScreenCapture(); 93 } else { 94 showError("Error: unknown command '" + op + "'"); 95 return; 96 } 97 } 98 99 private void runSetScreenCapture() throws Exception { 100 String userIdStr = nextArg(); 101 String enableStr = nextArg(); 102 int userId; 103 boolean disable; 104 105 try { 106 userId = Integer.parseInt(userIdStr); 107 } catch (NumberFormatException e) { 108 System.err.println("Error: bad number " + e); 109 return; 110 } 111 112 disable = !Boolean.parseBoolean(enableStr); 113 114 try { 115 mWm.setScreenCaptureDisabled(userId, disable); 116 } catch (RemoteException e) { 117 System.err.println("Error: Can't set screen capture " + e); 118 } 119 } 120 121 private void runDisplaySize() throws Exception { 122 String size = nextArg(); 123 int w, h; 124 if (size == null) { 125 Point initialSize = new Point(); 126 Point baseSize = new Point(); 127 try { 128 mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize); 129 mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize); 130 System.out.println("Physical size: " + initialSize.x + "x" + initialSize.y); 131 if (!initialSize.equals(baseSize)) { 132 System.out.println("Override size: " + baseSize.x + "x" + baseSize.y); 133 } 134 } catch (RemoteException e) { 135 } 136 return; 137 } else if ("reset".equals(size)) { 138 w = h = -1; 139 } else { 140 int div = size.indexOf('x'); 141 if (div <= 0 || div >= (size.length()-1)) { 142 System.err.println("Error: bad size " + size); 143 return; 144 } 145 String wstr = size.substring(0, div); 146 String hstr = size.substring(div+1); 147 try { 148 w = parseDimension(wstr); 149 h = parseDimension(hstr); 150 } catch (NumberFormatException e) { 151 System.err.println("Error: bad number " + e); 152 return; 153 } 154 } 155 156 try { 157 if (w >= 0 && h >= 0) { 158 // TODO(multidisplay): For now Configuration only applies to main screen. 159 mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h); 160 } else { 161 mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY); 162 } 163 } catch (RemoteException e) { 164 } 165 } 166 167 private void runDisplayDensity() throws Exception { 168 String densityStr = nextArg(); 169 int density; 170 if (densityStr == null) { 171 try { 172 int initialDensity = mWm.getInitialDisplayDensity(Display.DEFAULT_DISPLAY); 173 int baseDensity = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY); 174 System.out.println("Physical density: " + initialDensity); 175 if (initialDensity != baseDensity) { 176 System.out.println("Override density: " + baseDensity); 177 } 178 } catch (RemoteException e) { 179 } 180 return; 181 } else if ("reset".equals(densityStr)) { 182 density = -1; 183 } else { 184 try { 185 density = Integer.parseInt(densityStr); 186 } catch (NumberFormatException e) { 187 System.err.println("Error: bad number " + e); 188 return; 189 } 190 if (density < 72) { 191 System.err.println("Error: density must be >= 72"); 192 return; 193 } 194 } 195 196 try { 197 if (density > 0) { 198 // TODO(multidisplay): For now Configuration only applies to main screen. 199 mWm.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, density); 200 } else { 201 mWm.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY); 202 } 203 } catch (RemoteException e) { 204 } 205 } 206 207 private void runDisplayOverscan() throws Exception { 208 String overscanStr = nextArgRequired(); 209 Rect rect = new Rect(); 210 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 System.err.println("Error: bad rectangle arg: " + overscanStr); 218 return; 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 226 try { 227 mWm.setOverscan(Display.DEFAULT_DISPLAY, rect.left, rect.top, rect.right, rect.bottom); 228 } catch (RemoteException e) { 229 } 230 } 231 232 private void runDisplayScaling() throws Exception { 233 String scalingStr = nextArgRequired(); 234 if ("auto".equals(scalingStr)) { 235 mWm.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 0); 236 } else if ("off".equals(scalingStr)) { 237 mWm.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 1); 238 } else { 239 System.err.println("Error: scaling must be 'auto' or 'off'"); 240 } 241 } 242 243 private int parseDimension(String s) throws NumberFormatException { 244 if (s.endsWith("px")) { 245 return Integer.parseInt(s.substring(0, s.length() - 2)); 246 } 247 if (s.endsWith("dp")) { 248 int density; 249 try { 250 density = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY); 251 } catch (RemoteException e) { 252 density = DisplayMetrics.DENSITY_DEFAULT; 253 } 254 return Integer.parseInt(s.substring(0, s.length() - 2)) * density / 255 DisplayMetrics.DENSITY_DEFAULT; 256 } 257 return Integer.parseInt(s); 258 } 259} 260