diff --git a/api/current.txt b/api/current.txt index 429caa5a27779..7d83fcfe98c8d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -40,6 +40,9 @@ package android { field public static final java.lang.String CALL_PHONE = "android.permission.CALL_PHONE"; field public static final java.lang.String CALL_PRIVILEGED = "android.permission.CALL_PRIVILEGED"; field public static final java.lang.String CAMERA = "android.permission.CAMERA"; + field public static final java.lang.String CAPTURE_AUDIO_OUTPUT = "android.permission.CAPTURE_AUDIO_OUTPUT"; + field public static final java.lang.String CAPTURE_SECURE_VIDEO_OUTPUT = "android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"; + field public static final java.lang.String CAPTURE_VIDEO_OUTPUT = "android.permission.CAPTURE_VIDEO_OUTPUT"; field public static final java.lang.String CHANGE_COMPONENT_ENABLED_STATE = "android.permission.CHANGE_COMPONENT_ENABLED_STATE"; field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION"; field public static final java.lang.String CHANGE_NETWORK_STATE = "android.permission.CHANGE_NETWORK_STATE"; @@ -10798,13 +10801,16 @@ package android.hardware.camera2 { package android.hardware.display { public final class DisplayManager { - method public android.hardware.display.VirtualDisplay createPrivateVirtualDisplay(java.lang.String, int, int, int, android.view.Surface); + method public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, android.view.Surface, int); method public android.view.Display getDisplay(int); method public android.view.Display[] getDisplays(); method public android.view.Display[] getDisplays(java.lang.String); method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler); method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener); field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION"; + field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2 + field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1 + field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4 } public static abstract interface DisplayManager.DisplayListener { @@ -25610,6 +25616,7 @@ package android.view { method public deprecated int getWidth(); method public boolean isValid(); field public static final int DEFAULT_DISPLAY = 0; // 0x0 + field public static final int FLAG_PRESENTATION = 8; // 0x8 field public static final int FLAG_PRIVATE = 4; // 0x4 field public static final int FLAG_SECURE = 2; // 0x2 field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1 diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 9e2e4ba11f563..7d65736851523 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -69,16 +69,110 @@ public final class DisplayManager { * Display category: Presentation displays. *
* This category can be used to identify secondary displays that are suitable for - * use as presentation displays. + * use as presentation displays such as HDMI or Wireless displays. Applications + * may automatically project their content to presentation displays to provide + * richer second screen experiences. *
* * @see android.app.Presentation for information about presenting content * on secondary displays. + * @see Display#FLAG_PRESENTATION * @see #getDisplays(String) */ public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION"; + /** + * Virtual display flag: Create a public display. + * + *+ * When this flag is set, the virtual display is public. + *
+ * A public virtual display behaves just like most any other display that is connected + * to the system such as an HDMI or Wireless display. Applications can open + * windows on the display and the system may mirror the contents of other displays + * onto it. + *
+ * Creating a public virtual display requires the + * {@link android.Manifest.permission#CAPTURE_VIDEO_OUTPUT} + * or {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT} permission. + * These permissions are reserved for use by system components and are not available to + * third-party applications. + *
+ * + *+ * When this flag is not set, the virtual display is private as defined by the + * {@link Display#FLAG_PRIVATE} display flag. + *
+ * A private virtual display belongs to the application that created it. + * Only the a owner of a private virtual display is allowed to place windows upon it. + * The private virtual display also does not participate in display mirroring: it will + * neither receive mirrored content from another display nor allow its own content to + * be mirrored elsewhere. More precisely, the only processes that are allowed to + * enumerate or interact with the private display are those that have the same UID as the + * application that originally created the private virtual display. + * + * + * @see #createVirtualDisplay + */ + public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1 << 0; + + /** + * Virtual display flag: Create a presentation display. + * + *+ * When this flag is set, the virtual display is registered as a presentation + * display in the {@link #DISPLAY_CATEGORY_PRESENTATION presentation display category}. + * Applications may automatically project their content to presentation displays + * to provide richer second screen experiences. + *
+ * + *+ * When this flag is not set, the virtual display is not registered as a presentation + * display. Applications can still project their content on the display but they + * will typically not do so automatically. This option is appropriate for + * more special-purpose displays. + *
+ * + * @see android.app.Presentation for information about presenting content + * on secondary displays. + * @see #createVirtualDisplay + * @see #DISPLAY_CATEGORY_PRESENTATION + * @see Display#FLAG_PRESENTATION + */ + public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 1 << 1; + + /** + * Virtual display flag: Create a secure display. + * + *+ * When this flag is set, the virtual display is considered secure as defined + * by the {@link Display#FLAG_SECURE} display flag. The caller promises to take + * reasonable measures, such as over-the-air encryption, to prevent the contents + * of the display from being intercepted or recorded on a persistent medium. + *
+ * Creating a secure virtual display requires the + * {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT} permission. + * This permission is reserved for use by system components and is not available to + * third-party applications. + *
+ * + *+ * When this flag is not set, the virtual display is considered unsecure. + * The content of secure windows will be blanked if shown on this display. + *
+ * + * @see Display#FLAG_SECURE for information about secure displays. + * @see #createVirtualDisplay + */ + public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 1 << 2; + /** @hide */ public DisplayManager(Context context) { mContext = context; @@ -130,12 +224,12 @@ public final class DisplayManager { synchronized (mLock) { try { if (category == null) { - addMatchingDisplaysLocked(mTempDisplays, displayIds, -1); + addAllDisplaysLocked(mTempDisplays, displayIds); } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) { - addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI); - addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI); - addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY); - addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL); + addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI); + addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI); + addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY); + addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL); } return mTempDisplays.toArray(new Display[mTempDisplays.size()]); } finally { @@ -144,12 +238,22 @@ public final class DisplayManager { } } - private void addMatchingDisplaysLocked( + private void addAllDisplaysLocked(ArrayList* The content of a virtual display is rendered to a {@link Surface} provided - * by the application that created the virtual display. + * by the application. *
- * Only the application that created a private virtual display is allowed to - * place windows upon it. The private virtual display also does not participate - * in display mirroring: it will neither receive mirrored content from another - * display nor allow its own content to be mirrored elsewhere. More precisely, - * the only processes that are allowed to enumerate or interact with a private - * display are those that have the same UID as the application that originally - * created the private virtual display. - *
- * The private virtual display should be {@link VirtualDisplay#release released} - * when no longer needed. Because a private virtual display renders to a surface + * The virtual display should be {@link VirtualDisplay#release released} + * when no longer needed. Because a virtual display renders to a surface * provided by the application, it will be released automatically when the * process terminates and all remaining windows on it will be forcibly removed. + *
+ * The behavior of the virtual display depends on the flags that are provided + * to this method. By default, virtual displays are created to be private, + * non-presentation and unsecure. Permissions may be required to use certain flags. *
* * @param name The name of the virtual display, must be non-empty. @@ -302,13 +402,19 @@ public final class DisplayManager { * @param densityDpi The density of the virtual display in dpi, must be greater than 0. * @param surface The surface to which the content of the virtual display should * be rendered, must be non-null. + * @param flags A combination of virtual display flags: + * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION} + * or {@link #VIRTUAL_DISPLAY_FLAG_SECURE}. * @return The newly created virtual display, or null if the application could * not create the virtual display. + * + * @throws SecurityException if the caller does not have permission to create + * a virtual display with the specified flags. */ - public VirtualDisplay createPrivateVirtualDisplay(String name, - int width, int height, int densityDpi, Surface surface) { - return mGlobal.createPrivateVirtualDisplay(mContext, - name, width, height, densityDpi, surface); + public VirtualDisplay createVirtualDisplay(String name, + int width, int height, int densityDpi, Surface surface, int flags) { + return mGlobal.createVirtualDisplay(mContext, + name, width, height, densityDpi, surface, flags); } /** diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index 320185d906d8d..10c14ff6c0fe6 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -329,8 +329,8 @@ public final class DisplayManagerGlobal { } } - public VirtualDisplay createPrivateVirtualDisplay(Context context, String name, - int width, int height, int densityDpi, Surface surface) { + public VirtualDisplay createVirtualDisplay(Context context, String name, + int width, int height, int densityDpi, Surface surface, int flags) { if (TextUtils.isEmpty(name)) { throw new IllegalArgumentException("name must be non-null and non-empty"); } @@ -345,20 +345,20 @@ public final class DisplayManagerGlobal { Binder token = new Binder(); int displayId; try { - displayId = mDm.createPrivateVirtualDisplay(token, context.getPackageName(), - name, width, height, densityDpi, surface); + displayId = mDm.createVirtualDisplay(token, context.getPackageName(), + name, width, height, densityDpi, surface, flags); } catch (RemoteException ex) { - Log.e(TAG, "Could not create private virtual display: " + name, ex); + Log.e(TAG, "Could not create virtual display: " + name, ex); return null; } if (displayId < 0) { - Log.e(TAG, "Could not create private virtual display: " + name); + Log.e(TAG, "Could not create virtual display: " + name); return null; } Display display = getRealDisplay(displayId); if (display == null) { Log.wtf(TAG, "Could not obtain display info for newly created " - + "private virtual display: " + name); + + "virtual display: " + name); try { mDm.releaseVirtualDisplay(token); } catch (RemoteException ex) { diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index cd4896a5c11fa..afaf436fc1874 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -48,9 +48,10 @@ interface IDisplayManager { // No permissions required. WifiDisplayStatus getWifiDisplayStatus(); - // No permissions required. - int createPrivateVirtualDisplay(IBinder token, String packageName, - String name, int width, int height, int densityDpi, in Surface surface); + // Requires CAPTURE_VIDEO_OUTPUT or CAPTURE_SECURE_VIDEO_OUTPUT for certain + // combinations of flags. + int createVirtualDisplay(IBinder token, String packageName, + String name, int width, int height, int densityDpi, in Surface surface, int flags); // No permissions required but must be same Uid as the creator. void releaseVirtualDisplay(in IBinder token); diff --git a/core/java/android/hardware/display/VirtualDisplay.java b/core/java/android/hardware/display/VirtualDisplay.java index 145a217dbd273..908aadd5a314e 100644 --- a/core/java/android/hardware/display/VirtualDisplay.java +++ b/core/java/android/hardware/display/VirtualDisplay.java @@ -21,7 +21,7 @@ import android.view.Display; /** * Represents a virtual display. * - * @see DisplayManager#createPrivateVirtualDisplay + * @see DisplayManager#createVirtualDisplay */ public final class VirtualDisplay { private final DisplayManagerGlobal mGlobal; diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 5f614b150ad85..354ea6613a397 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -149,15 +149,24 @@ public final class Display { /** * Display flag: Indicates that the display is private. Only the application that * owns the display can create windows on it. - *- * This flag is associated with displays that were created using - * {@link android.hardware.display.DisplayManager#createPrivateVirtualDisplay}. - *
* * @see #getFlags */ public static final int FLAG_PRIVATE = 1 << 2; + /** + * Display flag: Indicates that the display is a presentation display. + *+ * This flag identifies secondary displays that are suitable for + * use as presentation displays such as HDMI or Wireless displays. Applications + * may automatically project their content to presentation displays to provide + * richer second screen experiences. + *
+ * + * @see #getFlags + */ + public static final int FLAG_PRESENTATION = 1 << 3; + /** * Display type: Unknown display type. * @hide diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 9a9c4cd3b4c02..8944207eb4475 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -466,6 +466,9 @@ public final class DisplayInfo implements Parcelable { if ((flags & Display.FLAG_PRIVATE) != 0) { result.append(", FLAG_PRIVATE"); } + if ((flags & Display.FLAG_PRESENTATION) != 0) { + result.append(", FLAG_PRESENTATION"); + } return result.toString(); } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 74d383f2b49bd..a9a14ad8cf254 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2026,6 +2026,27 @@ android:description="@string/permdesc_controlWifiDisplay" android:protectionLevel="signature" /> + +