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

Commit 507da8e1 authored by Tiger Huang's avatar Tiger Huang
Browse files

Make display frame compatible

The display frame is used to limit the windows boundary. The frame is
the same as the parent frame in most cases if the window is not
attched. However, if a window doesn't have any layout related
window/sysui flags and the soft input mode is not ADJUST_RESIZE, the
display frame doesn't need to be inset by IME (but the parent frame
does).

Fix: 163435784
Test: atest ViewRootImplTest DisplayPolicyLayoutTests
Change-Id: Ia61933120027642d1f0e0a490546071ca2b6c853
parent d64cb948
Loading
Loading
Loading
Loading
+16 −13
Original line number Original line Diff line number Diff line
@@ -53,6 +53,9 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CO
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
@@ -1439,11 +1442,10 @@ public final class ViewRootImpl implements ViewParent,
            }
            }


            // Don't lose the mode we last auto-computed.
            // Don't lose the mode we last auto-computed.
            if ((attrs.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
            if ((attrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
                    == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
                    == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
                mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode
                mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode
                        & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
                        & ~SOFT_INPUT_MASK_ADJUST) | (oldSoftInputMode & SOFT_INPUT_MASK_ADJUST);
                        | (oldSoftInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);
            }
            }


            if ((changes & LayoutParams.SOFT_INPUT_MODE_CHANGED) != 0) {
            if ((changes & LayoutParams.SOFT_INPUT_MODE_CHANGED) != 0) {
@@ -2063,6 +2065,7 @@ public final class ViewRootImpl implements ViewParent,
        final int sysUiVis = inOutParams.systemUiVisibility | inOutParams.subtreeSystemUiVisibility;
        final int sysUiVis = inOutParams.systemUiVisibility | inOutParams.subtreeSystemUiVisibility;
        final int flags = inOutParams.flags;
        final int flags = inOutParams.flags;
        final int type = inOutParams.type;
        final int type = inOutParams.type;
        final int adjust = inOutParams.softInputMode & SOFT_INPUT_MASK_ADJUST;


        if ((inOutParams.privateFlags & PRIVATE_FLAG_APPEARANCE_CONTROLLED) == 0) {
        if ((inOutParams.privateFlags & PRIVATE_FLAG_APPEARANCE_CONTROLLED) == 0) {
            inOutParams.insetsFlags.appearance = 0;
            inOutParams.insetsFlags.appearance = 0;
@@ -2088,12 +2091,13 @@ public final class ViewRootImpl implements ViewParent,
            }
            }
        }
        }


        inOutParams.privateFlags &= ~PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;

        if ((inOutParams.privateFlags & PRIVATE_FLAG_FIT_INSETS_CONTROLLED) != 0) {
        if ((inOutParams.privateFlags & PRIVATE_FLAG_FIT_INSETS_CONTROLLED) != 0) {
            return;
            return;
        }
        }


        int types = inOutParams.getFitInsetsTypes();
        int types = inOutParams.getFitInsetsTypes();
        int sides = inOutParams.getFitInsetsSides();
        boolean ignoreVis = inOutParams.isFitInsetsIgnoringVisibility();
        boolean ignoreVis = inOutParams.isFitInsetsIgnoringVisibility();


        if (((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0
        if (((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0
@@ -2108,10 +2112,13 @@ public final class ViewRootImpl implements ViewParent,
        if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
        if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
            ignoreVis = true;
            ignoreVis = true;
        } else if ((types & Type.systemBars()) == Type.systemBars()) {
        } else if ((types & Type.systemBars()) == Type.systemBars()) {
            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
                types |= Type.ime();
                types |= Type.ime();
            } else {
                inOutParams.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
            }
        }
        }
        inOutParams.setFitInsetsTypes(types);
        inOutParams.setFitInsetsTypes(types);
        inOutParams.setFitInsetsSides(sides);
        inOutParams.setFitInsetsIgnoringVisibility(ignoreVis);
        inOutParams.setFitInsetsIgnoringVisibility(ignoreVis);


        // The fitting of insets are not really controlled by the clients, so we remove the flag.
        // The fitting of insets are not really controlled by the clients, so we remove the flag.
@@ -2481,8 +2488,7 @@ public final class ViewRootImpl implements ViewParent,


        if (mFirst || mAttachInfo.mViewVisibilityChanged) {
        if (mFirst || mAttachInfo.mViewVisibilityChanged) {
            mAttachInfo.mViewVisibilityChanged = false;
            mAttachInfo.mViewVisibilityChanged = false;
            int resizeMode = mSoftInputMode &
            int resizeMode = mSoftInputMode & SOFT_INPUT_MASK_ADJUST;
                    WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
            // If we are in auto resize mode, then we need to determine
            // If we are in auto resize mode, then we need to determine
            // what mode to use now.
            // what mode to use now.
            if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
            if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
@@ -2495,11 +2501,8 @@ public final class ViewRootImpl implements ViewParent,
                if (resizeMode == 0) {
                if (resizeMode == 0) {
                    resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
                    resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
                }
                }
                if ((lp.softInputMode &
                if ((lp.softInputMode & SOFT_INPUT_MASK_ADJUST) != resizeMode) {
                        WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) != resizeMode) {
                    lp.softInputMode = (lp.softInputMode & ~SOFT_INPUT_MASK_ADJUST) | resizeMode;
                    lp.softInputMode = (lp.softInputMode &
                            ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) |
                            resizeMode;
                    params = lp;
                    params = lp;
                }
                }
            }
            }
+6 −0
Original line number Original line Diff line number Diff line
@@ -2104,6 +2104,12 @@ public interface WindowManager extends ViewManager {
         */
         */
        public static final int PRIVATE_FLAG_TRUSTED_OVERLAY = 0x20000000;
        public static final int PRIVATE_FLAG_TRUSTED_OVERLAY = 0x20000000;


        /**
         * Flag to indicate that the parent frame of a window should be inset by IME.
         * @hide
         */
        public static final int PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME = 0x40000000;

        /**
        /**
         * An internal annotation for flags that can be specified to {@link #softInputMode}.
         * An internal annotation for flags that can be specified to {@link #softInputMode}.
         *
         *
+10 −1
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -117,7 +118,15 @@ public class ViewRootImplTest {
        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
        ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
        ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);


        // A window which fits system bars must fit IME, unless its type is toast or system alert.
        assertEquals(Type.systemBars(), attrs.getFitInsetsTypes());
    }

    @Test
    public void adjustLayoutParamsForCompatibility_fitSystemBarsAndIme() {
        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
        attrs.softInputMode |= SOFT_INPUT_ADJUST_RESIZE;
        ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);

        assertEquals(Type.systemBars() | Type.ime(), attrs.getFitInsetsTypes());
        assertEquals(Type.systemBars() | Type.ime(), attrs.getFitInsetsTypes());
    }
    }


+10 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
@@ -63,6 +64,7 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
@@ -2055,6 +2057,7 @@ public class DisplayPolicy {


        final int type = attrs.type;
        final int type = attrs.type;
        final int fl = PolicyControl.getWindowFlags(win, attrs);
        final int fl = PolicyControl.getWindowFlags(win, attrs);
        final int pfl = attrs.privateFlags;
        final int sim = attrs.softInputMode;
        final int sim = attrs.softInputMode;


        displayFrames = win.getDisplayFrames(displayFrames);
        displayFrames = win.getDisplayFrames(displayFrames);
@@ -2102,6 +2105,13 @@ public class DisplayPolicy {
        df.set(dfu.left + left, dfu.top + top, dfu.right - right, dfu.bottom - bottom);
        df.set(dfu.left + left, dfu.top + top, dfu.right - right, dfu.bottom - bottom);
        if (attached == null) {
        if (attached == null) {
            pf.set(df);
            pf.set(df);
            if ((pfl & PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME) != 0) {
                final InsetsSource source = mDisplayContent.getInsetsPolicy()
                        .getInsetsForDispatch(win).peekSource(ITYPE_IME);
                if (source != null) {
                    pf.inset(source.calculateInsets(pf, false /* ignoreVisibility */));
                }
            }
            vf.set(adjust != SOFT_INPUT_ADJUST_NOTHING
            vf.set(adjust != SOFT_INPUT_ADJUST_NOTHING
                    ? displayFrames.mCurrent : displayFrames.mDock);
                    ? displayFrames.mCurrent : displayFrames.mDock);
        } else {
        } else {
+19 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -368,6 +369,24 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
        assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
        assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
    }
    }


    @Test
    public void layoutWindowLw_insetParentFrameByIme() {
        final InsetsState state =
                mDisplayContent.getInsetsStateController().getRawInsetsState();
        state.getSource(InsetsState.ITYPE_IME).setVisible(true);
        state.getSource(InsetsState.ITYPE_IME).setFrame(
                0, DISPLAY_HEIGHT - IME_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT);
        mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
        mWindow.mBehindIme = true;
        addWindow(mWindow);

        mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
        mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);

        assertInsetByTopBottom(mWindow.getDisplayFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
        assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, IME_HEIGHT);
    }

    @Test
    @Test
    public void layoutWindowLw_fitDisplayCutout() {
    public void layoutWindowLw_fitDisplayCutout() {
        addDisplayCutout();
        addDisplayCutout();
Loading