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

Commit 31e2e5a6 authored by Cosmin Băieș's avatar Cosmin Băieș
Browse files

Remove testing variant of setImeLayeringTarget

This removes the testing variant of setImeLayeringTarget, that was
simply updating the field without reporting the update to other
components. Tests are updated to use the real method, which triggers all
the updates. Mentioned below are the tests with slight changes to
accomdate this.

The two WindowState tests were using old code paths, and were not
setting the IME control target properly. They are now updated in line
with recent code changes.

Flag: EXEMPT cleanup
Bug: 281029564
Test: atest DisplayContentTests#testComputeImeLayeringTarget_shouldNotCheckOutdatedImeLayeringTargetWhenRemoved
  WindowStateTests#testAdjustImeInsetsVisibilityWhenSwitchingApps
  WindowStateTests#testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode
Change-Id: Ic7f336e578e397d07f6bae583de81b15450b2ede
parent 3eb26f21
Loading
Loading
Loading
Loading
+8 −12
Original line number Diff line number Diff line
@@ -675,10 +675,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    private InsetsControlTarget mImeControlTarget;

    /**
     * The last {@link #mImeInputTarget} processed from {@link #setImeLayeringTargetInner}. This
     * enables updating the {@link #mImeControlTarget} when the {@link #mImeLayeringTarget} remains
     * the same, and only the {@link #mImeInputTarget} changes. For example, this can happen when
     * the IME is moving to a SurfaceControlViewHost backed EmbeddedWindow.
     * The last {@link #mImeInputTarget} processed from {@link #setImeLayeringTarget}. This enables
     * updating the {@link #mImeControlTarget} when the {@link #mImeLayeringTarget} remains the
     * same, and only the {@link #mImeInputTarget} changes. For example, this can happen when the
     * IME is moving to a SurfaceControlViewHost backed EmbeddedWindow.
     */
    @Nullable
    private InputTarget mLastImeInputTarget;
@@ -4165,7 +4165,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        }

        if (update) {
            setImeLayeringTargetInner(target);
            setImeLayeringTarget(target);
        }

        return target;
@@ -4306,11 +4306,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        }
    }

    @VisibleForTesting
    void setImeLayeringTarget(@Nullable WindowState target) {
        mImeLayeringTarget = target;
    }

    /**
     * Sets the IME layering target, and updates the IME control target. Also updates the IME parent
     * if necessary.
@@ -4318,7 +4313,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     * @param target the window to place the IME on top of. If {@code null}, the IME will be placed
     *               on top of its parent's surface.
     */
    private void setImeLayeringTargetInner(@Nullable WindowState target) {
    @VisibleForTesting
    void setImeLayeringTarget(@Nullable WindowState target) {
        // This function is also responsible for updating the IME control target and so in the case
        // where the IME layering target does not change but the IME input target does (for example,
        // IME moving to a SurfaceControlViewHost) we have to continue executing this function,
@@ -4342,7 +4338,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            }
        }

        ProtoLog.i(WM_DEBUG_IME, "setImeLayeringTargetInner %s", target);
        ProtoLog.i(WM_DEBUG_IME, "setImeLayeringTarget %s", target);
        boolean forceUpdateImeParent = target != mImeLayeringTarget;
        mImeLayeringTarget = target;

+28 −24
Original line number Diff line number Diff line
@@ -644,8 +644,8 @@ public class DisplayContentTests extends WindowTestsBase {
        final DisplayContent dc = mDisplayContent;
        final WindowState ws = newWindowBuilder("app window", TYPE_APPLICATION).setDisplay(
                dc).build();
        dc.setImeLayeringTarget(ws);
        dc.setImeInputTarget(ws);
        dc.setImeLayeringTarget(ws);

        // Adjust bounds so that matchesRootDisplayAreaBounds() returns false.
        final Rect bounds = new Rect(dc.getBounds());
@@ -1230,8 +1230,9 @@ public class DisplayContentTests extends WindowTestsBase {
    @Test
    public void testComputeImeParent_app() {
        final DisplayContent dc = createNewDisplay();
        dc.setImeLayeringTarget(newWindowBuilder("app", TYPE_BASE_APPLICATION).build());
        dc.setImeInputTarget(dc.getImeLayeringTarget());
        final var appWin = newWindowBuilder("appWin", TYPE_BASE_APPLICATION).setDisplay(dc).build();
        dc.setImeInputTarget(appWin);
        dc.setImeLayeringTarget(appWin);
        assertEquals(dc.getImeLayeringTarget().mActivityRecord.getSurfaceControl(),
                dc.computeImeParent().getSurfaceControl());
    }
@@ -1239,9 +1240,10 @@ public class DisplayContentTests extends WindowTestsBase {
    @Test
    public void testComputeImeParent_app_notFullscreen() {
        final DisplayContent dc = createNewDisplay();
        dc.setImeLayeringTarget(newWindowBuilder("app", TYPE_STATUS_BAR).build());
        dc.getImeLayeringTarget().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
        dc.setImeInputTarget(dc.getImeLayeringTarget());
        final var appWin = newWindowBuilder("appWin", TYPE_STATUS_BAR).setDisplay(dc)
                .setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW).build();
        dc.setImeInputTarget(appWin);
        dc.setImeLayeringTarget(appWin);
        assertEquals(dc.getImeContainer().getParentSurfaceControl(),
                dc.computeImeParent().getSurfaceControl());
    }
@@ -1260,8 +1262,9 @@ public class DisplayContentTests extends WindowTestsBase {
    @Test
    public void testComputeImeParent_noApp() {
        final DisplayContent dc = createNewDisplay();
        dc.setImeLayeringTarget(newWindowBuilder("statusBar", TYPE_STATUS_BAR).build());
        dc.setImeInputTarget(dc.getImeLayeringTarget());
        final var statusBar = newWindowBuilder("statusBar", TYPE_STATUS_BAR).setDisplay(dc).build();
        dc.setImeInputTarget(statusBar);
        dc.setImeLayeringTarget(statusBar);
        assertEquals(dc.getImeContainer().getParentSurfaceControl(),
                dc.computeImeParent().getSurfaceControl());
    }
@@ -1272,8 +1275,8 @@ public class DisplayContentTests extends WindowTestsBase {
        WindowState app1 = newWindowBuilder("app1", TYPE_BASE_APPLICATION).build();
        WindowState app2 = newWindowBuilder("app2", TYPE_BASE_APPLICATION).build();
        doReturn(true).when(mDisplayContent).shouldImeAttachedToApp();
        mDisplayContent.setImeLayeringTarget(app1);
        mDisplayContent.setImeInputTarget(app1);
        mDisplayContent.setImeLayeringTarget(app1);
        assertEquals(app1.mActivityRecord.getSurfaceControl(),
                mDisplayContent.computeImeParent().getSurfaceControl());
        mDisplayContent.setImeLayeringTarget(app2);
@@ -1289,8 +1292,8 @@ public class DisplayContentTests extends WindowTestsBase {
        overlay.setBounds(100, 100, 200, 200);
        overlay.mAttrs.flags = FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM;
        WindowState app = newWindowBuilder("app", TYPE_BASE_APPLICATION).build();
        mDisplayContent.setImeLayeringTarget(overlay);
        mDisplayContent.setImeInputTarget(app);
        mDisplayContent.setImeLayeringTarget(overlay);
        assertFalse(mDisplayContent.shouldImeAttachedToApp());
        assertEquals(mDisplayContent.getImeContainer().getParentSurfaceControl(),
                mDisplayContent.computeImeParent().getSurfaceControl());
@@ -1302,9 +1305,9 @@ public class DisplayContentTests extends WindowTestsBase {
        WindowState app1 = newWindowBuilder("app1", TYPE_BASE_APPLICATION).build();
        WindowState app2 = newWindowBuilder("app2", TYPE_BASE_APPLICATION).build();

        dc.setImeLayeringTarget(app1);
        dc.setImeInputTarget(app2);
        dc.setRemoteInsetsController(createDisplayWindowInsetsController());
        dc.setImeInputTarget(app2);
        dc.setImeLayeringTarget(app1);
        dc.getImeLayeringTarget().setWindowingMode(
                WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
        dc.getImeInputTarget().getWindowState().setWindowingMode(
@@ -1357,11 +1360,11 @@ public class DisplayContentTests extends WindowTestsBase {
    @Test
    public void testComputeImeControlTarget_splitscreen() {
        final DisplayContent dc = createNewDisplay();
        dc.setImeInputTarget(newWindowBuilder("app", TYPE_BASE_APPLICATION).build());
        dc.getImeInputTarget().getWindowState().setWindowingMode(
                WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
        dc.setImeLayeringTarget(dc.getImeInputTarget().getWindowState());
        dc.setRemoteInsetsController(createDisplayWindowInsetsController());
        final var appWin = newWindowBuilder("appWin", TYPE_BASE_APPLICATION).setDisplay(dc)
                .setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW).build();
        dc.setImeInputTarget(appWin);
        dc.setImeLayeringTarget(appWin);
        assertNotEquals(dc.getImeInputTarget().getWindowState(), dc.computeImeControlTarget());
    }

@@ -1384,9 +1387,9 @@ public class DisplayContentTests extends WindowTestsBase {
    public void testComputeImeControlTarget_notMatchParentBounds() {
        spyOn(mAppWindow.mActivityRecord);
        doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
        mDisplayContent.setImeInputTarget(mAppWindow);
        mDisplayContent.setImeLayeringTarget(mDisplayContent.getImeInputTarget().getWindowState());
        mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
        mDisplayContent.setImeInputTarget(mAppWindow);
        mDisplayContent.setImeLayeringTarget(mAppWindow);
        assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget());
    }

@@ -1400,9 +1403,9 @@ public class DisplayContentTests extends WindowTestsBase {
        spyOn(mAppWindow.mActivityRecord);
        doReturn(imeTargetBounds).when(mAppWindow).getBounds();
        doReturn(true).when(mAppWindow.mActivityRecord).matchParentBounds();
        mDisplayContent.setImeInputTarget(mAppWindow);
        mDisplayContent.setImeLayeringTarget(mDisplayContent.getImeInputTarget().getWindowState());
        mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
        mDisplayContent.setImeInputTarget(mAppWindow);
        mDisplayContent.setImeLayeringTarget(mAppWindow);
        final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer();
        spyOn(imeContainer);
        doReturn(imeContainerBounds).when(imeContainer).getBounds();
@@ -2244,6 +2247,7 @@ public class DisplayContentTests extends WindowTestsBase {
        spyOn(child1);
        doReturn(false).when(mDisplayContent).shouldImeAttachedToApp();
        mDisplayContent.setImeLayeringTarget(child1);
        verify(child1).needsRelativeLayeringToIme();

        spyOn(nextImeTargetApp);
        spyOn(mAppWindow);
@@ -2255,7 +2259,8 @@ public class DisplayContentTests extends WindowTestsBase {

        verify(mDisplayContent).computeImeLayeringTarget(true /* update */);
        assertNull(mDisplayContent.getImeInputTarget());
        verify(child1, never()).needsRelativeLayeringToIme();
        // Still only one call, earlier when child1 was set as IME layering target.
        verify(child1).needsRelativeLayeringToIme();
    }

    @SetupWindows(addWindows = W_INPUT_METHOD)
@@ -2321,9 +2326,8 @@ public class DisplayContentTests extends WindowTestsBase {
        final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
                activity).build();

        mDisplayContent.setImeLayeringTarget(win);
        mDisplayContent.setImeInputTarget(win);
        spyOn(mDisplayContent);
        mDisplayContent.setImeLayeringTarget(win);
        spyOn(mDisplayContent.mInputMethodWindow);
        doReturn(true).when(mDisplayContent.mInputMethodWindow).isVisible();
        mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true);
@@ -2349,8 +2353,8 @@ public class DisplayContentTests extends WindowTestsBase {
                activity).build();
        makeWindowVisible(mDisplayContent.mInputMethodWindow);

        mDisplayContent.setImeLayeringTarget(win);
        mDisplayContent.setImeInputTarget(win);
        mDisplayContent.setImeLayeringTarget(win);
        mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true);
        mDisplayContent.showImeScreenshot();
        assertNotNull(mDisplayContent.mImeScreenshot);
+3 −3
Original line number Diff line number Diff line
@@ -787,9 +787,9 @@ public class SizeCompatTests extends WindowTestsBase {
        assertFitted();

        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
        mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity));
        mActivity.mDisplayContent.setImeInputTarget(
                mActivity.mDisplayContent.getImeLayeringTarget());
        final var appWindow = addWindowToActivity(mActivity);
        mActivity.mDisplayContent.setImeInputTarget(appWindow);
        mActivity.mDisplayContent.setImeLayeringTarget(appWindow);
        // Because the aspect ratio of display doesn't exceed the max aspect ratio of activity.
        // The activity should still fill its parent container and IME can attach to the activity.
        assertTrue(mActivity.matchParentBounds());
+1 −1
Original line number Diff line number Diff line
@@ -66,8 +66,8 @@ public class WindowContainerTraversalTests extends WindowTestsBase {
    @SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD })
    @Test
    public void testTraverseImeRegardlessOfImeTarget() {
        mDisplayContent.setImeLayeringTarget(mAppWindow);
        mDisplayContent.setImeInputTarget(mAppWindow);
        mDisplayContent.setImeLayeringTarget(mAppWindow);
        mAppWindow.mHasSurface = false;
        mAppWindow.mActivityRecord.setVisibleRequested(false);
        mAppWindow.mActivityRecord.setVisible(false);
+70 −65
Original line number Diff line number Diff line
@@ -113,7 +113,6 @@ import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowRelayoutResult;
import android.view.inputmethod.ImeTracker;
import android.window.ClientWindowFrames;
import android.window.ITaskFragmentOrganizer;
import android.window.TaskFragmentOrganizer;
@@ -1329,80 +1328,86 @@ public class WindowStateTests extends WindowTestsBase {
        assertTrue(mAppWindow.getInsetsState().isSourceOrDefaultVisible(navId, navigationBars()));
    }

    @SetupWindows(addWindows = { W_INPUT_METHOD })
    @Test
    public void testAdjustImeInsetsVisibilityWhenSwitchingApps() {
        final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
        final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).build();
        final WindowState imeWindow = newWindowBuilder("imeWindow", TYPE_APPLICATION).build();
        spyOn(imeWindow);
        doReturn(true).when(imeWindow).isVisible();
        mDisplayContent.mInputMethodWindow = imeWindow;
        final var appWin1 = newWindowBuilder("appWin1", TYPE_APPLICATION).build();
        final var appWin2 = newWindowBuilder("appWin2", TYPE_APPLICATION).build();
        makeWindowVisibleAndDrawn(mImeWindow);

        final InsetsStateController controller = mDisplayContent.getInsetsStateController();
        controller.getImeSourceProvider().setWindowContainer(imeWindow, null, null);

        // Simulate app requests IME with updating all windows Insets State when IME is above app.
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.setImeInputTarget(app);
        app.setRequestedVisibleTypes(ime(), ime());
        assertTrue(mDisplayContent.shouldImeAttachedToApp());
        controller.getImeSourceProvider().scheduleShowImePostLayout(app, ImeTracker.Token.empty());
        controller.getImeSourceProvider().getSource().setVisible(true);
        controller.updateAboveInsetsState(false);

        // Expect all app windows behind IME can receive IME insets visible.
        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        assertTrue(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));

        // Simulate app plays closing transition to app2.
        app.mActivityRecord.commitVisibility(false, false);
        mDisplayContent.computeImeLayeringTarget(true /* update */);
        assertTrue(app.mActivityRecord.mLastImeShown);

        // Verify the IME insets is visible on app, but not for app2 during app task switching.
        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        controller.getImeSourceProvider().setWindowContainer(mImeWindow, null, null);

        // Simulate appWin2 requests IME.
        appWin2.setRequestedVisibleTypes(ime(), ime());
        mDisplayContent.setImeInputTarget(appWin2);
        mDisplayContent.setImeLayeringTarget(appWin2);
        assertEquals("appWin2 is the IME control target",
                appWin2, mDisplayContent.getImeControlTarget());
        controller.getImeSourceProvider().onPostLayout();

        // Expect all windows behind IME can receive IME insets visible.
        assertTrue("appWin1 has IME insets visible",
                appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        assertTrue("appWin2 has IME insets visible",
                appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));

        // Simulate appWin2 plays closing transition to appWin1.
        appWin2.mActivityRecord.commitVisibility(false /* visible */, false /* performLayout */);
        assertNull("appWin1 does not have frozen insets", appWin1.getFrozenInsetsState());
        assertNotNull("appWin2 has frozen insets", appWin2.getFrozenInsetsState());
        mDisplayContent.setImeInputTarget(appWin1);
        mDisplayContent.setImeLayeringTarget(appWin1);
        assertEquals("appWin1 is the IME control target",
                appWin1, mDisplayContent.getImeControlTarget());

        assertFalse("appWin1 does not have IME insets visible",
                appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        assertTrue("appWin2 still has IME insets visible, as they were frozen",
                appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
    }

    @SetupWindows(addWindows = { W_INPUT_METHOD })
    @Test
    public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() {
        final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
        final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).setWindowingMode(
                WINDOWING_MODE_MULTI_WINDOW).setActivityType(ACTIVITY_TYPE_STANDARD).setDisplay(
                mDisplayContent).build();
        final WindowState imeWindow = newWindowBuilder("imeWindow", TYPE_APPLICATION).build();
        spyOn(imeWindow);
        doReturn(true).when(imeWindow).isVisible();
        mDisplayContent.mInputMethodWindow = imeWindow;
        final var appWin1 = newWindowBuilder("appWin1", TYPE_APPLICATION)
                .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW).build();
        final var appWin2 = newWindowBuilder("appWin2", TYPE_APPLICATION).build();
        makeWindowVisibleAndDrawn(mImeWindow);
        mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());

        final InsetsStateController controller = mDisplayContent.getInsetsStateController();
        controller.getImeSourceProvider().setWindowContainer(imeWindow, null, null);

        // Simulate app2 in multi-window mode is going to background to switch to the fullscreen
        // app which requests IME with updating all windows Insets State when IME is above app.
        app2.mActivityRecord.setVisibleRequested(false);
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.setImeInputTarget(app);
        app.setRequestedVisibleTypes(ime(), ime());
        assertTrue(mDisplayContent.shouldImeAttachedToApp());
        controller.getImeSourceProvider().scheduleShowImePostLayout(app, ImeTracker.Token.empty());
        controller.getImeSourceProvider().getSource().setVisible(true);
        controller.updateAboveInsetsState(false);

        // Expect app windows behind IME can receive IME insets visible,
        // but not for app2 in background.
        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));

        // Simulate app plays closing transition to app2.
        // And app2 is now IME layering target but not yet to be the IME input target.
        mDisplayContent.setImeLayeringTarget(app2);
        app.mActivityRecord.commitVisibility(false, false);
        assertTrue(app.mActivityRecord.mLastImeShown);

        // Verify the IME insets is still visible on app, but not for app2 during task switching.
        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        controller.getImeSourceProvider().setWindowContainer(mImeWindow, null, null);

        // Simulate appWin1 in multi-window mode is going to background to switch to the
        // fullscreen appWin2 which requests IME.
        appWin1.mActivityRecord.commitVisibility(false /* visible */, false /* performLayout */);
        assertNotNull("appWin1 has frozen insets", appWin1.getFrozenInsetsState());
        assertNull("appWin2 does not have frozen insets", appWin2.getFrozenInsetsState());
        appWin2.setRequestedVisibleTypes(ime(), ime());
        mDisplayContent.setImeInputTarget(appWin2);
        mDisplayContent.setImeLayeringTarget(appWin2);
        controller.getImeSourceProvider().onPostLayout();

        assertFalse("appWin1 does not have IME insets visible, as it is in background",
                appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        assertTrue("appWin2 has IME insets visible",
                appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));

        // Simulate appWin2 plays closing transition to appWin1.
        appWin2.mActivityRecord.commitVisibility(false /* visible */, false /* performLayout */);
        appWin1.mActivityRecord.commitVisibility(true /* visible */, false /* performLayout */);
        assertNull("appWin1 does not have frozen insets", appWin1.getFrozenInsetsState());
        assertNotNull("appWin2 has frozen insets", appWin2.getFrozenInsetsState());
        mDisplayContent.setImeInputTarget(appWin1);
        mDisplayContent.setImeLayeringTarget(appWin1);
        assertEquals("RemoteInsetsControlTarget is the IME control target",
                mDisplayContent.mRemoteInsetsControlTarget, mDisplayContent.getImeControlTarget());

        assertFalse("appWin1 does not have IME insets visible",
                appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
        assertTrue("appWin2 still has IME insets visible, as they were frozen",
                appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
    }

    @SetupWindows(addWindows = W_ACTIVITY)
Loading