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

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. + * 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" /> + + + + + + + + + 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 11f8d6a3943ea..11c5d879b498d 100644 --- a/services/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/java/com/android/server/display/DisplayDeviceInfo.java @@ -72,6 +72,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. */ @@ -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 c339c26e51e53..19a11c0f40713 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 475f27b83e293..cb8f3e20d3683 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 775ebb235c29c..b9839c27c9bd2 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 315289730ce64..ce402a5211624 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 634fba7fcf192..3a71361949fed 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 4c80cf5c9fefc..11d38190faab9 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 ccead44a6357a..256f900ed5a7c 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();