From 47307ac8f01c712ad050e00422bf8433d918f191 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 2 Jun 2021 14:40:22 -0700 Subject: [PATCH] WM Wallpaper: Set offset and scale on WindowState level When we set it on the WindowStateAnimator we are potentially coming in to disagreement with scaling applied via the BLASTBufferQueue. Bug: 188504567 Test: Repro from bug. Existing tests pass. Change-Id: I7843fa12e52812a5cd3a3dd34114e0c6d58aecd3 --- .../server/wm/WallpaperController.java | 2 +- .../com/android/server/wm/WindowState.java | 31 +++++++- .../server/wm/WindowStateAnimator.java | 79 +------------------ .../server/wm/DisplayContentTests.java | 6 +- .../server/wm/WallpaperControllerTests.java | 2 +- 5 files changed, 35 insertions(+), 85 deletions(-) diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 5635c33995b16..95e5fc2e6b274 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -340,7 +340,7 @@ class WallpaperController { rawChanged = true; } - boolean changed = wallpaperWin.mWinAnimator.setWallpaperOffset(xOffset, yOffset, + boolean changed = wallpaperWin.setWallpaperOffset(xOffset, yOffset, wallpaperWin.mShouldScaleWallpaper ? zoomOutToScale(wallpaperWin.mWallpaperZoomOut) : 1); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 20a992d244c5d..a29d693cc58a3 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -444,6 +444,17 @@ class WindowState extends WindowContainer implements WindowManagerP float mOverrideScale = 1; float mHScale=1, mVScale=1; float mLastHScale=1, mLastVScale=1; + + // 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; + + // A scale factor for the surface contents, that will be applied from the center of the visible + // region. + float mWallpaperScale = 1f; + final Matrix mTmpMatrix = new Matrix(); final float[] mTmpMatrixArray = new float[9]; @@ -5422,10 +5433,12 @@ class WindowState extends WindowContainer implements WindowManagerP } private void updateScaleIfNeeded() { - if (mLastGlobalScale != mGlobalScale || mLastHScale != mHScale || - mLastVScale != mVScale ) { + float newHScale = mHScale * mGlobalScale * mWallpaperScale; + float newVScale = mVScale * mGlobalScale * mWallpaperScale; + if (mLastHScale != newHScale || + mLastVScale != newVScale ) { getPendingTransaction().setMatrix(getSurfaceControl(), - mGlobalScale*mHScale, 0, 0, mGlobalScale*mVScale); + newHScale, 0, 0, newVScale); mLastGlobalScale = mGlobalScale; mLastHScale = mHScale; mLastVScale = mVScale; @@ -5463,6 +5476,7 @@ class WindowState extends WindowContainer implements WindowManagerP mSurfacePlacementNeeded = false; transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top, mSurfacePosition); + mSurfacePosition.offset(mXOffset, mYOffset); // Freeze position while we're unrotated, so the surface remains at the position it was // prior to the rotation. @@ -6071,4 +6085,15 @@ class WindowState extends WindowContainer implements WindowManagerP void markRedrawForSyncReported() { mRedrawForSyncReported = true; } + + boolean setWallpaperOffset(int dx, int dy, float scale) { + if (mXOffset == dx && mYOffset == dy && Float.compare(mWallpaperScale, scale) == 0) { + return false; + } + mXOffset = dx; + mYOffset = dy; + mWallpaperScale = scale; + scheduleAnimation(); + return true; + } } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index ea3b0658c4d55..9a6e4448966d9 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -169,16 +169,6 @@ class WindowStateAnimator { int mAttrType; - // 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; - - // A scale factor for the surface contents, that will be applied from the center of the visible - // region. - float mWallpaperScale = 1f; - private final Rect mTmpSize = new Rect(); /** @@ -502,18 +492,6 @@ class WindowStateAnimator { } final WindowState w = mWin; - - if (!w.mSeamlesslyRotated) { - // Used to offset the WSA when stack position changes before a resize. - int xOffset = mXOffset; - int yOffset = mYOffset; - if (!mIsWallpaper) { - mSurfaceController.setPosition(t, xOffset, yOffset); - } else { - setWallpaperPositionAndScale(t, xOffset, yOffset, mWallpaperScale); - } - } - final Task task = w.getTask(); if (shouldConsumeMainWindowSizeTransaction()) { if (isInBlastSync()) { @@ -575,14 +553,8 @@ class WindowStateAnimator { "SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s", mSurfaceController, mShownAlpha, w.mHScale, w.mVScale, w); - boolean prepared = true; - - if (mIsWallpaper) { - setWallpaperPositionAndScale(t, mXOffset, mYOffset, mWallpaperScale); - } else { - prepared = - mSurfaceController.prepareToShowInTransaction(t, mShownAlpha); - } + boolean prepared = + mSurfaceController.prepareToShowInTransaction(t, mShownAlpha); if (prepared && mDrawState == HAS_DRAWN) { if (mLastHidden) { @@ -635,53 +607,6 @@ class WindowStateAnimator { } } - boolean setWallpaperOffset(int dx, int dy, float scale) { - if (mXOffset == dx && mYOffset == dy && Float.compare(mWallpaperScale, scale) == 0) { - return false; - } - mXOffset = dx; - mYOffset = dy; - mWallpaperScale = scale; - - if (mSurfaceController != null) { - try { - if (SHOW_LIGHT_TRANSACTIONS) { - Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset"); - } - mService.openSurfaceTransaction(); - setWallpaperPositionAndScale(SurfaceControl.getGlobalTransaction(), dx, dy, scale); - } catch (RuntimeException e) { - Slog.w(TAG, "Error positioning surface of " + mWin - + " pos=(" + dx + "," + dy + ")", e); - } finally { - mService.closeSurfaceTransaction("setWallpaperOffset"); - if (SHOW_LIGHT_TRANSACTIONS) { - Slog.i(TAG, "<<< CLOSE TRANSACTION setWallpaperOffset"); - } - } - } - - return true; - } - - private void setWallpaperPositionAndScale(SurfaceControl.Transaction t, int dx, int dy, - float scale) { - DisplayInfo displayInfo = mWin.getDisplayInfo(); - Matrix matrix = mWin.mTmpMatrix; - matrix.setTranslate(dx, dy); - matrix.postScale(scale, scale, displayInfo.logicalWidth / 2f, - displayInfo.logicalHeight / 2f); - matrix.getValues(mWin.mTmpMatrixArray); - matrix.reset(); - - mSurfaceController.setPosition(t,mWin.mTmpMatrixArray[MTRANS_X], - mWin.mTmpMatrixArray[MTRANS_Y]); - mSurfaceController.setMatrix(t, mWin.mTmpMatrixArray[MSCALE_X], - mWin.mTmpMatrixArray[MSKEW_Y], - mWin.mTmpMatrixArray[MSKEW_X], - mWin.mTmpMatrixArray[MSCALE_Y]); - } - /** * Try to change the pixel format without recreating the surface. This * will be common in the case of changing from PixelFormat.OPAQUE to diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 94297be0c121e..5bc4c82f8d43d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1386,11 +1386,11 @@ public class DisplayContentTests extends WindowTestsBase { performLayout(mDisplayContent); // Force the negative offset to verify it can be updated. - mWallpaperWindow.mWinAnimator.mXOffset = mWallpaperWindow.mWinAnimator.mYOffset = -1; + mWallpaperWindow.mXOffset = mWallpaperWindow.mYOffset = -1; assertTrue(mDisplayContent.mWallpaperController.updateWallpaperOffset(mWallpaperWindow, false /* sync */)); - assertThat(mWallpaperWindow.mWinAnimator.mXOffset).isGreaterThan(-1); - assertThat(mWallpaperWindow.mWinAnimator.mYOffset).isGreaterThan(-1); + assertThat(mWallpaperWindow.mXOffset).isGreaterThan(-1); + assertThat(mWallpaperWindow.mYOffset).isGreaterThan(-1); // The wallpaper need to animate with transformed position, so its surface position should // not be reset. diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java index ada58a586ffcb..3f0c13c838163 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java @@ -212,7 +212,7 @@ public class WallpaperControllerTests extends WindowTestsBase { // value did, and we do dispatch the zoom to the wallpaper service dc.mWallpaperController.setWallpaperZoomOut(homeWindow, newZoom); assertEquals(newZoom, wallpaperWindow.mWallpaperZoomOut, .01f); - assertEquals(1f, wallpaperWindow.mWinAnimator.mWallpaperScale, .01f); + assertEquals(1f, wallpaperWindow.mWallpaperScale, .01f); verify(wallpaperWindow.mClient).dispatchWallpaperOffsets(anyFloat(), anyFloat(), anyFloat(), anyFloat(), eq(newZoom), anyBoolean()); }