Merge "Add support for dynamically setting the virtual display surface." into klp-modular-dev

This commit is contained in:
Jeff Brown
2014-04-17 21:49:49 +00:00
committed by Android (Google) Code Review
7 changed files with 100 additions and 13 deletions

View File

@@ -10950,7 +10950,9 @@ package android.hardware.display {
public final class VirtualDisplay {
method public android.view.Display getDisplay();
method public android.view.Surface getSurface();
method public void release();
method public void setSurface(android.view.Surface);
}
}

View File

@@ -437,6 +437,14 @@ public final class DisplayManager {
* 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><p>
* As of {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}, the surface may
* be attached or detached dynamically using {@link VirtualDisplay#setSurface}.
* Previously, the surface had to be non-null when {@link #createVirtualDisplay}
* was called and could not be changed for the lifetime of the display.
* </p><p>
* Detaching the surface that backs a virtual display has a similar effect to
* turning off the screen.
* </p>
*
* @param name The name of the virtual display, must be non-empty.
@@ -444,7 +452,7 @@ public final class DisplayManager {
* @param height The height of the virtual display in pixels, must be greater than 0.
* @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.
* be rendered, or null if there is none initially.
* @param flags A combination of virtual display flags:
* {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION},
* {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, or {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}.

View File

@@ -377,9 +377,6 @@ public final class DisplayManagerGlobal {
throw new IllegalArgumentException("width, height, and densityDpi must be "
+ "greater than 0");
}
if (surface == null) {
throw new IllegalArgumentException("surface must not be null");
}
Binder token = new Binder();
int displayId;
@@ -404,7 +401,15 @@ public final class DisplayManagerGlobal {
}
return null;
}
return new VirtualDisplay(this, display, token);
return new VirtualDisplay(this, display, token, surface);
}
public void setVirtualDisplaySurface(IBinder token, Surface surface) {
try {
mDm.setVirtualDisplaySurface(token, surface);
} catch (RemoteException ex) {
Log.w(TAG, "Failed to set virtual display surface.", ex);
}
}
public void releaseVirtualDisplay(IBinder token) {

View File

@@ -62,6 +62,9 @@ interface IDisplayManager {
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 setVirtualDisplaySurface(in IBinder token, in Surface surface);
// No permissions required but must be same Uid as the creator.
void releaseVirtualDisplay(in IBinder token);
}

View File

@@ -17,15 +17,18 @@ package android.hardware.display;
import android.os.IBinder;
import android.view.Display;
import android.view.Surface;
/**
* Represents a virtual display. The content of a virtual display is rendered to a
* {@link android.view.Surface} that you must provide to {@link DisplayManager#createVirtualDisplay
* createVirtualDisplay()}.
* <p>Because a virtual display renders to a surface provided by the application, it will be
* <p>
* 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. However, you should also explicitly call {@link #release} when you're
* done with it.
* be forcibly removed. However, you should also explicitly call {@link #release} when
* you're done with it.
* </p>
*
* @see DisplayManager#createVirtualDisplay
*/
@@ -33,11 +36,14 @@ public final class VirtualDisplay {
private final DisplayManagerGlobal mGlobal;
private final Display mDisplay;
private IBinder mToken;
private Surface mSurface;
VirtualDisplay(DisplayManagerGlobal global, Display display, IBinder token) {
VirtualDisplay(DisplayManagerGlobal global, Display display, IBinder token,
Surface surface) {
mGlobal = global;
mDisplay = display;
mToken = token;
mSurface = surface;
}
/**
@@ -47,6 +53,32 @@ public final class VirtualDisplay {
return mDisplay;
}
/**
* Gets the surface that backs the virtual display.
*/
public Surface getSurface() {
return mSurface;
}
/**
* Sets the surface that backs the virtual display.
* <p>
* Detaching the surface that backs a virtual display has a similar effect to
* turning off the screen.
* </p><p>
* It is still the caller's responsibility to destroy the surface after it has
* been detached.
* </p>
*
* @param surface The surface to set, or null to detach the surface from the virtual display.
*/
public void setSurface(Surface surface) {
if (mSurface != surface) {
mGlobal.setVirtualDisplaySurface(mToken, surface);
mSurface = surface;
}
}
/**
* Releases the virtual display and destroys its underlying surface.
* <p>
@@ -63,6 +95,7 @@ public final class VirtualDisplay {
@Override
public String toString() {
return "VirtualDisplay{display=" + mDisplay + ", token=" + mToken + "}";
return "VirtualDisplay{display=" + mDisplay + ", token=" + mToken
+ ", surface=" + mSurface + "}";
}
}

View File

@@ -517,6 +517,16 @@ public final class DisplayManagerService extends SystemService {
return -1;
}
private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
synchronized (mSyncRoot) {
if (mVirtualDisplayAdapter == null) {
return;
}
mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
}
}
private void releaseVirtualDisplayInternal(IBinder appToken) {
synchronized (mSyncRoot) {
if (mVirtualDisplayAdapter == null) {
@@ -1221,9 +1231,6 @@ public final class DisplayManagerService extends SystemService {
throw new IllegalArgumentException("width, height, and densityDpi must be "
+ "greater than 0");
}
if (surface == null) {
throw new IllegalArgumentException("surface must not be null");
}
if (callingUid != Process.SYSTEM_UID &&
(flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
@@ -1254,6 +1261,16 @@ public final class DisplayManagerService extends SystemService {
}
}
@Override // Binder call
public void setVirtualDisplaySurface(IBinder appToken, Surface surface) {
final long token = Binder.clearCallingIdentity();
try {
setVirtualDisplaySurfaceInternal(appToken, surface);
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override // Binder call
public void releaseVirtualDisplay(IBinder appToken) {
final long token = Binder.clearCallingIdentity();

View File

@@ -69,6 +69,13 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
return device;
}
public void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) {
VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
if (device != null) {
device.setSurfaceLocked(surface);
}
}
public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) {
VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
if (device != null) {
@@ -144,6 +151,17 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
}
}
public void setSurfaceLocked(Surface surface) {
if (mSurface != surface) {
if ((mSurface != null) != (surface != null)) {
sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
}
sendTraversalRequestLocked();
mSurface = surface;
mInfo = null;
}
}
@Override
public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
if (mInfo == null) {
@@ -171,6 +189,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
}
mInfo.type = Display.TYPE_VIRTUAL;
mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
mInfo.state = mSurface != null ? Display.STATE_ON : Display.STATE_OFF;
mInfo.ownerUid = mOwnerUid;
mInfo.ownerPackageName = mOwnerPackageName;
}