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

Commit dd637175 authored by Tony Huang's avatar Tony Huang
Browse files

Fix divider disappear when rotation on shell transition

When rotation, it will re-init the split divider for new rotation on
DAinfoChanged callback, but when shell transition, we should do it on
startAnimation to make transition smooth and make didider could release
by specfic Transcation to avoid it hide immediately but didn't sync with
transition.

Fix: 222158856
Test: manual
Test: pass existing tests
Change-Id: I797ffd0ea35d89b4ec1e3ef4828ce36e18c860be
parent 64e22982
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -217,9 +217,13 @@ public class WindowlessWindowManager implements IWindowSession {
            throw new IllegalArgumentException(
                    "Invalid window token (never added or removed already)");
        }
        removeSurface(state.mSurfaceControl);
    }

    /** Separate from {@link #remove} so that subclasses can put removal on a sync transaction. */
    protected void removeSurface(SurfaceControl sc) {
        try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
            t.remove(state.mSurfaceControl).apply();
            t.remove(sc).apply();
        }
    }

+24 −7
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
    private WindowContainerToken mWinToken2;
    private int mDividePosition;
    private boolean mInitialized = false;
    private boolean mFreezeDividerWindow = false;
    private int mOrientation;
    private int mRotation;

@@ -225,11 +226,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
        mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
        initDividerPosition(mTempRect);

        if (mInitialized) {
            release();
            init();
        }

        return true;
    }

@@ -298,20 +294,37 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
    }

    /** Releases the surface holding the current {@link DividerView}. */
    public void release() {
    public void release(SurfaceControl.Transaction t) {
        if (!mInitialized) return;
        mInitialized = false;
        mSplitWindowManager.release();
        mSplitWindowManager.release(t);
        mDisplayImeController.removePositionProcessor(mImePositionProcessor);
        mImePositionProcessor.reset();
    }

    public void release() {
        release(null /* t */);
    }

    /** Releases and re-inflates {@link DividerView} on the root surface. */
    public void update(SurfaceControl.Transaction t) {
        if (!mInitialized) return;
        mSplitWindowManager.release(t);
        mImePositionProcessor.reset();
        mSplitWindowManager.init(this, mInsetsState);
    }

    @Override
    public void insetsChanged(InsetsState insetsState) {
        mInsetsState.set(insetsState);
        if (!mInitialized) {
            return;
        }
        if (mFreezeDividerWindow) {
            // DO NOT change its layout before transition actually run because it might cause
            // flicker.
            return;
        }
        mSplitWindowManager.onInsetsChanged(insetsState);
    }

@@ -323,6 +336,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
        }
    }

    public void setFreezeDividerWindow(boolean freezeDividerWindow) {
        mFreezeDividerWindow = freezeDividerWindow;
    }

    /**
     * Updates bounds with the passing position. Usually used to update recording bounds while
     * performing animation or dragging divider bar to resize the splits.
+21 −2
Original line number Diff line number Diff line
@@ -58,6 +58,9 @@ public final class SplitWindowManager extends WindowlessWindowManager {
    private SurfaceControl mLeash;
    private DividerView mDividerView;

    // Used to "pass" a transaction to WWM.remove so that view removal can be synchronized.
    private SurfaceControl.Transaction mSyncTransaction = null;

    public interface ParentContainerCallbacks {
        void attachToParentSurface(SurfaceControl.Builder b);
        void onLeashReady(SurfaceControl leash);
@@ -130,22 +133,38 @@ public final class SplitWindowManager extends WindowlessWindowManager {
     * Releases the surface control of the current {@link DividerView} and tear down the view
     * hierarchy.
     */
    void release() {
    void release(@Nullable SurfaceControl.Transaction t) {
        if (mDividerView != null) {
            mDividerView = null;
        }

        if (mViewHost != null){
            mSyncTransaction = t;
            mViewHost.release();
            mSyncTransaction = null;
            mViewHost = null;
        }

        if (mLeash != null) {
            if (t == null) {
                new SurfaceControl.Transaction().remove(mLeash).apply();
            } else {
                t.remove(mLeash);
            }
            mLeash = null;
        }
    }

    @Override
    protected void removeSurface(SurfaceControl sc) {
        // This gets called via SurfaceControlViewHost.release()
        if (mSyncTransaction != null) {
            mSyncTransaction.remove(sc);
        } else {
            super.removeSurface(sc);
        }
    }

    void setInteractive(boolean interactive) {
        if (mDividerView == null) return;
        mDividerView.setInteractive(interactive);
+18 −7
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;

import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -1171,6 +1172,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                updateUnfoldBounds();
                return;
            }

            mSplitLayout.update(null /* t */);
            onLayoutSizeChanged(mSplitLayout);
        }
    }
@@ -1198,7 +1201,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        if (!ENABLE_SHELL_TRANSITIONS) return;

        final SurfaceControl.Transaction t = mTransactionPool.acquire();
        setDividerVisibility(false, t);
        mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
        mSplitLayout.rotateTo(toRotation, mDisplayLayout.stableInsets());
        updateWindowBounds(mSplitLayout, wct);
@@ -1255,8 +1257,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            @Nullable TransitionRequestInfo request) {
        final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
        if (triggerTask == null) {
            if (mMainStage.isActive()) {
                if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null) {
                    mSplitLayout.setFreezeDividerWindow(true);
                }
                // Still want to monitor everything while in split-screen, so return non-null.
            return mMainStage.isActive() ? new WindowContainerTransaction() : null;
                return new WindowContainerTransaction();
            } else {
                return null;
            }
        } else if (triggerTask.displayId != mDisplayId) {
            // Skip handling task on the other display.
            return null;
@@ -1352,8 +1361,14 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            // If we're not in split-mode, just abort so something else can handle it.
            if (!mMainStage.isActive()) return false;

            mSplitLayout.setFreezeDividerWindow(false);
            for (int iC = 0; iC < info.getChanges().size(); ++iC) {
                final TransitionInfo.Change change = info.getChanges().get(iC);
                if (change.getMode() == TRANSIT_CHANGE
                        && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
                    mSplitLayout.update(startTransaction);
                }

                final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                if (taskInfo == null || !taskInfo.hasParentTask()) continue;
                final StageTaskListener stage = getStageOfTask(taskInfo);
@@ -1368,10 +1383,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                        Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
                                + " 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) {
+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ public class SplitWindowManagerTests extends ShellTestCase {
    public void testInitRelease() {
        mSplitWindowManager.init(mSplitLayout, new InsetsState());
        assertThat(mSplitWindowManager.getSurfaceControl()).isNotNull();
        mSplitWindowManager.release();
        mSplitWindowManager.release(null /* t */);
        assertThat(mSplitWindowManager.getSurfaceControl()).isNull();
    }
}