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
This commit is contained in:
Riddle Hsu
2022-05-31 00:03:03 +08:00
parent 1854ffeaff
commit da3433f0d9
2 changed files with 64 additions and 46 deletions

View File

@@ -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()
*/

View File

@@ -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())