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

Commit e9f13e13 authored by Evan Rosky's avatar Evan Rosky
Browse files

Aggregate stage-split operations into WCT

Previously different operations were just applying transactions
as they were called. We need better control over this for
synchronization purposes, so we basically pass wct into these
operations so that everything can be aggregated into one WCT
if desired.

Bug: 192291727
Test: existing tests pass (this is a refactor)
Change-Id: Ie26d634bcd3ab6baf4d2a4788986689914a58c13
parent 2e5a48be
Loading
Loading
Loading
Loading
+12 −11
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
    }

    public void setSideStagePosition(@SplitPosition int sideStagePosition) {
        mStageCoordinator.setSideStagePosition(sideStagePosition);
        mStageCoordinator.setSideStagePosition(sideStagePosition, null /* wct */);
    }

    public void setSideStageVisibility(boolean visible) {
@@ -185,7 +185,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,

    public void startTask(int taskId, @SplitScreen.StageType int stage,
            @SplitPosition int position, @Nullable Bundle options) {
        options = resolveStartStage(stage, position, options);
        options = resolveStartStage(stage, position, options, null /* wct */);

        try {
            ActivityTaskManager.getService().startActivityFromRecents(taskId, options);
@@ -197,7 +197,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
    public void startShortcut(String packageName, String shortcutId,
            @SplitScreen.StageType int stage, @SplitPosition int position,
            @Nullable Bundle options, UserHandle user) {
        options = resolveStartStage(stage, position, options);
        options = resolveStartStage(stage, position, options, null /* wct */);

        try {
            LauncherApps launcherApps =
@@ -222,32 +222,33 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
    }

    private Bundle resolveStartStage(@SplitScreen.StageType int stage,
            @SplitPosition int position, @Nullable Bundle options) {
            @SplitPosition int position, @Nullable Bundle options,
            @Nullable WindowContainerTransaction wct) {
        switch (stage) {
            case STAGE_TYPE_UNDEFINED: {
                // Use the stage of the specified position is valid.
                if (position != SPLIT_POSITION_UNDEFINED) {
                    if (position == mStageCoordinator.getSideStagePosition()) {
                        options = resolveStartStage(STAGE_TYPE_SIDE, position, options);
                        options = resolveStartStage(STAGE_TYPE_SIDE, position, options, wct);
                    } else {
                        options = resolveStartStage(STAGE_TYPE_MAIN, position, options);
                        options = resolveStartStage(STAGE_TYPE_MAIN, position, options, wct);
                    }
                } else {
                    // Exit split-screen and launch fullscreen since stage wasn't specified.
                    mStageCoordinator.exitSplitScreen();
                    mStageCoordinator.prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
                }
                break;
            }
            case STAGE_TYPE_SIDE: {
                if (position != SPLIT_POSITION_UNDEFINED) {
                    mStageCoordinator.setSideStagePosition(position);
                    mStageCoordinator.setSideStagePosition(position, wct);
                } else {
                    position = mStageCoordinator.getSideStagePosition();
                }
                if (options == null) {
                    options = new Bundle();
                }
                mStageCoordinator.updateActivityOptions(options, position);
                mStageCoordinator.updateActivityOptions(options, position, wct);
                break;
            }
            case STAGE_TYPE_MAIN: {
@@ -255,14 +256,14 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
                    // Set the side stage opposite of what we want to the main stage.
                    final int sideStagePosition = position == SPLIT_POSITION_TOP_OR_LEFT
                            ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
                    mStageCoordinator.setSideStagePosition(sideStagePosition);
                    mStageCoordinator.setSideStagePosition(sideStagePosition, wct);
                } else {
                    position = mStageCoordinator.getMainStagePosition();
                }
                if (options == null) {
                    options = new Bundle();
                }
                mStageCoordinator.updateActivityOptions(options, position);
                mStageCoordinator.updateActivityOptions(options, position, wct);
                break;
            }
            default:
+51 −24
Original line number Diff line number Diff line
@@ -211,7 +211,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
            @SplitPosition int sideStagePosition) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        setSideStagePosition(sideStagePosition);
        setSideStagePosition(sideStagePosition, wct);
        mMainStage.activate(getMainStageBounds(), wct);
        mSideStage.addTask(task, getSideStageBounds(), wct);
        mTaskOrganizer.applyTransaction(wct);
@@ -243,7 +243,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        mainOptions = mainOptions != null ? mainOptions : new Bundle();
        sideOptions = sideOptions != null ? sideOptions : new Bundle();
        setSideStagePosition(sidePosition);
        setSideStagePosition(sidePosition, wct);

        // Build a request WCT that will launch both apps such that task 0 is on the main stage
        // while task 1 is on the side stage.
@@ -312,7 +312,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }

        sideOptions = sideOptions != null ? sideOptions : new Bundle();
        setSideStagePosition(sidePosition);
        setSideStagePosition(sidePosition, wct);

        // Build a request WCT that will launch both apps such that task 0 is on the main stage
        // while task 1 is on the side stage.
@@ -342,18 +342,24 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
    }

    void setSideStagePosition(@SplitPosition int sideStagePosition) {
        setSideStagePosition(sideStagePosition, true /* updateBounds */);
    void setSideStagePosition(@SplitPosition int sideStagePosition,
            @Nullable WindowContainerTransaction wct) {
        setSideStagePosition(sideStagePosition, true /* updateBounds */, wct);
    }

    private void setSideStagePosition(@SplitPosition int sideStagePosition,
            boolean updateBounds) {
            boolean updateBounds, @Nullable WindowContainerTransaction wct) {
        if (mSideStagePosition == sideStagePosition) return;
        mSideStagePosition = sideStagePosition;
        sendOnStagePositionChanged();

        if (mSideStageListener.mVisible && updateBounds) {
            if (wct == null) {
                // onBoundsChanged builds/applies a wct with the contents of updateWindowBounds.
                onBoundsChanged(mSplitLayout);
            } else {
                updateWindowBounds(mSplitLayout, wct);
            }
        }
    }

@@ -388,7 +394,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mSplitLayout.resetDividerPosition();
    }

    private void prepareExitSplitScreen(@SplitScreen.StageType int stageToTop,
    /**
     * Unlike exitSplitScreen, this takes a stagetype vs an actual stage-reference and populates
     * an existing WindowContainerTransaction (rather than applying immediately). This is intended
     * to be used when exiting split might be bundled with other window operations.
     */
    void prepareExitSplitScreen(@SplitScreen.StageType int stageToTop,
            @NonNull WindowContainerTransaction wct) {
        mSideStage.removeAllTasks(wct, stageToTop == STAGE_TYPE_SIDE);
        mMainStage.deactivate(wct, stageToTop == STAGE_TYPE_MAIN);
@@ -403,17 +414,23 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        opts.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, stage.mRootTaskInfo.token);
    }

    void updateActivityOptions(Bundle opts, @SplitPosition int position) {
    void updateActivityOptions(Bundle opts, @SplitPosition int position,
            @Nullable WindowContainerTransaction wct) {
        addActivityOptions(opts, position == mSideStagePosition ? mSideStage : mMainStage);

        if (!mMainStage.isActive()) {
            // Activate the main stage in anticipation of an app launch.
            final WindowContainerTransaction wct = new WindowContainerTransaction();
            boolean needsApply = wct == null;
            if (needsApply) {
                wct = new WindowContainerTransaction();
            }
            mMainStage.activate(getMainStageBounds(), wct);
            mSideStage.setBounds(getSideStageBounds(), wct);
            if (needsApply) {
                mTaskOrganizer.applyTransaction(wct);
            }
        }
    }

    void registerSplitScreenListener(SplitScreen.SplitScreenListener listener) {
        if (mListeners.contains(listener)) return;
@@ -624,32 +641,41 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    @Override
    public void onDoubleTappedDivider() {
        setSideStagePosition(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT
                ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT);
                ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT, null /* wct */);
    }

    @Override
    public void onBoundsChanging(SplitLayout layout) {
        mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
    }

    @Override
    public void onBoundsChanged(SplitLayout layout) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        updateWindowBounds(layout, wct);
        mSyncQueue.queue(wct);
        mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
    }

    /**
     * Populates `wct` with operations that match the split windows to the current layout.
     * To match relevant surfaces, make sure to call updateSurfaceBounds after `wct` is applied
     */
    private void updateWindowBounds(SplitLayout layout, WindowContainerTransaction wct) {
        final StageTaskListener topLeftStage =
                mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
        final StageTaskListener bottomRightStage =
                mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;

        mSyncQueue.runInSync(t -> layout.applySurfaceChanges(t, topLeftStage.mRootLeash,
                bottomRightStage.mRootLeash, topLeftStage.mDimLayer, bottomRightStage.mDimLayer));
        layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo);
    }

    @Override
    public void onBoundsChanged(SplitLayout layout) {
    void updateSurfaceBounds(@Nullable SplitLayout layout, @NonNull SurfaceControl.Transaction t) {
        final StageTaskListener topLeftStage =
                mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
        final StageTaskListener bottomRightStage =
                mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;

        final WindowContainerTransaction wct = new WindowContainerTransaction();
        layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo);
        mSyncQueue.queue(wct);
        mSyncQueue.runInSync(t -> layout.applySurfaceChanges(t, topLeftStage.mRootLeash,
                bottomRightStage.mRootLeash, topLeftStage.mDimLayer, bottomRightStage.mDimLayer));
        (layout != null ? layout : mSplitLayout).applySurfaceChanges(t, topLeftStage.mRootLeash,
                bottomRightStage.mRootLeash, topLeftStage.mDimLayer, bottomRightStage.mDimLayer);
    }

    @Override
@@ -869,7 +895,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,

            // Update local states (before animating).
            setDividerVisibility(true);
            setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, false /* updateBounds */);
            setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, false /* updateBounds */,
                    null /* wct */);
            setSplitsVisible(true);

            addDividerBarToTransition(info, t, true /* show */);