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

Commit da44526b authored by Jerry Chang's avatar Jerry Chang
Browse files

Fix the content of the bottom split being truncated while showing IME

Freeze the configuration size when shifting split layout so that client
apps can calculate insets properly and won't get config or relaunch.

Fix: 192410210
Test: atest WMShellUnitTests
Test: verified the content of the bottom split won't be truncated when
adjusting split layout with IME and won't get relaunch.

Change-Id: I38da063ffacc19b691c14b74d118949293414492
parent ae5d3b43
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -215,7 +215,7 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou

            if (mSplitLayout != null) {
                if (mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) {
                    onBoundsChanged(mSplitLayout);
                    onLayoutChanged(mSplitLayout);
                }
                // updateConfiguration re-inits the dividerbar, so show it now
                mSyncQueue.runInSync(t -> t.show(mSplitLayout.getDividerLeash()));
@@ -299,17 +299,24 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou
    }

    @Override
    public void onBoundsChanging(SplitLayout layout) {
    public void onLayoutChanging(SplitLayout layout) {
        mSyncQueue.runInSync(t ->
                layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2));
    }

    @Override
    public void onBoundsChanged(SplitLayout layout) {
    public void onLayoutChanged(SplitLayout layout) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        layout.applyTaskChanges(wct, mTaskInfo1, mTaskInfo2);
        mSyncQueue.queue(wct);
        mSyncQueue.runInSync(t ->
                layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2));
    }

    @Override
    public void onLayoutShifted(int offsetX, int offsetY, SplitLayout layout) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        layout.applyLayoutShifted(wct, offsetX, offsetY, mTaskInfo1, mTaskInfo2);
        mController.getTaskOrganizer().applyTransaction(wct);
    }
}
+69 −7
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.wm.shell.common.split;

import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_TOP;

@@ -224,13 +226,13 @@ public final class SplitLayout {
    void updateDivideBounds(int position) {
        updateBounds(position);
        mSplitWindowManager.setResizingSplits(true);
        mSplitLayoutHandler.onBoundsChanging(this);
        mSplitLayoutHandler.onLayoutChanging(this);
    }

    void setDividePosition(int position) {
        mDividePosition = position;
        updateBounds(mDividePosition);
        mSplitLayoutHandler.onBoundsChanged(this);
        mSplitLayoutHandler.onLayoutChanged(this);
        mSplitWindowManager.setResizingSplits(false);
    }

@@ -352,6 +354,46 @@ public final class SplitLayout {
                .setBounds(task2.token, mImePositionProcessor.adjustForIme(mBounds2));
    }

    /**
     * Shift configuration bounds to prevent client apps get configuration changed or relaunch. And
     * restore shifted configuration bounds if it's no longer shifted.
     */
    public void applyLayoutShifted(WindowContainerTransaction wct, int offsetX, int offsetY,
            ActivityManager.RunningTaskInfo taskInfo1, ActivityManager.RunningTaskInfo taskInfo2) {
        if (offsetX == 0 && offsetY == 0) {
            wct.setBounds(taskInfo1.token, mBounds1);
            wct.setAppBounds(taskInfo1.token, null);
            wct.setScreenSizeDp(taskInfo1.token,
                    SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);

            wct.setBounds(taskInfo2.token, mBounds2);
            wct.setAppBounds(taskInfo2.token, null);
            wct.setScreenSizeDp(taskInfo2.token,
                    SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
        } else {
            final Rect bounds = new Rect();
            bounds.set(taskInfo1.configuration.windowConfiguration.getBounds());
            bounds.offset(offsetX, offsetY);
            wct.setBounds(taskInfo1.token, bounds);
            bounds.set(taskInfo1.configuration.windowConfiguration.getAppBounds());
            bounds.offset(offsetX, offsetY);
            wct.setAppBounds(taskInfo1.token, bounds);
            wct.setScreenSizeDp(taskInfo1.token,
                    taskInfo1.configuration.screenWidthDp,
                    taskInfo1.configuration.screenHeightDp);

            bounds.set(taskInfo2.configuration.windowConfiguration.getBounds());
            bounds.offset(offsetX, offsetY);
            wct.setBounds(taskInfo2.token, bounds);
            bounds.set(taskInfo2.configuration.windowConfiguration.getAppBounds());
            bounds.offset(offsetX, offsetY);
            wct.setAppBounds(taskInfo2.token, bounds);
            wct.setScreenSizeDp(taskInfo2.token,
                    taskInfo2.configuration.screenWidthDp,
                    taskInfo2.configuration.screenHeightDp);
        }
    }

    /** Handles layout change event. */
    public interface SplitLayoutHandler {

@@ -359,10 +401,18 @@ public final class SplitLayout {
        void onSnappedToDismiss(boolean snappedToEnd);

        /** Calls when the bounds is changing due to animation or dragging divider bar. */
        void onBoundsChanging(SplitLayout layout);
        void onLayoutChanging(SplitLayout layout);

        /** Calls when the target bounds changed. */
        void onBoundsChanged(SplitLayout layout);
        void onLayoutChanged(SplitLayout layout);

        /**
         * Notifies when the layout shifted. So the layout handler can shift configuration
         * bounds correspondingly to make sure client apps won't get configuration changed or
         * relaunch. If the layout is no longer shifted, layout handler should restore shifted
         * configuration bounds.
         */
        void onLayoutShifted(int offsetX, int offsetY, SplitLayout layout);

        /** Calls when user double tapped on the divider bar. */
        default void onDoubleTappedDivider() {
@@ -427,6 +477,18 @@ public final class SplitLayout {
                    && !isFloating && !isLandscape(mRootBounds) && showing;
            mTargetYOffset = needOffset ? getTargetYOffset() : 0;

            if (mTargetYOffset != mLastYOffset) {
                // Freeze the configuration size with offset to prevent app get a configuration
                // changed or relaunch. This is required to make sure client apps will calculate
                // insets properly after layout shifted.
                if (mTargetYOffset == 0) {
                    mSplitLayoutHandler.onLayoutShifted(0, 0, SplitLayout.this);
                } else {
                    mSplitLayoutHandler.onLayoutShifted(0, mTargetYOffset - mLastYOffset,
                            SplitLayout.this);
                }
            }

            // Make {@link DividerView} non-interactive while IME showing in split mode. Listen to
            // ImePositionProcessor#onImeVisibilityChanged directly in DividerView is not enough
            // because DividerView won't receive onImeVisibilityChanged callback after it being
@@ -441,7 +503,7 @@ public final class SplitLayout {
        public void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t) {
            if (displayId != mDisplayId) return;
            onProgress(getProgress(imeTop));
            mSplitLayoutHandler.onBoundsChanging(SplitLayout.this);
            mSplitLayoutHandler.onLayoutChanging(SplitLayout.this);
        }

        @Override
@@ -449,7 +511,7 @@ public final class SplitLayout {
                SurfaceControl.Transaction t) {
            if (displayId != mDisplayId || cancel) return;
            onProgress(1.0f);
            mSplitLayoutHandler.onBoundsChanging(SplitLayout.this);
            mSplitLayoutHandler.onLayoutChanging(SplitLayout.this);
        }

        @Override
@@ -459,7 +521,7 @@ public final class SplitLayout {
            if (!controlling && mImeShown) {
                reset();
                mSplitWindowManager.setInteractive(true);
                mSplitLayoutHandler.onBoundsChanging(SplitLayout.this);
                mSplitLayoutHandler.onLayoutChanging(SplitLayout.this);
            }
        }

+16 −4
Original line number Diff line number Diff line
@@ -422,7 +422,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        if (mSideStageListener.mVisible && updateBounds) {
            if (wct == null) {
                // onBoundsChanged builds/applies a wct with the contents of updateWindowBounds.
                onBoundsChanged(mSplitLayout);
                onLayoutChanged(mSplitLayout);
            } else {
                updateWindowBounds(mSplitLayout, wct);
            }
@@ -732,12 +732,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    }

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

    @Override
    public void onBoundsChanged(SplitLayout layout) {
    public void onLayoutChanged(SplitLayout layout) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        updateWindowBounds(layout, wct);
        mSyncQueue.queue(wct);
@@ -780,6 +780,18 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        return SPLIT_POSITION_UNDEFINED;
    }

    @Override
    public void onLayoutShifted(int offsetX, int offsetY, SplitLayout layout) {
        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.applyLayoutShifted(wct, offsetX, offsetY, topLeftStage.mRootTaskInfo,
                bottomRightStage.mRootTaskInfo);
        mTaskOrganizer.applyTransaction(wct);
    }

    @Override
    public void onDisplayAreaAppeared(DisplayAreaInfo displayAreaInfo) {
        mDisplayAreaInfo = displayAreaInfo;
@@ -802,7 +814,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        if (mSplitLayout != null
                && mSplitLayout.updateConfiguration(mDisplayAreaInfo.configuration)
                && mMainStage.isActive()) {
            onBoundsChanged(mSplitLayout);
            onLayoutChanged(mSplitLayout);
            mSyncQueue.runInSync(t -> applyDividerVisibility(t));
        }
    }
+2 −2
Original line number Diff line number Diff line
@@ -92,13 +92,13 @@ public class SplitLayoutTests extends ShellTestCase {
    @Test
    public void testUpdateDivideBounds() {
        mSplitLayout.updateDivideBounds(anyInt());
        verify(mSplitLayoutHandler).onBoundsChanging(any(SplitLayout.class));
        verify(mSplitLayoutHandler).onLayoutChanging(any(SplitLayout.class));
    }

    @Test
    public void testSetDividePosition() {
        mSplitLayout.setDividePosition(anyInt());
        verify(mSplitLayoutHandler).onBoundsChanged(any(SplitLayout.class));
        verify(mSplitLayoutHandler).onLayoutChanged(any(SplitLayout.class));
    }

    @Test