diff options
3 files changed, 127 insertions, 20 deletions
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index 7bc0d2f2fcd3..ce7e85868e8c 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -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. - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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. - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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); - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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 - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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 - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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() { - prepareControls(); + 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. - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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() { - prepareControls(); + 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() { - prepareControls(); + 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 - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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); - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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. - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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 - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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 - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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 - mController.show(ime(), true /* fromIme */, null /* statsToken */); + 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); - mController.show(ime(), true /* fromIme */, null /* statsToken */); + 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 - mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + 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; diff --git a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java index d8d5729700ca..ea175a5a52b0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java @@ -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); diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index 0dc56f8afc53..964264d82b65 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -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(); |