diff --git a/api/current.txt b/api/current.txt index 5469c6f0b95fa..a8b60ed238ccc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -13247,6 +13247,7 @@ package android.hardware.display { 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 1b9a0c5d1661f..8b44f3bc4ad0a 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -416,6 +416,15 @@ public final class DisplayManagerGlobal { } } + 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 44ffbc4467d81..cfaa5a0801469 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -65,6 +65,10 @@ interface IDisplayManager { 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 df6116b6c5780..1dd697812198c 100644 --- a/core/java/android/hardware/display/VirtualDisplay.java +++ b/core/java/android/hardware/display/VirtualDisplay.java @@ -79,6 +79,18 @@ public final class VirtualDisplay { } } + /** + * Asks the virtual display to resize. + *

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

+ */ + public void resize(int width, int height, int densityDpi) { + mGlobal.resizeVirtualDisplay(mToken, width, height, densityDpi); + } + /** * Releases the virtual display and destroys its underlying surface. *

diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 191ad64cc8e89..1e28e33c290fe 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -74,6 +74,7 @@ public class SurfaceControl { 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 class SurfaceControl { } } + 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 9783e91e17734..3fb084a79d439 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -369,6 +369,13 @@ static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz, SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect); } +static void nativeSetDisplaySize(JNIEnv* env, jclass clazz, + jobject tokenObj, jint width, jint height) { + sp token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + SurfaceComposerClient::setDisplaySize(token, width, height); +} + static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz, jobject tokenObj) { sp token(ibinderForJavaObject(env, tokenObj)); @@ -620,6 +627,8 @@ static JNINativeMethod sSurfaceControlMethods[] = { (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 b9acea583829b..7d3738c414d7f 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 @@ public final class DisplayManagerService extends SystemService { 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) { @@ -1303,6 +1314,17 @@ public final class DisplayManagerService extends SystemService { } } + @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(); diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index 10320816df7ff..0ebd2de12cbd0 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 @@ final class VirtualDisplayAdapter extends DisplayAdapter { 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 @@ final class VirtualDisplayAdapter extends DisplayAdapter { } 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 @@ final class VirtualDisplayAdapter extends DisplayAdapter { mSurface = surface; mFlags = flags; mCallbacks = callbacks; - mState = Display.STATE_UNKNOWN; + mDisplayState = Display.STATE_UNKNOWN; + mPendingChanges |= PENDING_SURFACE_CHANGE; } @Override @@ -175,8 +189,8 @@ final class VirtualDisplayAdapter extends DisplayAdapter { @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 @@ final class VirtualDisplayAdapter extends DisplayAdapter { @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 @@ final class VirtualDisplayAdapter extends DisplayAdapter { 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 @@ final class VirtualDisplayAdapter extends DisplayAdapter { 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); }