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

Commit e2f35542 authored by Hongwei Wang's avatar Hongwei Wang
Browse files

Get PictureInPictureParams from top activity

Task#getPictureInPictureParams used to get the params from root activity
and it is okay doing so without autoEnterPip since the activity to be
pinned will be put in a task with one and only one activity.

With autoEnterPip, it it possible that the root activity has no
PictureInPictureParams being attached when the transition starts in
Launcher side, switch to use the PictureInPictureParams tied to the top
visible activity here.

Fixes also
- when this happens, we need to reset the window crop leash on the
  original task in FullscreenTaskListener#onTaskInfoChanged
- ensure the reparented task inherits the current bounds
- ensure we do not hide the leash in Task#setHasBeenVisible by setting
  mHasBeenVisible=true on the newly created task

Video: http://rcll/aaaaaabFQoRHlzixHdtY/gIO4G5dybW7tJWXihkhXfE
Bug: 177335910
Test: see video
Change-Id: I198443b93b7d8cc11108f0d0606f98eac58c07b7
parent 7b956dd6
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -74,7 +74,13 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
        if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
        final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
        final Point positionInParent = taskInfo.positionInParent;
        mSyncQueue.runInSync(t -> t.setPosition(leash, positionInParent.x, positionInParent.y));
        mSyncQueue.runInSync(t -> {
            // Reset several properties back. For instance, when an Activity enters PiP with
            // multiple activities in the same task, a new task will be created from that Activity
            // and we want reset the leash of the original task.
            t.setPosition(leash, positionInParent.x, positionInParent.y);
            t.setWindowCrop(leash, null);
        });
    }

    @Override
+2 −1
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.window.TaskSnapshot;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
@@ -54,6 +53,7 @@ import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets.Type;
import android.window.TaskSnapshot;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.SoftInputShowHideReason;
@@ -1014,6 +1014,7 @@ public class RecentsAnimationController implements DeathRecipient {
                        .setPosition(taskSurface, mFinishBounds.left, mFinishBounds.top)
                        .setWindowCrop(taskSurface, mFinishBounds.width(), mFinishBounds.height())
                        .apply();
                mTask.mLastRecentsAnimationBounds.set(mFinishBounds);
                mFinishBounds.setEmpty();
            } else if (!mTask.isAttached()) {
                // Apply the task's pending transaction in case it is detached and its transaction
+12 −25
Original line number Diff line number Diff line
@@ -2104,30 +2104,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                onTop);
    }

    boolean moveTopRootTaskActivityToPinnedRootTask(int rootTaskId) {
        final Task rootTask = getRootTask(rootTaskId);
        if (rootTask == null) {
            throw new IllegalArgumentException(
                    "moveTopStackActivityToPinnedRootTask: Unknown rootTaskId=" + rootTaskId);
        }

        final ActivityRecord r = rootTask.topRunningActivity();
        if (r == null) {
            Slog.w(TAG, "moveTopStackActivityToPinnedRootTask: No top running activity"
                    + " in rootTask=" + rootTask);
            return false;
        }

        if (!mService.mForceResizableActivities && !r.supportsPictureInPicture()) {
            Slog.w(TAG, "moveTopStackActivityToPinnedRootTask: Picture-In-Picture not supported "
                    + "for r=" + r);
            return false;
        }

        moveActivityToPinnedRootTask(r, "moveTopStackActivityToPinnedRootTask");
        return true;
    }

    void moveActivityToPinnedRootTask(ActivityRecord r, String reason) {
        mService.deferWindowLayout();

@@ -2153,13 +2129,16 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                rootTask = task;
            } else {
                // In the case of multiple activities, we will create a new task for it and then
                // move the PIP activity into the task.
                // move the PIP activity into the task. Note that we explicitly defer the task
                // appear being sent in this case and mark this newly created task to been visible.
                rootTask = new Task.Builder(mService)
                        .setActivityType(r.getActivityType())
                        .setOnTop(true)
                        .setActivityInfo(r.info)
                        .setParent(taskDisplayArea)
                        .setIntent(r.intent)
                        .setDeferTaskAppear(true)
                        .setHasBeenVisible(true)
                        .build();
                // It's possible the task entering PIP is in freeform, so save the last
                // non-fullscreen bounds. Then when this new PIP task exits PIP, it can restore
@@ -2167,12 +2146,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                rootTask.setLastNonFullscreenBounds(task.mLastNonFullscreenBounds);
                rootTask.setBounds(task.getBounds());

                // Move reparent bounds from original task to the new one.
                rootTask.mLastRecentsAnimationBounds.set(task.mLastRecentsAnimationBounds);
                task.mLastRecentsAnimationBounds.setEmpty();

                // There are multiple activities in the task and moving the top activity should
                // reveal/leave the other activities in their original task.
                // On the other hand, ActivityRecord#onParentChanged takes care of setting the
                // up-to-dated pinned stack information on this newly created stack.
                r.reparent(rootTask, MAX_VALUE, reason);

                // Ensure the leash of new task is in sync with its current bounds after reparent.
                rootTask.maybeApplyLastRecentsAnimationBounds();

                // In the case of this activity entering PIP due to it being moved to the back,
                // the old activity would have a TRANSIT_TASK_TO_BACK transition that needs to be
                // ran. But, since its visibility did not change (note how it was STOPPED/not
@@ -2201,6 +2187,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
            // TODO(task-org): Figure-out more structured way to do this long term.
            r.setWindowingMode(intermediateWindowingMode);
            rootTask.setWindowingMode(WINDOWING_MODE_PINNED);
            rootTask.setDeferTaskAppear(false);

            // Reset the state that indicates it can enter PiP while pausing after we've moved it
            // to the pinned stack
+31 −4
Original line number Diff line number Diff line
@@ -457,6 +457,15 @@ class Task extends WindowContainer<WindowContainer> {
    int mMinWidth;
    int mMinHeight;

    // The bounds of the target when recents animation is finished.
    // This is originally introduced to carry out the current surface control position and window
    // crop when a multi-activity task enters pip with autoEnterPip enabled. In such case,
    // the surface control of the task will be animated in Launcher and then the top activity is
    // reparented to pinned root task.
    // Do not forget to reset this to null after reparenting.
    // TODO: remove this once the recents animation is moved to the Shell
    final Rect mLastRecentsAnimationBounds = new Rect();

    static final int LAYER_RANK_INVISIBLE = -1;
    // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
    // This number will be assigned when we evaluate OOM scores for all visible tasks.
@@ -4128,9 +4137,9 @@ class Task extends WindowContainer<WindowContainer> {

    private @Nullable PictureInPictureParams getPictureInPictureParams(Task top) {
        if (top == null) return null;
        final ActivityRecord rootActivity = top.getRootActivity();
        return (rootActivity == null || rootActivity.pictureInPictureArgs.empty())
                ? null : new PictureInPictureParams(rootActivity.pictureInPictureArgs);
        final ActivityRecord topVisibleActivity = top.getTopVisibleActivity();
        return (topVisibleActivity == null || topVisibleActivity.pictureInPictureArgs.empty())
                ? null : new PictureInPictureParams(topVisibleActivity.pictureInPictureArgs);
    }

    /**
@@ -4930,7 +4939,7 @@ class Task extends WindowContainer<WindowContainer> {
                commitPendingTransaction();
            }

            sendTaskAppeared();
            if (!mDeferTaskAppear) sendTaskAppeared();
            if (!isRootTask()) {
                getRootTask().setHasBeenVisible(true);
            }
@@ -7541,6 +7550,17 @@ class Task extends WindowContainer<WindowContainer> {
        reparent(newParent, onTop ? POSITION_TOP : POSITION_BOTTOM);
    }

    void maybeApplyLastRecentsAnimationBounds() {
        if (!mLastRecentsAnimationBounds.isEmpty()) {
            getPendingTransaction()
                    .setPosition(mSurfaceControl, mLastRecentsAnimationBounds.left,
                            mLastRecentsAnimationBounds.top)
                    .setWindowCrop(mSurfaceControl, mLastRecentsAnimationBounds.width(),
                            mLastRecentsAnimationBounds.height());
            mLastRecentsAnimationBounds.setEmpty();
        }
    }

    private void updateSurfaceBounds() {
        updateSurfaceSize(getSyncTransaction());
        updateSurfacePositionNonOrganized();
@@ -7775,6 +7795,7 @@ class Task extends WindowContainer<WindowContainer> {
        private boolean mDeferTaskAppear;
        private IBinder mLaunchCookie;
        private boolean mOnTop;
        private boolean mHasBeenVisible;

        Builder(ActivityTaskManagerService atm) {
            mAtmService = atm;
@@ -7867,6 +7888,11 @@ class Task extends WindowContainer<WindowContainer> {
            return this;
        }

        Builder setHasBeenVisible(boolean hasBeenVisible) {
            mHasBeenVisible = hasBeenVisible;
            return this;
        }

        private Builder setUserId(int userId) {
            mUserId = userId;
            return this;
@@ -8060,6 +8086,7 @@ class Task extends WindowContainer<WindowContainer> {
            }

            final Task task = buildInner();
            task.mHasBeenVisible = mHasBeenVisible;

            // Set activity type before adding the root task to TaskDisplayArea, so home task can
            // be cached, see TaskDisplayArea#addRootTaskReferenceIfNeeded().