diff options
| author | 2015-11-06 13:54:20 -0800 | |
|---|---|---|
| committer | 2015-11-10 19:21:22 +0000 | |
| commit | 64aadd08491172e90f6d6512d8affc9a4cfa04cc (patch) | |
| tree | 4c408846dae21538e7ddbc9e40262d56493f3af3 | |
| parent | 609b5b8c8e22ab0ea1caca1fed42cdf891c853c6 (diff) | |
Clarify geometry management for SurfaceView
In the hardware accelerated case, RenderThread needs
to be the authority of information on the geometry of
the SurfaceView (this will occur via moving the
repositionWindow call to RenderThread). In order
to support this we have to enable calling relayoutWindow
without geometry (so that it will not fight with
repositionWindow). Add such a mode to relayoutWindow
and use it from SurfaceView. Add size to repositionChild
while we are here.
Bug: 22802885
Change-Id: Ie45132c22f34cc6ecfe2446912b30bd1df414406
7 files changed, 96 insertions, 40 deletions
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 1be2f95cf55a..3fc70cc3b4d9 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -101,16 +101,24 @@ interface IWindowSession { * for the parent window appears. This allows for synchronizing movement of a child * to repainting the contents of the parent. * + * "width" and "height" correspond to the width and height members of + * WindowManager.LayoutParams in the {@link #relayout relayout()} case. + * This may differ from the surface buffer size in the + * case of {@link LayoutParams#FLAG_SCALED} and {@link #relayout relayout()} + * must be used with requestedWidth/height if this must be changed. + * * @param window The window being modified. Must be attached to a parent window * or this call will fail. * @param x The new x position * @param y The new y position + * @param width The new width + * @param height The new height * @param deferTransactionUntilFrame Frame number from our parent (attached) to * defer this action until. * @param outFrame Rect in which is placed the new position/size on screen. */ - void repositionChild(IWindow childWindow, int x, int y, long deferTransactionUntilFrame, - out Rect outFrame); + void repositionChild(IWindow childWindow, int left, int top, int right, int bottom, + long deferTransactionUntilFrame, out Rect outFrame); /** * If a call to relayout() asked to have the surface destroy deferred, diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 514f88bc7f24..589c0dc85b68 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -157,10 +157,10 @@ public class SurfaceView extends View { long mLastLockTime = 0; boolean mVisible = false; - int mLeft = -1; - int mTop = -1; - int mWidth = -1; - int mHeight = -1; + int mWindowSpaceLeft = -1; + int mWindowSpaceTop = -1; + int mWindowSpaceWidth = -1; + int mWindowSpaceHeight = -1; int mFormat = -1; final Rect mSurfaceFrame = new Rect(); int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1; @@ -445,32 +445,33 @@ public class SurfaceView extends View { getLocationInWindow(mLocation); final boolean creating = mWindow == null; final boolean formatChanged = mFormat != mRequestedFormat; - final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight; + final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight; final boolean visibleChanged = mVisible != mRequestedVisible; - final boolean layoutSizeChanged = getWidth() != mLayout.width || getHeight() != mLayout.height; - final boolean positionChanged = mLeft != mLocation[0] || mTop != mLocation[1]; + final boolean layoutSizeChanged = getWidth() != mLayout.width + || getHeight() != mLayout.height; + final boolean positionChanged = mWindowSpaceLeft != mLocation[0] || mWindowSpaceTop != mLocation[1]; if (force || creating || formatChanged || sizeChanged || visibleChanged - || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded || layoutSizeChanged) { + || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) { if (DEBUG) Log.i(TAG, "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged + " visible=" + visibleChanged - + " left=" + (mLeft != mLocation[0]) - + " top=" + (mTop != mLocation[1])); + + " left=" + (mWindowSpaceLeft != mLocation[0]) + + " top=" + (mWindowSpaceTop != mLocation[1])); try { final boolean visible = mVisible = mRequestedVisible; - mLeft = mLocation[0]; - mTop = mLocation[1]; - mWidth = myWidth; - mHeight = myHeight; + mWindowSpaceLeft = mLocation[0]; + mWindowSpaceTop = mLocation[1]; + mWindowSpaceWidth = myWidth; + mWindowSpaceHeight = myHeight; mFormat = mRequestedFormat; // Scaling/Translate window's layout here because mLayout is not used elsewhere. // Places the window relative - mLayout.x = mLeft; - mLayout.y = mTop; + mLayout.x = mWindowSpaceLeft; + mLayout.y = mWindowSpaceTop; mLayout.width = getWidth(); mLayout.height = getHeight(); if (mTranslator != null) { @@ -485,6 +486,14 @@ public class SurfaceView extends View { | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE ; + if (!creating && !force && !mUpdateWindowNeeded) { + mLayout.privateFlags |= + WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY; + } else { + mLayout.privateFlags &= + ~WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY; + } + if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) { mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; @@ -516,7 +525,7 @@ public class SurfaceView extends View { if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface); relayoutResult = mSession.relayout( - mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, + mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight, visible ? VISIBLE : GONE, WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY, mWinFrame, mOverscanInsets, mContentInsets, @@ -621,11 +630,19 @@ public class SurfaceView extends View { TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y + " w=" + mLayout.width + " h=" + mLayout.height + ", frame=" + mSurfaceFrame); - } else if (positionChanged) { // Only the position has changed - mLeft = mLocation[0]; - mTop = mLocation[1]; + } else if (positionChanged || layoutSizeChanged) { // Only the position has changed + mWindowSpaceLeft = mLocation[0]; + mWindowSpaceTop = mLocation[1]; + // For our size changed check, we keep mLayout.width and mLayout.height + // in view local space. + mLocation[0] = mLayout.width = getWidth(); + mLocation[1] = mLayout.height = getHeight(); + + transformFromViewToWindowSpace(mLocation); + try { - mSession.repositionChild(mWindow, mLeft, mTop, + mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop, + mLocation[0], mLocation[1], viewRoot != null ? viewRoot.getNextFrameNumber() : -1, mWinFrame); } catch (RemoteException ex) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c2af9f7bb24a..66b05a20492f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -18498,21 +18498,29 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * must be an array of two integers. After the method returns, the array * contains the x and y location in that order.</p> * - * @param location an array of two integers in which to hold the coordinates + * @param outWindowSpace an array of two integers in which to hold the coordinates */ - public void getLocationInWindow(@Size(2) int[] location) { - if (location == null || location.length < 2) { - throw new IllegalArgumentException("location must be an array of two integers"); + public void getLocationInWindow(@Size(2) int[] outWindowSpace) { + outWindowSpace[0] = 0; + outWindowSpace[1] = 0; + + transformFromViewToWindowSpace(outWindowSpace); + } + + void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) { + if (inOutLocation == null || inOutLocation.length < 2) { + throw new IllegalArgumentException("inOutLocation must be an array of two integers"); } if (mAttachInfo == null) { // When the view is not attached to a window, this method does not make sense - location[0] = location[1] = 0; + inOutLocation[0] = inOutLocation[1] = 0; return; } - float[] position = mAttachInfo.mTmpTransformLocation; - position[0] = position[1] = 0.0f; + float position[] = mAttachInfo.mTmpTransformLocation; + position[0] = inOutLocation[0]; + position[1] = inOutLocation[1]; if (!hasIdentityMatrix()) { getMatrix().mapPoints(position); @@ -18544,8 +18552,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, position[1] -= vr.mCurScrollY; } - location[0] = (int) (position[0] + 0.5f); - location[1] = (int) (position[1] + 0.5f); + inOutLocation[0] = (int) (position[0] + 0.5f); + inOutLocation[1] = (int) (position[1] + 0.5f); } /** diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 2d0435f4c7e3..edf4297afdea 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1148,6 +1148,16 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT = 0x00001000; /** + * Flag indicating that the x, y, width, and height members should be + * ignored (and thus their previous value preserved). For example + * because they are being managed externally through repositionChild. + * + * {@hide} + */ + public static final int PRIVATE_FLAG_PRESERVE_GEOMETRY = 0x00002000; + + + /** * Control flags that are private to the platform. * @hide */ diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index c47c377f4cb8..1caeca09238d 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -188,9 +188,10 @@ final class Session extends IWindowSession.Stub } @Override - public void repositionChild(IWindow window, int x, int y, long deferTransactionUntilFrame, - Rect outFrame) { - mService.repositionChild(this, window, x, y, deferTransactionUntilFrame, outFrame); + public void repositionChild(IWindow window, int left, int top, int right, int bottom, + long deferTransactionUntilFrame, Rect outFrame) { + mService.repositionChild(this, window, left, top, right, bottom, + deferTransactionUntilFrame, outFrame); } public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 05e88caf7bd4..c747d4769f0a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2504,7 +2504,8 @@ public class WindowManagerService extends IWindowManager.Stub } void repositionChild(Session session, IWindow client, - int x, int y, long deferTransactionUntilFrame, Rect outFrame) { + int top, int left, int right, int bottom, + long deferTransactionUntilFrame, Rect outFrame) { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild"); long origId = Binder.clearCallingIdentity(); @@ -2520,8 +2521,10 @@ public class WindowManagerService extends IWindowManager.Stub + "attached to a parent win=" + win); } - win.mFrame.left = x; - win.mFrame.top = y; + win.mFrame.left = left; + win.mFrame.top = top; + win.mFrame.right = right; + win.mFrame.bottom = bottom; win.mWinAnimator.computeShownFrameLocked(); @@ -2594,6 +2597,15 @@ public class WindowManagerService extends IWindowManager.Stub throw new IllegalArgumentException( "Window type can not be changed after the window is added."); } + + // Odd choice but less odd than embedding in copyFrom() + if ((attrs.flags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY) != 0) { + attrs.x = win.mAttrs.x; + attrs.y = win.mAttrs.y; + attrs.width = win.mAttrs.width; + attrs.height = win.mAttrs.height; + } + flagChanges = win.mAttrs.flags ^= attrs.flags; attrChanges = win.mAttrs.copyFrom(attrs); if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java index 11bd15d780fc..1ec054720547 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java @@ -95,8 +95,8 @@ public final class BridgeWindowSession implements IWindowSession { } @Override - public void repositionChild(IWindow childWindow, int x, int y, long deferTransactionUntilFrame, - Rect outFrame) { + public void repositionChild(IWindow childWindow, int x, int y, int width, int height, + long deferTransactionUntilFrame, Rect outFrame) { // pass for now. return; } |