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

Commit 43624020 authored by Felix Stern's avatar Felix Stern
Browse files

Only update remote target, if visibility is different from input target

When syncing the visibility of the imeInputTarget to the (RemoteInsets)ControlTarget, without having an actual change, the upcoming call to updateClientVisibility will be ignored and we don't invoke the IMMS listener.
Therefore, we should only sync the visibility when it's different between imeInputTarget and controlTarget - otherwise we can directly invoke the listener.

Fix: 402547338
Fix: 405296840
Flag: android.view.inputmethod.refactor_insets_controller
Test: atest ImeInsetsSourceProviderTest#testUpdateControlForTarget_remoteInsetsControlTargetUnchanged
Test: manual: open view where controlTarget=RemoteInsetsControlTarget; Open another fullscreen app and request IME; close new window to return to RICT
Change-Id: I96ffe688ae5eb32e325f3f7c9c62b392f7287100
parent ae136715
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -326,9 +326,12 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider {
                // IME input target to update IME request state. For example, switch from a task
                // with showing IME to a split-screen task without showing IME.
                InputTarget imeInputTarget = mDisplayContent.getImeInputTarget();
                if (imeInputTarget != target && imeInputTarget != null) {
                    // The controlTarget should be updated with the visibility of the
                    // current IME input target.
                if (imeInputTarget != target && imeInputTarget != null
                        && imeInputTarget.isRequestedVisible(WindowInsets.Type.ime())
                        != target.isRequestedVisible(WindowInsets.Type.ime())) {
                    // Only update the controlTarget, if it has a different requested visibility
                    // than the imeInputTarget. Otherwise, updateClientVisibility won't invoke
                    // the listener, as nothing changed.
                    reportImeInputTargetStateToControlTarget(imeInputTarget, target,
                            statsToken);
                } else {
+39 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.server.wm.WindowStateAnimator.NO_SURFACE;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
@@ -245,11 +246,48 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase {

        assertTrue(inputTarget.isRequestedVisible(WindowInsets.Type.ime()));
        assertFalse(controlTarget.isRequestedVisible(WindowInsets.Type.ime()));
        mImeProvider.updateControlForTarget(controlTarget, true /* force */, null /* statsToken */);
        mImeProvider.updateControlForTarget(controlTarget, true /* force */,
                ImeTracker.Token.empty());
        verify(displayWindowInsetsController, times(1)).setImeInputTargetRequestedVisibility(
                eq(true), any());
    }

    @Test
    @RequiresFlagsEnabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
    public void testUpdateControlForTarget_remoteInsetsControlTargetUnchanged()
            throws RemoteException {
        final WindowState ime = newWindowBuilder("ime", TYPE_INPUT_METHOD).build();
        mImeProvider.setWindowContainer(ime, null, null);
        final WindowState inputTarget = newWindowBuilder("app", TYPE_APPLICATION).build();
        final var displayWindowInsetsController = spy(createDisplayWindowInsetsController());
        mDisplayContent.setRemoteInsetsController(displayWindowInsetsController);
        final var controlTarget = mDisplayContent.mRemoteInsetsControlTarget;
        mDisplayContent.setImeInputTarget(inputTarget);
        mDisplayContent.setImeControlTarget(controlTarget);

        // Test for visible
        inputTarget.setRequestedVisibleTypes(WindowInsets.Type.ime());
        controlTarget.updateRequestedVisibleTypes(WindowInsets.Type.ime(), WindowInsets.Type.ime());
        clearInvocations(mDisplayContent);
        assertTrue(inputTarget.isRequestedVisible(WindowInsets.Type.ime()));
        assertTrue((controlTarget.isRequestedVisible(WindowInsets.Type.ime())));
        mImeProvider.updateControlForTarget(controlTarget, true /* force */,
                ImeTracker.Token.empty());
        verify(displayWindowInsetsController, never()).setImeInputTargetRequestedVisibility(
                anyBoolean(), any());

        // Test for not visible
        inputTarget.setRequestedVisibleTypes(0);
        controlTarget.updateRequestedVisibleTypes(0 /* visibleTypes */, WindowInsets.Type.ime());
        clearInvocations(mDisplayContent);
        assertFalse(inputTarget.isRequestedVisible(WindowInsets.Type.ime()));
        assertFalse((controlTarget.isRequestedVisible(WindowInsets.Type.ime())));
        mImeProvider.updateControlForTarget(controlTarget, true /* force */,
                ImeTracker.Token.empty());
        verify(displayWindowInsetsController, never()).setImeInputTargetRequestedVisibility(
                anyBoolean(), any());
    }

    @Test
    @RequiresFlagsEnabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
    public void testOnPostLayout_resetServerVisibilityWhenImeIsNotDrawn() {