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
This commit is contained in:
@ -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
|
||||
|
@ -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.
|
||||
* by the application.
|
||||
* </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.
|
||||
* </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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
* <p>
|
||||
* This flag is associated with displays that were created using
|
||||
* {@link android.hardware.display.DisplayManager#createPrivateVirtualDisplay}.
|
||||
* </p>
|
||||
*
|
||||
* @see #getFlags
|
||||
*/
|
||||
public static final int FLAG_PRIVATE = 1 << 2;
|
||||
|
||||
/**
|
||||
* Display flag: Indicates that the display is a presentation display.
|
||||
* <p>
|
||||
* 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_PRESENTATION = 1 << 3;
|
||||
|
||||
/**
|
||||
* Display type: Unknown display type.
|
||||
* @hide
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user