diff options
2 files changed, 66 insertions, 26 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index e4db7b636ed9..0beda678e79a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -95,6 +95,7 @@ import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; @@ -1273,42 +1274,42 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } // Copy initial changes to final transition final TransitionInfo init = mOpenTransitionInfo; - // find prepare open target + // Find prepare open target boolean openShowWallpaper = false; - ComponentName openComponent = null; + final ArrayList<OpenChangeInfo> targets = new ArrayList<>(); int tmpSize; - int openTaskId = INVALID_TASK_ID; - WindowContainerToken openToken = null; for (int j = init.getChanges().size() - 1; j >= 0; --j) { final TransitionInfo.Change change = init.getChanges().get(j); - if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { - openComponent = findComponentName(change); - openTaskId = findTaskId(change); - openToken = findToken(change); + if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED) + && TransitionUtil.isOpeningMode(change.getMode())) { + final ComponentName openComponent = findComponentName(change); + final int openTaskId = findTaskId(change); + final WindowContainerToken openToken = findToken(change); + if (openComponent == null && openTaskId == INVALID_TASK_ID + && openToken == null) { + continue; + } + targets.add(new OpenChangeInfo(openComponent, openTaskId, openToken)); if (change.hasFlags(FLAG_SHOW_WALLPAPER)) { openShowWallpaper = true; } - break; } } - if (openComponent == null && openTaskId == INVALID_TASK_ID && openToken == null) { + if (targets.isEmpty()) { // This shouldn't happen, but if that happen, consume the initial transition anyway. Log.e(TAG, "Unable to merge following transition, cannot find the gesture " + "animated target from the open transition=" + mOpenTransitionInfo); mOpenTransitionInfo = null; return; } - // find first non-prepare open target + // Find first non-prepare open target boolean isOpen = false; tmpSize = info.getChanges().size(); for (int j = 0; j < tmpSize; ++j) { final TransitionInfo.Change change = info.getChanges().get(j); - final ComponentName firstNonOpen = findComponentName(change); - final int firstTaskId = findTaskId(change); - if ((firstNonOpen != null && firstNonOpen != openComponent) - || (firstTaskId != INVALID_TASK_ID && firstTaskId != openTaskId)) { - // this is original close target, potential be close, but cannot determine from - // it + if (isOpenChangeMatched(targets, change)) { + // This is original close target, potential be close, but cannot determine + // from it. if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { isOpen = !TransitionUtil.isClosingMode(change.getMode()); } else { @@ -1317,33 +1318,44 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } - if (!isOpen) { // Close transition, the transition info should be: // init info(open A & wallpaper) // current info(close B target) // remove init info(open/change A target & wallpaper) boolean moveToTop = false; + boolean excludeOpenTarget = false; + boolean mergePredictive = false; for (int j = info.getChanges().size() - 1; j >= 0; --j) { final TransitionInfo.Change change = info.getChanges().get(j); - if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) { + if (isOpenChangeMatched(targets, change)) { + if (TransitionUtil.isClosingMode(change.getMode())) { + excludeOpenTarget = true; + } moveToTop = change.hasFlags(FLAG_MOVED_TO_TOP); info.getChanges().remove(j); } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER)) || !change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { info.getChanges().remove(j); + } else if (!mergePredictive && TransitionUtil.isClosingMode(change.getMode())) { + mergePredictive = true; } } // Ignore merge if there is no close target - if (!info.getChanges().isEmpty()) { + if (!info.getChanges().isEmpty() && mergePredictive) { tmpSize = init.getChanges().size(); for (int i = 0; i < tmpSize; ++i) { final TransitionInfo.Change change = init.getChanges().get(i); if (change.hasFlags(FLAG_IS_WALLPAPER)) { continue; } - if (moveToTop) { - if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) { + if (isOpenChangeMatched(targets, change)) { + if (excludeOpenTarget) { + // App has triggered another change during predictive back + // transition, filter out predictive back target. + continue; + } + if (moveToTop) { change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP); } } @@ -1372,7 +1384,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont if (nonBackClose && nonBackOpen) { for (int j = info.getChanges().size() - 1; j >= 0; --j) { final TransitionInfo.Change change = info.getChanges().get(j); - if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) { + if (isOpenChangeMatched(targets, change)) { info.getChanges().remove(j); } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER))) { info.getChanges().remove(j); @@ -1655,9 +1667,21 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont final ComponentName openChange = findComponentName(change); final int firstTaskId = findTaskId(change); final WindowContainerToken openToken = findToken(change); - return (openChange != null && openChange == topActivity) + return (openChange != null && openChange.equals(topActivity)) || (firstTaskId != INVALID_TASK_ID && firstTaskId == taskId) - || (openToken != null && token == openToken); + || (openToken != null && openToken.equals(token)); + } + + static boolean isOpenChangeMatched(@NonNull ArrayList<OpenChangeInfo> targets, + TransitionInfo.Change change) { + for (int i = targets.size() - 1; i >= 0; --i) { + final OpenChangeInfo next = targets.get(i); + if (isSameChangeTarget(next.mOpenComponent, next.mOpenTaskId, next.mOpenToken, + change)) { + return true; + } + } + return false; } private static boolean canBeTransitionTarget(TransitionInfo.Change change) { @@ -1717,4 +1741,16 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } } + + static class OpenChangeInfo { + final ComponentName mOpenComponent; + final int mOpenTaskId; + final WindowContainerToken mOpenToken; + OpenChangeInfo(ComponentName openComponent, int openTaskId, + WindowContainerToken openToken) { + mOpenComponent = openComponent; + mOpenTaskId = openTaskId; + mOpenToken = openToken; + } + } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java index dee0b23a42f5..f99e96109f88 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java @@ -51,6 +51,7 @@ import android.content.pm.ApplicationInfo; import android.graphics.Point; import android.graphics.Rect; import android.hardware.input.InputManager; +import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -804,7 +805,10 @@ public class BackAnimationControllerTest extends ShellTestCase { if (taskId != INVALID_TASK_ID) { final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = taskId; - taskInfo.token = new WindowContainerToken(mock(IWindowContainerToken.class)); + final IWindowContainerToken mockT = mock(IWindowContainerToken.class); + Binder binder = new Binder(); + doReturn(binder).when(mockT).asBinder(); + taskInfo.token = new WindowContainerToken(mockT); change = new TransitionInfo.Change( taskInfo.token, b.build()); change.setTaskInfo(taskInfo); |