Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4bbb1cc authored by Craig Mautner's avatar Craig Mautner
Browse files

Catch BadTokenException and continue.

BadTokenException is a normal consequence of swapping IMEs while there
is a DO_SHOW_SOFT_INPUT message in the IIMethodWrapper queue. This
race condition cannot be avoided without an unacceptable lock down of
InputMethodManagerService.

Fixes bug 8387663.
Fixes bug 8263462.

Change-Id: I2c21573cf972145ab08e66604cdb9344139a3f31
parent b38258f3
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -284,12 +284,6 @@ 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));
+9 −5
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import android.text.method.MovementMethod;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -49,6 +48,7 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.BadTokenException;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
@@ -352,7 +352,6 @@ public class InputMethodService extends AbstractInputMethodService {
         * Take care of attaching the given window token provided by the system.
         */
        public void attachToken(IBinder token) {
            Slog.i(TAG, "attachToken: Existing token=" + mToken + " new token=" + token);
            if (mToken == null) {
                mToken = token;
                mWindow.setToken(token);
@@ -419,11 +418,16 @@ public class InputMethodService extends AbstractInputMethodService {
         * Handle a request by the system to show the soft input area.
         */
        public void showSoftInput(int flags, ResultReceiver resultReceiver) {
            if (true || DEBUG) Slog.v(TAG, "showSoftInput()");
            if (DEBUG) Log.v(TAG, "showSoftInput()");
            boolean wasVis = isInputViewShown();
            mShowInputFlags = 0;
            if (onShowInputRequested(flags, false)) {
                try {
                    showWindow(true);
                } catch (BadTokenException e) {
                    if (DEBUG) Log.v(TAG, "BadTokenException: IME is done.");
                    mWindowVisible = false;
                }
            }
            // If user uses hard keyboard, IME button should always be shown.
            boolean showing = onEvaluateInputViewShown();
@@ -1390,7 +1394,7 @@ public class InputMethodService extends AbstractInputMethodService {
    }
    
    public void showWindow(boolean showInput) {
        if (true || DEBUG) Slog.v(TAG, "Showing window: showInput=" + showInput
        if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput
                + " mShowInputRequested=" + mShowInputRequested
                + " mWindowAdded=" + mWindowAdded
                + " mWindowCreated=" + mWindowCreated
+22 −24
Original line number Diff line number Diff line
@@ -33,28 +33,26 @@ import com.android.internal.view.IInputMethodSession;
 * Service).
 * {@hide}
 */
interface IInputMethod {
    oneway void attachToken(IBinder token);
oneway interface IInputMethod {
    void attachToken(IBinder token);

    oneway void bindInput(in InputBinding binding);
    void bindInput(in InputBinding binding);

    oneway void unbindInput();
    void unbindInput();

    oneway void startInput(in IInputContext inputContext, in EditorInfo attribute);
    void startInput(in IInputContext inputContext, in EditorInfo attribute);

    oneway void restartInput(in IInputContext inputContext, in EditorInfo attribute);
    void restartInput(in IInputContext inputContext, in EditorInfo attribute);

    oneway void createSession(IInputMethodCallback callback);
    void createSession(IInputMethodCallback callback);

    oneway void setSessionEnabled(IInputMethodSession session, boolean enabled);
    void setSessionEnabled(IInputMethodSession session, boolean enabled);

    oneway void revokeSession(IInputMethodSession session);
    void revokeSession(IInputMethodSession session);

    oneway void showSoftInput(int flags, in ResultReceiver resultReceiver);
    void showSoftInput(int flags, in ResultReceiver resultReceiver);

    oneway void hideSoftInput(int flags, in ResultReceiver resultReceiver);
    void hideSoftInput(int flags, in ResultReceiver resultReceiver);

    void removeSoftInputMessages();

    oneway void changeInputMethodSubtype(in InputMethodSubtype subtype);
    void changeInputMethodSubtype(in InputMethodSubtype subtype);
}
+8 −22
Original line number Diff line number Diff line
@@ -1237,24 +1237,13 @@ 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 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);
                if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
                executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
                        MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
                if (mCurClient != null) {
@@ -1700,7 +1689,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                    }
                }

                if (true || DEBUG) Slog.v(TAG, "Client requesting input be shown");
                if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
                return showCurrentInputLocked(flags, resultReceiver);
            }
        } finally {
@@ -1724,8 +1713,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub

        boolean res = false;
        if (mCurMethod != null) {
            if (true ||DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken,
                    new RuntimeException("here").fillInStackTrace());
            if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken);
            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
                    resultReceiver));
@@ -1797,13 +1785,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
    boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
        if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
                && (mShowExplicitlyRequested || mShowForced)) {
            if (true ||DEBUG) Slog.v(TAG,
                    "Not hiding: explicit show not cancelled by non-explicit hide");
            if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
            return false;
        }
        if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
            if (true ||DEBUG) Slog.v(TAG,
                    "Not hiding: forced show not cancelled by not-always hide");
            if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
            return false;
        }
        boolean res;
@@ -2314,7 +2300,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
            case MSG_SHOW_SOFT_INPUT:
                args = (SomeArgs)msg.obj;
                try {
                    if (true || DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
                            + msg.arg1 + ", " + args.arg2 + ")");
                    ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);
                } catch (RemoteException e) {
@@ -2324,7 +2310,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
            case MSG_HIDE_SOFT_INPUT:
                args = (SomeArgs)msg.obj;
                try {
                    if (true || DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
                            + args.arg2 + ")");
                    ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2);
                } catch (RemoteException e) {
@@ -2334,7 +2320,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
            case MSG_ATTACH_TOKEN:
                args = (SomeArgs)msg.obj;
                try {
                    if (true || DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
                    if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
                    ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
                } catch (RemoteException e) {
                }