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