Add resize method for virtual displays
Change-Id: I2632fc56c2d2cba356379e42f5c1a3e283b11d1e
diff --git a/api/current.txt b/api/current.txt
index 5469c6f..a8b60ed 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13247,6 +13247,7 @@
method public android.view.Display getDisplay();
method public android.view.Surface getSurface();
method public void release();
+ method public void resize(int, int, int);
method public void setSurface(android.view.Surface);
}
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 1b9a0c5..8b44f3b 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -416,6 +416,15 @@
}
}
+ public void resizeVirtualDisplay(IVirtualDisplayCallbacks token,
+ int width, int height, int densityDpi) {
+ try {
+ mDm.resizeVirtualDisplay(token, width, height, densityDpi);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Failed to resize virtual display.", ex);
+ }
+ }
+
public void releaseVirtualDisplay(IVirtualDisplayCallbacks token) {
try {
mDm.releaseVirtualDisplay(token);
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 44ffbc4..cfaa5a0 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -65,6 +65,10 @@
in IMediaProjection projectionToken, 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 resizeVirtualDisplay(in IVirtualDisplayCallbacks token,
+ int width, int height, int densityDpi);
+
// No permissions required but must be same Uid as the creator.
void setVirtualDisplaySurface(in IVirtualDisplayCallbacks token, in Surface surface);
diff --git a/core/java/android/hardware/display/VirtualDisplay.java b/core/java/android/hardware/display/VirtualDisplay.java
index df6116b..1dd6978 100644
--- a/core/java/android/hardware/display/VirtualDisplay.java
+++ b/core/java/android/hardware/display/VirtualDisplay.java
@@ -80,6 +80,18 @@
}
/**
+ * Asks the virtual display to resize.
+ *<p>
+ * This is really just a convenience to allow applications using
+ * virtual displays to adapt to changing conditions without having
+ * to tear down and recreate the display.
+ * </p>
+ */
+ public void resize(int width, int height, int densityDpi) {
+ mGlobal.resizeVirtualDisplay(mToken, width, height, densityDpi);
+ }
+
+ /**
* Releases the virtual display and destroys its underlying surface.
* <p>
* All remaining windows on the virtual display will be forcibly removed
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 191ad64..1e28e33 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -74,6 +74,7 @@
IBinder displayToken, int orientation,
int l, int t, int r, int b,
int L, int T, int R, int B);
+ private static native void nativeSetDisplaySize(IBinder displayToken, int width, int height);
private static native SurfaceControl.PhysicalDisplayInfo[] nativeGetDisplayConfigs(
IBinder displayToken);
private static native int nativeGetActiveConfig(IBinder displayToken);
@@ -588,6 +589,17 @@
}
}
+ public static void setDisplaySize(IBinder displayToken, int width, int height) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+ if (width <= 0 || height <= 0) {
+ throw new IllegalArgumentException("width and height must be positive");
+ }
+
+ nativeSetDisplaySize(displayToken, width, height);
+ }
+
public static IBinder createDisplay(String name, boolean secure) {
if (name == null) {
throw new IllegalArgumentException("name must not be null");
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 9783e91..3fb084a 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -369,6 +369,13 @@
SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
}
+static void nativeSetDisplaySize(JNIEnv* env, jclass clazz,
+ jobject tokenObj, jint width, jint height) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+ if (token == NULL) return;
+ SurfaceComposerClient::setDisplaySize(token, width, height);
+}
+
static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
jobject tokenObj) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
@@ -620,6 +627,8 @@
(void*)nativeSetDisplayLayerStack },
{"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V",
(void*)nativeSetDisplayProjection },
+ {"nativeSetDisplaySize", "(Landroid/os/IBinder;II)V",
+ (void*)nativeSetDisplaySize },
{"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;",
(void*)nativeGetDisplayConfigs },
{"nativeGetActiveConfig", "(Landroid/os/IBinder;)I",
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b9acea5..7d3738c 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -523,6 +523,17 @@
return -1;
}
+ private void resizeVirtualDisplayInternal(IBinder appToken,
+ int width, int height, int densityDpi) {
+ synchronized (mSyncRoot) {
+ if (mVirtualDisplayAdapter == null) {
+ return;
+ }
+
+ mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi);
+ }
+ }
+
private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
synchronized (mSyncRoot) {
if (mVirtualDisplayAdapter == null) {
@@ -1304,6 +1315,17 @@
}
@Override // Binder call
+ public void resizeVirtualDisplay(IVirtualDisplayCallbacks callbacks,
+ int width, int height, int densityDpi) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ resizeVirtualDisplayInternal(callbacks.asBinder(), width, height, densityDpi);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
public void setVirtualDisplaySurface(IVirtualDisplayCallbacks callbacks, Surface surface) {
final long token = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 1032081..0ebd2de 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -83,6 +83,15 @@
return device;
}
+ public void resizeVirtualDisplayLocked(IBinder appToken,
+ int width, int height, int densityDpi) {
+ VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
+ if (device != null) {
+ device.resizeLocked(width, height, densityDpi);
+ }
+ }
+
+
public void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) {
VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
if (device != null) {
@@ -122,20 +131,24 @@
}
private final class VirtualDisplayDevice extends DisplayDevice implements DeathRecipient {
+ private static final int PENDING_SURFACE_CHANGE = 0x01;
+ private static final int PENDING_RESIZE = 0x02;
+
private final IBinder mAppToken;
private final int mOwnerUid;
final String mOwnerPackageName;
final String mName;
- private final int mWidth;
- private final int mHeight;
- private final int mDensityDpi;
private final int mFlags;
private final Callbacks mCallbacks;
+ private int mWidth;
+ private int mHeight;
+ private int mDensityDpi;
private Surface mSurface;
private DisplayDeviceInfo mInfo;
- private int mState;
+ private int mDisplayState;
private boolean mStopped;
+ private int mPendingChanges;
public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
int ownerUid, String ownerPackageName,
@@ -152,7 +165,8 @@
mSurface = surface;
mFlags = flags;
mCallbacks = callbacks;
- mState = Display.STATE_UNKNOWN;
+ mDisplayState = Display.STATE_UNKNOWN;
+ mPendingChanges |= PENDING_SURFACE_CHANGE;
}
@Override
@@ -175,8 +189,8 @@
@Override
public void requestDisplayStateLocked(int state) {
- if (state != mState) {
- mState = state;
+ if (state != mDisplayState) {
+ mDisplayState = state;
if (state == Display.STATE_OFF) {
mCallbacks.dispatchDisplayPaused();
} else {
@@ -187,7 +201,13 @@
@Override
public void performTraversalInTransactionLocked() {
- setSurfaceInTransactionLocked(mSurface);
+ if ((mPendingChanges & PENDING_RESIZE) != 0) {
+ SurfaceControl.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight);
+ }
+ if ((mPendingChanges & PENDING_SURFACE_CHANGE) != 0) {
+ setSurfaceInTransactionLocked(mSurface);
+ }
+ mPendingChanges = 0;
}
public void setSurfaceLocked(Surface surface) {
@@ -198,6 +218,19 @@
sendTraversalRequestLocked();
mSurface = surface;
mInfo = null;
+ mPendingChanges |= PENDING_SURFACE_CHANGE;
+ }
+ }
+
+ public void resizeLocked(int width, int height, int densityDpi) {
+ if (mWidth != width || mHeight != height || mDensityDpi != densityDpi) {
+ sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
+ sendTraversalRequestLocked();
+ mWidth = width;
+ mHeight = height;
+ mDensityDpi = densityDpi;
+ mInfo = null;
+ mPendingChanges |= PENDING_RESIZE;
}
}
@@ -210,7 +243,7 @@
public void dumpLocked(PrintWriter pw) {
super.dumpLocked(pw);
pw.println("mFlags=" + mFlags);
- pw.println("mState=" + Display.stateToString(mState));
+ pw.println("mDisplayState=" + Display.stateToString(mDisplayState));
pw.println("mStopped=" + mStopped);
}