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

Commit 36b5dd8b authored by Tony Huang's avatar Tony Huang
Browse files

Handle split rotation in rotation callback

By current split design, we always update bounds and apply WCT on
DA info changed callback. However, with shell transition, we should
avoid apply WCT while transition running.

Add display rotation callback we used in legacy split to new split
and apply bounds on such callback. This can ensure that WCT sync to
running rotation transition.

Bug: 206872147
Test: manual
Test: pass existing tests
Change-Id: I358a00ab6ecfb56ececcc93204a78366c48cabda
parent d77c92a3
Loading
Loading
Loading
Loading
+18 −2
Original line number Original line Diff line number Diff line
@@ -180,8 +180,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange


    /** Applies new configuration, returns {@code false} if there's no effect to the layout. */
    /** Applies new configuration, returns {@code false} if there's no effect to the layout. */
    public boolean updateConfiguration(Configuration configuration) {
    public boolean updateConfiguration(Configuration configuration) {
        boolean affectsLayout = false;

        // Update the split bounds when necessary. Besides root bounds changed, split bounds need to
        // Update the split bounds when necessary. Besides root bounds changed, split bounds need to
        // be updated when the rotation changed to cover the case that users rotated the screen 180
        // be updated when the rotation changed to cover the case that users rotated the screen 180
        // degrees.
        // degrees.
@@ -214,6 +212,24 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
        return true;
        return true;
    }
    }


    /** Rotate the layout to specific rotation and assume its new bounds. */
    public void rotateTo(int newRotation) {
        final int rotationDelta = (newRotation - mRotation + 4) % 4;
        final boolean changeOrient = (rotationDelta % 2) != 0;

        mRotation = newRotation;
        Rect tmpRect = new Rect(mRootBounds);
        if (changeOrient) {
            tmpRect.set(mRootBounds.top, mRootBounds.left, mRootBounds.bottom, mRootBounds.right);
        }

        final Configuration config = new Configuration();
        config.setTo(mContext.getResources().getConfiguration());
        config.orientation = mOrientation;
        config.windowConfiguration.setBounds(tmpRect);
        updateConfiguration(config);
    }

    private void initDividerPosition(Rect oldBounds) {
    private void initDividerPosition(Rect oldBounds) {
        final float snapRatio = (float) mDividePosition
        final float snapRatio = (float) mDividePosition
                / (float) (isLandscape(oldBounds) ? oldBounds.width() : oldBounds.height());
                / (float) (isLandscape(oldBounds) ? oldBounds.width() : oldBounds.height());
+2 −1
Original line number Original line Diff line number Diff line
@@ -161,13 +161,14 @@ public class WMShellModule {
            SyncTransactionQueue syncQueue, Context context,
            SyncTransactionQueue syncQueue, Context context,
            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellMainThread ShellExecutor mainExecutor,
            DisplayController displayController,
            DisplayImeController displayImeController,
            DisplayImeController displayImeController,
            DisplayInsetsController displayInsetsController, Transitions transitions,
            DisplayInsetsController displayInsetsController, Transitions transitions,
            TransactionPool transactionPool, IconProvider iconProvider,
            TransactionPool transactionPool, IconProvider iconProvider,
            Optional<RecentTasksController> recentTasks,
            Optional<RecentTasksController> recentTasks,
            Provider<Optional<StageTaskUnfoldController>> stageTaskUnfoldControllerProvider) {
            Provider<Optional<StageTaskUnfoldController>> stageTaskUnfoldControllerProvider) {
        return new SplitScreenController(shellTaskOrganizer, syncQueue, context,
        return new SplitScreenController(shellTaskOrganizer, syncQueue, context,
                rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController,
                rootTaskDisplayAreaOrganizer, mainExecutor, displayController, displayImeController,
                displayInsetsController, transitions, transactionPool, iconProvider,
                displayInsetsController, transitions, transactionPool, iconProvider,
                recentTasks, stageTaskUnfoldControllerProvider);
                recentTasks, stageTaskUnfoldControllerProvider);
    }
    }
+6 −2
Original line number Original line Diff line number Diff line
@@ -58,6 +58,7 @@ import com.android.internal.logging.InstanceId;
import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.RemoteCallable;
@@ -124,6 +125,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
    private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
    private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
    private final ShellExecutor mMainExecutor;
    private final ShellExecutor mMainExecutor;
    private final SplitScreenImpl mImpl = new SplitScreenImpl();
    private final SplitScreenImpl mImpl = new SplitScreenImpl();
    private final DisplayController mDisplayController;
    private final DisplayImeController mDisplayImeController;
    private final DisplayImeController mDisplayImeController;
    private final DisplayInsetsController mDisplayInsetsController;
    private final DisplayInsetsController mDisplayInsetsController;
    private final Transitions mTransitions;
    private final Transitions mTransitions;
@@ -138,7 +140,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
    public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
    public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
            SyncTransactionQueue syncQueue, Context context,
            SyncTransactionQueue syncQueue, Context context,
            RootTaskDisplayAreaOrganizer rootTDAOrganizer,
            RootTaskDisplayAreaOrganizer rootTDAOrganizer,
            ShellExecutor mainExecutor, DisplayImeController displayImeController,
            ShellExecutor mainExecutor, DisplayController displayController,
            DisplayImeController displayImeController,
            DisplayInsetsController displayInsetsController,
            DisplayInsetsController displayInsetsController,
            Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider,
            Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider,
            Optional<RecentTasksController> recentTasks,
            Optional<RecentTasksController> recentTasks,
@@ -148,6 +151,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        mContext = context;
        mContext = context;
        mRootTDAOrganizer = rootTDAOrganizer;
        mRootTDAOrganizer = rootTDAOrganizer;
        mMainExecutor = mainExecutor;
        mMainExecutor = mainExecutor;
        mDisplayController = displayController;
        mDisplayImeController = displayImeController;
        mDisplayImeController = displayImeController;
        mDisplayInsetsController = displayInsetsController;
        mDisplayInsetsController = displayInsetsController;
        mTransitions = transitions;
        mTransitions = transitions;
@@ -176,7 +180,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        if (mStageCoordinator == null) {
        if (mStageCoordinator == null) {
            // TODO: Multi-display
            // TODO: Multi-display
            mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
            mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
                    mRootTDAOrganizer, mTaskOrganizer, mDisplayImeController,
                    mRootTDAOrganizer, mTaskOrganizer, mDisplayController, mDisplayImeController,
                    mDisplayInsetsController, mTransitions, mTransactionPool, mLogger,
                    mDisplayInsetsController, mTransitions, mTransactionPool, mLogger,
                    mIconProvider, mRecentTasksOptional, mUnfoldControllerProvider);
                    mIconProvider, mRecentTasksOptional, mUnfoldControllerProvider);
        }
        }
+3 −2
Original line number Original line Diff line number Diff line
@@ -144,8 +144,9 @@ class SplitScreenTransitions {


            if (transition == mPendingEnter && (mainRoot.equals(change.getContainer())
            if (transition == mPendingEnter && (mainRoot.equals(change.getContainer())
                    || sideRoot.equals(change.getContainer()))) {
                    || sideRoot.equals(change.getContainer()))) {
                t.setWindowCrop(leash, change.getStartAbsBounds().width(),
                t.setPosition(leash, change.getEndAbsBounds().left, change.getEndAbsBounds().top);
                        change.getStartAbsBounds().height());
                t.setWindowCrop(leash, change.getEndAbsBounds().width(),
                        change.getEndAbsBounds().height());
            }
            }
            boolean isOpening = isOpeningType(info.getType());
            boolean isOpening = isOpeningType(info.getType());
            if (isOpening && (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
            if (isOpening && (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
+78 −32
Original line number Original line Diff line number Diff line
@@ -21,7 +21,9 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
import static android.view.WindowManager.transitTypeToString;
@@ -83,6 +85,7 @@ import com.android.internal.protolog.common.ProtoLog;
import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -118,7 +121,8 @@ import javax.inject.Provider;
 * {@link #onStageHasChildrenChanged(StageListenerImpl).}
 * {@link #onStageHasChildrenChanged(StageListenerImpl).}
 */
 */
class StageCoordinator implements SplitLayout.SplitLayoutHandler,
class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        RootTaskDisplayAreaOrganizer.RootTaskDisplayAreaListener, Transitions.TransitionHandler {
        RootTaskDisplayAreaOrganizer.RootTaskDisplayAreaListener,
        DisplayController.OnDisplaysChangedListener, Transitions.TransitionHandler {


    private static final String TAG = StageCoordinator.class.getSimpleName();
    private static final String TAG = StageCoordinator.class.getSimpleName();


@@ -142,8 +146,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    private DisplayAreaInfo mDisplayAreaInfo;
    private DisplayAreaInfo mDisplayAreaInfo;
    private final Context mContext;
    private final Context mContext;
    private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>();
    private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>();
    private final DisplayController mDisplayController;
    private final DisplayImeController mDisplayImeController;
    private final DisplayImeController mDisplayImeController;
    private final DisplayInsetsController mDisplayInsetsController;
    private final DisplayInsetsController mDisplayInsetsController;
    private final TransactionPool mTransactionPool;
    private final SplitScreenTransitions mSplitTransitions;
    private final SplitScreenTransitions mSplitTransitions;
    private final SplitscreenEventLogger mLogger;
    private final SplitscreenEventLogger mLogger;
    private final Optional<RecentTasksController> mRecentTasks;
    private final Optional<RecentTasksController> mRecentTasks;
@@ -163,7 +169,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        if (!isSplitScreenVisible()) {
        if (!isSplitScreenVisible()) {
            // Update divider state after animation so that it is still around and positioned
            // Update divider state after animation so that it is still around and positioned
            // properly for the animation itself.
            // properly for the animation itself.
            setDividerVisibility(false);
            mSplitLayout.release();
            mSplitLayout.resetDividerPosition();
            mSplitLayout.resetDividerPosition();
        }
        }
    };
    };
@@ -183,6 +189,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,


    StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
    StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
            RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
            RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
            DisplayController displayController,
            DisplayImeController displayImeController,
            DisplayImeController displayImeController,
            DisplayInsetsController displayInsetsController, Transitions transitions,
            DisplayInsetsController displayInsetsController, Transitions transitions,
            TransactionPool transactionPool, SplitscreenEventLogger logger,
            TransactionPool transactionPool, SplitscreenEventLogger logger,
@@ -217,8 +224,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                mSurfaceSession,
                mSurfaceSession,
                iconProvider,
                iconProvider,
                mSideUnfoldController);
                mSideUnfoldController);
        mDisplayController = displayController;
        mDisplayImeController = displayImeController;
        mDisplayImeController = displayImeController;
        mDisplayInsetsController = displayInsetsController;
        mDisplayInsetsController = displayInsetsController;
        mTransactionPool = transactionPool;
        mRootTDAOrganizer.registerListener(displayId, this);
        mRootTDAOrganizer.registerListener(displayId, this);
        final DeviceStateManager deviceStateManager =
        final DeviceStateManager deviceStateManager =
                mContext.getSystemService(DeviceStateManager.class);
                mContext.getSystemService(DeviceStateManager.class);
@@ -226,13 +235,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                new DeviceStateManager.FoldStateListener(mContext, this::onFoldedStateChanged));
                new DeviceStateManager.FoldStateListener(mContext, this::onFoldedStateChanged));
        mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
        mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
                mOnTransitionAnimationComplete);
                mOnTransitionAnimationComplete);
        mDisplayController.addDisplayWindowListener(this);
        transitions.addHandler(this);
        transitions.addHandler(this);
    }
    }


    @VisibleForTesting
    @VisibleForTesting
    StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
    StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
            RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
            RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
            MainStage mainStage, SideStage sideStage, DisplayImeController displayImeController,
            MainStage mainStage, SideStage sideStage, DisplayController displayController,
            DisplayImeController displayImeController,
            DisplayInsetsController displayInsetsController, SplitLayout splitLayout,
            DisplayInsetsController displayInsetsController, SplitLayout splitLayout,
            Transitions transitions, TransactionPool transactionPool,
            Transitions transitions, TransactionPool transactionPool,
            SplitscreenEventLogger logger,
            SplitscreenEventLogger logger,
@@ -245,8 +256,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mTaskOrganizer = taskOrganizer;
        mTaskOrganizer = taskOrganizer;
        mMainStage = mainStage;
        mMainStage = mainStage;
        mSideStage = sideStage;
        mSideStage = sideStage;
        mDisplayController = displayController;
        mDisplayImeController = displayImeController;
        mDisplayImeController = displayImeController;
        mDisplayInsetsController = displayInsetsController;
        mDisplayInsetsController = displayInsetsController;
        mTransactionPool = transactionPool;
        mRootTDAOrganizer.registerListener(displayId, this);
        mRootTDAOrganizer.registerListener(displayId, this);
        mSplitLayout = splitLayout;
        mSplitLayout = splitLayout;
        mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
        mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
@@ -255,6 +268,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mSideUnfoldController = unfoldControllerProvider.get().orElse(null);
        mSideUnfoldController = unfoldControllerProvider.get().orElse(null);
        mLogger = logger;
        mLogger = logger;
        mRecentTasks = recentTasks;
        mRecentTasks = recentTasks;
        mDisplayController.addDisplayWindowListener(this);
        transitions.addHandler(this);
        transitions.addHandler(this);
    }
    }


@@ -630,8 +644,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                .setWindowCrop(mSideStage.mRootLeash, null));
                .setWindowCrop(mSideStage.mRootLeash, null));


        // Hide divider and reset its position.
        // Hide divider and reset its position.
        setDividerVisibility(false);
        mSplitLayout.resetDividerPosition();
        mSplitLayout.resetDividerPosition();
        mSplitLayout.release();
        mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
        mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
        Slog.i(TAG, "applyExitSplitScreen, reason = " + exitReasonToString(exitReason));
        Slog.i(TAG, "applyExitSplitScreen, reason = " + exitReasonToString(exitReason));
        // Log the exit
        // Log the exit
@@ -811,29 +825,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
        }
    }
    }


    private void setDividerVisibility(boolean visible) {
        if (mDividerVisible == visible) return;
        mDividerVisible = visible;
        if (visible) {
            mSplitLayout.init();
            updateUnfoldBounds();
        } else {
            mSplitLayout.release();
        }
        sendSplitVisibilityChanged();
    }

    private void onStageVisibilityChanged(StageListenerImpl stageListener) {
    private void onStageVisibilityChanged(StageListenerImpl stageListener) {
        final boolean sideStageVisible = mSideStageListener.mVisible;
        final boolean sideStageVisible = mSideStageListener.mVisible;
        final boolean mainStageVisible = mMainStageListener.mVisible;
        final boolean mainStageVisible = mMainStageListener.mVisible;
        final boolean bothStageVisible = sideStageVisible && mainStageVisible;
        final boolean bothStageVisible = sideStageVisible && mainStageVisible;
        final boolean bothStageInvisible = !sideStageVisible && !mainStageVisible;
        final boolean bothStageInvisible = !sideStageVisible && !mainStageVisible;
        final boolean sameVisibility = sideStageVisible == mainStageVisible;
        final boolean sameVisibility = sideStageVisible == mainStageVisible;
        // Only add or remove divider when both visible or both invisible to avoid sometimes we only
        // got one stage visibility changed for a moment and it will cause flicker.
        if (sameVisibility) {
            setDividerVisibility(bothStageVisible);
        }


        if (bothStageInvisible) {
        if (bothStageInvisible) {
            if (mExitSplitScreenOnHide
            if (mExitSplitScreenOnHide
@@ -854,11 +851,21 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            if (sameVisibility) {
            if (sameVisibility) {
                t.setVisibility(mSideStage.mRootLeash, bothStageVisible)
                t.setVisibility(mSideStage.mRootLeash, bothStageVisible)
                        .setVisibility(mMainStage.mRootLeash, bothStageVisible);
                        .setVisibility(mMainStage.mRootLeash, bothStageVisible);
                applyDividerVisibility(t);
                setDividerVisibility(bothStageVisible, t);
            }
            }
        });
        });
    }
    }


    private void setDividerVisibility(boolean visible, @Nullable SurfaceControl.Transaction t) {
        mDividerVisible = visible;
        sendSplitVisibilityChanged();
        if (t != null) {
            applyDividerVisibility(t);
        } else {
            mSyncQueue.runInSync(transaction -> applyDividerVisibility(transaction));
        }
    }

    private void applyDividerVisibility(SurfaceControl.Transaction t) {
    private void applyDividerVisibility(SurfaceControl.Transaction t) {
        final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
        final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
        if (dividerLeash == null) {
        if (dividerLeash == null) {
@@ -866,11 +873,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
        }


        if (mDividerVisible) {
        if (mDividerVisible) {
            t.show(dividerLeash)
            t.show(dividerLeash);
                    .setLayer(dividerLeash, SPLIT_DIVIDER_LAYER)
            t.setLayer(dividerLeash, SPLIT_DIVIDER_LAYER);
                    .setPosition(dividerLeash,
            t.setPosition(dividerLeash,
                            mSplitLayout.getDividerBounds().left,
                    mSplitLayout.getDividerBounds().left, mSplitLayout.getDividerBounds().top);
                            mSplitLayout.getDividerBounds().top);
        } else {
        } else {
            t.hide(dividerLeash);
            t.hide(dividerLeash);
        }
        }
@@ -1050,10 +1056,39 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        if (mSplitLayout != null
        if (mSplitLayout != null
                && mSplitLayout.updateConfiguration(mDisplayAreaInfo.configuration)
                && mSplitLayout.updateConfiguration(mDisplayAreaInfo.configuration)
                && mMainStage.isActive()) {
                && mMainStage.isActive()) {
            // TODO(b/204925795): With Shell transition, We are handle roation case for apply split
            //  bounds at onRotateDisplay. But still need to handle unfold case.
            if (ENABLE_SHELL_TRANSITIONS) {
                updateUnfoldBounds();
                return;
            }
            onLayoutSizeChanged(mSplitLayout);
            onLayoutSizeChanged(mSplitLayout);
        }
        }
    }
    }


    @Override
    public void onDisplayAdded(int displayId) {
        if (displayId != DEFAULT_DISPLAY) {
            return;
        }
        mDisplayController.addDisplayChangingController(this::onRotateDisplay);
    }

    private void onRotateDisplay(int displayId, int fromRotation, int toRotation,
            WindowContainerTransaction wct) {
        if (!mMainStage.isActive()) return;
        // Only do this when shell transition
        if (!ENABLE_SHELL_TRANSITIONS) return;

        final SurfaceControl.Transaction t = mTransactionPool.acquire();
        setDividerVisibility(false, t);
        mSplitLayout.rotateTo(toRotation);
        updateWindowBounds(mSplitLayout, wct);
        updateUnfoldBounds();
        t.apply();
        mTransactionPool.release(t);
    }

    private void onFoldedStateChanged(boolean folded) {
    private void onFoldedStateChanged(boolean folded) {
        mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
        mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
        if (!folded) return;
        if (!folded) return;
@@ -1192,6 +1227,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                        Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
                        Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
                                + " with " + taskInfo.taskId + " before startAnimation().");
                                + " with " + taskInfo.taskId + " before startAnimation().");
                    }
                    }
                } else if (info.getType() == TRANSIT_CHANGE
                        && change.getStartRotation() != change.getEndRotation()) {
                    // Show the divider after transition finished.
                    setDividerVisibility(true, finishTransaction);
                }
                }
            }
            }
            if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
            if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
@@ -1216,7 +1255,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        } else if (mSplitTransitions.mPendingDismiss != null
        } else if (mSplitTransitions.mPendingDismiss != null
                && mSplitTransitions.mPendingDismiss.mTransition == transition) {
                && mSplitTransitions.mPendingDismiss.mTransition == transition) {
            shouldAnimate = startPendingDismissAnimation(
            shouldAnimate = startPendingDismissAnimation(
                    mSplitTransitions.mPendingDismiss, info, startTransaction);
                    mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
        }
        }
        if (!shouldAnimate) return false;
        if (!shouldAnimate) return false;


@@ -1249,7 +1288,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
        }


        // Update local states (before animating).
        // Update local states (before animating).
        setDividerVisibility(true);
        mSplitLayout.init();
        setDividerVisibility(true, t);
        setSplitsVisible(true);
        setSplitsVisible(true);


        addDividerBarToTransition(info, t, true /* show */);
        addDividerBarToTransition(info, t, true /* show */);
@@ -1286,7 +1326,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,


    private boolean startPendingDismissAnimation(
    private boolean startPendingDismissAnimation(
            @NonNull SplitScreenTransitions.DismissTransition dismissTransition,
            @NonNull SplitScreenTransitions.DismissTransition dismissTransition,
            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t,
            @NonNull SurfaceControl.Transaction finishT) {
        // Make some noise if things aren't totally expected. These states shouldn't effect
        // Make some noise if things aren't totally expected. These states shouldn't effect
        // transitions locally, but remotes (like Launcher) may get confused if they were
        // transitions locally, but remotes (like Launcher) may get confused if they were
        // depending on listener callbacks. This can happen because task-organizer callbacks
        // depending on listener callbacks. This can happen because task-organizer callbacks
@@ -1343,8 +1384,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            logExit(dismissTransition.mReason);
            logExit(dismissTransition.mReason);
            // TODO: Have a proper remote for this. Until then, though, reset state and use the
            // TODO: Have a proper remote for this. Until then, though, reset state and use the
            //       normal animation stuff (which falls back to the normal launcher remote).
            //       normal animation stuff (which falls back to the normal launcher remote).
            t.hide(mSplitLayout.getDividerLeash());
            setDividerVisibility(false, t);
            setDividerVisibility(false);
            mSplitLayout.release();
            mSplitTransitions.mPendingDismiss = null;
            mSplitTransitions.mPendingDismiss = null;
            return false;
            return false;
        } else {
        } else {
@@ -1356,6 +1397,11 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        // We're dismissing split by moving the other one to fullscreen.
        // We're dismissing split by moving the other one to fullscreen.
        // Since we don't have any animations for this yet, just use the internal example
        // Since we don't have any animations for this yet, just use the internal example
        // animations.
        // animations.

        // Hide divider and dim layer on transition finished.
        setDividerVisibility(false, finishT);
        finishT.hide(mMainStage.mDimLayer);
        finishT.hide(mSideStage.mDimLayer);
        return true;
        return true;
    }
    }


Loading