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