diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java index d8a88770072d8..75659960bc32e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java @@ -27,6 +27,7 @@ import static android.view.WindowManager.TRANSIT_SLEEP; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.view.WindowManager.fixScale; +import static android.window.TransitionInfo.FLAG_IS_BEHIND_STARTING_WINDOW; import static android.window.TransitionInfo.FLAG_IS_OCCLUDED; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP; @@ -728,11 +729,15 @@ public class Transitions implements RemoteCallable, final int changeSize = info.getChanges().size(); boolean taskChange = false; boolean transferStartingWindow = false; + int noAnimationBehindStartingWindow = 0; boolean allOccluded = changeSize > 0; for (int i = changeSize - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); taskChange |= change.getTaskInfo() != null; transferStartingWindow |= change.hasFlags(FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT); + if (change.hasAllFlags(FLAG_IS_BEHIND_STARTING_WINDOW | FLAG_NO_ANIMATION)) { + noAnimationBehindStartingWindow++; + } if (!change.hasFlags(FLAG_IS_OCCLUDED)) { allOccluded = false; } @@ -740,9 +745,11 @@ public class Transitions implements RemoteCallable, // There does not need animation when: // A. Transfer starting window. Apply transfer starting window directly if there is no other // task change. Since this is an activity->activity situation, we can detect it by selecting - // transitions with only 2 changes where neither are tasks and one is a starting-window - // recipient. - if (!taskChange && transferStartingWindow && changeSize == 2 + // transitions with only 2 changes where + // 1. neither are tasks, and + // 2. one is a starting-window recipient, or all change is behind starting window. + if (!taskChange && (transferStartingWindow || noAnimationBehindStartingWindow == changeSize) + && changeSize == 2 // B. It's visibility change if the TRANSIT_TO_BACK/TO_FRONT happened when all // changes are underneath another change. || ((info.getType() == TRANSIT_TO_BACK || info.getType() == TRANSIT_TO_FRONT) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 788bfbcd65c95..0994fa4464db0 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4560,6 +4560,26 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } task.forAllActivities(fromActivity -> { if (fromActivity == this) return true; + // The snapshot starting window could remove itself when receive resized request without + // redraw, so transfer it to a different size activity could only cause flicker. + // By schedule remove snapshot starting window, the remove process will happen when + // transition ready, transition ready means the app window is drawn. + final StartingData tmpStartingData = fromActivity.mStartingData; + if (tmpStartingData != null && tmpStartingData.mAssociatedTask == null + && mTransitionController.isCollecting(fromActivity) + && tmpStartingData instanceof SnapshotStartingData) { + final Rect fromBounds = fromActivity.getBounds(); + final Rect myBounds = getBounds(); + if (!fromBounds.equals(myBounds)) { + // Mark as no animation, so these changes won't merge into playing transition. + if (mTransitionController.inPlayingTransition(fromActivity)) { + mTransitionController.setNoAnimation(this); + mTransitionController.setNoAnimation(fromActivity); + } + fromActivity.removeStartingWindow(); + return true; + } + } return !fromActivity.isVisibleRequested() && transferStartingWindow(fromActivity); }); }