diff options
author | 2024-10-23 15:46:07 +0800 | |
---|---|---|
committer | 2024-10-24 09:20:32 +0000 | |
commit | bbeaa71bb64ebe36ebcf86acb34ff99051295e40 (patch) | |
tree | 96f25171ce6fbebe090c3e2e313517ad48a23bd4 | |
parent | faec1367aae5f649063ebfb092db45ae3bc8082b (diff) |
[PB] Filter out activity transition under TaskFragment
...from predictive back transition.
1. The opening target in predict_back transition could be multiple
because of activity embedded adjacent.
2. To be more accurate to filter out none participant predictive back
transition targets, checking the opening type, and prevent the
predictive target involved into app transition.
Flag: EXEMPT bugfix
Bug: 375111994
Test: atest BackAnimationControllerTest
Test: Back to activity adjacent, and verify the transition when both
commit and cancel gesture can work as expect.
Test: tap on the edge of Settings multiple times, verify the activity
embedded changes can be filter out from back transition handler, and
corresponding handler can play with the transition.
Change-Id: I1f527770eaa8b542215a6d679c86f9873f659993
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); |