OSDN Git Service

Refresh IMMS#mBoundToMethod when IMS is disconnected
authorYohei Yukawa <yukawa@google.com>
Thu, 5 Jan 2017 04:15:02 +0000 (20:15 -0800)
committerYohei Yukawa <yukawa@google.com>
Thu, 5 Jan 2017 04:15:02 +0000 (20:15 -0800)
It turns out that InputMethodManagerService#mBoundToMethod is not
correctly reset to false when the current InputMethodService is
killed by the system before IMMS explicitly terminates the connection.

As a result, InputMethodService#onBindInput() is not called when the
same IMS is reconnected to the IMMS.  This also means that
IMS#mInputBinding and IMS#mInputConnection remain to be null
unexpectedly.  Crashes of IMEs and APK replacement of IMEs can trigger
such a situation.

With this CL, IMMS#onServiceDisconnected() eventually calls
IMMS#unbindCurrentClientLocked(). It not only resets
IMMS#mBoundToMethod but also updates NavBar icons and closes the IME
switcher dialog, but it is probably an acceptable and reasonable
behavior change because we have done so when switching the IME.

Bug: b.android.com/225029
Bug: 32102706
Test: `adb shell dumpsys input_method | grep "mBoundToMethod"` becomes "false" after the current IME crashes
Change-Id: Id87252a1a50029481d08b70afb12f38830bcd1d9

services/core/java/com/android/server/InputMethodManagerService.java

index 372e9a6..f718fa1 100644 (file)
@@ -1666,6 +1666,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
 
     @Override
     public void onServiceDisconnected(ComponentName name) {
+        // Note that mContext.unbindService(this) does not trigger this.  Hence if we are here the
+        // disconnection is not intended by IMMS (e.g. triggered because the current IMS crashed),
+        // which is irregular but can eventually happen for everyone just by continuing using the
+        // device.  Thus it is important to make sure that all the internal states are properly
+        // refreshed when this method is called back.  Running
+        //    adb install -r <APK that implements the current IME>
+        // would be a good way to trigger such a situation.
         synchronized (mMethodMap) {
             if (DEBUG) Slog.v(TAG, "Service disconnected: " + name
                     + " mCurIntent=" + mCurIntent);
@@ -1677,11 +1684,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                 mLastBindTime = SystemClock.uptimeMillis();
                 mShowRequested = mInputShown;
                 mInputShown = false;
-                if (mCurClient != null) {
-                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO(
-                            MSG_UNBIND_CLIENT, InputMethodClient.UNBIND_REASON_DISCONNECT_IME,
-                            mCurSeq, mCurClient.client));
-                }
+                unbindCurrentClientLocked(InputMethodClient.UNBIND_REASON_DISCONNECT_IME);
             }
         }
     }