summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt9
-rw-r--r--core/java/android/hardware/display/DisplayManager.java154
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java14
-rw-r--r--core/java/android/hardware/display/IDisplayManager.aidl7
-rw-r--r--core/java/android/hardware/display/VirtualDisplay.java2
-rw-r--r--core/java/android/view/Display.java15
-rw-r--r--core/java/android/view/DisplayInfo.java3
-rw-r--r--core/res/AndroidManifest.xml21
-rw-r--r--core/res/res/values/strings.xml14
-rw-r--r--services/java/com/android/server/display/DisplayDeviceInfo.java8
-rw-r--r--services/java/com/android/server/display/DisplayManagerService.java30
-rw-r--r--services/java/com/android/server/display/LocalDisplayAdapter.java1
-rw-r--r--services/java/com/android/server/display/LogicalDisplay.java3
-rw-r--r--services/java/com/android/server/display/OverlayDisplayAdapter.java2
-rw-r--r--services/java/com/android/server/display/VirtualDisplayAdapter.java26
-rw-r--r--services/java/com/android/server/display/WifiDisplayAdapter.java2
-rw-r--r--tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/DisplaySourceService.java4
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.
* <p>
* 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.
* </p>
*
* @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.
+ *
+ * <h3>Public virtual displays</h3>
+ * <p>
+ * When this flag is set, the virtual display is public.
+ * </p><p>
+ * 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.
+ * </p><p>
+ * 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.
+ * </p>
+ *
+ * <h3>Private virtual displays</h3>
+ * <p>
+ * When this flag is not set, the virtual display is private as defined by the
+ * {@link Display#FLAG_PRIVATE} display flag.
+ * </p>
+ * 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.
+ * </p>
+ *
+ * @see #createVirtualDisplay
+ */
+ public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1 << 0;
+
+ /**
+ * Virtual display flag: Create a presentation display.
+ *
+ * <h3>Presentation virtual displays</h3>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * <h3>Non-presentation virtual displays</h3>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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.
+ *
+ * <h3>Secure virtual displays</h3>
+ * <p>
+ * 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.
+ * </p><p>
+ * 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.
+ * </p>
+ *
+ * <h3>Non-secure virtual displays</h3>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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<Display> 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<Display> 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.
* <p>
* The content of a virtual display is rendered to a {@link Surface} provided
- * by the application that created the virtual display.
- * </p><p>
- * 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.
* </p><p>
- * 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.
+ * </p><p>
+ * 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.
* </p>
*
* @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.
* <p>
- * 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.
* </p>
*
* @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 an application to capture audio output.
+ <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"
+ android:label="@string/permlab_captureAudioOutput"
+ android:description="@string/permdesc_captureAudioOutput"
+ android:protectionLevel="signature|system" />
+
+ <!-- Allows an application to capture video output.
+ <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
+ android:label="@string/permlab_captureVideoOutput"
+ android:description="@string/permdesc_captureVideoOutput"
+ android:protectionLevel="signature|system" />
+
+ <!-- Allows an application to capture secure video output.
+ <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
+ android:label="@string/permlab_captureSecureVideoOutput"
+ android:description="@string/permdesc_captureSecureVideoOutput"
+ android:protectionLevel="signature|system" />
+
<!-- Required to be able to disable the device (very dangerous!).
<p>Not for use by third-party applications.. -->
<permission android:name="android.permission.BRICK"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a9d1c8615f8a..4830a19232b5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1394,9 +1394,19 @@
<string name="permdesc_configureWifiDisplay">Allows the app to configure and connect to Wifi displays.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_controlWifiDisplay">control Wifi displays</string>
+ <string name="permlab_captureAudioOutput">capture audio output</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_controlWifiDisplay">Allows the app to control low-level features of Wifi displays.</string>
+ <string name="permdesc_captureAudioOutput">Allows the app to capture and redirect audio output.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_captureVideoOutput">capture video output</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_captureVideoOutput">Allows the app to capture and redirect video output.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_captureSecureVideoOutput">capture secure video output</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_captureSecureVideoOutput">Allows the app to capture and redirect secure video output.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_modifyAudioSettings">change your audio settings</string>
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();