From 08a970caf5116b0f67226af1a61fef098affc2d1 Mon Sep 17 00:00:00 2001 From: Ming-Shin Lu Date: Mon, 20 Mar 2023 10:24:09 +0000 Subject: [PATCH] Fix an edge case of IME surface overlapped on the overview A race condition might happen when a IME layering overlay target visible unexpectedly during swiping the app task to the overview, that causes InputMonitor didn't call hideCurrentInputMethod when the input focus change since isImeAttachedToApp still return true in that time, but acutally it will become false after the IME layering overlay became visible. Refine the logic to keep tracking isImeAttachedToApp and IME visible state during the swiping up gesture, and hide IME when the IME is visible and not attachable on the new target. Fix: 222064495 Test: manual as test steps: 1) install a 3rd-party app "Always visible volume button" 2) enabling "Display over the other apps" for 1) to show the volume button 3) launching any apps with showing IME 4) swping up to the overview screen, verify if IME hides expectedly 5) repeat 3-5 10 times, expect no IME being overlapped on the overview screen, and the task snapshot didn't show the IME snapshot after hiding the IME. Change-Id: I71f397b93b9f94e9351ded8191676b1dfb249d9e --- .../java/com/android/server/wm/InputMonitor.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 8c5954856ed7c..ac343dbbf17b4 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -415,8 +415,12 @@ final class InputMonitor { if (mInputFocus != recentsAnimationInputConsumer.mWindowHandle.token) { requestFocus(recentsAnimationInputConsumer.mWindowHandle.token, recentsAnimationInputConsumer.mName); + } + if (mDisplayContent.mInputMethodWindow != null + && mDisplayContent.mInputMethodWindow.isVisible()) { // Hiding IME/IME icon when recents input consumer gain focus. - if (!mDisplayContent.isImeAttachedToApp()) { + final boolean isImeAttachedToApp = mDisplayContent.isImeAttachedToApp(); + if (!isImeAttachedToApp) { // Hiding IME if IME window is not attached to app since it's not proper to // snapshot Task with IME window to animate together in this case. final InputMethodManagerInternal inputMethodManagerInternal = @@ -425,6 +429,14 @@ final class InputMonitor { inputMethodManagerInternal.hideCurrentInputMethod( SoftInputShowHideReason.HIDE_RECENTS_ANIMATION); } + // Ensure removing the IME snapshot when the app no longer to show on the + // task snapshot (also taking the new task snaphot to update the overview). + final ActivityRecord app = mDisplayContent.getImeInputTarget() != null + ? mDisplayContent.getImeInputTarget().getActivityRecord() : null; + if (app != null) { + mDisplayContent.removeImeSurfaceImmediately(); + mDisplayContent.mAtmService.takeTaskSnapshot(app.getTask().mTaskId); + } } else { // Disable IME icon explicitly when IME attached to the app in case // IME icon might flickering while swiping to the next app task still