From ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20 Mon Sep 17 00:00:00 2001 From: Craig Mautner Date: Thu, 14 Mar 2013 09:43:02 -0700 Subject: Remove WindowManager messages from remote queue. When a new IME is attached it is not enough to remove the WindowManager messages from the local queue, but the ones in the previous IME queue must also be removed. Fixes bug 8263462. Change-Id: I9e916c6052a83dc7691bcba0b6ab8328b9b7cc36 --- .../inputmethodservice/IInputMethodWrapper.java | 6 +++++ .../com/android/internal/view/IInputMethod.aidl | 26 ++++++++++++---------- .../android/server/InputMethodManagerService.java | 19 ++++++++++------ 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index 2d67875c6084..d59c7b819df3 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -284,6 +284,12 @@ class IInputMethodWrapper extends IInputMethod.Stub flags, resultReceiver)); } + @Override + public void removeSoftInputMessages() { + mCaller.removeMessages(DO_SHOW_SOFT_INPUT); + mCaller.removeMessages(DO_HIDE_SOFT_INPUT); + } + public void changeInputMethodSubtype(InputMethodSubtype subtype) { mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_CHANGE_INPUTMETHOD_SUBTYPE, subtype)); diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl index c7fcab8ecd29..c2a7fc73b0c3 100644 --- a/core/java/com/android/internal/view/IInputMethod.aidl +++ b/core/java/com/android/internal/view/IInputMethod.aidl @@ -33,26 +33,28 @@ import com.android.internal.view.IInputMethodSession; * Service). * {@hide} */ -oneway interface IInputMethod { - void attachToken(IBinder token); +interface IInputMethod { + oneway void attachToken(IBinder token); - void bindInput(in InputBinding binding); + oneway void bindInput(in InputBinding binding); - void unbindInput(); + oneway void unbindInput(); - void startInput(in IInputContext inputContext, in EditorInfo attribute); + oneway void startInput(in IInputContext inputContext, in EditorInfo attribute); - void restartInput(in IInputContext inputContext, in EditorInfo attribute); + oneway void restartInput(in IInputContext inputContext, in EditorInfo attribute); - void createSession(IInputMethodCallback callback); + oneway void createSession(IInputMethodCallback callback); - void setSessionEnabled(IInputMethodSession session, boolean enabled); + oneway void setSessionEnabled(IInputMethodSession session, boolean enabled); - void revokeSession(IInputMethodSession session); + oneway void revokeSession(IInputMethodSession session); - void showSoftInput(int flags, in ResultReceiver resultReceiver); + oneway void showSoftInput(int flags, in ResultReceiver resultReceiver); - void hideSoftInput(int flags, in ResultReceiver resultReceiver); + oneway void hideSoftInput(int flags, in ResultReceiver resultReceiver); - void changeInputMethodSubtype(in InputMethodSubtype subtype); + void removeSoftInputMessages(); + + oneway void changeInputMethodSubtype(in InputMethodSubtype subtype); } diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index d0048bf440a9..14841af70f43 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1199,7 +1199,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurId = info.getId(); mCurToken = new Binder(); try { - if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken); + if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken); mIWindowManager.addWindowToken(mCurToken, WindowManager.LayoutParams.TYPE_INPUT_METHOD); } catch (RemoteException e) { @@ -1237,14 +1237,21 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public void onServiceConnected(ComponentName name, IBinder service) { synchronized (mMethodMap) { if (mCurIntent != null && name.equals(mCurIntent.getComponent())) { + IInputMethod prevMethod = mCurMethod; mCurMethod = IInputMethod.Stub.asInterface(service); if (mCurToken == null) { Slog.w(TAG, "Service connected without a token!"); unbindCurrentMethodLocked(false, false); return; } - // Remove commands relating to the previous service. Otherwise WindowManagerService - // will reject the command because the token attached to these messages is invalid. + // Remove messages relating to the previous service. Otherwise WindowManagerService + // will throw a BadTokenException because the old token is being removed. + if (prevMethod != null) { + try { + prevMethod.removeSoftInputMessages(); + } catch (RemoteException e) { + } + } mCaller.removeMessages(MSG_SHOW_SOFT_INPUT); mCaller.removeMessages(MSG_HIDE_SOFT_INPUT); if (true || DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken); @@ -2309,8 +2316,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub try { if (true || DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput(" + msg.arg1 + ", " + args.arg2 + ")"); - ((IInputMethod)args.arg1).showSoftInput(msg.arg1, - (ResultReceiver)args.arg2); + ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2); } catch (RemoteException e) { } args.recycle(); @@ -2320,8 +2326,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub try { if (true || DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, " + args.arg2 + ")"); - ((IInputMethod)args.arg1).hideSoftInput(0, - (ResultReceiver)args.arg2); + ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2); } catch (RemoteException e) { } args.recycle(); -- cgit v1.2.3-59-g8ed1b