From fac4cdfce6d7e5f72eb1078309defb6d888d8fff Mon Sep 17 00:00:00 2001 From: Ming-Shin Lu Date: Tue, 2 Nov 2021 17:17:04 +0800 Subject: [PATCH] Fix unexpected hide IME cases When testing testImeSwitchingWithoutWindowFocusAfterDisplayOffOnFull on the virtual device, the test flows will be: 1) Launch an activity and click the editor to show IME 2) Turn off/on the screen 3) Launch the IME picker dialog and expecting no window focus change. 4) Switch to another IME app and expect the IME visible after switched. Somehow the flaky point is in step 4) that if attaching the new input to show the IME comes first, before the input target updated to WM, in the meantime the app received onControlChanged callback with null control from WMS#relayoutWindow, then in ImeInsetsSourceConsumer#setControl -> hide() will end up calling notifyImeHidden for IME to invoke hideMySoftInput(), which is not expected result. As this unexpected IME hidden issue is related the timing issue of updating IME targets to WM a bit late and showing IME request happends from IMMS instead of from ImeInsetsSourceConsumer#requestShow. (i.e. consumer#hide() be invoked when mIsRequestedVisibleAwaitingControl is false but the control is null when setControl called) To fix this issue case, it looks make sense to check with ImeInsetsSourceConsumer#isRequestedVisibleAwaitingControl() when the null control callback in setControl(), since isRequestedVisibleAwaitingControl() will be true when requested the IME visible, so that it won't fall into hide() logic. Also, modified "Animation finished abruptly." debug log in InsetsAnimationControlImpl#applyChangeInsets to print only when the animation actually finished, since it does not make sense to print when the animation is not finish. Fix: 204524304 Test: atest InputMethodServiceLifecycleTest#\ testImeSwitchingWithoutWindowFocusAfterDisplayOffOnFull \ --rerun-until-failure 100 Change-Id: I3071af14bf78e23f9526d6a9c138ab6ae2e0e339 --- core/java/android/view/ImeInsetsSourceConsumer.java | 2 +- core/java/android/view/InsetsAnimationControlImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index 06861046f2c7c..02b2c5d5db84c 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -124,7 +124,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { public void setControl(@Nullable InsetsSourceControl control, int[] showTypes, int[] hideTypes) { super.setControl(control, showTypes, hideTypes); - if (control == null && !mIsRequestedVisibleAwaitingControl) { + if (control == null && !isRequestedVisibleAwaitingControl()) { hide(); removeSurface(); } diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index 7d8d653f5ab3b..805727c871b21 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -284,8 +284,8 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro mShownOnFinish, mCurrentAlpha, mCurrentInsets)); mController.notifyFinished(this, mShownOnFinish); releaseLeashes(); + if (DEBUG) Log.d(TAG, "Animation finished abruptly."); } - if (DEBUG) Log.d(TAG, "Animation finished abruptly."); return mFinished; }