Wm.java revision 672cf45de7aa5ad6fd1f75512ee5a451a16c0b39
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.view.Display; 28import android.view.IWindowManager; 29 30import java.util.regex.Matcher; 31import java.util.regex.Pattern; 32 33public class Wm { 34 35 private IWindowManager mWm; 36 private String[] mArgs; 37 private int mNextArg; 38 private String mCurArgData; 39 40 // These are magic strings understood by the Eclipse plugin. 41 private static final String FATAL_ERROR_CODE = "Error type 1"; 42 private static final String NO_SYSTEM_ERROR_CODE = "Error type 2"; 43 private static final String NO_CLASS_ERROR_CODE = "Error type 3"; 44 45 /** 46 * Command-line entry point. 47 * 48 * @param args The command-line arguments 49 */ 50 public static void main(String[] args) { 51 try { 52 (new Wm()).run(args); 53 } catch (IllegalArgumentException e) { 54 showUsage(); 55 System.err.println("Error: " + e.getMessage()); 56 } catch (Exception e) { 57 e.printStackTrace(System.err); 58 System.exit(1); 59 } 60 } 61 62 private void run(String[] args) throws Exception { 63 if (args.length < 1) { 64 showUsage(); 65 return; 66 } 67 68 mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService( 69 Context.WINDOW_SERVICE)); 70 if (mWm == null) { 71 System.err.println(NO_SYSTEM_ERROR_CODE); 72 throw new AndroidException("Can't connect to window manager; is the system running?"); 73 } 74 75 mArgs = args; 76 String op = args[0]; 77 mNextArg = 1; 78 79 if (op.equals("size")) { 80 runDisplaySize(); 81 } else if (op.equals("density")) { 82 runDisplayDensity(); 83 } else if (op.equals("overscan")) { 84 runDisplayOverscan(); 85 } else { 86 throw new IllegalArgumentException("Unknown command: " + op); 87 } 88 } 89 90 private void runDisplaySize() throws Exception { 91 String size = nextArg(); 92 int w, h; 93 if (size == null) { 94 Point initialSize = new Point(); 95 Point baseSize = new Point(); 96 try { 97 mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize); 98 mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize); 99 System.out.println("Physical size: " + initialSize.x + "x" + initialSize.y); 100 if (!initialSize.equals(baseSize)) { 101 System.out.println("Override size: " + baseSize.x + "x" + baseSize.y); 102 } 103 } catch (RemoteException e) { 104 } 105 return; 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 System.err.println("Error: bad size " + size); 112 return; 113 } 114 String wstr = size.substring(0, div); 115 String hstr = size.substring(div+1); 116 try { 117 w = Integer.parseInt(wstr); 118 h = Integer.parseInt(hstr); 119 } catch (NumberFormatException e) { 120 System.err.println("Error: bad number " + e); 121 return; 122 } 123 } 124 125 try { 126 if (w >= 0 && h >= 0) { 127 // TODO(multidisplay): For now Configuration only applies to main screen. 128 mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h); 129 } else { 130 mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY); 131 } 132 } catch (RemoteException e) { 133 } 134 } 135 136 private void runDisplayDensity() throws Exception { 137 String densityStr = nextArg(); 138 int density; 139 if (densityStr == null) { 140 try { 141 int initialDensity = mWm.getInitialDisplayDensity(Display.DEFAULT_DISPLAY); 142 int baseDensity = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY); 143 System.out.println("Physical density: " + initialDensity); 144 if (initialDensity != baseDensity) { 145 System.out.println("Override density: " + baseDensity); 146 } 147 } catch (RemoteException e) { 148 } 149 return; 150 } else if ("reset".equals(densityStr)) { 151 density = -1; 152 } else { 153 try { 154 density = Integer.parseInt(densityStr); 155 } catch (NumberFormatException e) { 156 System.err.println("Error: bad number " + e); 157 return; 158 } 159 if (density < 72) { 160 System.err.println("Error: density must be >= 72"); 161 return; 162 } 163 } 164 165 try { 166 if (density > 0) { 167 // TODO(multidisplay): For now Configuration only applies to main screen. 168 mWm.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, density); 169 } else { 170 mWm.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY); 171 } 172 } catch (RemoteException e) { 173 } 174 } 175 176 private void runDisplayOverscan() throws Exception { 177 String overscanStr = nextArgRequired(); 178 Rect rect = new Rect(); 179 int density; 180 if ("reset".equals(overscanStr)) { 181 rect.set(0, 0, 0, 0); 182 } else { 183 final Pattern FLATTENED_PATTERN = Pattern.compile( 184 "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)"); 185 Matcher matcher = FLATTENED_PATTERN.matcher(overscanStr); 186 if (!matcher.matches()) { 187 System.err.println("Error: bad rectangle arg: " + overscanStr); 188 return; 189 } 190 rect.left = Integer.parseInt(matcher.group(1)); 191 rect.top = Integer.parseInt(matcher.group(2)); 192 rect.right = Integer.parseInt(matcher.group(3)); 193 rect.bottom = Integer.parseInt(matcher.group(4)); 194 } 195 196 try { 197 mWm.setOverscan(Display.DEFAULT_DISPLAY, rect.left, rect.top, rect.right, rect.bottom); 198 } catch (RemoteException e) { 199 } 200 } 201 202 private String nextOption() { 203 if (mCurArgData != null) { 204 String prev = mArgs[mNextArg - 1]; 205 throw new IllegalArgumentException("No argument expected after \"" + prev + "\""); 206 } 207 if (mNextArg >= mArgs.length) { 208 return null; 209 } 210 String arg = mArgs[mNextArg]; 211 if (!arg.startsWith("-")) { 212 return null; 213 } 214 mNextArg++; 215 if (arg.equals("--")) { 216 return null; 217 } 218 if (arg.length() > 1 && arg.charAt(1) != '-') { 219 if (arg.length() > 2) { 220 mCurArgData = arg.substring(2); 221 return arg.substring(0, 2); 222 } else { 223 mCurArgData = null; 224 return arg; 225 } 226 } 227 mCurArgData = null; 228 return arg; 229 } 230 231 private String nextArg() { 232 if (mCurArgData != null) { 233 String arg = mCurArgData; 234 mCurArgData = null; 235 return arg; 236 } else if (mNextArg < mArgs.length) { 237 return mArgs[mNextArg++]; 238 } else { 239 return null; 240 } 241 } 242 243 private String nextArgRequired() { 244 String arg = nextArg(); 245 if (arg == null) { 246 String prev = mArgs[mNextArg - 1]; 247 throw new IllegalArgumentException("Argument expected after \"" + prev + "\""); 248 } 249 return arg; 250 } 251 252 private static void showUsage() { 253 System.err.println( 254 "usage: wm [subcommand] [options]\n" + 255 " wm size [reset|WxH]\n" + 256 " wm density [reset|DENSITY]\n" + 257 " wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" + 258 "\n" + 259 "wm size: return or override display size.\n" + 260 "\n" + 261 "wm density: override display density.\n" + 262 "\n" + 263 "wm overscan: set overscan area for display.\n" 264 ); 265 } 266} 267