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

Commit a70fd879 authored by Tiger Huang's avatar Tiger Huang
Browse files

Set IME insets invisible if the target is above IME

We would remove the insets source of IME before dispatching to the
target above IME previously. However, when the z-order of an invisible
IME is changed, the client may receive unnecessary insets-change
callcacks (InsetsState with or without IME source).

With this CL, as long as IME is invisible, no matter what z-order the
IME has, the client will get the same IME source.

Fix: 152722388
Test: atest ChildlessActivityTest InsetsStateControllerTest
Change-Id: I9f147976be47a9fced4493dba10113b8ab048f4e
parent 82dc6147
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ class InsetsStateController {

        if (aboveIme) {
            state = new InsetsState(state);
            state.removeSource(ITYPE_IME);
            state.setSourceVisible(ITYPE_IME, false);
        }

        return state;
+34 −29
Original line number Diff line number Diff line
@@ -29,9 +29,11 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.spy;
@@ -44,7 +46,6 @@ import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.test.InsetsModeSession;

import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;

import org.junit.AfterClass;
@@ -153,22 +154,24 @@ public class InsetsStateControllerTest extends WindowTestsBase {

    @Test
    public void testStripForDispatch_belowIme() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
        getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);

        getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        app.mBehindIme = true;

        assertNotNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
        assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
    }

    @Test
    public void testStripForDispatch_aboveIme() {
        final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);

        getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        app.mBehindIme = false;

        assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
        assertFalse(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
    }

    @Test
@@ -191,8 +194,9 @@ public class InsetsStateControllerTest extends WindowTestsBase {
        mDisplayContent.setLayoutNeeded();
        mDisplayContent.applySurfaceChangesTransaction();

        // app won't get IME insets while above IME.
        assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
        // app won't get visible IME insets while above IME even when IME is visible.
        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
        assertFalse(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());

        // Reset invocation counter.
        clearInvocations(app);
@@ -206,43 +210,44 @@ public class InsetsStateControllerTest extends WindowTestsBase {
        // Make sure app got notified.
        verify(app, atLeast(1)).notifyInsetsChanged();

        // app will get IME insets while below IME.
        assertNotNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
        // app will get visible IME insets while below IME when IME is visible.
        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
        assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
    }

    @Test
    public void testStripForDispatch_childWindow_altFocusable() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);

        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
        child.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;

        final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");

        // IME cannot be the IME target.
        ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;

        getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
        mDisplayContent.computeImeTarget(true);
        mDisplayContent.setLayoutNeeded();
        mDisplayContent.applySurfaceChangesTransaction();

        assertNull(getController().getInsetsForDispatch(child).peekSource(ITYPE_IME));
        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
        assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
        assertFalse(getController().getInsetsForDispatch(child).getSource(ITYPE_IME).isVisible());
    }

    @Test
    public void testStripForDispatch_childWindow_splitScreen() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);

        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
        child.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
        child.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);

        final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");

        // IME cannot be the IME target.
        ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;

        getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
        mDisplayContent.computeImeTarget(true);
        mDisplayContent.setLayoutNeeded();
        mDisplayContent.applySurfaceChangesTransaction();

        assertNull(getController().getInsetsForDispatch(child).peekSource(ITYPE_IME));
        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
        assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
        assertFalse(getController().getInsetsForDispatch(child).getSource(ITYPE_IME).isVisible());
    }

    @Test