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

Commit 9a1c7472 authored by Ming-Shin Lu's avatar Ming-Shin Lu
Browse files

Fix lockscreen can't get IME insets when split-screen activated

As CL[1] fixed Keyboard covered input box after leaving split screen
with using getDefaultTaskDisplayArea().isSplitScreenModeActivated()
to check if needs to let IME window above the window when updating
the above insets state of windows, in case the windowing mode
configuration change not yet updated correctly during task reparenting.

However, this change will let notificationShade won't get IME insets
like when password lock shown, even split-screen is activated behind.

Since notificationShade is not the task window and shouldn't be affected
with splict-screen activivated checking, and we should exclude for
non-task window to ensure the shade can get IME insets.

[1]: I47bcb1234a49ea35c5e0d7281973fb3237e420eb

Fix: 188126678
Test: atest WindowStateTests#\
      testNotificationShadeHasImeInsetsWhenSplitscreenActivated
Test: manual as issue steps:
      1) Set password lock
      2) Active split screen with any 2 apps
      3) Lock phone then try to unlock
      4) Verify if password entry is visible and not covered by IME
Change-Id: Iff537bead93c977d19b820d6e64286a46f8e4982
parent b8cfbebb
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -4603,13 +4603,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            return super.forAllWindows(callback, traverseTopToBottom);
        }

        private boolean skipImeWindowsDuringTraversal(DisplayContent dc) {
        private static boolean skipImeWindowsDuringTraversal(DisplayContent dc) {
            // We skip IME windows so they're processed just above their target, except
            // in split-screen mode where we process the IME containers above the docked divider.
            // Note that this method check should align with {@link
            // WindowState#applyImeWindowsIfNeeded} in case of any state mismatch.
            return dc.getImeTarget(IME_TARGET_LAYERING) != null
                    && !dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated();
            return dc.mImeLayeringTarget != null
                    && (!dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
                             || dc.mImeLayeringTarget.getTask() == null);
        }

        /** Like {@link #forAllWindows}, but ignores {@link #skipImeWindowsDuringTraversal} */
+3 −2
Original line number Diff line number Diff line
@@ -4855,8 +4855,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        // (i.e. Like {@link DisplayContent.ImeContainer#skipImeWindowsDuringTraversal}, the IME
        // window will be ignored to traverse when the IME target is still in split-screen mode).
        if (isImeLayeringTarget()
                && !getDisplayContent().getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
            if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
                && (!mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
                         || getTask() == null)) {
            if (mDisplayContent.forAllImeWindows(callback, traverseTopToBottom)) {
                return true;
            }
        }
+33 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.Surface.ROTATION_0;
@@ -50,6 +51,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.WindowContainer.SYNC_STATE_WAITING_FOR_DRAW;

import static com.google.common.truth.Truth.assertThat;
@@ -58,6 +60,7 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -923,4 +926,34 @@ public class WindowStateTests extends WindowTestsBase {
        verify(app.getDisplayContent()).updateImeControlTarget();
        assertEquals(mAppWindow, mDisplayContent.getImeTarget(IME_TARGET_CONTROL).getWindow());
    }

    @UseTestDisplay(addWindows = { W_ACTIVITY, W_INPUT_METHOD, W_NOTIFICATION_SHADE })
    @Test
    public void testNotificationShadeHasImeInsetsWhenSplitscreenActivated() {
        WindowState app = createWindow(null, TYPE_BASE_APPLICATION,
                mAppWindow.mToken, "app");

        // Simulate entering multi-window mode and verify if the split-screen is activated.
        app.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, app.getWindowingMode());
        assertTrue(mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated());

        // Simulate notificationShade is shown and being IME layering target.
        mNotificationShadeWindow.setHasSurface(true);
        mNotificationShadeWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
        assertTrue(mNotificationShadeWindow.canBeImeTarget());
        mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_IME).setWindow(
                mImeWindow, null, null);

        mDisplayContent.computeImeTarget(true);
        assertEquals(mNotificationShadeWindow, mDisplayContent.getImeTarget(IME_TARGET_LAYERING));
        mDisplayContent.getInsetsStateController().getRawInsetsState()
                .setSourceVisible(ITYPE_IME, true);

        // Verify notificationShade can still get IME insets even the split-screen is activated.
        InsetsState state = mDisplayContent.getInsetsStateController().getInsetsForWindow(
                mNotificationShadeWindow);
        assertNotNull(state.peekSource(ITYPE_IME));
        assertTrue(state.getSource(ITYPE_IME).isVisible());
    }
}