From da3433f0d9ec2138ef4ef35e7590f8832355653c Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 31 May 2022 00:03:03 +0800 Subject: [PATCH] Only consider occluding transient below-task for wallpaper target Otherwise if keyguard is not locked (recents will be moved to top), the wallpaper target may be updated to the window of below-task temporally when swiping-up. Which causes the wallpaper window cannot apply the same fixed-rotation transform if the recents activity has the transform. Such as when swiping up to portrait home from a landscape activity, the wallpaper will be rotated to landscape and trigger an unnecessary display rotation animation. Bug: 230582311 Test: atest WallpaperControllerTests# \ testFixedRotationRecentsAnimatingTask Test: adb shell setprop persist.wm.debug.shell_transit 1; reboot Swipe landscape app to home and no additional display rotation animation for rotated wallpaper. With show-when-locked activity on lockscreen, the wallpaper can be visible when swiping up. Change-Id: Ibd47e9d78c2f6767a78255db62284bbbf176918c --- .../server/wm/WallpaperController.java | 24 ++++-- .../server/wm/WallpaperControllerTests.java | 86 ++++++++++--------- 2 files changed, 64 insertions(+), 46 deletions(-) diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 483f51a1c0f5b..6245005606d75 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -21,6 +21,7 @@ import static android.app.WallpaperManager.COMMAND_UNFREEZE; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; +import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; @@ -181,16 +182,11 @@ class WallpaperController { mFindResults.setUseTopWallpaperAsTarget(true); } - final RecentsAnimationController recentsAnimationController = - mService.getRecentsAnimationController(); final boolean animationWallpaper = animatingContainer != null && animatingContainer.getAnimation() != null && animatingContainer.getAnimation().getShowWallpaper(); final boolean hasWallpaper = w.hasWallpaper() || animationWallpaper; - final boolean isRecentsTransitionTarget = (recentsAnimationController != null - && recentsAnimationController.isWallpaperVisible(w)) - || w.mTransitionController.isTransientHide(w.getTask()); - if (isRecentsTransitionTarget) { + if (isRecentsTransitionTarget(w)) { if (DEBUG_WALLPAPER) Slog.v(TAG, "Found recents animation wallpaper target: " + w); mFindResults.setWallpaperTarget(w); return true; @@ -214,6 +210,22 @@ class WallpaperController { return false; }; + private boolean isRecentsTransitionTarget(WindowState w) { + if (w.mTransitionController.isShellTransitionsEnabled()) { + // Because the recents activity is invisible in background while keyguard is occluded + // (the activity window is on screen while keyguard is locked) with recents animation, + // the task animating by recents needs to be wallpaper target to make wallpaper visible. + // While for unlocked case, because recents activity will be moved to top, it can be + // the wallpaper target naturally. + return w.mActivityRecord != null && w.mAttrs.type == TYPE_BASE_APPLICATION + && mDisplayContent.isKeyguardLocked() + && w.mTransitionController.isTransientHide(w.getTask()); + } + // The window is either the recents activity or is in the task animating by the recents. + final RecentsAnimationController controller = mService.getRecentsAnimationController(); + return controller != null && controller.isWallpaperVisible(w); + } + /** * @see #computeLastWallpaperZoomOut() */ 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 1f68608d2ce67..996382782b842 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java @@ -35,6 +35,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyFloat; @@ -82,10 +83,7 @@ public class WallpaperControllerTests extends WindowTestsBase { assertFalse(dc.mWallpaperController.canScreenshotWallpaper()); // No wallpaper WSA Surface - WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class), - true, dc, true /* ownerCanManageAppTokens */); - WindowState wallpaperWindow = createWindow(null /* parent */, TYPE_WALLPAPER, - wallpaperWindowToken, "wallpaperWindow"); + final WindowState wallpaperWindow = createWallpaperWindow(dc); assertFalse(dc.mWallpaperController.canScreenshotWallpaper()); // Wallpaper with not visible WSA surface. @@ -107,13 +105,10 @@ public class WallpaperControllerTests extends WindowTestsBase { @Test public void testWallpaperSizeWithFixedTransform() { // No wallpaper - final DisplayContent dc = createNewDisplay(); + final DisplayContent dc = mDisplayContent; // No wallpaper WSA Surface - WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class), - true, dc, true /* ownerCanManageAppTokens */); - WindowState wallpaperWindow = createWindow(null /* parent */, TYPE_WALLPAPER, - wallpaperWindowToken, "wallpaperWindow"); + final WindowState wallpaperWindow = createWallpaperWindow(dc); WindowManager.LayoutParams attrs = wallpaperWindow.getAttrs(); Rect bounds = dc.getBounds(); @@ -153,7 +148,7 @@ public class WallpaperControllerTests extends WindowTestsBase { final WmDisplayCutout cutout = dc.calculateDisplayCutoutForRotation(Surface.ROTATION_0); final DisplayFrames displayFrames = new DisplayFrames(dc.getDisplayId(), new InsetsState(), info, cutout, RoundedCorners.NO_ROUNDED_CORNERS, new PrivacyIndicatorBounds()); - wallpaperWindowToken.applyFixedRotationTransform(info, displayFrames, config); + wallpaperWindow.mToken.applyFixedRotationTransform(info, displayFrames, config); // Check that the wallpaper has the same frame in landscape than in portrait assertEquals(Configuration.ORIENTATION_LANDSCAPE, dc.getConfiguration().orientation); @@ -163,10 +158,7 @@ public class WallpaperControllerTests extends WindowTestsBase { @Test public void testWallpaperZoom() throws RemoteException { final DisplayContent dc = mWm.mRoot.getDefaultDisplay(); - final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, - mock(IBinder.class), true, dc, true /* ownerCanManageAppTokens */); - final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken, - "wallpaperWindow"); + final WindowState wallpaperWindow = createWallpaperWindow(dc); wallpaperWindow.getAttrs().privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS; @@ -189,10 +181,7 @@ public class WallpaperControllerTests extends WindowTestsBase { @Test public void testWallpaperZoom_shouldNotScaleWallpaper() throws RemoteException { final DisplayContent dc = mWm.mRoot.getDefaultDisplay(); - final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, - mock(IBinder.class), true, dc, true /* ownerCanManageAppTokens */); - final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken, - "wallpaperWindow"); + final WindowState wallpaperWindow = createWallpaperWindow(dc); wallpaperWindow.getAttrs().privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS; @@ -219,11 +208,7 @@ public class WallpaperControllerTests extends WindowTestsBase { @Test public void testWallpaperZoom_multipleCallers() { final DisplayContent dc = mWm.mRoot.getDefaultDisplay(); - final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, - mock(IBinder.class), true, dc, - true /* ownerCanManageAppTokens */); - final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken, - "wallpaperWindow"); + final WindowState wallpaperWindow = createWallpaperWindow(dc); wallpaperWindow.getAttrs().privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS; @@ -278,37 +263,51 @@ public class WallpaperControllerTests extends WindowTestsBase { assertEquals(WINDOWING_MODE_FULLSCREEN, token.getWindowingMode()); } - @UseTestDisplay(addWindows = W_ACTIVITY) @Test public void testFixedRotationRecentsAnimatingTask() { + final WindowState wallpaperWindow = createWallpaperWindow(mDisplayContent); + final WallpaperWindowToken wallpaperToken = wallpaperWindow.mToken.asWallpaperToken(); + final WindowState appWin = createWindow(null, TYPE_BASE_APPLICATION, "app"); + makeWindowVisible(appWin); + final ActivityRecord r = appWin.mActivityRecord; final RecentsAnimationController recentsController = mock(RecentsAnimationController.class); - doReturn(true).when(recentsController).isWallpaperVisible(eq(mAppWindow)); + doReturn(true).when(recentsController).isWallpaperVisible(eq(appWin)); mWm.setRecentsAnimationController(recentsController); - mAppWindow.mActivityRecord.applyFixedRotationTransform(mDisplayContent.getDisplayInfo(), + r.applyFixedRotationTransform(mDisplayContent.getDisplayInfo(), mDisplayContent.mDisplayFrames, mDisplayContent.getConfiguration()); - mAppWindow.mActivityRecord.mVisibleRequested = true; - mDisplayContent.mWallpaperController.adjustWallpaperWindows(); - - assertEquals(mAppWindow, mDisplayContent.mWallpaperController.getWallpaperTarget()); - // Wallpaper should link the transform of its target. - assertTrue(mAppWindow.mActivityRecord.hasFixedRotationTransform()); - - mAppWindow.mActivityRecord.finishFixedRotationTransform(); // Invisible requested activity should not share its rotation transform. - mAppWindow.mActivityRecord.mVisibleRequested = false; + r.mVisibleRequested = false; mDisplayContent.mWallpaperController.adjustWallpaperWindows(); + assertFalse(wallpaperToken.hasFixedRotationTransform()); - assertFalse(mAppWindow.mActivityRecord.hasFixedRotationTransform()); + // Wallpaper should link the transform of its target. + r.mVisibleRequested = true; + mDisplayContent.mWallpaperController.adjustWallpaperWindows(); + assertEquals(appWin, mDisplayContent.mWallpaperController.getWallpaperTarget()); + assertTrue(r.hasFixedRotationTransform()); + assertTrue(wallpaperToken.hasFixedRotationTransform()); + + // The case with shell transition. + registerTestTransitionPlayer(); + final Transition t = r.mTransitionController.createTransition(TRANSIT_OPEN); + final ActivityRecord recents = mock(ActivityRecord.class); + t.collect(r.getTask()); + r.mTransitionController.setTransientLaunch(recents, r.getTask()); + // The activity in restore-below task should not be the target if keyguard is not locked. + mDisplayContent.mWallpaperController.adjustWallpaperWindows(); + assertNotEquals(appWin, mDisplayContent.mWallpaperController.getWallpaperTarget()); + // The activity in restore-below task should be the target if keyguard is occluded. + doReturn(true).when(mDisplayContent).isKeyguardLocked(); + mDisplayContent.mWallpaperController.adjustWallpaperWindows(); + assertEquals(appWin, mDisplayContent.mWallpaperController.getWallpaperTarget()); } @Test public void testWallpaperTokenVisibility() { final DisplayContent dc = mWm.mRoot.getDefaultDisplay(); - final WallpaperWindowToken token = new WallpaperWindowToken(mWm, mock(IBinder.class), - true, dc, true /* ownerCanManageAppTokens */); - final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, token, - "wallpaperWindow"); + final WindowState wallpaperWindow = createWallpaperWindow(dc); + final WallpaperWindowToken token = wallpaperWindow.mToken.asWallpaperToken(); wallpaperWindow.setHasSurface(true); // Set-up mock shell transitions @@ -350,6 +349,13 @@ public class WallpaperControllerTests extends WindowTestsBase { assertTrue(token.isVisible()); } + private WindowState createWallpaperWindow(DisplayContent dc) { + final WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class), + true /* explicit */, dc, true /* ownerCanManageAppTokens */); + return createWindow(null /* parent */, TYPE_WALLPAPER, wallpaperWindowToken, + "wallpaperWindow"); + } + private WindowState createWallpaperTargetWindow(DisplayContent dc) { final ActivityRecord homeActivity = new ActivityBuilder(mWm.mAtmService) .setTask(dc.getDefaultTaskDisplayArea().getRootHomeTask())