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