Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 584c7686 authored by wilsonshih's avatar wilsonshih
Browse files

[PB] Only handle one merge transition request.

App can request another transition after the first close transition,
e.g. the second stage transition for continues close activity. Ignore
the following transition to ask other handlers.

Flag: com.android.window.flags.migrate_predictive_back_transition
Bug: 361726487
Test: create a three level+ activities. When finish the top activity,
also finish the second activity to trigger a separate close transition.
Verify the second stage close transition be played with default
transition handler so no jumpcut occur.

Change-Id: I336f2ee302c04b369ca42a804c5ea0ad48eda640
parent 3f98e2b4
Loading
Loading
Loading
Loading
+24 −8
Original line number Original line Diff line number Diff line
@@ -74,6 +74,7 @@ import android.window.IBackAnimationRunner;
import android.window.IOnBackInvokedCallback;
import android.window.IOnBackInvokedCallback;
import android.window.TransitionInfo;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
import android.window.TransitionRequestInfo;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransaction;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
@@ -1272,19 +1273,24 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
            ComponentName openComponent = null;
            ComponentName openComponent = null;
            int tmpSize;
            int tmpSize;
            int openTaskId = INVALID_TASK_ID;
            int openTaskId = INVALID_TASK_ID;
            WindowContainerToken openToken = null;
            for (int j = init.getChanges().size() - 1; j >= 0; --j) {
            for (int j = init.getChanges().size() - 1; j >= 0; --j) {
                final TransitionInfo.Change change = init.getChanges().get(j);
                final TransitionInfo.Change change = init.getChanges().get(j);
                if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) {
                if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) {
                    openComponent = findComponentName(change);
                    openComponent = findComponentName(change);
                    openTaskId = findTaskId(change);
                    openTaskId = findTaskId(change);
                    openToken = findToken(change);
                    if (change.hasFlags(FLAG_SHOW_WALLPAPER)) {
                    if (change.hasFlags(FLAG_SHOW_WALLPAPER)) {
                        openShowWallpaper = true;
                        openShowWallpaper = true;
                    }
                    }
                    break;
                    break;
                }
                }
            }
            }
            if (openComponent == null && openTaskId == INVALID_TASK_ID) {
            if (openComponent == null && openTaskId == INVALID_TASK_ID && openToken == null) {
                // shouldn't happen.
                // 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;
                return;
            }
            }
            // find first non-prepare open target
            // find first non-prepare open target
@@ -1315,7 +1321,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                boolean moveToTop = false;
                boolean moveToTop = false;
                for (int j = info.getChanges().size() - 1; j >= 0; --j) {
                for (int j = info.getChanges().size() - 1; j >= 0; --j) {
                    final TransitionInfo.Change change = info.getChanges().get(j);
                    final TransitionInfo.Change change = info.getChanges().get(j);
                    if (isSameChangeTarget(openComponent, openTaskId, change)) {
                    if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) {
                        moveToTop = change.hasFlags(FLAG_MOVED_TO_TOP);
                        moveToTop = change.hasFlags(FLAG_MOVED_TO_TOP);
                        info.getChanges().remove(j);
                        info.getChanges().remove(j);
                    } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER))
                    } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER))
@@ -1329,7 +1335,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                    for (int i = 0; i < tmpSize; ++i) {
                    for (int i = 0; i < tmpSize; ++i) {
                        final TransitionInfo.Change change = init.getChanges().get(i);
                        final TransitionInfo.Change change = init.getChanges().get(i);
                        if (moveToTop) {
                        if (moveToTop) {
                            if (isSameChangeTarget(openComponent, openTaskId, change)) {
                            if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) {
                                change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP);
                                change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP);
                            }
                            }
                        }
                        }
@@ -1358,7 +1364,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                if (nonBackClose && nonBackOpen) {
                if (nonBackClose && nonBackOpen) {
                    for (int j = info.getChanges().size() - 1; j >= 0; --j) {
                    for (int j = info.getChanges().size() - 1; j >= 0; --j) {
                        final TransitionInfo.Change change = info.getChanges().get(j);
                        final TransitionInfo.Change change = info.getChanges().get(j);
                        if (isSameChangeTarget(openComponent, openTaskId, change)) {
                        if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) {
                            info.getChanges().remove(j);
                            info.getChanges().remove(j);
                        } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER))) {
                        } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER))) {
                            info.getChanges().remove(j);
                            info.getChanges().remove(j);
@@ -1368,6 +1374,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
            }
            }
            ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation transition, merge pending "
            ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation transition, merge pending "
                    + "transitions result=%s", info);
                    + "transitions result=%s", info);
            // Only handle one merge transition request.
            mOpenTransitionInfo = null;
        }
        }


        @Override
        @Override
@@ -1378,7 +1386,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                mClosePrepareTransition = null;
                mClosePrepareTransition = null;
            }
            }
            // try to handle unexpected transition
            // try to handle unexpected transition
            if (mOpenTransitionInfo != null) {
                mergePendingTransitions(info);
                mergePendingTransitions(info);
            }


            if (isNotGestureBackTransition(info) || shouldCancelAnimation(info)
            if (isNotGestureBackTransition(info) || shouldCancelAnimation(info)
                    || !mCloseTransitionRequested) {
                    || !mCloseTransitionRequested) {
@@ -1628,6 +1638,10 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
        return false;
        return false;
    }
    }


    private static WindowContainerToken findToken(TransitionInfo.Change change) {
        return change.getContainer();
    }

    private static ComponentName findComponentName(TransitionInfo.Change change) {
    private static ComponentName findComponentName(TransitionInfo.Change change) {
        final ComponentName componentName = change.getActivityComponent();
        final ComponentName componentName = change.getActivityComponent();
        if (componentName != null) {
        if (componentName != null) {
@@ -1649,11 +1663,13 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
    }
    }


    private static boolean isSameChangeTarget(ComponentName topActivity, int taskId,
    private static boolean isSameChangeTarget(ComponentName topActivity, int taskId,
            TransitionInfo.Change change) {
            WindowContainerToken token, TransitionInfo.Change change) {
        final ComponentName openChange = findComponentName(change);
        final ComponentName openChange = findComponentName(change);
        final int firstTaskId = findTaskId(change);
        final int firstTaskId = findTaskId(change);
        final WindowContainerToken openToken = findToken(change);
        return (openChange != null && openChange == topActivity)
        return (openChange != null && openChange == topActivity)
                || (firstTaskId != INVALID_TASK_ID && firstTaskId == taskId);
                || (firstTaskId != INVALID_TASK_ID && firstTaskId == taskId)
                || (openToken != null && token == openToken);
    }
    }


    private static boolean canBeTransitionTarget(TransitionInfo.Change change) {
    private static boolean canBeTransitionTarget(TransitionInfo.Change change) {
+1 −0
Original line number Original line Diff line number Diff line
@@ -882,6 +882,7 @@ class BackNavigationController {
        } else {
        } else {
            if (mAnimationHandler.mPrepareCloseTransition != null) {
            if (mAnimationHandler.mPrepareCloseTransition != null) {
                Slog.e(TAG, "Gesture animation is applied on another transition?");
                Slog.e(TAG, "Gesture animation is applied on another transition?");
                return;
            }
            }
            mAnimationHandler.mPrepareCloseTransition = transition;
            mAnimationHandler.mPrepareCloseTransition = transition;
            if (!migratePredictToTransition) {
            if (!migratePredictToTransition) {