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

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

Disable certain transaction when swiping pip to home

When swiping pip to home is happening, following transactions become
conflicts
- onFixedRotationStarted / onFixedRotationFinished
- onMovementBoundsChanged

skip these transactions entirely if that's the case

- Added also scaleAndRotate support in PipSurfaceTransactionHelper
- Need to address the final glitch

Video: http://rcll/aaaaaabFQoRHlzixHdtY/cOco1yoMXwFzSifFqQET9U
Video: http://rcll/aaaaaabFQoRHlzixHdtY/f3IWG09DRO9aUNnzqSdPLU
Bug: 171802909
Test: see video
Change-Id: Ied0e9d485e3d9ecff4d7a9e4ea3687103b7b47c3
parent ec66eb30
Loading
Loading
Loading
Loading
+26 −17
Original line number Diff line number Diff line
@@ -64,9 +64,9 @@ import com.android.internal.os.SomeArgs;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.pip.phone.PipUpdateThread;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -251,7 +251,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     * If set to {@code true}, the entering animation will be skipped and we will wait for
     * {@link #onFixedRotationFinished(int)} callback to actually enter PiP.
     */
    private boolean mShouldDeferEnteringPip;
    private boolean mWaitForFixedRotation;

    /**
     * If set to {@code true}, no entering PiP transition would be kicked off and most likely
@@ -259,7 +259,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     * auto PiP-able Activity to home.
     * See also {@link #startSwipePipToHome(ComponentName, ActivityInfo, PictureInPictureParams)}.
     */
    private boolean mShouldIgnoreEnteringPipTransition;
    private boolean mInSwipePipToHomeTransition;

    public PipTaskOrganizer(Context context, @NonNull PipBoundsState pipBoundsState,
            @NonNull PipBoundsAlgorithm boundsHandler,
@@ -304,7 +304,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
    }

    public boolean isDeferringEnterPipAnimation() {
        return mState.isInPip() && mShouldDeferEnteringPip;
        return mState.isInPip() && mWaitForFixedRotation;
    }

    /**
@@ -336,9 +336,12 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     */
    public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
            PictureInPictureParams pictureInPictureParams) {
        mShouldIgnoreEnteringPipTransition = true;
        mInSwipePipToHomeTransition = true;
        sendOnPipTransitionStarted(componentName, TRANSITION_DIRECTION_TO_PIP);
        setBoundsStateForEntry(componentName, pictureInPictureParams, activityInfo);
        // disable the conflicting transaction from fixed rotation, see also
        // onFixedRotationStarted and onFixedRotationFinished
        mWaitForFixedRotation = false;
        return mPipBoundsAlgorithm.getEntryDestinationBounds();
    }

@@ -348,7 +351,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     */
    public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
        // do nothing if there is no startSwipePipToHome being called before
        if (mShouldIgnoreEnteringPipTransition) {
        if (mInSwipePipToHomeTransition) {
            mPipBoundsState.setBounds(destinationBounds);
        }
    }
@@ -502,7 +505,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,

        mPipMenuController.attach(leash);

        if (mShouldIgnoreEnteringPipTransition) {
        if (mInSwipePipToHomeTransition) {
            final Rect destinationBounds = mPipBoundsState.getBounds();
            // animation is finished in the Launcher and here we directly apply the final touch.
            applyEnterPipSyncTransaction(destinationBounds, () -> {
@@ -510,11 +513,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                finishResizeForMenu(destinationBounds);
                sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
            });
            mShouldIgnoreEnteringPipTransition = false;
            mInSwipePipToHomeTransition = false;
            return;
        }

        if (mShouldDeferEnteringPip) {
        if (mWaitForFixedRotation) {
            if (DEBUG) Log.d(TAG, "Defer entering PiP animation, fixed rotation is ongoing");
            // if deferred, hide the surface till fixed rotation is completed
            final SurfaceControl.Transaction tx =
@@ -666,8 +669,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            Log.wtf(TAG, "Unrecognized token: " + token);
            return;
        }
        mShouldDeferEnteringPip = false;
        mShouldIgnoreEnteringPipTransition = false;
        mWaitForFixedRotation = false;
        mInSwipePipToHomeTransition = false;
        mPictureInPictureParams = null;
        mState = State.UNDEFINED;
        mPipUiEventLoggerLogger.setTaskInfo(null);
@@ -694,17 +697,17 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,

    @Override
    public void onFixedRotationStarted(int displayId, int newRotation) {
        mShouldDeferEnteringPip = true;
        mWaitForFixedRotation = true;
    }

    @Override
    public void onFixedRotationFinished(int displayId) {
        if (mShouldDeferEnteringPip && mState.isInPip()) {
        if (mWaitForFixedRotation && mState.isInPip()) {
            final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
            // schedule a regular animation to ensure all the callbacks are still being sent
            enterPipWithAlphaAnimation(destinationBounds, 0 /* durationMs */);
        }
        mShouldDeferEnteringPip = false;
        mWaitForFixedRotation = false;
    }

    /**
@@ -723,6 +726,12 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
    public void onMovementBoundsChanged(Rect destinationBoundsOut, boolean fromRotation,
            boolean fromImeAdjustment, boolean fromShelfAdjustment,
            WindowContainerTransaction wct) {
        // note that this can be called when swiping pip to home is happening. For instance,
        // swiping an app in landscape to portrait home. skip this entirely if that's the case.
        if (mInSwipePipToHomeTransition && fromRotation) {
            if (DEBUG) Log.d(TAG, "skip onMovementBoundsChanged due to swipe-pip-to-home");
            return;
        }
        final PipAnimationController.PipTransitionAnimator animator =
                mPipAnimationController.getCurrentAnimator();
        if (animator == null || !animator.isRunning()
@@ -806,7 +815,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     */
    public void scheduleAnimateResizePip(Rect toBounds, int duration,
            Consumer<Rect> updateBoundsCallback) {
        if (mShouldDeferEnteringPip) {
        if (mWaitForFixedRotation) {
            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
            return;
        }
@@ -820,7 +829,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     */
    public void scheduleAnimateResizePip(Rect fromBounds, Rect toBounds, int duration,
            Consumer<Rect> updateBoundsCallback) {
        if (mShouldDeferEnteringPip) {
        if (mWaitForFixedRotation) {
            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
            return;
        }
@@ -922,7 +931,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        if (mState.shouldBlockResizeRequest()) {
            return;
        }
        if (mShouldDeferEnteringPip) {
        if (mWaitForFixedRotation) {
            Log.d(TAG, "skip scheduleOffsetPip, entering pip deferred");
            return;
        }
+34 −1
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.systemui.shared.pip;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.Choreographer;
import android.view.Surface;
import android.view.SurfaceControl;

/**
@@ -50,8 +52,32 @@ public class PipSurfaceTransactionHelper {
                .setPosition(leash, left, top);
    }

    public void reset(SurfaceControl.Transaction tx, SurfaceControl leash, Rect destinationBounds) {
    public void scaleAndRotate(SurfaceControl.Transaction tx, SurfaceControl leash,
            Rect sourceBounds, Rect destinationBounds, Rect insets,
            float degree, float positionX, float positionY) {
        mTmpSourceRectF.set(sourceBounds);
        mTmpDestinationRect.set(sourceBounds);
        mTmpDestinationRect.inset(insets);
        // Scale by the shortest edge and offset such that the top/left of the scaled inset
        // source rect aligns with the top/left of the destination bounds
        final float scale = sourceBounds.width() <= sourceBounds.height()
                ? (float) destinationBounds.width() / sourceBounds.width()
                : (float) destinationBounds.height() / sourceBounds.height();
        mTmpTransform.setRotate(degree, 0, 0);
        mTmpTransform.postScale(scale, scale);
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
                .setWindowCrop(leash, mTmpDestinationRect)
                .setPosition(leash, positionX, positionY);
    }

    public void reset(SurfaceControl.Transaction tx, SurfaceControl leash, Rect destinationBounds,
            @Surface.Rotation int rotation) {
        resetScale(tx, leash, destinationBounds);
        if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
            final int degree = (rotation == Surface.ROTATION_90) ? -90 : 90;
            mTmpTransform.setRotate(degree, 0, 0);
            tx.setMatrix(leash, mTmpTransform, mTmpFloat9);
        }
        resetCornerRadius(tx, leash);
        crop(tx, leash, destinationBounds);
    }
@@ -71,4 +97,11 @@ public class PipSurfaceTransactionHelper {
        tx.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height())
                .setPosition(leash, destinationBounds.left, destinationBounds.top);
    }

    /** @return {@link SurfaceControl.Transaction} instance with vsync-id */
    public static SurfaceControl.Transaction newSurfaceControlTransaction() {
        final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
        tx.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
        return tx;
    }
}