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

Commit 0473179f authored by Hongwei Wang's avatar Hongwei Wang Committed by Automerger Merge Worker
Browse files

Merge "Dismiss PiP to split screen if applicable" into rvc-dev am: 283be9f7

Change-Id: Ia22beefc25d8ef6ca1685b167e25f2c4e90e0402
parents cab93722 283be9f7
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -53,16 +53,23 @@ public class PipAnimationController {
    public static final int TRANSITION_DIRECTION_SAME = 1;
    public static final int TRANSITION_DIRECTION_TO_PIP = 2;
    public static final int TRANSITION_DIRECTION_TO_FULLSCREEN = 3;
    public static final int TRANSITION_DIRECTION_TO_SPLIT_SCREEN = 4;

    @IntDef(prefix = { "TRANSITION_DIRECTION_" }, value = {
            TRANSITION_DIRECTION_NONE,
            TRANSITION_DIRECTION_SAME,
            TRANSITION_DIRECTION_TO_PIP,
            TRANSITION_DIRECTION_TO_FULLSCREEN
            TRANSITION_DIRECTION_TO_FULLSCREEN,
            TRANSITION_DIRECTION_TO_SPLIT_SCREEN
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TransitionDirection {}

    public static boolean isOutPipDirection(@TransitionDirection int direction) {
        return direction == TRANSITION_DIRECTION_TO_FULLSCREEN
                || direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
    }

    private final Interpolator mFastOutSlowInInterpolator;
    private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;

@@ -253,14 +260,13 @@ public class PipAnimationController {
        }

        boolean shouldApplyCornerRadius() {
            return mTransitionDirection != TRANSITION_DIRECTION_TO_FULLSCREEN;
            return !isOutPipDirection(mTransitionDirection);
        }

        boolean inScaleTransition() {
            if (mAnimationType != ANIM_TYPE_BOUNDS) return false;
            final int direction = getTransitionDirection();
            return direction != TRANSITION_DIRECTION_TO_FULLSCREEN
                    && direction != TRANSITION_DIRECTION_TO_PIP;
            return !isOutPipDirection(direction) && direction != TRANSITION_DIRECTION_TO_PIP;
        }

        /**
+41 −15
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.systemui.pip;

import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;

import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
@@ -25,6 +24,8 @@ import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTI
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_SAME;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
import static com.android.systemui.pip.PipAnimationController.isOutPipDirection;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -48,6 +49,7 @@ import android.window.WindowOrganizer;
import com.android.internal.os.SomeArgs;
import com.android.systemui.R;
import com.android.systemui.pip.phone.PipUpdateThread;
import com.android.systemui.stackdivider.Divider;

import java.util.ArrayList;
import java.util.HashMap;
@@ -85,6 +87,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
    private final int mEnterExitAnimationDuration;
    private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
    private final Map<IBinder, Rect> mBoundsToRestore = new HashMap<>();
    private final Divider mSplitDivider;

    // These callbacks are called on the update thread
    private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
@@ -189,7 +192,8 @@ public class PipTaskOrganizer extends TaskOrganizer {
            mSurfaceControlTransactionFactory;

    public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler,
            @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper) {
            @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
            @Nullable Divider divider) {
        mMainHandler = new Handler(Looper.getMainLooper());
        mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
        mPipBoundsHandler = boundsHandler;
@@ -198,6 +202,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
        mSurfaceTransactionHelper = surfaceTransactionHelper;
        mPipAnimationController = new PipAnimationController(context, surfaceTransactionHelper);
        mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
        mSplitDivider = divider;
    }

    public Handler getUpdateHandler() {
@@ -226,20 +231,21 @@ public class PipTaskOrganizer extends TaskOrganizer {

    /**
     * Dismiss PiP, this is done in two phases using {@link WindowContainerTransaction}
     * - setActivityWindowingMode to fullscreen at beginning of the transaction. without changing
     *   the windowing mode of the Task itself. This makes sure the activity render it's fullscreen
     * - setActivityWindowingMode to undefined at beginning of the transaction. without changing
     *   the windowing mode of the Task itself. This makes sure the activity render it's final
     *   configuration while the Task is still in PiP.
     * - setWindowingMode to fullscreen at the end of transition
     * - setWindowingMode to undefined at the end of transition
     * @param animationDurationMs duration in millisecond for the exiting PiP transition
     */
    public void dismissPip(int animationDurationMs) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN);
        wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
        WindowOrganizer.applyTransaction(wct);
        final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder());
        final int direction = syncWithSplitScreenBounds(destinationBounds)
                ? TRANSITION_DIRECTION_TO_SPLIT_SCREEN : TRANSITION_DIRECTION_TO_FULLSCREEN;
        scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
                TRANSITION_DIRECTION_TO_FULLSCREEN, animationDurationMs,
                null /* updateBoundsCallback */);
                direction, animationDurationMs, null /* updateBoundsCallback */);
        mInPip = false;
    }

@@ -282,6 +288,9 @@ public class PipTaskOrganizer extends TaskOrganizer {
     */
    @Override
    public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
        if (!mInPip) {
            return;
        }
        final WindowContainerToken token = info.token;
        Objects.requireNonNull(token, "Requires valid WindowContainerToken");
        if (token.asBinder() != mToken.asBinder()) {
@@ -519,14 +528,13 @@ public class PipTaskOrganizer extends TaskOrganizer {
        mLastReportedBounds.set(destinationBounds);
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final Rect taskBounds;
        if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
        if (isOutPipDirection(direction)) {
            // If we are animating to fullscreen, then we need to reset the override bounds
            // on the task to ensure that the task "matches" the parent's bounds, this applies
            // also to the final windowing mode, which should be reset to undefined rather than
            // fullscreen.
            taskBounds = null;
            wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED)
                    .setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
            // on the task to ensure that the task "matches" the parent's bounds.
            taskBounds = (direction == TRANSITION_DIRECTION_TO_FULLSCREEN)
                    ? null : destinationBounds;
            // As for the final windowing mode, simply reset it to undefined.
            wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
        } else {
            taskBounds = destinationBounds;
        }
@@ -577,6 +585,24 @@ public class PipTaskOrganizer extends TaskOrganizer {
                : params.getAspectRatio();
    }

    /**
     * Sync with {@link #mSplitDivider} on destination bounds if PiP is going to split screen.
     *
     * @param destinationBoundsOut contain the updated destination bounds if applicable
     * @return {@code true} if destinationBounds is altered for split screen
     */
    private boolean syncWithSplitScreenBounds(Rect destinationBoundsOut) {
        if (mSplitDivider == null || !mSplitDivider.inSplitMode()) {
            // bail early if system is not in split screen mode
            return false;
        }
        // PiP window will go to split-secondary mode instead of fullscreen, populates the
        // split screen bounds here.
        destinationBoundsOut.set(
                mSplitDivider.getView().getNonMinimizedSplitScreenSecondaryBounds());
        return true;
    }

    /**
     * Callback interface for PiP transitions (both from and to PiP mode)
     */
+6 −4
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.systemui.pip.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;

import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
import static com.android.systemui.pip.PipAnimationController.isOutPipDirection;

import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -53,6 +53,7 @@ import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.wm.DisplayChangeController;
@@ -199,7 +200,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
            DeviceConfigProxy deviceConfig,
            PipBoundsHandler pipBoundsHandler,
            PipSnapAlgorithm pipSnapAlgorithm,
            PipSurfaceTransactionHelper surfaceTransactionHelper) {
            PipSurfaceTransactionHelper surfaceTransactionHelper,
            Divider divider) {
        mContext = context;
        mActivityManager = ActivityManager.getService();

@@ -214,7 +216,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
        final IActivityTaskManager activityTaskManager = ActivityTaskManager.getService();
        mPipBoundsHandler = pipBoundsHandler;
        mPipTaskOrganizer = new PipTaskOrganizer(context, pipBoundsHandler,
                surfaceTransactionHelper);
                surfaceTransactionHelper, divider);
        mPipTaskOrganizer.registerPipTransitionCallback(this);
        mInputConsumerController = InputConsumerController.getPipInputConsumer();
        mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
@@ -312,7 +314,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio

    @Override
    public void onPipTransitionStarted(ComponentName activity, int direction) {
        if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
        if (isOutPipDirection(direction)) {
            // On phones, the expansion animation that happens on pip tap before restoring
            // to fullscreen makes it so that the bounds received here are the expanded
            // bounds. We want to restore to the unexpanded bounds when re-entering pip,
+4 −2
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.stackdivider.Divider;

import java.util.ArrayList;
import java.util.List;
@@ -232,7 +233,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
    @Inject
    public PipManager(Context context, BroadcastDispatcher broadcastDispatcher,
            PipBoundsHandler pipBoundsHandler,
            PipSurfaceTransactionHelper surfaceTransactionHelper) {
            PipSurfaceTransactionHelper surfaceTransactionHelper,
            Divider divider) {
        if (mInitialized) {
            return;
        }
@@ -249,7 +251,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
        mResizeAnimationDuration = context.getResources()
                .getInteger(R.integer.config_pipResizeAnimationDuration);
        mPipTaskOrganizer = new PipTaskOrganizer(mContext, mPipBoundsHandler,
                surfaceTransactionHelper);
                surfaceTransactionHelper, divider);
        mPipTaskOrganizer.registerPipTransitionCallback(this);
        mActivityTaskManager = ActivityTaskManager.getService();
        ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
+10 −5
Original line number Diff line number Diff line
@@ -1188,12 +1188,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
        if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
            // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
            // update that here in order. Set the last reported MW state to the same as the PiP
            // state since we haven't yet actually resized the task (these callbacks need to
            // preceed the configuration change from the resiez.
            // Picture-in-picture mode change normal triggers also multi-window mode change
            // except transitions between pip and split screen mode, so update that here in order.
            // Set the last reported MW state to the same as the PiP state since we haven't yet
            // actually resized the task (these callbacks need to proceed the configuration change
            // from the resize).
            // TODO(110009072): Once we move these callbacks to the client, remove all logic related
            // to forcing the update of the picture-in-picture mode as a part of the PiP animation.
            final boolean shouldScheduleMultiWindowModeChange =
                    mLastReportedMultiWindowMode != inMultiWindowMode();
            mLastReportedPictureInPictureMode = inPictureInPictureMode;
            mLastReportedMultiWindowMode = inPictureInPictureMode;
            final Configuration newConfig = new Configuration();
@@ -1204,9 +1207,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                task.computeConfigResourceOverrides(newConfig, task.getParent().getConfiguration());
            }
            schedulePictureInPictureModeChanged(newConfig);
            if (shouldScheduleMultiWindowModeChange) {
                scheduleMultiWindowModeChanged(newConfig);
            }
        }
    }

    private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
        try {
Loading