blob: 0a7a2e71b770aa6685b9c6508848d1d652e92ea1 [file] [log] [blame]
Jeff Brownfa25bf52012-07-23 19:26:30 -07001/*
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;
Jeff Brown98365d72012-08-19 20:30:52 -070020import android.os.Handler;
Jeff Brownbd6e1502012-08-28 03:27:37 -070021import android.util.SparseArray;
Jeff Brown98365d72012-08-19 20:30:52 -070022import android.view.Display;
Jeff Brown98365d72012-08-19 20:30:52 -070023
Jeff Brown92130f62012-10-24 21:28:33 -070024import java.util.ArrayList;
25
Jeff Brownfa25bf52012-07-23 19:26:30 -070026/**
Jeff Brownbd6e1502012-08-28 03:27:37 -070027 * Manages the properties of attached displays.
Jeff Brownfa25bf52012-07-23 19:26:30 -070028 * <p>
29 * Get an instance of this class by calling
30 * {@link android.content.Context#getSystemService(java.lang.String)
31 * Context.getSystemService()} with the argument
32 * {@link android.content.Context#DISPLAY_SERVICE}.
33 * </p>
34 */
35public final class DisplayManager {
36 private static final String TAG = "DisplayManager";
Jeff Brown98365d72012-08-19 20:30:52 -070037 private static final boolean DEBUG = false;
38
Jeff Brownbd6e1502012-08-28 03:27:37 -070039 private final Context mContext;
40 private final DisplayManagerGlobal mGlobal;
Jeff Brownfa25bf52012-07-23 19:26:30 -070041
Jeff Brownbd6e1502012-08-28 03:27:37 -070042 private final Object mLock = new Object();
43 private final SparseArray<Display> mDisplays = new SparseArray<Display>();
Jeff Brownfa25bf52012-07-23 19:26:30 -070044
Jeff Brown92130f62012-10-24 21:28:33 -070045 private final ArrayList<Display> mTempDisplays = new ArrayList<Display>();
46
Jeff Browne08ae382012-09-07 20:36:36 -070047 /**
48 * Broadcast receiver that indicates when the Wifi display status changes.
49 * <p>
50 * The status is provided as a {@link WifiDisplayStatus} object in the
51 * {@link #EXTRA_WIFI_DISPLAY_STATUS} extra.
52 * </p><p>
Jeff Brownbc335452012-09-26 18:34:47 -070053 * This broadcast is only sent to registered receivers and can only be sent by the system.
Jeff Browne08ae382012-09-07 20:36:36 -070054 * </p>
55 * @hide
56 */
57 public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED =
58 "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED";
59
60 /**
61 * Contains a {@link WifiDisplayStatus} object.
62 * @hide
63 */
64 public static final String EXTRA_WIFI_DISPLAY_STATUS =
65 "android.hardware.display.extra.WIFI_DISPLAY_STATUS";
66
Jeff Brown92130f62012-10-24 21:28:33 -070067 /**
68 * Display category: Presentation displays.
69 * <p>
70 * This category can be used to identify secondary displays that are suitable for
71 * use as presentation displays.
72 * </p>
73 *
74 * @see android.app.Presentation for information about presenting content
75 * on secondary displays.
76 * @see #getDisplays(String)
77 */
78 public static final String DISPLAY_CATEGORY_PRESENTATION =
79 "android.hardware.display.category.PRESENTATION";
80
Jeff Brownbd6e1502012-08-28 03:27:37 -070081 /** @hide */
82 public DisplayManager(Context context) {
83 mContext = context;
84 mGlobal = DisplayManagerGlobal.getInstance();
Jeff Brownfa25bf52012-07-23 19:26:30 -070085 }
86
87 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -070088 * Gets information about a logical display.
Jeff Brown848c2dc2012-08-19 20:18:08 -070089 *
Jeff Brownbd6e1502012-08-28 03:27:37 -070090 * The display metrics may be adjusted to provide compatibility
91 * for legacy applications.
Jeff Brown848c2dc2012-08-19 20:18:08 -070092 *
Jeff Brownbd6e1502012-08-28 03:27:37 -070093 * @param displayId The logical display id.
94 * @return The display object, or null if there is no valid display with the given id.
Jeff Brownfa25bf52012-07-23 19:26:30 -070095 */
Jeff Brownbd6e1502012-08-28 03:27:37 -070096 public Display getDisplay(int displayId) {
97 synchronized (mLock) {
98 return getOrCreateDisplayLocked(displayId, false /*assumeValid*/);
99 }
100 }
101
102 /**
103 * Gets all currently valid logical displays.
104 *
105 * @return An array containing all displays.
106 */
107 public Display[] getDisplays() {
Jeff Brown92130f62012-10-24 21:28:33 -0700108 return getDisplays(null);
109 }
110
111 /**
112 * Gets all currently valid logical displays of the specified category.
113 * <p>
114 * When there are multiple displays in a category the returned displays are sorted
115 * of preference. For example, if the requested category is
116 * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays
117 * then the displays are sorted so that the first display in the returned array
118 * is the most preferred presentation display. The application may simply
119 * use the first display or allow the user to choose.
120 * </p>
121 *
122 * @param category The requested display category or null to return all displays.
123 * @return An array containing all displays sorted by order of preference.
124 *
125 * @see #DISPLAY_CATEGORY_PRESENTATION
126 */
127 public Display[] getDisplays(String category) {
128 final int[] displayIds = mGlobal.getDisplayIds();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700129 synchronized (mLock) {
Jeff Brown92130f62012-10-24 21:28:33 -0700130 try {
131 if (category == null) {
132 addMatchingDisplaysLocked(mTempDisplays, displayIds, -1);
133 } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
134 addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
135 addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI);
136 addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700137 }
Jeff Brown92130f62012-10-24 21:28:33 -0700138 return mTempDisplays.toArray(new Display[mTempDisplays.size()]);
139 } finally {
140 mTempDisplays.clear();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700141 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700142 }
Jeff Brown92130f62012-10-24 21:28:33 -0700143 }
144
145 private void addMatchingDisplaysLocked(
146 ArrayList<Display> displays, int[] displayIds, int matchType) {
147 for (int i = 0; i < displayIds.length; i++) {
148 Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/);
149 if (display != null
150 && (matchType < 0 || display.getType() == matchType)) {
151 displays.add(display);
152 }
153 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700154 }
155
Jeff Brownbd6e1502012-08-28 03:27:37 -0700156 private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) {
157 Display display = mDisplays.get(displayId);
158 if (display == null) {
159 display = mGlobal.getCompatibleDisplay(displayId,
Jeff Browna492c3a2012-08-23 19:48:44 -0700160 mContext.getCompatibilityInfo(displayId));
Jeff Brownbd6e1502012-08-28 03:27:37 -0700161 if (display != null) {
162 mDisplays.put(displayId, display);
163 }
164 } else if (!assumeValid && !display.isValid()) {
165 display = null;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700166 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700167 return display;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700168 }
Jeff Brown98365d72012-08-19 20:30:52 -0700169
Jeff Brown98365d72012-08-19 20:30:52 -0700170 /**
171 * Registers an display listener to receive notifications about when
172 * displays are added, removed or changed.
173 *
174 * @param listener The listener to register.
175 * @param handler The handler on which the listener should be invoked, or null
176 * if the listener should be invoked on the calling thread's looper.
177 *
178 * @see #unregisterDisplayListener
179 */
180 public void registerDisplayListener(DisplayListener listener, Handler handler) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700181 mGlobal.registerDisplayListener(listener, handler);
Jeff Brown98365d72012-08-19 20:30:52 -0700182 }
183
184 /**
185 * Unregisters an input device listener.
186 *
187 * @param listener The listener to unregister.
188 *
189 * @see #registerDisplayListener
190 */
191 public void unregisterDisplayListener(DisplayListener listener) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700192 mGlobal.unregisterDisplayListener(listener);
Jeff Brown98365d72012-08-19 20:30:52 -0700193 }
194
195 /**
Jeff Browne08ae382012-09-07 20:36:36 -0700196 * Initiates a fresh scan of availble Wifi displays.
197 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
198 * @hide
199 */
200 public void scanWifiDisplays() {
201 mGlobal.scanWifiDisplays();
202 }
203
204 /**
205 * Connects to a Wifi display.
206 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
Jeff Brown89d55462012-09-19 11:33:42 -0700207 * <p>
208 * Automatically remembers the display after a successful connection, if not
209 * already remembered.
Jeff Brownbc335452012-09-26 18:34:47 -0700210 * </p><p>
211 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} to connect
212 * to unknown displays. No permissions are required to connect to already known displays.
Jeff Brown89d55462012-09-19 11:33:42 -0700213 * </p>
Jeff Browne08ae382012-09-07 20:36:36 -0700214 *
215 * @param deviceAddress The MAC address of the device to which we should connect.
216 * @hide
217 */
218 public void connectWifiDisplay(String deviceAddress) {
219 mGlobal.connectWifiDisplay(deviceAddress);
220 }
221
222 /**
223 * Disconnects from the current Wifi display.
224 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
225 * @hide
226 */
227 public void disconnectWifiDisplay() {
228 mGlobal.disconnectWifiDisplay();
229 }
230
231 /**
Jeff Brown89d55462012-09-19 11:33:42 -0700232 * Renames a Wifi display.
233 * <p>
234 * The display must already be remembered for this call to succeed. In other words,
235 * we must already have successfully connected to the display at least once and then
236 * not forgotten it.
Jeff Brownbc335452012-09-26 18:34:47 -0700237 * </p><p>
238 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
Jeff Brown89d55462012-09-19 11:33:42 -0700239 * </p>
240 *
241 * @param deviceAddress The MAC address of the device to rename.
242 * @param alias The alias name by which to remember the device, or null
243 * or empty if no alias should be used.
244 * @hide
245 */
246 public void renameWifiDisplay(String deviceAddress, String alias) {
247 mGlobal.renameWifiDisplay(deviceAddress, alias);
248 }
249
250 /**
251 * Forgets a previously remembered Wifi display.
252 * <p>
253 * Automatically disconnects from the display if currently connected to it.
Jeff Brownbc335452012-09-26 18:34:47 -0700254 * </p><p>
255 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
Jeff Brown89d55462012-09-19 11:33:42 -0700256 * </p>
257 *
258 * @param deviceAddress The MAC address of the device to forget.
259 * @hide
260 */
261 public void forgetWifiDisplay(String deviceAddress) {
262 mGlobal.forgetWifiDisplay(deviceAddress);
263 }
264
265 /**
Jeff Browne08ae382012-09-07 20:36:36 -0700266 * Gets the current Wifi display status.
267 * Watch for changes in the status by registering a broadcast receiver for
268 * {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED}.
269 *
270 * @return The current Wifi display status.
271 * @hide
272 */
273 public WifiDisplayStatus getWifiDisplayStatus() {
274 return mGlobal.getWifiDisplayStatus();
275 }
276
277 /**
Jeff Brown98365d72012-08-19 20:30:52 -0700278 * Listens for changes in available display devices.
279 */
280 public interface DisplayListener {
281 /**
282 * Called whenever a logical display has been added to the system.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700283 * Use {@link DisplayManager#getDisplay} to get more information about
284 * the display.
Jeff Brown98365d72012-08-19 20:30:52 -0700285 *
286 * @param displayId The id of the logical display that was added.
287 */
288 void onDisplayAdded(int displayId);
289
290 /**
291 * Called whenever a logical display has been removed from the system.
292 *
293 * @param displayId The id of the logical display that was removed.
294 */
295 void onDisplayRemoved(int displayId);
296
297 /**
298 * Called whenever the properties of a logical display have changed.
299 *
300 * @param displayId The id of the logical display that changed.
301 */
302 void onDisplayChanged(int displayId);
303 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700304}