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 17 package android.hardware.display; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.Context; 22 import android.media.projection.MediaProjection; 23 import android.os.Handler; 24 import android.util.SparseArray; 25 import android.view.Display; 26 import android.view.Surface; 27 28 import java.util.ArrayList; 29 30 /** 31 * Manages the properties of attached displays. 32 * <p> 33 * Get an instance of this class by calling 34 * {@link android.content.Context#getSystemService(java.lang.String) 35 * Context.getSystemService()} with the argument 36 * {@link android.content.Context#DISPLAY_SERVICE}. 37 * </p> 38 */ 39 public final class DisplayManager { 40 private static final String TAG = "DisplayManager"; 41 private static final boolean DEBUG = false; 42 43 private final Context mContext; 44 private final DisplayManagerGlobal mGlobal; 45 46 private final Object mLock = new Object(); 47 private final SparseArray<Display> mDisplays = new SparseArray<Display>(); 48 49 private final ArrayList<Display> mTempDisplays = new ArrayList<Display>(); 50 51 /** 52 * Broadcast receiver that indicates when the Wifi display status changes. 53 * <p> 54 * The status is provided as a {@link WifiDisplayStatus} object in the 55 * {@link #EXTRA_WIFI_DISPLAY_STATUS} extra. 56 * </p><p> 57 * This broadcast is only sent to registered receivers and can only be sent by the system. 58 * </p> 59 * @hide 60 */ 61 public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED = 62 "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED"; 63 64 /** 65 * Contains a {@link WifiDisplayStatus} object. 66 * @hide 67 */ 68 public static final String EXTRA_WIFI_DISPLAY_STATUS = 69 "android.hardware.display.extra.WIFI_DISPLAY_STATUS"; 70 71 /** 72 * Display category: Presentation displays. 73 * <p> 74 * This category can be used to identify secondary displays that are suitable for 75 * use as presentation displays such as HDMI or Wireless displays. Applications 76 * may automatically project their content to presentation displays to provide 77 * richer second screen experiences. 78 * </p> 79 * 80 * @see android.app.Presentation 81 * @see Display#FLAG_PRESENTATION 82 * @see #getDisplays(String) 83 */ 84 public static final String DISPLAY_CATEGORY_PRESENTATION = 85 "android.hardware.display.category.PRESENTATION"; 86 87 /** 88 * Virtual display flag: Create a public display. 89 * 90 * <h3>Public virtual displays</h3> 91 * <p> 92 * When this flag is set, the virtual display is public. 93 * </p><p> 94 * A public virtual display behaves just like most any other display that is connected 95 * to the system such as an HDMI or Wireless display. Applications can open 96 * windows on the display and the system may mirror the contents of other displays 97 * onto it. 98 * </p><p> 99 * Creating a public virtual display that isn't restricted to own-content only implicitly 100 * creates an auto-mirroring display. See {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR} for 101 * restrictions on who is allowed to create an auto-mirroring display. 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 * 110 * <p> 111 * A private virtual display belongs to the application that created it. 112 * Only the a owner of a private virtual display is allowed to place windows upon it. 113 * The private virtual display also does not participate in display mirroring: it will 114 * neither receive mirrored content from another display nor allow its own content to 115 * be mirrored elsewhere. More precisely, the only processes that are allowed to 116 * enumerate or interact with the private display are those that have the same UID as the 117 * application that originally created the private virtual display. 118 * </p> 119 * 120 * @see #createVirtualDisplay 121 * @see #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY 122 * @see #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR 123 */ 124 public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1 << 0; 125 126 /** 127 * Virtual display flag: Create a presentation display. 128 * 129 * <h3>Presentation virtual displays</h3> 130 * <p> 131 * When this flag is set, the virtual display is registered as a presentation 132 * display in the {@link #DISPLAY_CATEGORY_PRESENTATION presentation display category}. 133 * Applications may automatically project their content to presentation displays 134 * to provide richer second screen experiences. 135 * </p> 136 * 137 * <h3>Non-presentation virtual displays</h3> 138 * <p> 139 * When this flag is not set, the virtual display is not registered as a presentation 140 * display. Applications can still project their content on the display but they 141 * will typically not do so automatically. This option is appropriate for 142 * more special-purpose displays. 143 * </p> 144 * 145 * @see android.app.Presentation 146 * @see #createVirtualDisplay 147 * @see #DISPLAY_CATEGORY_PRESENTATION 148 * @see Display#FLAG_PRESENTATION 149 */ 150 public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 1 << 1; 151 152 /** 153 * Virtual display flag: Create a secure display. 154 * 155 * <h3>Secure virtual displays</h3> 156 * <p> 157 * When this flag is set, the virtual display is considered secure as defined 158 * by the {@link Display#FLAG_SECURE} display flag. The caller promises to take 159 * reasonable measures, such as over-the-air encryption, to prevent the contents 160 * of the display from being intercepted or recorded on a persistent medium. 161 * </p><p> 162 * Creating a secure virtual display requires the 163 * {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT} permission. 164 * This permission is reserved for use by system components and is not available to 165 * third-party applications. 166 * </p> 167 * 168 * <h3>Non-secure virtual displays</h3> 169 * <p> 170 * When this flag is not set, the virtual display is considered unsecure. 171 * The content of secure windows will be blanked if shown on this display. 172 * </p> 173 * 174 * @see Display#FLAG_SECURE 175 * @see #createVirtualDisplay 176 */ 177 public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 1 << 2; 178 179 /** 180 * Virtual display flag: Only show this display's own content; do not mirror 181 * the content of another display. 182 * 183 * <p> 184 * This flag is used in conjunction with {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}. 185 * Ordinarily public virtual displays will automatically mirror the content of the 186 * default display if they have no windows of their own. When this flag is 187 * specified, the virtual display will only ever show its own content and 188 * will be blanked instead if it has no windows. 189 * </p> 190 * 191 * <p> 192 * This flag is mutually exclusive with {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}. If both 193 * flags are specified then the own-content only behavior will be applied. 194 * </p> 195 * 196 * <p> 197 * This behavior of this flag is implied whenever neither {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC} 198 * nor {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR} have been set. This flag is only required to 199 * override the default behavior when creating a public display. 200 * </p> 201 * 202 * @see #createVirtualDisplay 203 */ 204 public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 1 << 3; 205 206 207 /** 208 * Virtual display flag: Allows content to be mirrored on private displays when no content is 209 * being shown. 210 * 211 * <p> 212 * This flag is mutually exclusive with {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}. 213 * If both flags are specified then the own-content only behavior will be applied. 214 * </p> 215 * 216 * <p> 217 * The behavior of this flag is implied whenever {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC} is set 218 * and {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY} has not been set. This flag is only 219 * required to override the default behavior when creating a private display. 220 * </p> 221 * 222 * <p> 223 * Creating an auto-mirroing virtual display requires the 224 * {@link android.Manifest.permission#CAPTURE_VIDEO_OUTPUT} 225 * or {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT} permission. 226 * These permissions are reserved for use by system components and are not available to 227 * third-party applications. 228 * 229 * Alternatively, an appropriate {@link MediaProjection} may be used to create an 230 * auto-mirroring virtual display. 231 * </p> 232 * 233 * @see #createVirtualDisplay 234 */ 235 public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 1 << 4; 236 237 /** @hide */ DisplayManager(Context context)238 public DisplayManager(Context context) { 239 mContext = context; 240 mGlobal = DisplayManagerGlobal.getInstance(); 241 } 242 243 /** 244 * Gets information about a logical display. 245 * 246 * The display metrics may be adjusted to provide compatibility 247 * for legacy applications. 248 * 249 * @param displayId The logical display id. 250 * @return The display object, or null if there is no valid display with the given id. 251 */ getDisplay(int displayId)252 public Display getDisplay(int displayId) { 253 synchronized (mLock) { 254 return getOrCreateDisplayLocked(displayId, false /*assumeValid*/); 255 } 256 } 257 258 /** 259 * Gets all currently valid logical displays. 260 * 261 * @return An array containing all displays. 262 */ getDisplays()263 public Display[] getDisplays() { 264 return getDisplays(null); 265 } 266 267 /** 268 * Gets all currently valid logical displays of the specified category. 269 * <p> 270 * When there are multiple displays in a category the returned displays are sorted 271 * of preference. For example, if the requested category is 272 * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays 273 * then the displays are sorted so that the first display in the returned array 274 * is the most preferred presentation display. The application may simply 275 * use the first display or allow the user to choose. 276 * </p> 277 * 278 * @param category The requested display category or null to return all displays. 279 * @return An array containing all displays sorted by order of preference. 280 * 281 * @see #DISPLAY_CATEGORY_PRESENTATION 282 */ getDisplays(String category)283 public Display[] getDisplays(String category) { 284 final int[] displayIds = mGlobal.getDisplayIds(); 285 synchronized (mLock) { 286 try { 287 if (category == null) { 288 addAllDisplaysLocked(mTempDisplays, displayIds); 289 } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) { 290 addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI); 291 addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI); 292 addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY); 293 addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL); 294 } 295 return mTempDisplays.toArray(new Display[mTempDisplays.size()]); 296 } finally { 297 mTempDisplays.clear(); 298 } 299 } 300 } 301 addAllDisplaysLocked(ArrayList<Display> displays, int[] displayIds)302 private void addAllDisplaysLocked(ArrayList<Display> displays, int[] displayIds) { 303 for (int i = 0; i < displayIds.length; i++) { 304 Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/); 305 if (display != null) { 306 displays.add(display); 307 } 308 } 309 } 310 addPresentationDisplaysLocked( ArrayList<Display> displays, int[] displayIds, int matchType)311 private void addPresentationDisplaysLocked( 312 ArrayList<Display> displays, int[] displayIds, int matchType) { 313 for (int i = 0; i < displayIds.length; i++) { 314 Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/); 315 if (display != null 316 && (display.getFlags() & Display.FLAG_PRESENTATION) != 0 317 && display.getType() == matchType) { 318 displays.add(display); 319 } 320 } 321 } 322 getOrCreateDisplayLocked(int displayId, boolean assumeValid)323 private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) { 324 Display display = mDisplays.get(displayId); 325 if (display == null) { 326 display = mGlobal.getCompatibleDisplay(displayId, 327 mContext.getDisplayAdjustments(displayId)); 328 if (display != null) { 329 mDisplays.put(displayId, display); 330 } 331 } else if (!assumeValid && !display.isValid()) { 332 display = null; 333 } 334 return display; 335 } 336 337 /** 338 * Registers an display listener to receive notifications about when 339 * displays are added, removed or changed. 340 * 341 * @param listener The listener to register. 342 * @param handler The handler on which the listener should be invoked, or null 343 * if the listener should be invoked on the calling thread's looper. 344 * 345 * @see #unregisterDisplayListener 346 */ registerDisplayListener(DisplayListener listener, Handler handler)347 public void registerDisplayListener(DisplayListener listener, Handler handler) { 348 mGlobal.registerDisplayListener(listener, handler); 349 } 350 351 /** 352 * Unregisters a display listener. 353 * 354 * @param listener The listener to unregister. 355 * 356 * @see #registerDisplayListener 357 */ unregisterDisplayListener(DisplayListener listener)358 public void unregisterDisplayListener(DisplayListener listener) { 359 mGlobal.unregisterDisplayListener(listener); 360 } 361 362 /** 363 * Starts scanning for available Wifi displays. 364 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. 365 * <p> 366 * Calls to this method nest and must be matched by an equal number of calls to 367 * {@link #stopWifiDisplayScan()}. 368 * </p><p> 369 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 370 * </p> 371 * 372 * @hide 373 */ startWifiDisplayScan()374 public void startWifiDisplayScan() { 375 mGlobal.startWifiDisplayScan(); 376 } 377 378 /** 379 * Stops scanning for available Wifi displays. 380 * <p> 381 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 382 * </p> 383 * 384 * @hide 385 */ stopWifiDisplayScan()386 public void stopWifiDisplayScan() { 387 mGlobal.stopWifiDisplayScan(); 388 } 389 390 /** 391 * Connects to a Wifi display. 392 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. 393 * <p> 394 * Automatically remembers the display after a successful connection, if not 395 * already remembered. 396 * </p><p> 397 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 398 * </p> 399 * 400 * @param deviceAddress The MAC address of the device to which we should connect. 401 * @hide 402 */ connectWifiDisplay(String deviceAddress)403 public void connectWifiDisplay(String deviceAddress) { 404 mGlobal.connectWifiDisplay(deviceAddress); 405 } 406 407 /** @hide */ pauseWifiDisplay()408 public void pauseWifiDisplay() { 409 mGlobal.pauseWifiDisplay(); 410 } 411 412 /** @hide */ resumeWifiDisplay()413 public void resumeWifiDisplay() { 414 mGlobal.resumeWifiDisplay(); 415 } 416 417 /** 418 * Disconnects from the current Wifi display. 419 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. 420 * @hide 421 */ disconnectWifiDisplay()422 public void disconnectWifiDisplay() { 423 mGlobal.disconnectWifiDisplay(); 424 } 425 426 /** 427 * Renames a Wifi display. 428 * <p> 429 * The display must already be remembered for this call to succeed. In other words, 430 * we must already have successfully connected to the display at least once and then 431 * not forgotten it. 432 * </p><p> 433 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 434 * </p> 435 * 436 * @param deviceAddress The MAC address of the device to rename. 437 * @param alias The alias name by which to remember the device, or null 438 * or empty if no alias should be used. 439 * @hide 440 */ renameWifiDisplay(String deviceAddress, String alias)441 public void renameWifiDisplay(String deviceAddress, String alias) { 442 mGlobal.renameWifiDisplay(deviceAddress, alias); 443 } 444 445 /** 446 * Forgets a previously remembered Wifi display. 447 * <p> 448 * Automatically disconnects from the display if currently connected to it. 449 * </p><p> 450 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 451 * </p> 452 * 453 * @param deviceAddress The MAC address of the device to forget. 454 * @hide 455 */ forgetWifiDisplay(String deviceAddress)456 public void forgetWifiDisplay(String deviceAddress) { 457 mGlobal.forgetWifiDisplay(deviceAddress); 458 } 459 460 /** 461 * Gets the current Wifi display status. 462 * Watch for changes in the status by registering a broadcast receiver for 463 * {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED}. 464 * 465 * @return The current Wifi display status. 466 * @hide 467 */ getWifiDisplayStatus()468 public WifiDisplayStatus getWifiDisplayStatus() { 469 return mGlobal.getWifiDisplayStatus(); 470 } 471 472 /** 473 * Creates a virtual display. 474 * 475 * @see #createVirtualDisplay(String, int, int, int, Surface, int, 476 * VirtualDisplay.Callback, Handler) 477 */ createVirtualDisplay(@onNull String name, int width, int height, int densityDpi, @Nullable Surface surface, int flags)478 public VirtualDisplay createVirtualDisplay(@NonNull String name, 479 int width, int height, int densityDpi, @Nullable Surface surface, int flags) { 480 return createVirtualDisplay(name, width, height, densityDpi, surface, flags, null, null); 481 } 482 483 /** 484 * Creates a virtual display. 485 * <p> 486 * The content of a virtual display is rendered to a {@link Surface} provided 487 * by the application. 488 * </p><p> 489 * The virtual display should be {@link VirtualDisplay#release released} 490 * when no longer needed. Because a virtual display renders to a surface 491 * provided by the application, it will be released automatically when the 492 * process terminates and all remaining windows on it will be forcibly removed. 493 * </p><p> 494 * The behavior of the virtual display depends on the flags that are provided 495 * to this method. By default, virtual displays are created to be private, 496 * non-presentation and unsecure. Permissions may be required to use certain flags. 497 * </p><p> 498 * As of {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}, the surface may 499 * be attached or detached dynamically using {@link VirtualDisplay#setSurface}. 500 * Previously, the surface had to be non-null when {@link #createVirtualDisplay} 501 * was called and could not be changed for the lifetime of the display. 502 * </p><p> 503 * Detaching the surface that backs a virtual display has a similar effect to 504 * turning off the screen. 505 * </p> 506 * 507 * @param name The name of the virtual display, must be non-empty. 508 * @param width The width of the virtual display in pixels, must be greater than 0. 509 * @param height The height of the virtual display in pixels, must be greater than 0. 510 * @param densityDpi The density of the virtual display in dpi, must be greater than 0. 511 * @param surface The surface to which the content of the virtual display should 512 * be rendered, or null if there is none initially. 513 * @param flags A combination of virtual display flags: 514 * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION}, 515 * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}, 516 * or {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}. 517 * @param callback Callback to call when the state of the {@link VirtualDisplay} changes 518 * @param handler The handler on which the listener should be invoked, or null 519 * if the listener should be invoked on the calling thread's looper. 520 * @return The newly created virtual display, or null if the application could 521 * not create the virtual display. 522 * 523 * @throws SecurityException if the caller does not have permission to create 524 * a virtual display with the specified flags. 525 */ createVirtualDisplay(@onNull String name, int width, int height, int densityDpi, @Nullable Surface surface, int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler)526 public VirtualDisplay createVirtualDisplay(@NonNull String name, 527 int width, int height, int densityDpi, @Nullable Surface surface, int flags, 528 @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) { 529 return createVirtualDisplay(null, 530 name, width, height, densityDpi, surface, flags, callback, handler); 531 } 532 533 /** @hide */ createVirtualDisplay(@ullable MediaProjection projection, @NonNull String name, int width, int height, int densityDpi, @Nullable Surface surface, int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler)534 public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection, 535 @NonNull String name, int width, int height, int densityDpi, @Nullable Surface surface, 536 int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) { 537 return mGlobal.createVirtualDisplay(mContext, projection, 538 name, width, height, densityDpi, surface, flags, callback, handler); 539 } 540 541 /** 542 * Listens for changes in available display devices. 543 */ 544 public interface DisplayListener { 545 /** 546 * Called whenever a logical display has been added to the system. 547 * Use {@link DisplayManager#getDisplay} to get more information about 548 * the display. 549 * 550 * @param displayId The id of the logical display that was added. 551 */ onDisplayAdded(int displayId)552 void onDisplayAdded(int displayId); 553 554 /** 555 * Called whenever a logical display has been removed from the system. 556 * 557 * @param displayId The id of the logical display that was removed. 558 */ onDisplayRemoved(int displayId)559 void onDisplayRemoved(int displayId); 560 561 /** 562 * Called whenever the properties of a logical display have changed. 563 * 564 * @param displayId The id of the logical display that changed. 565 */ onDisplayChanged(int displayId)566 void onDisplayChanged(int displayId); 567 } 568 } 569