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; 29import com.android.internal.os.BaseCommand; 30 31import java.io.PrintStream; 32import java.util.regex.Matcher; 33import java.util.regex.Pattern; 34 35public class Wm extends BaseCommand { 36 37 private IWindowManager mWm; 38 39 /** 40 * Command-line entry point. 41 * 42 * @param args The command-line arguments 43 */ 44 public static void main(String[] args) { 45 (new Wm()).run(args); 46 } 47 48 public void onShowUsage(PrintStream out) { 49 out.println( 50 "usage: wm [subcommand] [options]\n" + 51 " wm size [reset|WxH]\n" + 52 " wm density [reset|DENSITY]\n" + 53 " wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" + 54 "\n" + 55 "wm size: return or override display size.\n" + 56 "\n" + 57 "wm density: override display density.\n" + 58 "\n" + 59 "wm overscan: set overscan area for display.\n" 60 ); 61 } 62 63 public void onRun() throws Exception { 64 mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService( 65 Context.WINDOW_SERVICE)); 66 if (mWm == null) { 67 System.err.println(NO_SYSTEM_ERROR_CODE); 68 throw new AndroidException("Can't connect to window manager; is the system running?"); 69 } 70 71 String op = nextArgRequired(); 72 73 if (op.equals("size")) { 74 runDisplaySize(); 75 } else if (op.equals("density")) { 76 runDisplayDensity(); 77 } else if (op.equals("overscan")) { 78 runDisplayOverscan(); 79 } else { 80 showError("Error: unknown command '" + op + "'"); 81 return; 82 } 83 } 84 85 private void runDisplaySize() throws Exception { 86 String size = nextArg(); 87 int w, h; 88 if (size == null) { 89 Point initialSize = new Point(); 90 Point baseSize = new Point(); 91 try { 92 mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize); 93 mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize); 94 System.out.println("Physical size: " + initialSize.x + "x" + initialSize.y); 95 if (!initialSize.equals(baseSize)) { 96 System.out.println("Override size: " + baseSize.x + "x" + baseSize.y); 97 } 98 } catch (RemoteException e) { 99 } 100 return; 101 } else if ("reset".equals(size)) { 102 w = h = -1; 103 } else { 104 int div = size.indexOf('x'); 105 if (div <= 0 || div >= (size.length()-1)) { 106 System.err.println("Error: bad size " + size); 107 return; 108 } 109 String wstr = size.substring(0, div); 110 String hstr = size.substring(div+1); 111 try { 112 w = Integer.parseInt(wstr); 113 h = Integer.parseInt(hstr); 114 } catch (NumberFormatException e) { 115 System.err.println("Error: bad number " + e); 116 return; 117 } 118 } 119 120 try { 121 if (w >= 0 && h >= 0) { 122 // TODO(multidisplay): For now Configuration only applies to main screen. 123 mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h); 124 } else { 125 mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY); 126 } 127 } catch (RemoteException e) { 128 } 129 } 130 131 private void runDisplayDensity() throws Exception { 132 String densityStr = nextArg(); 133 int density; 134 if (densityStr == null) { 135 try { 136 int initialDensity = mWm.getInitialDisplayDensity(Display.DEFAULT_DISPLAY); 137 int baseDensity = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY); 138 System.out.println("Physical density: " + initialDensity); 139 if (initialDensity != baseDensity) { 140 System.out.println("Override density: " + baseDensity); 141 } 142 } catch (RemoteException e) { 143 } 144 return; 145 } else if ("reset".equals(densityStr)) { 146 density = -1; 147 } else { 148 try { 149 density = Integer.parseInt(densityStr); 150 } catch (NumberFormatException e) { 151 System.err.println("Error: bad number " + e); 152 return; 153 } 154 if (density < 72) { 155 System.err.println("Error: density must be >= 72"); 156 return; 157 } 158 } 159 160 try { 161 if (density > 0) { 162 // TODO(multidisplay): For now Configuration only applies to main screen. 163 mWm.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, density); 164 } else { 165 mWm.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY); 166 } 167 } catch (RemoteException e) { 168 } 169 } 170 171 private void runDisplayOverscan() throws Exception { 172 String overscanStr = nextArgRequired(); 173 Rect rect = new Rect(); 174 int density; 175 if ("reset".equals(overscanStr)) { 176 rect.set(0, 0, 0, 0); 177 } else { 178 final Pattern FLATTENED_PATTERN = Pattern.compile( 179 "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)"); 180 Matcher matcher = FLATTENED_PATTERN.matcher(overscanStr); 181 if (!matcher.matches()) { 182 System.err.println("Error: bad rectangle arg: " + overscanStr); 183 return; 184 } 185 rect.left = Integer.parseInt(matcher.group(1)); 186 rect.top = Integer.parseInt(matcher.group(2)); 187 rect.right = Integer.parseInt(matcher.group(3)); 188 rect.bottom = Integer.parseInt(matcher.group(4)); 189 } 190 191 try { 192 mWm.setOverscan(Display.DEFAULT_DISPLAY, rect.left, rect.top, rect.right, rect.bottom); 193 } catch (RemoteException e) { 194 } 195 } 196} 197