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

Commit 6db8fb27 authored by Ben Lin's avatar Ben Lin
Browse files

Stop task reparenting when enter/exit PIP.

With only one activity in the PIP task, we can simply change the
windowing mode (this was already done implicitly when re-parenting) and
let the display know the existing stack is the new pinned stack as
opposed to creating a new stack just to move the task over.

With multiple activities, we will remain moving the PIP activity into a
separate stack, but we will move it to a stack with the same windowing
mode as the original rather than a pinned one. Then, we will do a
windowing mode change on it also, so it performs the same as the single
activity case.

When exiting, we then simply do a windowing mode change.

Bug: 143772438
Test: Try PIP with one activity (e.g. Youtube) and multiple activities
(VLC), enter/exits works fine. atest PinnedStackTests
Change-Id: Ie961e120762e5e244f14b6ac181509656b107969
parent a7aeb79b
Loading
Loading
Loading
Loading
+30 −9
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService;
@@ -795,14 +796,6 @@ class ActivityStack extends ConfigurationContainer {
                return;
            }

            if (windowingMode == WINDOWING_MODE_PINNED || currentMode == WINDOWING_MODE_PINNED) {
                // TODO: Need to remove use of PinnedActivityStack for this to be supported.
                // NOTE: Need to ASS.scheduleUpdatePictureInPictureModeIfNeeded() in
                // setWindowModeUnchecked() when this support is added. See TaskRecord.reparent()
                throw new IllegalArgumentException(
                        "Changing pinned windowing mode not currently supported");
            }

            if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && splitScreenStack != null) {
                // We already have a split-screen stack in this display, so just move the tasks over.
                // TODO: Figure-out how to do all the stuff in
@@ -4957,7 +4950,7 @@ class ActivityStack extends ConfigurationContainer {
                // The final orientation of this activity will change after moving to full screen.
                // Start freezing screen here to prevent showing a temporary full screen window.
                top.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
                mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
                dismissPip();
                return;
            }
        }
@@ -4966,6 +4959,34 @@ class ActivityStack extends ConfigurationContainer {
                animationDuration, fromFullscreen);
    }

    void dismissPip() {
        if (!isActivityTypeStandardOrUndefined()) {
            throw new IllegalArgumentException(
                    "You can't move tasks from non-standard stacks.");
        }
        if (getWindowingMode() != WINDOWING_MODE_PINNED) {
            throw new IllegalArgumentException(
                    "Can't exit pinned mode if it's not pinned already.");
        }

        final ArrayList<TaskRecord> tasks = getAllTasks();

        if (tasks.size() != 1) {
            throw new RuntimeException("There should be only one task in a pinned stack.");
        }

        mWindowManager.inSurfaceTransaction(() -> {
            final TaskRecord task = tasks.get(0);
            setWindowingMode(WINDOWING_MODE_UNDEFINED);

            getDisplay().positionChildAtTop(this, false /* includingParents */);

            mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, this);
            MetricsLoggerWrapper.logPictureInPictureFullScreen(mService.mContext,
                    task.effectiveUid, task.realActivity.flattenToString());
        });
    }

    /**
     * Get current bounds of this stack, return empty when it is unavailable.
     * @see TaskStack#getAnimationOrCurrentBounds(Rect)
+2 −2
Original line number Diff line number Diff line
@@ -1499,7 +1499,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
        mService.deferWindowLayout();
        try {
            final int windowingMode = fromStack.getWindowingMode();
            final boolean inPinnedWindowingMode = windowingMode == WINDOWING_MODE_PINNED;
            final ActivityDisplay toDisplay =
                    mRootActivityContainer.getActivityDisplay(toDisplayId);

@@ -1526,7 +1525,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {

            // If we are moving from the pinned stack, then the animation takes care of updating
            // the picture-in-picture mode.
            final boolean schedulePictureInPictureModeChange = inPinnedWindowingMode;
            final boolean schedulePictureInPictureModeChange =
                    windowingMode == WINDOWING_MODE_PINNED;
            final ArrayList<TaskRecord> tasks = fromStack.getAllTasks();

            if (!tasks.isEmpty()) {
+1 −6
Original line number Diff line number Diff line
@@ -4010,7 +4010,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                    stack.animateResizePinnedStack(null /* sourceHintBounds */,
                            null /* destBounds */, animationDuration, false /* fromFullscreen */);
                } else {
                    mStackSupervisor.moveTasksToFullscreenStackLocked(stack, true /* onTop */);
                    stack.dismissPip();
                }
            }
        } finally {
@@ -4026,11 +4026,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        }
    }

    /**
     * NOTE: For the pinned stack, this method is usually called after the bounds animation has
     *       animated the stack to the fullscreen, but can also be called if we are relaunching an
     *       activity and clearing the task at the same time.
     */
    @Override
    // TODO: API should just be about changing windowing modes...
    public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
+20 −20
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
@@ -964,30 +963,29 @@ class RootActivityContainer extends ConfigurationContainer
        mService.deferWindowLayout();

        final ActivityDisplay display = r.getActivityStack().getDisplay();
        ActivityStack stack = display.getPinnedStack();

        // This will clear the pinned stack by moving an existing task to the full screen stack,
        // ensuring only one task is present.
        if (stack != null) {
            mStackSupervisor.moveTasksToFullscreenStackLocked(stack, !ON_TOP);
        }

        // Need to make sure the pinned stack exist so we can resize it below...
        stack = display.getOrCreateStack(WINDOWING_MODE_PINNED, r.getActivityType(), ON_TOP);

        try {
            final TaskRecord task = r.getTaskRecord();
            // Resize the pinned stack to match the current size of the task the activity we are
            // going to be moving is currently contained in. We do this to have the right starting
            // animation bounds for the pinned stack to the desired bounds the caller wants.
            stack.resize(task.getRequestedOverrideBounds(), null /* tempTaskBounds */,
                    null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS, !DEFER_RESUME);

            if (task.getChildCount() == 1) {
                // Defer resume until below, and do not schedule PiP changes until we animate below
                task.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE, DEFER_RESUME,
                        false /* schedulePictureInPictureModeChange */, reason);
            final ActivityStack pinnedStack = display.getPinnedStack();
            // This will change the pinned stack's windowing mode to its original mode, ensuring
            // we only have one stack that is in pinned mode.
            if (pinnedStack != null) {
                pinnedStack.dismissPip();
            }

            final boolean singleActivity = task.getChildCount() == 1;

            final ActivityStack stack;
            if (singleActivity) {
                stack = r.getActivityStack();
            } else {
                // In the case of multiple activities, we will create a new stack for it and then
                // move the PIP activity into the stack.
                // We will then perform a windowing mode change for both scenarios.
                stack = display.createStack(
                        r.getActivityStack().getRequestedOverrideWindowingMode(),
                        r.getActivityType(), ON_TOP);
                // There are multiple activities in the task and moving the top activity should
                // reveal/leave the other activities in their original task.

@@ -1006,6 +1004,8 @@ class RootActivityContainer extends ConfigurationContainer
                        DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
            }

            stack.setWindowingMode(WINDOWING_MODE_PINNED);

            // Reset the state that indicates it can enter PiP while pausing after we've moved it
            // to the pinned stack
            r.supportsEnterPipOnTaskSwitch = false;
+1 −1
Original line number Diff line number Diff line
@@ -1585,7 +1585,7 @@ public class TaskStack extends WindowContainer<Task> implements

            mActivityStack.mService.notifyPinnedStackAnimationEnded();
            if (moveToFullscreen) {
                mActivityStack.mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
                mActivityStack.dismissPip();
            }
        } else {
            // No PiP animation, just run the normal animation-end logic
Loading