From 32807ad564c8614eab371d5d0839d87ca8f4e3bc Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Wed, 4 Mar 2020 12:27:29 -0800 Subject: [PATCH] Fix session race due to pending user-switch task This is a follow up CL to my previous CL [1], which aimed to optimize InputMethodManagerService#startInputOrWindowGainedFocus() by introducing UserSwitchHandlerTask to minimize the wall time consumed there so that we can unblock IME target's UI thread as soon as possible. To make it work, InputMethodManagerService (IMMS) now needs to check whether there is any pending UserSwitchHandlerTask or not when dealing with incoming calls such as another IMMS#onSwitchUser. My previous CL updated most of the cases correctly, but it turns out that I overlooked IMMS#onSessionCreated(), which can also be called asynchronously. As a result, an app running for user X might end up being connected to an IME running as user Y, which is not OK. With this CL, any IMMS#onSessionCreated() will simply be ignored when there is a pending UserSwitchHandlerTask, because it means that the callback is from the previously used IME, which will soon be destroyed because IMMS is now switching to a different user. [1]: I5a73a66d2b8acadad9b3577ebc4c17b5a25fd011 d277d6902f4b66af7c2a4b11375ed77595d273a9 Bug: 139806621 Fix: 150235502 Test: atest CtsInputMethodTestCases CtsInputMethodServiceHostTestCases Change-Id: Ia530df401645a979d983b8eb262dcba23eff4fbd --- .../server/inputmethod/InputMethodManagerService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 571f582ced33f..1869a46ff9f7d 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -2480,6 +2480,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub void onSessionCreated(IInputMethod method, IInputMethodSession session, InputChannel channel) { synchronized (mMethodMap) { + if (mUserSwitchHandlerTask != null) { + // We have a pending user-switching task so it's better to just ignore this session. + channel.dispose(); + return; + } if (mCurMethod != null && method != null && mCurMethod.asBinder() == method.asBinder()) { if (mCurClient != null) {