From 7d00affce6e25b22fd8fc135933b3bf6b547a0dc Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Fri, 2 Aug 2013 19:03:49 -0700 Subject: [PATCH] Support public virtual displays. Refactor the new private virtual display API to also support creating public virtual displays with various characteristics. This feature requires special permissions and is only intended for use by the system. Change-Id: I44dd19f37cf76ea6d6e313afe42f4a412bd96663 --- api/current.txt | 9 +- .../android/hardware/display/DisplayManager.java | 154 +++++++++++++++++---- .../hardware/display/DisplayManagerGlobal.java | 14 +- .../android/hardware/display/IDisplayManager.aidl | 7 +- .../android/hardware/display/VirtualDisplay.java | 2 +- core/java/android/view/Display.java | 15 +- core/java/android/view/DisplayInfo.java | 3 + core/res/AndroidManifest.xml | 21 +++ core/res/res/values/strings.xml | 14 +- .../android/server/display/DisplayDeviceInfo.java | 8 ++ .../server/display/DisplayManagerService.java | 30 +++- .../server/display/LocalDisplayAdapter.java | 1 + .../com/android/server/display/LogicalDisplay.java | 3 + .../server/display/OverlayDisplayAdapter.java | 2 +- .../server/display/VirtualDisplayAdapter.java | 26 +++- .../android/server/display/WifiDisplayAdapter.java | 2 +- .../source/DisplaySourceService.java | 4 +- 17 files changed, 259 insertions(+), 56 deletions(-) diff --git a/api/current.txt b/api/current.txt index 429caa5a2777..7d83fcfe98c8 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 9e2e4ba11f56..7d6573685152 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. + * + *

Public virtual displays

+ *

+ * 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. + *

+ * + *

Private virtual displays

+ *

+ * 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. + * + *

Presentation virtual displays

+ *

+ * 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. + *

+ * + *

Non-presentation virtual displays

+ *

+ * 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. + * + *

Secure virtual displays

+ *

+ * 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. + *

+ * + *

Non-secure virtual displays

+ *

+ * 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 displays, int[] displayIds) { + for (int i = 0; i < displayIds.length; i++) { + Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/); + if (display != null) { + displays.add(display); + } + } + } + + private void addPresentationDisplaysLocked( ArrayList displays, int[] displayIds, int matchType) { for (int i = 0; i < displayIds.length; i++) { Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/); if (display != null - && (matchType < 0 || display.getType() == matchType)) { + && (display.getFlags() & Display.FLAG_PRESENTATION) != 0 + && display.getType() == matchType) { displays.add(display); } } @@ -277,23 +381,19 @@ public final class DisplayManager { } /** - * Creates a private virtual display. + * Creates a virtual display. *

* The content of a virtual display is rendered to a {@link Surface} provided - * by the application that created the virtual display. - *

- * 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. + * by the application. *

- * 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 320185d906d8..10c14ff6c0fe 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 cd4896a5c11f..afaf436fc187 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 145a217dbd27..908aadd5a314 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 5f614b150ad8..354ea6613a39 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -149,14 +149,23 @@ public final class Display { /** * Display flag: Indicates that the display is private. Only the application that * owns the display can create windows on it. + * + * @see #getFlags + */ + public static final int FLAG_PRIVATE = 1 << 2; + + /** + * Display flag: Indicates that the display is a presentation display. *

- * This flag is associated with displays that were created using - * {@link android.hardware.display.DisplayManager#createPrivateVirtualDisplay}. + * 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_PRIVATE = 1 << 2; + public static final int FLAG_PRESENTATION = 1 << 3; /** * Display type: Unknown display type. diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 9a9c4cd3b4c0..8944207eb447 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 74d383f2b49b..a9a14ad8cf25 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2026,6 +2026,27 @@ android:description="@string/permdesc_controlWifiDisplay" android:protectionLevel="signature" /> + + + + + + + + + Allows the app to configure and connect to Wifi displays. - control Wifi displays + capture audio output - Allows the app to control low-level features of Wifi displays. + Allows the app to capture and redirect audio output. + + + capture video output + + Allows the app to capture and redirect video output. + + + capture secure video output + + Allows the app to capture and redirect secure video output. change your audio settings diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java index 11f8d6a3943e..11c5d879b498 100644 --- a/services/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/java/com/android/server/display/DisplayDeviceInfo.java @@ -73,6 +73,11 @@ final class DisplayDeviceInfo { public static final int FLAG_NEVER_BLANK = 1 << 5; /** + * Flag: Indicates that the display is suitable for presentations. + */ + public static final int FLAG_PRESENTATION = 1 << 6; + + /** * Touch attachment: Display does not receive touch. */ public static final int TOUCH_NONE = 0; @@ -289,6 +294,9 @@ final class DisplayDeviceInfo { if ((flags & FLAG_NEVER_BLANK) != 0) { msg.append(", FLAG_NEVER_BLANK"); } + if ((flags & FLAG_PRESENTATION) != 0) { + msg.append(", FLAG_PRESENTATION"); + } return msg.toString(); } } diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index c339c26e51e5..19a11c0f4071 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -21,6 +21,7 @@ import com.android.internal.util.IndentingPrintWriter; import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; +import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.IDisplayManager; import android.hardware.display.IDisplayManagerCallback; @@ -589,8 +590,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } @Override // Binder call - public int createPrivateVirtualDisplay(IBinder appToken, String packageName, - String name, int width, int height, int densityDpi, Surface surface) { + public int createVirtualDisplay(IBinder appToken, String packageName, + String name, int width, int height, int densityDpi, Surface surface, int flags) { final int callingUid = Binder.getCallingUid(); if (!validatePackageName(callingUid, packageName)) { throw new SecurityException("packageName must match the calling uid"); @@ -608,6 +609,25 @@ public final class DisplayManagerService extends IDisplayManager.Stub { if (surface == null) { throw new IllegalArgumentException("surface must not be null"); } + if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { + if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) + != PackageManager.PERMISSION_GRANTED + && mContext.checkCallingPermission( + android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " + + "CAPTURE_SECURE_VIDEO_OUTPUT permission to create a " + + "public virtual display."); + } + } + if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { + if (mContext.checkCallingPermission( + android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " + + "to create a secure virtual display."); + } + } final long token = Binder.clearCallingIdentity(); try { @@ -618,9 +638,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub { return -1; } - DisplayDevice device = mVirtualDisplayAdapter.createPrivateVirtualDisplayLocked( + DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked( appToken, callingUid, packageName, name, width, height, densityDpi, - surface); + surface, flags); if (device == null) { return -1; } @@ -632,7 +652,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } // Something weird happened and the logical display was not created. - Slog.w(TAG, "Rejecting request to create private virtual display " + Slog.w(TAG, "Rejecting request to create virtual display " + "because the logical display was not created."); mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); handleDisplayDeviceRemovedLocked(device); diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java index 475f27b83e29..cb8f3e20d368 100644 --- a/services/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/java/com/android/server/display/LocalDisplayAdapter.java @@ -155,6 +155,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL; } else { mInfo.type = Display.TYPE_HDMI; + mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION; mInfo.name = getContext().getResources().getString( com.android.internal.R.string.display_manager_hdmi_display_name); mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/java/com/android/server/display/LogicalDisplay.java index 775ebb235c29..b9839c27c9bd 100644 --- a/services/java/com/android/server/display/LogicalDisplay.java +++ b/services/java/com/android/server/display/LogicalDisplay.java @@ -205,6 +205,9 @@ final class LogicalDisplay { if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0) { mBaseDisplayInfo.flags |= Display.FLAG_PRIVATE; } + if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRESENTATION) != 0) { + mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION; + } mBaseDisplayInfo.type = deviceInfo.type; mBaseDisplayInfo.address = deviceInfo.address; mBaseDisplayInfo.name = deviceInfo.name; diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/java/com/android/server/display/OverlayDisplayAdapter.java index 315289730ce6..ce402a521162 100644 --- a/services/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java @@ -245,7 +245,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { mInfo.densityDpi = mDensityDpi; mInfo.xDpi = mDensityDpi; mInfo.yDpi = mDensityDpi; - mInfo.flags = 0; + mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION; if (mSecure) { mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; } diff --git a/services/java/com/android/server/display/VirtualDisplayAdapter.java b/services/java/com/android/server/display/VirtualDisplayAdapter.java index 634fba7fcf19..3a71361949fe 100644 --- a/services/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/java/com/android/server/display/VirtualDisplayAdapter.java @@ -17,6 +17,7 @@ package com.android.server.display; import android.content.Context; +import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; @@ -46,12 +47,13 @@ final class VirtualDisplayAdapter extends DisplayAdapter { super(syncRoot, context, handler, listener, TAG); } - public DisplayDevice createPrivateVirtualDisplayLocked(IBinder appToken, + public DisplayDevice createVirtualDisplayLocked(IBinder appToken, int ownerUid, String ownerPackageName, - String name, int width, int height, int densityDpi, Surface surface) { - IBinder displayToken = SurfaceControl.createDisplay(name, false /*secure*/); + String name, int width, int height, int densityDpi, Surface surface, int flags) { + boolean secure = (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0; + IBinder displayToken = SurfaceControl.createDisplay(name, secure); VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken, - ownerUid, ownerPackageName, name, width, height, densityDpi, surface); + ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags); try { appToken.linkToDeath(device, 0); @@ -96,6 +98,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter { private final int mWidth; private final int mHeight; private final int mDensityDpi; + private final int mFlags; private boolean mReleased; private Surface mSurface; @@ -103,7 +106,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter { public VirtualDisplayDevice(IBinder displayToken, IBinder appToken, int ownerUid, String ownerPackageName, - String name, int width, int height, int densityDpi, Surface surface) { + String name, int width, int height, int densityDpi, Surface surface, int flags) { super(VirtualDisplayAdapter.this, displayToken); mAppToken = appToken; mOwnerUid = ownerUid; @@ -113,6 +116,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter { mHeight = height; mDensityDpi = densityDpi; mSurface = surface; + mFlags = flags; } @Override @@ -149,7 +153,17 @@ final class VirtualDisplayAdapter extends DisplayAdapter { mInfo.densityDpi = mDensityDpi; mInfo.xDpi = mDensityDpi; mInfo.yDpi = mDensityDpi; - mInfo.flags = DisplayDeviceInfo.FLAG_PRIVATE | DisplayDeviceInfo.FLAG_NEVER_BLANK; + mInfo.flags = 0; + if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE | + DisplayDeviceInfo.FLAG_NEVER_BLANK; + } + if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; + } + if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION; + } mInfo.type = Display.TYPE_VIRTUAL; mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; mInfo.ownerUid = mOwnerUid; diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java index 4c80cf5c9fef..11d38190faab 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/java/com/android/server/display/WifiDisplayAdapter.java @@ -352,7 +352,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { } boolean secure = (flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0; - int deviceFlags = 0; + int deviceFlags = DisplayDeviceInfo.FLAG_PRESENTATION; if (secure) { deviceFlags |= DisplayDeviceInfo.FLAG_SECURE; if (mSupportsProtectedBuffers) { diff --git a/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/DisplaySourceService.java b/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/DisplaySourceService.java index ccead44a6357..256f900ed5a7 100644 --- a/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/DisplaySourceService.java +++ b/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/DisplaySourceService.java @@ -197,8 +197,8 @@ public class DisplaySourceService extends Service { Surface surface = codec.createInputSurface(); codec.start(); - VirtualDisplay virtualDisplay = mDisplayManager.createPrivateVirtualDisplay( - DISPLAY_NAME, mWidth, mHeight, mDensityDpi, surface); + VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay( + DISPLAY_NAME, mWidth, mHeight, mDensityDpi, surface, 0); if (virtualDisplay != null) { mHandler.obtainMessage(MSG_DISPATCH_DISPLAY_ADDED, virtualDisplay.getDisplay()).sendToTarget(); -- 2.11.0