DisplayManager.java revision 7d00affce6e25b22fd8fc135933b3bf6b547a0dc
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; 23import android.view.Surface; 24 25import java.util.ArrayList; 26 27/** 28 * Manages the properties of attached displays. 29 * <p> 30 * Get an instance of this class by calling 31 * {@link android.content.Context#getSystemService(java.lang.String) 32 * Context.getSystemService()} with the argument 33 * {@link android.content.Context#DISPLAY_SERVICE}. 34 * </p> 35 */ 36public final class DisplayManager { 37 private static final String TAG = "DisplayManager"; 38 private static final boolean DEBUG = false; 39 40 private final Context mContext; 41 private final DisplayManagerGlobal mGlobal; 42 43 private final Object mLock = new Object(); 44 private final SparseArray<Display> mDisplays = new SparseArray<Display>(); 45 46 private final ArrayList<Display> mTempDisplays = new ArrayList<Display>(); 47 48 /** 49 * Broadcast receiver that indicates when the Wifi display status changes. 50 * <p> 51 * The status is provided as a {@link WifiDisplayStatus} object in the 52 * {@link #EXTRA_WIFI_DISPLAY_STATUS} extra. 53 * </p><p> 54 * This broadcast is only sent to registered receivers and can only be sent by the system. 55 * </p> 56 * @hide 57 */ 58 public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED = 59 "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED"; 60 61 /** 62 * Contains a {@link WifiDisplayStatus} object. 63 * @hide 64 */ 65 public static final String EXTRA_WIFI_DISPLAY_STATUS = 66 "android.hardware.display.extra.WIFI_DISPLAY_STATUS"; 67 68 /** 69 * Display category: Presentation displays. 70 * <p> 71 * This category can be used to identify secondary displays that are suitable for 72 * use as presentation displays such as HDMI or Wireless displays. Applications 73 * may automatically project their content to presentation displays to provide 74 * richer second screen experiences. 75 * </p> 76 * 77 * @see android.app.Presentation for information about presenting content 78 * on secondary displays. 79 * @see Display#FLAG_PRESENTATION 80 * @see #getDisplays(String) 81 */ 82 public static final String DISPLAY_CATEGORY_PRESENTATION = 83 "android.hardware.display.category.PRESENTATION"; 84 85 /** 86 * Virtual display flag: Create a public display. 87 * 88 * <h3>Public virtual displays</h3> 89 * <p> 90 * When this flag is set, the virtual display is public. 91 * </p><p> 92 * A public virtual display behaves just like most any other display that is connected 93 * to the system such as an HDMI or Wireless display. Applications can open 94 * windows on the display and the system may mirror the contents of other displays 95 * onto it. 96 * </p><p> 97 * Creating a public virtual display requires the 98 * {@link android.Manifest.permission#CAPTURE_VIDEO_OUTPUT} 99 * or {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT} permission. 100 * These permissions are reserved for use by system components and are not available to 101 * third-party applications. 102 * </p> 103 * 104 * <h3>Private virtual displays</h3> 105 * <p> 106 * When this flag is not set, the virtual display is private as defined by the 107 * {@link Display#FLAG_PRIVATE} display flag. 108 * </p> 109 * A private virtual display belongs to the application that created it. 110 * Only the a owner of a private virtual display is allowed to place windows upon it. 111 * The private virtual display also does not participate in display mirroring: it will 112 * neither receive mirrored content from another display nor allow its own content to 113 * be mirrored elsewhere. More precisely, the only processes that are allowed to 114 * enumerate or interact with the private display are those that have the same UID as the 115 * application that originally created the private virtual display. 116 * </p> 117 * 118 * @see #createVirtualDisplay 119 */ 120 public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1 << 0; 121 122 /** 123 * Virtual display flag: Create a presentation display. 124 * 125 * <h3>Presentation virtual displays</h3> 126 * <p> 127 * When this flag is set, the virtual display is registered as a presentation 128 * display in the {@link #DISPLAY_CATEGORY_PRESENTATION presentation display category}. 129 * Applications may automatically project their content to presentation displays 130 * to provide richer second screen experiences. 131 * </p> 132 * 133 * <h3>Non-presentation virtual displays</h3> 134 * <p> 135 * When this flag is not set, the virtual display is not registered as a presentation 136 * display. Applications can still project their content on the display but they 137 * will typically not do so automatically. This option is appropriate for 138 * more special-purpose displays. 139 * </p> 140 * 141 * @see android.app.Presentation for information about presenting content 142 * on secondary displays. 143 * @see #createVirtualDisplay 144 * @see #DISPLAY_CATEGORY_PRESENTATION 145 * @see Display#FLAG_PRESENTATION 146 */ 147 public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 1 << 1; 148 149 /** 150 * Virtual display flag: Create a secure display. 151 * 152 * <h3>Secure virtual displays</h3> 153 * <p> 154 * When this flag is set, the virtual display is considered secure as defined 155 * by the {@link Display#FLAG_SECURE} display flag. The caller promises to take 156 * reasonable measures, such as over-the-air encryption, to prevent the contents 157 * of the display from being intercepted or recorded on a persistent medium. 158 * </p><p> 159 * Creating a secure virtual display requires the 160 * {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT} permission. 161 * This permission is reserved for use by system components and is not available to 162 * third-party applications. 163 * </p> 164 * 165 * <h3>Non-secure virtual displays</h3> 166 * <p> 167 * When this flag is not set, the virtual display is considered unsecure. 168 * The content of secure windows will be blanked if shown on this display. 169 * </p> 170 * 171 * @see Display#FLAG_SECURE for information about secure displays. 172 * @see #createVirtualDisplay 173 */ 174 public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 1 << 2; 175 176 /** @hide */ 177 public DisplayManager(Context context) { 178 mContext = context; 179 mGlobal = DisplayManagerGlobal.getInstance(); 180 } 181 182 /** 183 * Gets information about a logical display. 184 * 185 * The display metrics may be adjusted to provide compatibility 186 * for legacy applications. 187 * 188 * @param displayId The logical display id. 189 * @return The display object, or null if there is no valid display with the given id. 190 */ 191 public Display getDisplay(int displayId) { 192 synchronized (mLock) { 193 return getOrCreateDisplayLocked(displayId, false /*assumeValid*/); 194 } 195 } 196 197 /** 198 * Gets all currently valid logical displays. 199 * 200 * @return An array containing all displays. 201 */ 202 public Display[] getDisplays() { 203 return getDisplays(null); 204 } 205 206 /** 207 * Gets all currently valid logical displays of the specified category. 208 * <p> 209 * When there are multiple displays in a category the returned displays are sorted 210 * of preference. For example, if the requested category is 211 * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays 212 * then the displays are sorted so that the first display in the returned array 213 * is the most preferred presentation display. The application may simply 214 * use the first display or allow the user to choose. 215 * </p> 216 * 217 * @param category The requested display category or null to return all displays. 218 * @return An array containing all displays sorted by order of preference. 219 * 220 * @see #DISPLAY_CATEGORY_PRESENTATION 221 */ 222 public Display[] getDisplays(String category) { 223 final int[] displayIds = mGlobal.getDisplayIds(); 224 synchronized (mLock) { 225 try { 226 if (category == null) { 227 addAllDisplaysLocked(mTempDisplays, displayIds); 228 } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) { 229 addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI); 230 addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI); 231 addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY); 232 addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL); 233 } 234 return mTempDisplays.toArray(new Display[mTempDisplays.size()]); 235 } finally { 236 mTempDisplays.clear(); 237 } 238 } 239 } 240 241 private void addAllDisplaysLocked(ArrayList<Display> displays, int[] displayIds) { 242 for (int i = 0; i < displayIds.length; i++) { 243 Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/); 244 if (display != null) { 245 displays.add(display); 246 } 247 } 248 } 249 250 private void addPresentationDisplaysLocked( 251 ArrayList<Display> displays, int[] displayIds, int matchType) { 252 for (int i = 0; i < displayIds.length; i++) { 253 Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/); 254 if (display != null 255 && (display.getFlags() & Display.FLAG_PRESENTATION) != 0 256 && display.getType() == matchType) { 257 displays.add(display); 258 } 259 } 260 } 261 262 private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) { 263 Display display = mDisplays.get(displayId); 264 if (display == null) { 265 display = mGlobal.getCompatibleDisplay(displayId, 266 mContext.getDisplayAdjustments(displayId)); 267 if (display != null) { 268 mDisplays.put(displayId, display); 269 } 270 } else if (!assumeValid && !display.isValid()) { 271 display = null; 272 } 273 return display; 274 } 275 276 /** 277 * Registers an display listener to receive notifications about when 278 * displays are added, removed or changed. 279 * 280 * @param listener The listener to register. 281 * @param handler The handler on which the listener should be invoked, or null 282 * if the listener should be invoked on the calling thread's looper. 283 * 284 * @see #unregisterDisplayListener 285 */ 286 public void registerDisplayListener(DisplayListener listener, Handler handler) { 287 mGlobal.registerDisplayListener(listener, handler); 288 } 289 290 /** 291 * Unregisters an input device listener. 292 * 293 * @param listener The listener to unregister. 294 * 295 * @see #registerDisplayListener 296 */ 297 public void unregisterDisplayListener(DisplayListener listener) { 298 mGlobal.unregisterDisplayListener(listener); 299 } 300 301 /** 302 * Initiates a fresh scan of availble Wifi displays. 303 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. 304 * @hide 305 */ 306 public void scanWifiDisplays() { 307 mGlobal.scanWifiDisplays(); 308 } 309 310 /** 311 * Connects to a Wifi display. 312 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. 313 * <p> 314 * Automatically remembers the display after a successful connection, if not 315 * already remembered. 316 * </p><p> 317 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} to connect 318 * to unknown displays. No permissions are required to connect to already known displays. 319 * </p> 320 * 321 * @param deviceAddress The MAC address of the device to which we should connect. 322 * @hide 323 */ 324 public void connectWifiDisplay(String deviceAddress) { 325 mGlobal.connectWifiDisplay(deviceAddress); 326 } 327 328 /** 329 * Disconnects from the current Wifi display. 330 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. 331 * @hide 332 */ 333 public void disconnectWifiDisplay() { 334 mGlobal.disconnectWifiDisplay(); 335 } 336 337 /** 338 * Renames a Wifi display. 339 * <p> 340 * The display must already be remembered for this call to succeed. In other words, 341 * we must already have successfully connected to the display at least once and then 342 * not forgotten it. 343 * </p><p> 344 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 345 * </p> 346 * 347 * @param deviceAddress The MAC address of the device to rename. 348 * @param alias The alias name by which to remember the device, or null 349 * or empty if no alias should be used. 350 * @hide 351 */ 352 public void renameWifiDisplay(String deviceAddress, String alias) { 353 mGlobal.renameWifiDisplay(deviceAddress, alias); 354 } 355 356 /** 357 * Forgets a previously remembered Wifi display. 358 * <p> 359 * Automatically disconnects from the display if currently connected to it. 360 * </p><p> 361 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 362 * </p> 363 * 364 * @param deviceAddress The MAC address of the device to forget. 365 * @hide 366 */ 367 public void forgetWifiDisplay(String deviceAddress) { 368 mGlobal.forgetWifiDisplay(deviceAddress); 369 } 370 371 /** 372 * Gets the current Wifi display status. 373 * Watch for changes in the status by registering a broadcast receiver for 374 * {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED}. 375 * 376 * @return The current Wifi display status. 377 * @hide 378 */ 379 public WifiDisplayStatus getWifiDisplayStatus() { 380 return mGlobal.getWifiDisplayStatus(); 381 } 382 383 /** 384 * Creates a virtual display. 385 * <p> 386 * The content of a virtual display is rendered to a {@link Surface} provided 387 * by the application. 388 * </p><p> 389 * The virtual display should be {@link VirtualDisplay#release released} 390 * when no longer needed. Because a virtual display renders to a surface 391 * provided by the application, it will be released automatically when the 392 * process terminates and all remaining windows on it will be forcibly removed. 393 * </p><p> 394 * The behavior of the virtual display depends on the flags that are provided 395 * to this method. By default, virtual displays are created to be private, 396 * non-presentation and unsecure. Permissions may be required to use certain flags. 397 * </p> 398 * 399 * @param name The name of the virtual display, must be non-empty. 400 * @param width The width of the virtual display in pixels, must be greater than 0. 401 * @param height The height of the virtual display in pixels, must be greater than 0. 402 * @param densityDpi The density of the virtual display in dpi, must be greater than 0. 403 * @param surface The surface to which the content of the virtual display should 404 * be rendered, must be non-null. 405 * @param flags A combination of virtual display flags: 406 * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION} 407 * or {@link #VIRTUAL_DISPLAY_FLAG_SECURE}. 408 * @return The newly created virtual display, or null if the application could 409 * not create the virtual display. 410 * 411 * @throws SecurityException if the caller does not have permission to create 412 * a virtual display with the specified flags. 413 */ 414 public VirtualDisplay createVirtualDisplay(String name, 415 int width, int height, int densityDpi, Surface surface, int flags) { 416 return mGlobal.createVirtualDisplay(mContext, 417 name, width, height, densityDpi, surface, flags); 418 } 419 420 /** 421 * Listens for changes in available display devices. 422 */ 423 public interface DisplayListener { 424 /** 425 * Called whenever a logical display has been added to the system. 426 * Use {@link DisplayManager#getDisplay} to get more information about 427 * the display. 428 * 429 * @param displayId The id of the logical display that was added. 430 */ 431 void onDisplayAdded(int displayId); 432 433 /** 434 * Called whenever a logical display has been removed from the system. 435 * 436 * @param displayId The id of the logical display that was removed. 437 */ 438 void onDisplayRemoved(int displayId); 439 440 /** 441 * Called whenever the properties of a logical display have changed. 442 * 443 * @param displayId The id of the logical display that changed. 444 */ 445 void onDisplayChanged(int displayId); 446 } 447} 448