From 5edf6c373ece4fc2e89d620da94ce73912611f3a Mon Sep 17 00:00:00 2001 From: Felix Stern Date: Wed, 12 Feb 2025 11:55:09 +0000 Subject: Removing IMS surface in InputMethodService#hideSoftInput after hiding the window After hiding the IME, we formerly removed its surface via an explicit call in the ImeInsetsSourceConsumer, later in InsetsController, but was requested too early, as the animation was not finished at the time. Removing the surface should only happen, after the IME window was already hidden and can be done in InputMethodService#hideSoftInput. Bug: 298172246 Flag: android.view.inputmethod.refactor_insets_controller Test: atest com.android.inputmethodservice.InputMethodServiceTest#testSurfaceRemovedAfterHideSoftInput Change-Id: I546327a5dfb570dcf3999f94e4556d08ac2a70b6 --- .../inputmethodservice/InputMethodServiceTest.java | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'services') diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java index 2d3f7231cc5c..b6aee3cfa5c5 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java @@ -40,10 +40,14 @@ import android.content.res.Configuration; import android.graphics.Insets; import android.os.Build; import android.os.RemoteException; +import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.server.wm.WindowManagerStateHelper; import android.util.Log; +import android.view.View; +import android.view.WindowInsets; +import android.view.WindowInsetsAnimation; import android.view.WindowManagerGlobal; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.Flags; @@ -72,6 +76,7 @@ import org.junit.Test; import org.junit.rules.TestName; import org.junit.runner.RunWith; +import java.util.List; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -244,6 +249,61 @@ public class InputMethodServiceTest { EVENT_HIDE, true /* eventExpected */, false /* shown */, "IME is not shown"); } + /** + * This checks that the surface is removed after the window was hidden in + * InputMethodService#hideSoftInput + */ + @Test + @RequiresFlagsEnabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER) + public void testSurfaceRemovedAfterHideSoftInput() { + setShowImeWithHardKeyboard(true /* enabled */); + + // Triggers to show IME via public API. + verifyInputViewStatusOnMainSync(() -> mActivity.showImeWithWindowInsetsController(), + EVENT_SHOW, true /* eventExpected */, true /* shown */, "IME is shown"); + assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue(); + + final var window = mInputMethodService.getWindow().getWindow(); + assertWithMessage("IME window exists").that(window).isNotNull(); + assertWithMessage("IME window showing").that( + window.getDecorView().getVisibility()).isEqualTo(View.VISIBLE); + + mActivity.getWindow().getDecorView().setWindowInsetsAnimationCallback( + new WindowInsetsAnimation.Callback( + WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE) { + @NonNull + @Override + public WindowInsetsAnimation.Bounds onStart( + @NonNull WindowInsetsAnimation animation, + @NonNull WindowInsetsAnimation.Bounds bounds) { + return super.onStart(animation, bounds); + } + + @NonNull + @Override + public WindowInsets onProgress(@NonNull WindowInsets insets, + @NonNull List runningAnimations) { + assertWithMessage("IME surface not removed during the animation").that( + window.getDecorView().getVisibility()).isEqualTo(View.VISIBLE); + return insets; + } + + @Override + public void onEnd(@NonNull WindowInsetsAnimation animation) { + assertWithMessage( + "IME surface not removed before the end of the animation").that( + window.getDecorView().getVisibility()).isEqualTo(View.VISIBLE); + super.onEnd(animation); + } + }); + + // Triggers to hide IME via public API. + verifyInputViewStatusOnMainSync(() -> mActivity.hideImeWithWindowInsetsController(), + EVENT_HIDE, true /* eventExpected */, false /* shown */, "IME is not shown"); + eventually(() -> assertWithMessage("IME window not showing").that( + window.getDecorView().getVisibility()).isEqualTo(View.GONE)); + } + /** * This checks the result of calling IMS#requestShowSelf and IMS#requestHideSelf. */ -- cgit v1.2.3-59-g8ed1b