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