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