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

Commit 51cd1c2c authored by Felix Stern's avatar Felix Stern
Browse files

Adjust more insets related tests for refactor

Test: atest com.android.server.wm.InsetsStateControllerTest &&
      atest com.android.server.wm.ImeInsetsSourceProviderTest &&
      atest FrameworksCoreTests:android.view.InsetsControllerTest
Flag: android.view.inputmethod.refactor_insets_controller
Bug: 355030765
Bug: 355032418
Bug: 355031556
Change-Id: Id418adf9087debcf86c0490f3e4af8939a587037
parent cb197a1d
Loading
Loading
Loading
Loading
+109 −20
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ import android.view.WindowInsetsController.OnControllableInsetsChangedListener;
import android.view.WindowManager.BadTokenException;
import android.view.WindowManager.LayoutParams;
import android.view.animation.LinearInterpolator;
import android.view.inputmethod.Flags;
import android.view.inputmethod.ImeTracker;
import android.widget.TextView;

@@ -136,7 +137,7 @@ public class InsetsControllerTest {
            mTestHandler = new TestHandler(null, mTestClock);
            mTestHost = spy(new TestHost(mViewRoot));
            mController = new InsetsController(mTestHost, (controller, id, type) -> {
                if (type == ime()) {
                if (!Flags.refactorInsetsController() && type == ime()) {
                    return new InsetsSourceConsumer(id, type, controller.getState(),
                            Transaction::new, controller) {

@@ -260,7 +261,11 @@ public class InsetsControllerTest {
            mController.setSystemDrivenInsetsAnimationLoggingListener(loggingListener);
            mController.getSourceConsumer(ID_IME, ime()).onWindowFocusGained(true);
            // since there is no focused view, forcefully make IME visible.
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                mController.show(ime(), false /* fromIme */, ImeTracker.Token.empty());
            }
            // When using the animation thread, this must not invoke onReady()
            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
        });
@@ -277,7 +282,12 @@ public class InsetsControllerTest {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            mController.getSourceConsumer(ID_IME, ime()).onWindowFocusGained(true);
            // since there is no focused view, forcefully make IME visible.
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                InsetsSourceControl ime = createControl(ID_IME, ime());
                mController.onControlsChanged(new InsetsSourceControl[]{ime});
            }
            mController.show(all());
            // quickly jump to final state by cancelling it.
            mController.cancelExistingAnimations();
@@ -299,7 +309,11 @@ public class InsetsControllerTest {
        mController.onControlsChanged(new InsetsSourceControl[] { ime });
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            mController.getSourceConsumer(ID_IME, ime()).onWindowFocusGained(true);
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                mController.show(ime(), false /* fromIme */, ImeTracker.Token.empty());
            }
            mController.cancelExistingAnimations();
            assertTrue(isRequestedVisible(mController, ime()));
            mController.hide(ime(), true /* fromIme */, ImeTracker.Token.empty());
@@ -469,7 +483,12 @@ public class InsetsControllerTest {
            assertFalse(mController.getState().peekSource(ID_IME).isVisible());

            // Pretend IME is calling
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                InsetsSourceControl ime = createControl(ID_IME, ime());
                mController.onControlsChanged(new InsetsSourceControl[]{ime});
            }

            // Gaining control shortly after
            mController.onControlsChanged(createSingletonControl(ID_IME, ime()));
@@ -493,7 +512,12 @@ public class InsetsControllerTest {
            mController.onControlsChanged(createSingletonControl(ID_IME, ime()));

            // Pretend IME is calling
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                InsetsSourceControl ime = createControl(ID_IME, ime());
                mController.onControlsChanged(new InsetsSourceControl[]{ime});
            }

            assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ime()));
            mController.cancelExistingAnimations();
@@ -558,7 +582,13 @@ public class InsetsControllerTest {

    @Test
    public void testControlImeNotReady() {
        if (!Flags.refactorInsetsController()) {
            prepareControls();
        } else {
            // With the flag on, the IME control should not contain a leash, otherwise the custom
            // animation will start immediately.
            prepareControls(false /* imeControlHasLeash */);
        }
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            WindowInsetsAnimationControlListener listener =
                    mock(WindowInsetsAnimationControlListener.class);
@@ -571,7 +601,13 @@ public class InsetsControllerTest {
            verify(listener, never()).onReady(any(), anyInt());

            // Pretend that IME is calling.
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                // Send the IME control with leash, so that the animation can start
                InsetsSourceControl ime = createControl(ID_IME, ime(), true /* hasLeash */);
                mController.onControlsChanged(new InsetsSourceControl[]{ime});
            }

            // Ready gets deferred until next predraw
            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
@@ -583,7 +619,13 @@ public class InsetsControllerTest {

    @Test
    public void testControlImeNotReady_controlRevoked() {
        if (!Flags.refactorInsetsController()) {
            prepareControls();
        } else {
            // With the flag on, the IME control should not contain a leash, otherwise the custom
            // animation will start immediately.
            prepareControls(false /* imeControlHasLeash */);
        }
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            WindowInsetsAnimationControlListener listener =
                    mock(WindowInsetsAnimationControlListener.class);
@@ -604,7 +646,13 @@ public class InsetsControllerTest {

    @Test
    public void testControlImeNotReady_timeout() {
        if (!Flags.refactorInsetsController()) {
            prepareControls();
        } else {
            // With the flag on, the IME control should not contain a leash, otherwise the custom
            // animation will start immediately.
            prepareControls(false /* imeControlHasLeash */);
        }
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            WindowInsetsAnimationControlListener listener =
                    mock(WindowInsetsAnimationControlListener.class);
@@ -655,7 +703,11 @@ public class InsetsControllerTest {
            mController.onControlsChanged(createSingletonControl(ID_IME, ime()));

            // Pretend IME is calling
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                mController.show(ime(), false /* fromIme */, ImeTracker.Token.empty());
            }

            InsetsState copy = new InsetsState(mController.getState(), true /* copySources */);
            copy.peekSource(ID_IME).setFrame(0, 1, 2, 3);
@@ -886,7 +938,11 @@ public class InsetsControllerTest {

            // Showing invisible ime should only causes insets change once.
            clearInvocations(mTestHost);
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                mController.show(ime(), false /* fromIme */, ImeTracker.Token.empty());
            }
            verify(mTestHost, times(1)).notifyInsetsChanged();

            // Sending the same insets state should not cause insets change.
@@ -953,7 +1009,11 @@ public class InsetsControllerTest {
            assertNull(imeInsetsConsumer.getControl());

            // Verify IME requested visibility should be updated to IME consumer from controller.
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                mController.show(ime(), false /* fromIme */, ImeTracker.Token.empty());
            }
            assertTrue(isRequestedVisible(mController, ime()));

            mController.hide(ime());
@@ -966,7 +1026,11 @@ public class InsetsControllerTest {
        prepareControls();
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            // show ime as initial state
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                mController.show(ime(), false /* fromIme */, ImeTracker.Token.empty());
            }
            mController.cancelExistingAnimations(); // fast forward show animation
            assertTrue(mController.getState().peekSource(ID_IME).isVisible());

@@ -990,8 +1054,13 @@ public class InsetsControllerTest {
    public void testImeShowRequestCancelsPredictiveBackPostCommitAnim() {
        prepareControls();
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            InsetsSourceControl ime = createControl(ID_IME, ime());
            // show ime as initial state
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                mController.show(ime(), false /* fromIme */, ImeTracker.Token.empty());
            }
            mController.cancelExistingAnimations(); // fast forward show animation
            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
            assertTrue(mController.getState().peekSource(ID_IME).isVisible());
@@ -1008,12 +1077,20 @@ public class InsetsControllerTest {
            assertEquals(ANIMATION_TYPE_USER, mController.getAnimationType(ime()));

            // verify show request is ignored during pre commit phase of predictive back anim
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, null /* statsToken */);
            } else {
                mController.onControlsChanged(new InsetsSourceControl[]{ime});
            }
            assertEquals(ANIMATION_TYPE_USER, mController.getAnimationType(ime()));

            // verify show request is applied during post commit phase of predictive back anim
            mController.setPredictiveBackImeHideAnimInProgress(true);
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, null /* statsToken */);
            } else {
                mController.show(ime(), false /* fromIme */, null /* statsToken */);
            }
            assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ime()));

            // additionally verify that IME ends up visible
@@ -1027,7 +1104,11 @@ public class InsetsControllerTest {
        prepareControls();
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            // show ime as initial state
            if (!Flags.refactorInsetsController()) {
                mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
            } else {
                mController.show(ime(), false /* fromIme */, ImeTracker.Token.empty());
            }
            mController.cancelExistingAnimations(); // fast forward show animation
            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
            assertTrue(mController.getState().peekSource(ID_IME).isVisible());
@@ -1058,11 +1139,15 @@ public class InsetsControllerTest {
    }

    private InsetsSourceControl createControl(int id, @InsetsType int type) {
        return createControl(id, type, true);
    }

    private InsetsSourceControl createControl(int id, @InsetsType int type, boolean hasLeash) {

        // Simulate binder behavior by copying SurfaceControl. Otherwise, InsetsController will
        // attempt to release mLeash directly.
        SurfaceControl copy = new SurfaceControl(mLeash, "InsetsControllerTest.createControl");
        return new InsetsSourceControl(id, type, copy,
        return new InsetsSourceControl(id, type, hasLeash ? copy : null,
                (type & WindowInsets.Type.defaultVisible()) != 0, new Point(), Insets.NONE);
    }

@@ -1071,9 +1156,13 @@ public class InsetsControllerTest {
    }

    private InsetsSourceControl[] prepareControls() {
        return prepareControls(true);
    }

    private InsetsSourceControl[] prepareControls(boolean imeControlHasLeash) {
        final InsetsSourceControl navBar = createControl(ID_NAVIGATION_BAR, navigationBars());
        final InsetsSourceControl statusBar = createControl(ID_STATUS_BAR, statusBars());
        final InsetsSourceControl ime = createControl(ID_IME, ime());
        final InsetsSourceControl ime = createControl(ID_IME, ime(), imeControlHasLeash);

        InsetsSourceControl[] controls = new InsetsSourceControl[3];
        controls[0] = navBar;
+6 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import static org.junit.Assert.assertTrue;

import android.graphics.PixelFormat;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.view.inputmethod.Flags;
import android.view.inputmethod.ImeTracker;

import androidx.test.filters.SmallTest;
@@ -72,6 +74,7 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase {
     * Checks that scheduling with all the state set and manually triggering the show does succeed.
     */
    @Test
    @RequiresFlagsDisabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
    public void testScheduleShowIme() {
        final WindowState ime = createWindow(null, TYPE_INPUT_METHOD, "ime");
        makeWindowVisibleAndDrawn(ime);
@@ -99,6 +102,7 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase {
     * all the state becomes available.
     */
    @Test
    @RequiresFlagsDisabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
    public void testScheduleShowIme_noInitialState() {
        final WindowState target = createWindow(null, TYPE_APPLICATION, "app");

@@ -126,6 +130,7 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase {
     * does continue and succeed when the runnable is started.
     */
    @Test
    @RequiresFlagsDisabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
    public void testScheduleShowIme_delayedAfterPrepareSurfaces() {
        final WindowState ime = createWindow(null, TYPE_INPUT_METHOD, "ime");
        makeWindowVisibleAndDrawn(ime);
@@ -158,6 +163,7 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase {
     * when the surface placement happens.
     */
    @Test
    @RequiresFlagsDisabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
    public void testScheduleShowIme_delayedSurfacePlacement() {
        final WindowState ime = createWindow(null, TYPE_INPUT_METHOD, "ime");
        makeWindowVisibleAndDrawn(ime);
+12 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -202,6 +203,11 @@ public class InsetsStateControllerTest extends WindowTestsBase {
        getController().onImeControlTargetChanged(base);
        base.setRequestedVisibleTypes(ime(), ime());
        getController().onRequestedVisibleTypesChanged(base, null /* statsToken */);
        if (android.view.inputmethod.Flags.refactorInsetsController()) {
            // to set the serverVisibility, the IME needs to be drawn and onPostLayout be called.
            mImeWindow.mWinAnimator.mDrawState = HAS_DRAWN;
            getController().onPostLayout();
        }

        // Send our spy window (app) into the system so that we can detect the invocation.
        final WindowState win = createWindow(null, TYPE_APPLICATION, "app");
@@ -500,6 +506,12 @@ public class InsetsStateControllerTest extends WindowTestsBase {
        getController().onRequestedVisibleTypesChanged(app, null /* statsToken */);
        assertTrue(ime.getControllableInsetProvider().getSource().isVisible());

        if (android.view.inputmethod.Flags.refactorInsetsController()) {
            // The IME is only set to shown, after onPostLayout is called and all preconditions
            // (serverVisible, no givenInsetsPending, etc.) are fulfilled
            getController().getImeSourceProvider().onPostLayout();
        }

        getController().updateAboveInsetsState(true /* notifyInsetsChange */);
        assertNotNull(app.getInsetsState().peekSource(ID_IME));
        verify(app, atLeastOnce()).notifyInsetsChanged();