DisplayManager.java revision bc335457462a12434a9df6955de1dd693cdccac7
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.hardware.display;
18
19import android.content.Context;
20import android.os.Handler;
21import android.util.SparseArray;
22import android.view.Display;
23
24/**
25 * Manages the properties of attached displays.
26 * <p>
27 * Get an instance of this class by calling
28 * {@link android.content.Context#getSystemService(java.lang.String)
29 * Context.getSystemService()} with the argument
30 * {@link android.content.Context#DISPLAY_SERVICE}.
31 * </p>
32 */
33public final class DisplayManager {
34    private static final String TAG = "DisplayManager";
35    private static final boolean DEBUG = false;
36
37    private final Context mContext;
38    private final DisplayManagerGlobal mGlobal;
39
40    private final Object mLock = new Object();
41    private final SparseArray<Display> mDisplays = new SparseArray<Display>();
42
43    /**
44     * Broadcast receiver that indicates when the Wifi display status changes.
45     * <p>
46     * The status is provided as a {@link WifiDisplayStatus} object in the
47     * {@link #EXTRA_WIFI_DISPLAY_STATUS} extra.
48     * </p><p>
49     * This broadcast is only sent to registered receivers and can only be sent by the system.
50     * </p>
51     * @hide
52     */
53    public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED =
54            "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED";
55
56    /**
57     * Contains a {@link WifiDisplayStatus} object.
58     * @hide
59     */
60    public static final String EXTRA_WIFI_DISPLAY_STATUS =
61            "android.hardware.display.extra.WIFI_DISPLAY_STATUS";
62
63    /** @hide */
64    public DisplayManager(Context context) {
65        mContext = context;
66        mGlobal = DisplayManagerGlobal.getInstance();
67    }
68
69    /**
70     * Gets information about a logical display.
71     *
72     * The display metrics may be adjusted to provide compatibility
73     * for legacy applications.
74     *
75     * @param displayId The logical display id.
76     * @return The display object, or null if there is no valid display with the given id.
77     */
78    public Display getDisplay(int displayId) {
79        synchronized (mLock) {
80            return getOrCreateDisplayLocked(displayId, false /*assumeValid*/);
81        }
82    }
83
84    /**
85     * Gets all currently valid logical displays.
86     *
87     * @return An array containing all displays.
88     */
89    public Display[] getDisplays() {
90        int[] displayIds = mGlobal.getDisplayIds();
91        int expectedCount = displayIds.length;
92        Display[] displays = new Display[expectedCount];
93        synchronized (mLock) {
94            int actualCount = 0;
95            for (int i = 0; i < expectedCount; i++) {
96                Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/);
97                if (display != null) {
98                    displays[actualCount++] = display;
99                }
100            }
101            if (actualCount != expectedCount) {
102                Display[] oldDisplays = displays;
103                displays = new Display[actualCount];
104                System.arraycopy(oldDisplays, 0, displays, 0, actualCount);
105            }
106        }
107        return displays;
108    }
109
110    private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) {
111        Display display = mDisplays.get(displayId);
112        if (display == null) {
113            display = mGlobal.getCompatibleDisplay(displayId,
114                    mContext.getCompatibilityInfo(displayId));
115            if (display != null) {
116                mDisplays.put(displayId, display);
117            }
118        } else if (!assumeValid && !display.isValid()) {
119            display = null;
120        }
121        return display;
122    }
123
124    /**
125     * Registers an display listener to receive notifications about when
126     * displays are added, removed or changed.
127     *
128     * @param listener The listener to register.
129     * @param handler The handler on which the listener should be invoked, or null
130     * if the listener should be invoked on the calling thread's looper.
131     *
132     * @see #unregisterDisplayListener
133     */
134    public void registerDisplayListener(DisplayListener listener, Handler handler) {
135        mGlobal.registerDisplayListener(listener, handler);
136    }
137
138    /**
139     * Unregisters an input device listener.
140     *
141     * @param listener The listener to unregister.
142     *
143     * @see #registerDisplayListener
144     */
145    public void unregisterDisplayListener(DisplayListener listener) {
146        mGlobal.unregisterDisplayListener(listener);
147    }
148
149    /**
150     * Initiates a fresh scan of availble Wifi displays.
151     * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
152     * @hide
153     */
154    public void scanWifiDisplays() {
155        mGlobal.scanWifiDisplays();
156    }
157
158    /**
159     * Connects to a Wifi display.
160     * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
161     * <p>
162     * Automatically remembers the display after a successful connection, if not
163     * already remembered.
164     * </p><p>
165     * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} to connect
166     * to unknown displays.  No permissions are required to connect to already known displays.
167     * </p>
168     *
169     * @param deviceAddress The MAC address of the device to which we should connect.
170     * @hide
171     */
172    public void connectWifiDisplay(String deviceAddress) {
173        mGlobal.connectWifiDisplay(deviceAddress);
174    }
175
176    /**
177     * Disconnects from the current Wifi display.
178     * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
179     * @hide
180     */
181    public void disconnectWifiDisplay() {
182        mGlobal.disconnectWifiDisplay();
183    }
184
185    /**
186     * Renames a Wifi display.
187     * <p>
188     * The display must already be remembered for this call to succeed.  In other words,
189     * we must already have successfully connected to the display at least once and then
190     * not forgotten it.
191     * </p><p>
192     * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
193     * </p>
194     *
195     * @param deviceAddress The MAC address of the device to rename.
196     * @param alias The alias name by which to remember the device, or null
197     * or empty if no alias should be used.
198     * @hide
199     */
200    public void renameWifiDisplay(String deviceAddress, String alias) {
201        mGlobal.renameWifiDisplay(deviceAddress, alias);
202    }
203
204    /**
205     * Forgets a previously remembered Wifi display.
206     * <p>
207     * Automatically disconnects from the display if currently connected to it.
208     * </p><p>
209     * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
210     * </p>
211     *
212     * @param deviceAddress The MAC address of the device to forget.
213     * @hide
214     */
215    public void forgetWifiDisplay(String deviceAddress) {
216        mGlobal.forgetWifiDisplay(deviceAddress);
217    }
218
219    /**
220     * Gets the current Wifi display status.
221     * Watch for changes in the status by registering a broadcast receiver for
222     * {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED}.
223     *
224     * @return The current Wifi display status.
225     * @hide
226     */
227    public WifiDisplayStatus getWifiDisplayStatus() {
228        return mGlobal.getWifiDisplayStatus();
229    }
230
231    /**
232     * Listens for changes in available display devices.
233     */
234    public interface DisplayListener {
235        /**
236         * Called whenever a logical display has been added to the system.
237         * Use {@link DisplayManager#getDisplay} to get more information about
238         * the display.
239         *
240         * @param displayId The id of the logical display that was added.
241         */
242        void onDisplayAdded(int displayId);
243
244        /**
245         * Called whenever a logical display has been removed from the system.
246         *
247         * @param displayId The id of the logical display that was removed.
248         */
249        void onDisplayRemoved(int displayId);
250
251        /**
252         * Called whenever the properties of a logical display have changed.
253         *
254         * @param displayId The id of the logical display that changed.
255         */
256        void onDisplayChanged(int displayId);
257    }
258}
259