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

Commit 0de58934 authored by Tony Huang's avatar Tony Huang Committed by Android (Google) Code Review
Browse files

Merge "Implement split resize shell transition" into tm-qpr-dev

parents 0b26f2e5 104a5f5c
Loading
Loading
Loading
Loading
+55 −22
Original line number Diff line number Diff line
@@ -51,8 +51,6 @@ import com.android.wm.shell.R;
import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.SurfaceUtils;

import java.util.function.Consumer;

/**
 * Handles split decor like showing resizing hint for a specific split.
 */
@@ -72,17 +70,18 @@ public class SplitDecorManager extends WindowlessWindowManager {
    private SurfaceControl mIconLeash;
    private SurfaceControl mBackgroundLeash;
    private SurfaceControl mGapBackgroundLeash;
    private SurfaceControl mScreenshot;

    private boolean mShown;
    private boolean mIsResizing;
    private final Rect mBounds = new Rect();
    private final Rect mResizingBounds = new Rect();
    private final Rect mTempRect = new Rect();
    private ValueAnimator mFadeAnimator;

    private int mIconSize;
    private int mOffsetX;
    private int mOffsetY;
    private int mRunningAnimationCount = 0;

    public SplitDecorManager(Configuration configuration, IconProvider iconProvider,
            SurfaceSession surfaceSession) {
@@ -173,7 +172,6 @@ public class SplitDecorManager extends WindowlessWindowManager {
            mIsResizing = true;
            mBounds.set(newBounds);
        }
        mResizingBounds.set(newBounds);
        mOffsetX = offsetX;
        mOffsetY = offsetY;

@@ -227,33 +225,41 @@ public class SplitDecorManager extends WindowlessWindowManager {
                t.setVisibility(mBackgroundLeash, show);
                t.setVisibility(mIconLeash, show);
            } else {
                startFadeAnimation(show, null /* finishedConsumer */);
                startFadeAnimation(show, false, null);
            }
            mShown = show;
        }
    }

    /** Stops showing resizing hint. */
    public void onResized(SurfaceControl.Transaction t) {
        if (!mShown && mIsResizing) {
            mTempRect.set(mResizingBounds);
            mTempRect.offsetTo(-mOffsetX, -mOffsetY);
            final SurfaceControl screenshot = ScreenshotUtils.takeScreenshot(t,
                    mHostLeash, mTempRect, Integer.MAX_VALUE - 1);
    public void onResized(SurfaceControl.Transaction t, Runnable animFinishedCallback) {
        if (mScreenshot != null) {
            t.setPosition(mScreenshot, mOffsetX, mOffsetY);

            final SurfaceControl.Transaction animT = new SurfaceControl.Transaction();
            final ValueAnimator va = ValueAnimator.ofFloat(1, 0);
            va.addUpdateListener(valueAnimator -> {
                final float progress = (float) valueAnimator.getAnimatedValue();
                animT.setAlpha(screenshot, progress);
                animT.setAlpha(mScreenshot, progress);
                animT.apply();
            });
            va.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    mRunningAnimationCount++;
                }

                @Override
                public void onAnimationEnd(@androidx.annotation.NonNull Animator animation) {
                    animT.remove(screenshot);
                    mRunningAnimationCount--;
                    animT.remove(mScreenshot);
                    animT.apply();
                    animT.close();
                    mScreenshot = null;

                    if (mRunningAnimationCount == 0 && animFinishedCallback != null) {
                        animFinishedCallback.run();
                    }
                }
            });
            va.start();
@@ -285,10 +291,34 @@ public class SplitDecorManager extends WindowlessWindowManager {
            mFadeAnimator.cancel();
        }
        if (mShown) {
            fadeOutDecor(null /* finishedCallback */);
            fadeOutDecor(animFinishedCallback);
        } else {
            // Decor surface is hidden so release it directly.
            releaseDecor(t);
            if (mRunningAnimationCount == 0 && animFinishedCallback != null) {
                animFinishedCallback.run();
            }
        }
    }

    /** Screenshot host leash and attach on it if meet some conditions */
    public void screenshotIfNeeded(SurfaceControl.Transaction t) {
        if (!mShown && mIsResizing) {
            mTempRect.set(mBounds);
            mTempRect.offsetTo(0, 0);
            mScreenshot = ScreenshotUtils.takeScreenshot(t, mHostLeash, mTempRect,
                    Integer.MAX_VALUE - 1);
        }
    }

    /** Set screenshot and attach on host leash it if meet some conditions */
    public void setScreenshotIfNeeded(SurfaceControl screenshot, SurfaceControl.Transaction t) {
        if (screenshot == null || !screenshot.isValid()) return;

        if (!mShown && mIsResizing) {
            mScreenshot = screenshot;
            t.reparent(screenshot, mHostLeash);
            t.setLayer(screenshot, Integer.MAX_VALUE - 1);
        }
    }

@@ -296,18 +326,15 @@ public class SplitDecorManager extends WindowlessWindowManager {
     * directly. */
    public void fadeOutDecor(Runnable finishedCallback) {
        if (mShown) {
            startFadeAnimation(false /* show */, transaction -> {
                releaseDecor(transaction);
                if (finishedCallback != null) finishedCallback.run();
            });
            startFadeAnimation(false /* show */, true, finishedCallback);
            mShown = false;
        } else {
            if (finishedCallback != null) finishedCallback.run();
        }
    }

    private void startFadeAnimation(boolean show,
            Consumer<SurfaceControl.Transaction> finishedConsumer) {
    private void startFadeAnimation(boolean show, boolean releaseSurface,
            Runnable finishedCallback) {
        final SurfaceControl.Transaction animT = new SurfaceControl.Transaction();
        mFadeAnimator = ValueAnimator.ofFloat(0f, 1f);
        mFadeAnimator.setDuration(FADE_DURATION);
@@ -324,6 +351,7 @@ public class SplitDecorManager extends WindowlessWindowManager {
        mFadeAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(@NonNull Animator animation) {
                mRunningAnimationCount++;
                if (show) {
                    animT.show(mBackgroundLeash).show(mIconLeash);
                }
@@ -335,6 +363,7 @@ public class SplitDecorManager extends WindowlessWindowManager {

            @Override
            public void onAnimationEnd(@NonNull Animator animation) {
                mRunningAnimationCount--;
                if (!show) {
                    if (mBackgroundLeash != null) {
                        animT.hide(mBackgroundLeash);
@@ -343,11 +372,15 @@ public class SplitDecorManager extends WindowlessWindowManager {
                        animT.hide(mIconLeash);
                    }
                }
                if (finishedConsumer != null) {
                    finishedConsumer.accept(animT);
                if (releaseSurface) {
                    releaseDecor(animT);
                }
                animT.apply();
                animT.close();

                if (mRunningAnimationCount == 0 && finishedCallback != null) {
                    finishedCallback.run();
                }
            }
        });
        mFadeAnimator.start();
+67 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.window.WindowContainerTransactionCallback;

import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.split.SplitDecorManager;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.transition.OneShotRemoteHandler;
import com.android.wm.shell.transition.Transitions;
@@ -64,6 +65,7 @@ class SplitScreenTransitions {
    DismissTransition mPendingDismiss = null;
    TransitSession mPendingEnter = null;
    TransitSession mPendingRecent = null;
    TransitSession mPendingResize = null;

    private IBinder mAnimatingTransition = null;
    OneShotRemoteHandler mPendingRemoteHandler = null;
@@ -177,6 +179,43 @@ class SplitScreenTransitions {
        onFinish(null /* wct */, null /* wctCB */);
    }

    void applyResizeTransition(@NonNull IBinder transition, @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,
            @NonNull Transitions.TransitionFinishCallback finishCallback,
            @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot,
            @NonNull SplitDecorManager mainDecor, @NonNull SplitDecorManager sideDecor) {
        mFinishCallback = finishCallback;
        mAnimatingTransition = transition;
        mFinishTransaction = finishTransaction;

        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
            if (mainRoot.equals(change.getContainer()) || sideRoot.equals(change.getContainer())) {
                final SurfaceControl leash = change.getLeash();
                startTransaction.setPosition(leash, change.getEndAbsBounds().left,
                        change.getEndAbsBounds().top);
                startTransaction.setWindowCrop(leash, change.getEndAbsBounds().width(),
                        change.getEndAbsBounds().height());

                SplitDecorManager decor = mainRoot.equals(change.getContainer())
                        ? mainDecor : sideDecor;
                ValueAnimator va = new ValueAnimator();
                mAnimations.add(va);
                decor.setScreenshotIfNeeded(change.getSnapshot(), startTransaction);
                decor.onResized(startTransaction, () -> {
                    mTransitions.getMainExecutor().execute(() -> {
                        mAnimations.remove(va);
                        onFinish(null /* wct */, null /* wctCB */);
                    });
                });
            }
        }

        startTransaction.apply();
        onFinish(null /* wct */, null /* wctCB */);
    }

    boolean isPendingTransition(IBinder transition) {
        return getPendingTransition(transition) != null;
    }
@@ -193,6 +232,10 @@ class SplitScreenTransitions {
        return mPendingDismiss != null && mPendingDismiss.mTransition == transition;
    }

    boolean isPendingResize(IBinder transition) {
        return mPendingResize != null && mPendingResize.mTransition == transition;
    }

    @Nullable
    private TransitSession getPendingTransition(IBinder transition) {
        if (isPendingEnter(transition)) {
@@ -201,11 +244,14 @@ class SplitScreenTransitions {
            return mPendingRecent;
        } else if (isPendingDismiss(transition)) {
            return mPendingDismiss;
        } else if (isPendingResize(transition)) {
            return mPendingResize;
        }

        return null;
    }


    /** Starts a transition to enter split with a remote transition animator. */
    IBinder startEnterTransition(
            @WindowManager.TransitionType int transitType,
@@ -258,6 +304,21 @@ class SplitScreenTransitions {
                exitReasonToString(reason), stageTypeToString(dismissTop));
    }

    IBinder startResizeTransition(WindowContainerTransaction wct,
            Transitions.TransitionHandler handler,
            @Nullable TransitionFinishedCallback finishCallback) {
        IBinder transition = mTransitions.startTransition(TRANSIT_CHANGE, wct, handler);
        setResizeTransition(transition, finishCallback);
        return transition;
    }

    void setResizeTransition(@NonNull IBinder transition,
            @Nullable TransitionFinishedCallback finishCallback) {
        mPendingResize = new TransitSession(transition, null /* consumedCb */, finishCallback);
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "  splitTransition "
                + " deduced Resize split screen");
    }

    void setRecentTransition(@NonNull IBinder transition,
            @Nullable RemoteTransition remoteTransition,
            @Nullable TransitionFinishedCallback finishCallback) {
@@ -324,6 +385,9 @@ class SplitScreenTransitions {
            mPendingRecent.onConsumed(aborted);
            mPendingRecent = null;
            mPendingRemoteHandler = null;
        } else if (isPendingResize(transition)) {
            mPendingResize.onConsumed(aborted);
            mPendingResize = null;
        }
    }

@@ -340,6 +404,9 @@ class SplitScreenTransitions {
        } else if (isPendingDismiss(mAnimatingTransition)) {
            mPendingDismiss.onFinished(wct, mFinishTransaction);
            mPendingDismiss = null;
        } else if (isPendingResize(mAnimatingTransition)) {
            mPendingResize.onFinished(wct, mFinishTransaction);
            mPendingResize = null;
        }

        mPendingRemoteHandler = null;
+26 −6
Original line number Diff line number Diff line
@@ -1667,15 +1667,29 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    public void onLayoutSizeChanged(SplitLayout layout) {
        // Reset this flag every time onLayoutSizeChanged.
        mShowDecorImmediately = false;

        if (!ENABLE_SHELL_TRANSITIONS) {
            // Only need screenshot for legacy case because shell transition should screenshot
            // itself during transition.
            final SurfaceControl.Transaction startT = mTransactionPool.acquire();
            mMainStage.screenshotIfNeeded(startT);
            mSideStage.screenshotIfNeeded(startT);
            mTransactionPool.release(startT);
        }

        final WindowContainerTransaction wct = new WindowContainerTransaction();
        updateWindowBounds(layout, wct);
        sendOnBoundsChanged();
        if (ENABLE_SHELL_TRANSITIONS) {
            mSplitTransitions.startResizeTransition(wct, this, null /* callback */);
        } else {
            mSyncQueue.queue(wct);
            mSyncQueue.runInSync(t -> {
                updateSurfaceBounds(layout, t, false /* applyResizingOffset */);
                mMainStage.onResized(t);
                mSideStage.onResized(t);
            });
        }
        mLogger.logResize(mSplitLayout.getDividerPositionAsFraction());
    }

@@ -2029,6 +2043,12 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        } else if (mSplitTransitions.isPendingDismiss(transition)) {
            shouldAnimate = startPendingDismissAnimation(
                    mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
        } else if (mSplitTransitions.isPendingResize(transition)) {
            mSplitTransitions.applyResizeTransition(transition, info, startTransaction,
                    finishTransaction, finishCallback, mMainStage.mRootTaskInfo.token,
                    mSideStage.mRootTaskInfo.token, mMainStage.getSplitDecorManager(),
                    mSideStage.getSplitDecorManager());
            return true;
        }
        if (!shouldAnimate) return false;

+11 −1
Original line number Diff line number Diff line
@@ -292,7 +292,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {

    void onResized(SurfaceControl.Transaction t) {
        if (mSplitDecorManager != null) {
            mSplitDecorManager.onResized(t);
            mSplitDecorManager.onResized(t, null);
        }
    }

    void screenshotIfNeeded(SurfaceControl.Transaction t) {
        if (mSplitDecorManager != null) {
            mSplitDecorManager.screenshotIfNeeded(t);
        }
    }

@@ -304,6 +310,10 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        }
    }

    SplitDecorManager getSplitDecorManager() {
        return mSplitDecorManager;
    }

    void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) {
        // Clear overridden bounds and windowing mode to make sure the child task can inherit
        // windowing mode and bounds from split root.
+1 −1
Original line number Diff line number Diff line
@@ -2183,7 +2183,7 @@ class Task extends TaskFragment {
    }

    private boolean shouldStartChangeTransition(int prevWinMode, @NonNull Rect prevBounds) {
        if (!isLeafTask() || !canStartChangeTransition()) {
        if (!(isLeafTask() || mCreatedByOrganizer) || !canStartChangeTransition()) {
            return false;
        }
        final int newWinMode = getWindowingMode();