From 217e7cc2212204bb14eae15c055ee0c2d640e861 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 31 Jan 2018 18:08:39 -0800 Subject: Nuke WindowState#mShownPosition. Rework mXOffset/mYOffset. Ignoring Wallpaper Offsets, the WindowStateAnimator is now always positioned at (0,0), so we don't need to calculate or store this. For Wallpaper Offsets we can manipulate the position of the WindowStateAnimator surface directly. This seems to be a nice level to model the concept of scrolling a buffer larger than the "Window" to which it is assigned. Everything on top of WSA can ignore the offsets by only interacting with the WS and above. Seamless rotation may mess with the position so we need to be sure to reset it to 0,0. Test: Manual. go/wm-smoke Bug: 72038766 Change-Id: I961d190d1f1ee71faaede095617092a0ad32e16f --- .../android/server/windowmanagerservice.proto | 1 - .../android/server/policy/PhoneWindowManager.java | 4 +- .../android/server/policy/WindowManagerPolicy.java | 8 ---- .../com/android/server/wm/WallpaperController.java | 18 ++++---- .../android/server/wm/WallpaperWindowToken.java | 4 -- .../java/com/android/server/wm/WindowState.java | 33 ++------------- .../com/android/server/wm/WindowStateAnimator.java | 49 ++++++++++------------ .../com/android/server/policy/FakeWindowState.java | 5 --- 8 files changed, 34 insertions(+), 88 deletions(-) diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index c11058a22107..449e54672207 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -295,7 +295,6 @@ message WindowStateProto { optional bool animating_exit = 14; repeated WindowStateProto child_windows = 15; optional .android.graphics.RectProto surface_position = 16; - optional .android.graphics.RectProto shown_position = 17; optional int32 requested_width = 18; optional int32 requested_height = 19; optional int32 view_visibility = 20; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 7efc9876993b..f47a0a86e2e8 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -5642,9 +5642,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { final int fl = PolicyControl.getWindowFlags(null, mTopFullscreenOpaqueWindowState.getAttrs()); if (localLOGV) { - Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() - + " shown position: " - + mTopFullscreenOpaqueWindowState.getShownPositionLw()); + Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()); Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() + " lp.flags=0x" + Integer.toHexString(fl)); } diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index bf0c3da5b99c..a07f5eb09ab7 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -231,14 +231,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { */ public Rect getFrameLw(); - /** - * Retrieve the current position of the window that is actually shown. - * Must be called with the window manager lock held. - * - * @return Point The point holding the shown window position. - */ - public Point getShownPositionLw(); - /** * Retrieve the frame of the display that this window was last * laid out in. Must be called with the diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index a7d51f175ab5..2873b6db1a20 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -275,6 +275,8 @@ class WallpaperController { } boolean updateWallpaperOffset(WindowState wallpaperWin, int dw, int dh, boolean sync) { + int xOffset = 0; + int yOffset = 0; boolean rawChanged = false; // Set the default wallpaper x-offset to either edge of the screen (depending on RTL), to // match the behavior of most Launchers @@ -286,11 +288,8 @@ class WallpaperController { if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) { offset += mLastWallpaperDisplayOffsetX; } - boolean changed = wallpaperWin.mXOffset != offset; - if (changed) { - if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " x: " + offset); - wallpaperWin.mXOffset = offset; - } + xOffset = offset; + if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) { wallpaperWin.mWallpaperX = wpx; wallpaperWin.mWallpaperXStep = wpxs; @@ -304,17 +303,16 @@ class WallpaperController { if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) { offset += mLastWallpaperDisplayOffsetY; } - if (wallpaperWin.mYOffset != offset) { - if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " y: " + offset); - changed = true; - wallpaperWin.mYOffset = offset; - } + yOffset = offset; + if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) { wallpaperWin.mWallpaperY = wpy; wallpaperWin.mWallpaperYStep = wpys; rawChanged = true; } + boolean changed = wallpaperWin.mWinAnimator.setWallpaperOffset(xOffset, yOffset); + if (rawChanged && (wallpaperWin.mAttrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) { try { diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java index 2ae5c7bd9c25..ddda027595da 100644 --- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java +++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java @@ -74,10 +74,6 @@ class WallpaperWindowToken extends WindowToken { for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) { final WindowState wallpaper = mChildren.get(wallpaperNdx); if (wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, sync)) { - final WindowStateAnimator winAnimator = wallpaper.mWinAnimator; - winAnimator.computeShownFrameLocked(); - // No need to lay out the windows - we can just set the wallpaper position directly. - winAnimator.setWallpaperOffset(wallpaper.mShownPosition); // We only want to be synchronous with one wallpaper. sync = false; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b706096f3d0b..c0ab3f9a413f 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -138,7 +138,6 @@ import static com.android.server.wm.proto.WindowStateProto.REMOVED; import static com.android.server.wm.proto.WindowStateProto.REMOVE_ON_EXIT; import static com.android.server.wm.proto.WindowStateProto.REQUESTED_HEIGHT; import static com.android.server.wm.proto.WindowStateProto.REQUESTED_WIDTH; -import static com.android.server.wm.proto.WindowStateProto.SHOWN_POSITION; import static com.android.server.wm.proto.WindowStateProto.STABLE_INSETS; import static com.android.server.wm.proto.WindowStateProto.STACK_ID; import static com.android.server.wm.proto.WindowStateProto.SURFACE_INSETS; @@ -297,12 +296,6 @@ class WindowState extends WindowContainer implements WindowManagerP */ private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration(); - /** - * Actual position of the surface shown on-screen (may be modified by animation). These are - * in the screen's coordinate space (WITH the compatibility scale applied). - */ - final Point mShownPosition = new Point(); - /** * Insets that determine the actually visible area. These are in the application's * coordinate space (without compatibility scale applied). @@ -462,10 +455,6 @@ class WindowState extends WindowContainer implements WindowManagerP int mWallpaperDisplayOffsetX = Integer.MIN_VALUE; int mWallpaperDisplayOffsetY = Integer.MIN_VALUE; - // Wallpaper windows: pixels offset based on above variables. - int mXOffset; - int mYOffset; - /** * This is set after IWindowSession.relayout() has been called at * least once for the window. It allows us to detect the situation @@ -771,8 +760,6 @@ class WindowState extends WindowContainer implements WindowManagerP mRequestedHeight = 0; mLastRequestedWidth = 0; mLastRequestedHeight = 0; - mXOffset = 0; - mYOffset = 0; mLayer = 0; mInputWindowHandle = new InputWindowHandle( mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, c, @@ -1137,11 +1124,6 @@ class WindowState extends WindowContainer implements WindowManagerP return mFrame; } - @Override - public Point getShownPositionLw() { - return mShownPosition; - } - @Override public Rect getDisplayFrameLw() { return mDisplayFrame; @@ -3136,7 +3118,6 @@ class WindowState extends WindowContainer implements WindowManagerP mContentInsets.writeToProto(proto, CONTENT_INSETS); mAttrs.surfaceInsets.writeToProto(proto, SURFACE_INSETS); mSurfacePosition.writeToProto(proto, SURFACE_POSITION); - mShownPosition.writeToProto(proto, SHOWN_POSITION); mWinAnimator.writeToProto(proto, ANIMATOR); proto.write(ANIMATING_EXIT, mAnimatingExit); for (int i = 0; i < mChildren.size(); i++) { @@ -3252,10 +3233,6 @@ class WindowState extends WindowContainer implements WindowManagerP pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled); pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded); } - if (mXOffset != 0 || mYOffset != 0) { - pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset); - pw.print(" y="); pw.println(mYOffset); - } if (dumpAll) { pw.print(prefix); pw.print("mGivenContentInsets="); mGivenContentInsets.printShortString(pw); @@ -3274,7 +3251,6 @@ class WindowState extends WindowContainer implements WindowManagerP pw.println(getLastReportedConfiguration()); } pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface); - pw.print(" mShownPosition="); mShownPosition.printShortString(pw); pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay()); pw.print(" mWindowRemovalAllowed="); pw.println(mWindowRemovalAllowed); if (dumpAll) { @@ -4195,9 +4171,8 @@ class WindowState extends WindowContainer implements WindowManagerP final int width = mFrame.width(); final int height = mFrame.height(); - // Compute the offset of the window in relation to the decor rect. - final int left = mXOffset + mFrame.left; - final int top = mYOffset + mFrame.top; + final int left = mFrame.left; + final int top = mFrame.top; // Initialize the decor rect to the entire frame. if (isDockedResizing()) { @@ -4391,8 +4366,8 @@ class WindowState extends WindowContainer implements WindowManagerP float9[Matrix.MSKEW_Y] = mWinAnimator.mDtDx; float9[Matrix.MSKEW_X] = mWinAnimator.mDtDy; float9[Matrix.MSCALE_Y] = mWinAnimator.mDsDy; - int x = mSurfacePosition.x + mShownPosition.x; - int y = mSurfacePosition.y + mShownPosition.y; + int x = mSurfacePosition.x; + int y = mSurfacePosition.y; // If changed, also adjust transformFrameToSurfacePosition final WindowContainer parent = getParent(); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 9ce05376732e..92145be92115 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -209,6 +209,12 @@ class WindowStateAnimator { float mExtraHScale = (float) 1.0; float mExtraVScale = (float) 1.0; + // An offset in pixel of the surface contents from the window position. Used for Wallpaper + // to provide the effect of scrolling within a large surface. We just use these values as + // a cache. + int mXOffset = 0; + int mYOffset = 0; + private final Rect mTmpSize = new Rect(); private final SurfaceControl.Transaction mReparentTransaction = new SurfaceControl.Transaction(); @@ -438,7 +444,7 @@ class WindowStateAnimator { flags |= SurfaceControl.SECURE; } - mTmpSize.set(w.mFrame.left + w.mXOffset, w.mFrame.top + w.mYOffset, 0, 0); + mTmpSize.set(0, 0, 0, 0); calculateSurfaceBounds(w, attrs); final int width = mTmpSize.width(); final int height = mTmpSize.height(); @@ -679,8 +685,8 @@ class WindowStateAnimator { // WindowState.prepareSurfaces expands for surface insets (in order they don't get // clipped by the WindowState surface), so we need to go into the other direction here. - tmpMatrix.postTranslate(mWin.mXOffset + mWin.mAttrs.surfaceInsets.left, - mWin.mYOffset + mWin.mAttrs.surfaceInsets.top); + tmpMatrix.postTranslate(mWin.mAttrs.surfaceInsets.left, + mWin.mAttrs.surfaceInsets.top); // "convert" it into SurfaceFlinger's format @@ -695,9 +701,6 @@ class WindowStateAnimator { mDtDx = tmpFloats[Matrix.MSKEW_Y]; mDtDy = tmpFloats[Matrix.MSKEW_X]; mDsDy = tmpFloats[Matrix.MSCALE_Y]; - float x = tmpFloats[Matrix.MTRANS_X]; - float y = tmpFloats[Matrix.MTRANS_Y]; - mWin.mShownPosition.set(Math.round(x), Math.round(y)); // Now set the alpha... but because our current hardware // can't do alpha transformation on a non-opaque surface, @@ -707,8 +710,7 @@ class WindowStateAnimator { mShownAlpha = mAlpha; if (!mService.mLimitedAlphaCompositing || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format) - || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDtDy, mDsDy) - && x == frame.left && y == frame.top))) { + || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDtDy, mDsDy)))) { //Slog.i(TAG_WM, "Applying alpha transform"); if (screenAnimation) { mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha(); @@ -738,10 +740,6 @@ class WindowStateAnimator { TAG, "computeShownFrameLocked: " + this + " not attached, mAlpha=" + mAlpha); - // WindowState.prepareSurfaces expands for surface insets (in order they don't get - // clipped by the WindowState surface), so we need to go into the other direction here. - mWin.mShownPosition.set(mWin.mXOffset + mWin.mAttrs.surfaceInsets.left, - mWin.mYOffset + mWin.mAttrs.surfaceInsets.top); mShownAlpha = mAlpha; mHaveMatrix = false; mDsDx = mWin.mGlobalScale; @@ -792,12 +790,6 @@ class WindowStateAnimator { if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect + " fullscreen=" + fullscreen); - if (isFreeformResizing && !w.isChildWindow()) { - // For freeform resizing non child windows, we are using the big surface positioned - // at 0,0. Thus we must express the crop in that coordinate space. - clipRect.offset(w.mShownPosition.x, w.mShownPosition.y); - } - w.expandForSurfaceInsets(clipRect); // The clip rect was generated assuming (0,0) as the window origin, @@ -834,7 +826,7 @@ class WindowStateAnimator { final LayoutParams attrs = mWin.getAttrs(); final Task task = w.getTask(); - mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0); + mTmpSize.set(0, 0, 0, 0); calculateSurfaceBounds(w, attrs); mExtraHScale = (float) 1.0; @@ -970,8 +962,7 @@ class WindowStateAnimator { mForceScaleUntilResize = true; } else { if (!w.mSeamlesslyRotated) { - mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, - recoveringMemory); + mSurfaceController.setPositionInTransaction(0, 0, recoveringMemory); } } @@ -1139,24 +1130,26 @@ class WindowStateAnimator { mSurfaceController.setTransparentRegionHint(region); } - void setWallpaperOffset(Point shownPosition) { - final LayoutParams attrs = mWin.getAttrs(); - final int left = shownPosition.x - attrs.surfaceInsets.left; - final int top = shownPosition.y - attrs.surfaceInsets.top; + boolean setWallpaperOffset(int dx, int dy) { + if (mXOffset == dx && mYOffset == dy) { + return false; + } + mXOffset = dx; + mYOffset = dy; try { if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset"); mService.openSurfaceTransaction(); - mSurfaceController.setPositionInTransaction(mWin.mFrame.left + left, - mWin.mFrame.top + top, false); + mSurfaceController.setPositionInTransaction(dx, dy, false); applyCrop(null, false); } catch (RuntimeException e) { Slog.w(TAG, "Error positioning surface of " + mWin - + " pos=(" + left + "," + top + ")", e); + + " pos=(" + dx + "," + dy + ")", e); } finally { mService.closeSurfaceTransaction("setWallpaperOffset"); if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setWallpaperOffset"); + return true; } } diff --git a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java index a628b7b70c15..5de393c7ae2b 100644 --- a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java +++ b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java @@ -78,11 +78,6 @@ public class FakeWindowState implements WindowManagerPolicy.WindowState { return parentFrame; } - @Override - public Point getShownPositionLw() { - return new Point(parentFrame.left, parentFrame.top); - } - @Override public Rect getDisplayFrameLw() { return displayFrame; -- cgit v1.2.3-59-g8ed1b From 74a66a2c7ba0ee3472d4863c958df5d41bbc3267 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Fri, 23 Feb 2018 12:17:51 -0800 Subject: Various pinned animation bug fixes. First we need to change the way the aspect scale cropping happens on the way down, previously we relied on the stack bounds to crop us and did not expand the stack bounds for shadows. Now that the stack surface bounds are expanded for shadows we have to do the additional cropping required by this animation at the WSA level. Namely we interpolate such that when the animation reaches 100% progress everything except the source bounds will be cropped out. If we didn't do this we would see a surfaceInsets sized sliver of the original app at the end of the animation. A second fix is to update the stack bounds when changing windowing modes to make sure we immediately expand for the pinned insets (as the WindowState level may now immediately reposition to compensate). A third fix is to correct the stack outset logic to match the client side in WindowManager.java A fourth fix is to bump the default and arbitrary surface size to allow for surfaces slightly larger than full-screen and positioned at a negative position, e.g. a full-screen-surface which retained it's insets due to a slow or non-cooperative client. Bug: 70666541 Test: Manual. go/wm-smoke. Change-Id: I045ddf191cd3875f5d32c2e15da6e01fb50f3a01 --- .../java/com/android/server/wm/DisplayContent.java | 9 ++++++- .../core/java/com/android/server/wm/TaskStack.java | 8 ++++-- .../com/android/server/wm/WindowStateAnimator.java | 30 +++++++++++++++------- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 19c634a55d5a..332bdb7fa8fb 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -747,7 +747,14 @@ class DisplayContent extends WindowContainer implements int getStackOutset() { if (inPinnedWindowingMode()) { final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics(); - return mService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP, - displayMetrics); + + // We multiply by two to match the client logic for converting view elevation + // to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets} + return (int)Math.ceil(mService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP, + displayMetrics) * 2); } return 0; } @@ -824,6 +827,7 @@ public class TaskStack extends WindowContainer implements } updateDisplayInfo(bounds); + updateSurfaceBounds(); } /** diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 92145be92115..0e80819a149f 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -862,17 +862,19 @@ class WindowStateAnimator { float surfaceWidth = mSurfaceController.getWidth(); float surfaceHeight = mSurfaceController.getHeight(); + final Rect insets = attrs.surfaceInsets; + if (isForceScaled()) { - int hInsets = attrs.surfaceInsets.left + attrs.surfaceInsets.right; - int vInsets = attrs.surfaceInsets.top + attrs.surfaceInsets.bottom; + int hInsets = insets.left + insets.right; + int vInsets = insets.top + insets.bottom; float surfaceContentWidth = surfaceWidth - hInsets; float surfaceContentHeight = surfaceHeight - vInsets; if (!mForceScaleUntilResize) { mSurfaceController.forceScaleableInTransaction(true); } - int posX = mTmpSize.left; - int posY = mTmpSize.top; + int posX = 0; + int posY = 0; task.mStack.getDimBounds(mTmpStackBounds); boolean allowStretching = false; @@ -919,9 +921,19 @@ class WindowStateAnimator { posX -= (int) (tw * mExtraHScale * mTmpSourceBounds.left); posY -= (int) (th * mExtraVScale * mTmpSourceBounds.top); - // Always clip to the stack bounds since the surface can be larger with the current - // scale - clipRect = null; + // In pinned mode the clip rectangle applied to us by our stack has been + // expanded outwards to allow for shadows. However in case of source bounds set + // we need to crop to within the surface. The code above has scaled and positioned + // the surface to fit the unexpanded stack bounds, but now we need to reapply + // the cropping that the stack would have applied if it weren't expanded. This + // can be different in each direction based on the source bounds. + clipRect = mTmpClipRect; + clipRect.set((int)((insets.left + mTmpSourceBounds.left) * tw), + (int)((insets.top + mTmpSourceBounds.top) * th), + insets.left + (int)(surfaceWidth + - (tw* (surfaceWidth - mTmpSourceBounds.right))), + insets.top + (int)(surfaceHeight + - (th * (surfaceHeight - mTmpSourceBounds.bottom)))); } else { // We want to calculate the scaling based on the content area, not based on // the entire surface, so that we scale in sync with windows that don't have insets. @@ -947,8 +959,8 @@ class WindowStateAnimator { // non inset content at the same position, we have to shift the whole window // forward. Likewise for scaling up, we've increased this distance, and we need // to shift by a negative number to compensate. - posX += attrs.surfaceInsets.left * (1 - mExtraHScale); - posY += attrs.surfaceInsets.top * (1 - mExtraVScale); + posX += insets.left * (1 - mExtraHScale); + posY += insets.top * (1 - mExtraVScale); mSurfaceController.setPositionInTransaction((float) Math.floor(posX), (float) Math.floor(posY), recoveringMemory); -- cgit v1.2.3-59-g8ed1b From c6d5af556e9e8b682d24e457e6236fe5ee11e2a6 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 26 Feb 2018 17:46:00 -0800 Subject: Handle surfaceInset changes with deferred transactions. First we have the client pass up the next frameNumber from relayoutWindow and then we simply deferTransactions at the WindowState level until this frame number is reached. This was always a little terrifying because deferring transaction effecftively meant we gave up control of the surface until the frame number was reached. However now we can still control the surface from the stack and other SurfaceControl nodes and so the window can still be moved around and animated even if the client is unresponsive. Bug: 70666541 Test: Manual. go/wm-smoke Change-Id: I2fecbeaa30fc0eb9cc8f08e1ea734dcc65da0aa0 --- core/java/android/view/ViewRootImpl.java | 20 +++++++++++++------- core/java/android/view/WindowManager.java | 13 +++++++++++++ .../core/java/com/android/server/wm/WindowState.java | 18 ++++++++++-------- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 01d9265cc92c..098583c1e445 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -6440,18 +6440,24 @@ public final class ViewRootImpl implements ViewParent, params.backup(); mTranslator.translateWindowLayout(params); } + if (params != null) { if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params); - } - if (params != null && mOrigWindowType != params.type) { - // For compatibility with old apps, don't crash here. - if (mTargetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - Slog.w(mTag, "Window type can not be changed after " - + "the window is added; ignoring change of " + mView); - params.type = mOrigWindowType; + if (mOrigWindowType != params.type) { + // For compatibility with old apps, don't crash here. + if (mTargetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + Slog.w(mTag, "Window type can not be changed after " + + "the window is added; ignoring change of " + mView); + params.type = mOrigWindowType; + } + } + + if (mSurface.isValid()) { + params.frameNumber = mSurface.getNextFrameNumber(); } } + int relayoutResult = mWindowSession.relayout( mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index c0a966602b0a..e2717018bb2c 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -2370,6 +2370,13 @@ public interface WindowManager extends ViewManager { */ public long hideTimeoutMilliseconds = -1; + /** + * A frame number in which changes requested in this layout will be rendered. + * + * @hide + */ + public long frameNumber = -1; + /** * The color mode requested by this window. The target display may * not be able to honor the request. When the color mode is not set @@ -2543,6 +2550,7 @@ public interface WindowManager extends ViewManager { TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags); out.writeInt(mColorMode); out.writeLong(hideTimeoutMilliseconds); + out.writeLong(frameNumber); } public static final Parcelable.Creator CREATOR @@ -2599,6 +2607,7 @@ public interface WindowManager extends ViewManager { accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); mColorMode = in.readInt(); hideTimeoutMilliseconds = in.readLong(); + frameNumber = in.readLong(); } @SuppressWarnings({"PointlessBitwiseExpression"}) @@ -2799,6 +2808,10 @@ public interface WindowManager extends ViewManager { changes |= SURFACE_INSETS_CHANGED; } + // The frame number changing is only relevant in the context of other + // changes, and so we don't need to track it with a flag. + frameNumber = o.frameNumber; + if (hasManualSurfaceInsets != o.hasManualSurfaceInsets) { hasManualSurfaceInsets = o.hasManualSurfaceInsets; changes |= SURFACE_INSETS_CHANGED; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c0ab3f9a413f..e1aa4fc6657a 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4274,14 +4274,9 @@ class WindowState extends WindowContainer implements WindowManagerP // When we change the Surface size, in scenarios which may require changing // the surface position in sync with the resize, we use a preserved surface // so we can freeze it while waiting for the client to report draw on the newly - // sized surface. Don't preserve surfaces if the insets change while animating the pinned - // stack since it can lead to issues if a new surface is created while calculating the - // scale for the animation using the source hint rect - // (see WindowStateAnimator#setSurfaceBoundariesLocked()). - if (isDragResizeChanged() - || (surfaceInsetsChanging() && !inPinnedWindowingMode())) { - mLastSurfaceInsets.set(mAttrs.surfaceInsets); - + // sized surface. At the moment this logic is only in place for switching + // in and out of the big surface for split screen resize. + if (isDragResizeChanged()) { setDragResizing(); // We can only change top level windows to the full-screen surface when // resizing (as we only have one full-screen surface). So there is no need @@ -4529,9 +4524,16 @@ class WindowState extends WindowContainer implements WindowManagerP } transformFrameToSurfacePosition(mFrame.left, mFrame.top, mSurfacePosition); + if (!mSurfaceAnimator.hasLeash() && !mLastSurfacePosition.equals(mSurfacePosition)) { t.setPosition(mSurfaceControl, mSurfacePosition.x, mSurfacePosition.y); mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y); + if (surfaceInsetsChanging() && mWinAnimator.hasSurface()) { + mLastSurfaceInsets.set(mAttrs.surfaceInsets); + t.deferTransactionUntil(mSurfaceControl, + mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), + mAttrs.frameNumber); + } } } -- cgit v1.2.3-59-g8ed1b From 024378c5aecb50249b6dddd8dcd639c528135d1d Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 27 Feb 2018 11:21:05 -0800 Subject: Move frame validation logic for deferTransactionUntil. Currently it's only in place applying for operations on the global transaction. Bug: 70666541 Test: Manual Change-Id: I5c2facba14c783bad0d3aca0e8b66fea73df0776 --- core/java/android/view/SurfaceControl.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index bd7f8e5419eb..cc9b8a891782 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -763,18 +763,14 @@ public class SurfaceControl implements Parcelable { } public void deferTransactionUntil(IBinder handle, long frame) { - if (frame > 0) { - synchronized(SurfaceControl.class) { - sGlobalTransaction.deferTransactionUntil(this, handle, frame); - } + synchronized(SurfaceControl.class) { + sGlobalTransaction.deferTransactionUntil(this, handle, frame); } } public void deferTransactionUntil(Surface barrier, long frame) { - if (frame > 0) { - synchronized(SurfaceControl.class) { - sGlobalTransaction.deferTransactionUntilSurface(this, barrier, frame); - } + synchronized(SurfaceControl.class) { + sGlobalTransaction.deferTransactionUntilSurface(this, barrier, frame); } } @@ -1479,6 +1475,9 @@ public class SurfaceControl implements Parcelable { public Transaction deferTransactionUntil(SurfaceControl sc, IBinder handle, long frameNumber) { + if (frameNumber < 0) { + return this; + } sc.checkNotReleased(); nativeDeferTransactionUntil(mNativeObject, sc.mNativeObject, handle, frameNumber); return this; @@ -1486,6 +1485,9 @@ public class SurfaceControl implements Parcelable { public Transaction deferTransactionUntilSurface(SurfaceControl sc, Surface barrierSurface, long frameNumber) { + if (frameNumber < 0) { + return this; + } sc.checkNotReleased(); nativeDeferTransactionUntilSurface(mNativeObject, sc.mNativeObject, barrierSurface.mNativeObject, frameNumber); -- cgit v1.2.3-59-g8ed1b