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

Commit 4f7be5bd authored by Evan Rosky's avatar Evan Rosky
Browse files

Fix PiP transition ordering

First, this cancels the existing pip animation if it is
told to exit. Without this, an exit animation that
starts before an enter animation finishes will have its
state clobbered by the exit's finishTransition call.

Next, make pip-enter transitions queue-up so that they
don't interleave before other queued transitions (very
common during CTS).

Bug: 231150615
Test: atest PinnedStackTests
Change-Id: I7f162c0b1f24ab845770b805c8fae2252814945e
parent ded5484e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -3061,6 +3061,12 @@
      "group": "WM_DEBUG_STATES",
      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
    },
    "898260097": {
      "message": "Creating Pending Pip-Enter: %s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
    },
    "898863925": {
      "message": "Attempted to add QS dialog window with unknown token %s.  Aborting.",
      "level": "WARN",
+5 −0
Original line number Diff line number Diff line
@@ -145,6 +145,11 @@ public class PipTransition extends PipTransitionController {
        if (destinationBounds != null) {
            mExitDestinationBounds.set(destinationBounds);
        }
        final PipAnimationController.PipTransitionAnimator animator =
                mPipAnimationController.getCurrentAnimator();
        if (animator != null && animator.isRunning()) {
            animator.cancel();
        }
        mExitTransition = mTransitions.startTransition(type, out, this);
    }

+2 −0
Original line number Diff line number Diff line
@@ -377,6 +377,7 @@ public class Transitions implements RemoteCallable<Transitions> {
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Invalid root leash (%s): %s",
                    transitionToken, info);
            t.apply();
            finishT.apply();
            onAbort(transitionToken);
            return;
        }
@@ -400,6 +401,7 @@ public class Transitions implements RemoteCallable<Transitions> {
            }
            if (nonTaskChange && transferStartingWindow) {
                t.apply();
                finishT.apply();
                // Treat this as an abort since we are bypassing any merge logic and effectively
                // finishing immediately.
                onAbort(transitionToken);
+37 −3
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ import static android.provider.Settings.System.FONT_SCALE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT;
import static android.view.WindowManager.TRANSIT_PIP;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
@@ -237,6 +238,7 @@ import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.TransferPipe;
import com.android.internal.policy.AttributeCache;
import com.android.internal.policy.KeyguardDismissCallback;
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
@@ -3463,6 +3465,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            return false;
        }

        // Create a transition for this pip entry. We guarantee that this gets its own transition
        // by queueing this transition on SyncEngine. This is shared by all the entry paths.
        final Transition transition = getTransitionController().isShellTransitionsEnabled()
                ? new Transition(TRANSIT_PIP, 0 /* flags */,
                        getTransitionController(), mWindowManager.mSyncEngine)
                : null;

        final Runnable enterPipRunnable = () -> {
            synchronized (mGlobalLock) {
                if (r.getParent() == null) {
@@ -3471,7 +3480,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                }
                r.setPictureInPictureParams(params);
                mRootWindowContainer.moveActivityToPinnedRootTask(r,
                        null /* launchIntoPipHostActivity */, "enterPictureInPictureMode");
                        null /* launchIntoPipHostActivity */, "enterPictureInPictureMode",
                        transition);
                final Task task = r.getTask();
                // Continue the pausing process after entering pip.
                if (task.getPausingActivity() == r) {
@@ -3488,13 +3498,37 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            mActivityClientController.dismissKeyguard(r.token, new KeyguardDismissCallback() {
                @Override
                public void onDismissSucceeded() {
                    if (mWindowManager.mSyncEngine.hasActiveSync()) {
                        ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                                "Creating Pending Pip-Enter: %s", transition);
                        mWindowManager.mSyncEngine.queueSyncSet(
                                () -> getTransitionController().moveToCollecting(transition),
                                enterPipRunnable);
                    } else {
                        // Move to collecting immediately to "claim" the sync-engine for this
                        // transition.
                        if (transition != null) {
                            getTransitionController().moveToCollecting(transition);
                        }
                        mH.post(enterPipRunnable);
                    }
                }
            }, null /* message */);
        } else {
            // Enter picture in picture immediately otherwise
            if (mWindowManager.mSyncEngine.hasActiveSync()) {
                ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                        "Creating Pending Pip-Enter: %s", transition);
                mWindowManager.mSyncEngine.queueSyncSet(
                        () -> getTransitionController().moveToCollecting(transition),
                        enterPipRunnable);
            } else {
                if (transition != null) {
                    getTransitionController().moveToCollecting(transition);
                }
                enterPipRunnable.run();
            }
        }
        return true;
    }

+9 −4
Original line number Diff line number Diff line
@@ -1977,16 +1977,21 @@ class RootWindowContainer extends WindowContainer<DisplayContent>

    void moveActivityToPinnedRootTask(@NonNull ActivityRecord r,
            @Nullable ActivityRecord launchIntoPipHostActivity, String reason) {
        moveActivityToPinnedRootTask(r, launchIntoPipHostActivity, reason, null /* transition */);
    }

    void moveActivityToPinnedRootTask(@NonNull ActivityRecord r,
            @Nullable ActivityRecord launchIntoPipHostActivity, String reason,
            @Nullable Transition transition) {
        final TaskDisplayArea taskDisplayArea = r.getDisplayArea();
        final Task task = r.getTask();
        final Task rootTask;

        Transition newTransition = null;
        // Create a transition now to collect the current pinned Task dismiss. Only do the
        // create here as the Task (trigger) to enter PIP is not ready yet.
        Transition newTransition = transition;
        // Create a transition now (if not provided) to collect the current pinned Task dismiss.
        // Only do the create here as the Task (trigger) to enter PIP is not ready yet.
        final TransitionController transitionController = task.mTransitionController;
        if (!transitionController.isCollecting()
        if (newTransition == null && !transitionController.isCollecting()
                && transitionController.getTransitionPlayer() != null) {
            newTransition = transitionController.createTransition(TRANSIT_PIP);
        }