diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index 05daf63fdd5d6..a87b1338339a0 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -147,119 +147,146 @@ class IInputMethodWrapper extends IInputMethod.Stub @MainThread @Override public void executeMessage(Message msg) { - InputMethod inputMethod = mInputMethod.get(); - // Need a valid reference to the inputMethod for everything except a dump. - if (inputMethod == null && msg.what != DO_DUMP) { - Log.w(TAG, "Input method reference was null, ignoring message: " + msg.what); - return; - } - + final InputMethod inputMethod = mInputMethod.get(); + final InputMethodServiceInternal target = mTarget.get(); switch (msg.what) { case DO_DUMP: { - InputMethodServiceInternal target = mTarget.get(); - if (target == null) { - return; - } SomeArgs args = (SomeArgs)msg.obj; - try { - target.dump((FileDescriptor) args.arg1, - (PrintWriter) args.arg2, (String[]) args.arg3); - } catch (RuntimeException e) { - ((PrintWriter)args.arg2).println("Exception: " + e); - } - synchronized (args.arg4) { - ((CountDownLatch)args.arg4).countDown(); + if (isValid(inputMethod, target, "DO_DUMP")) { + final FileDescriptor fd = (FileDescriptor) args.arg1; + final PrintWriter fout = (PrintWriter) args.arg2; + final String[] dumpArgs = (String[]) args.arg3; + final CountDownLatch latch = (CountDownLatch) args.arg4; + try { + target.dump(fd, fout, dumpArgs); + } catch (RuntimeException e) { + fout.println("Exception: " + e); + } finally { + latch.countDown(); + } } args.recycle(); return; } case DO_INITIALIZE_INTERNAL: - inputMethod.initializeInternal((IInputMethod.InitParams) msg.obj); + if (isValid(inputMethod, target, "DO_INITIALIZE_INTERNAL")) { + inputMethod.initializeInternal((IInputMethod.InitParams) msg.obj); + } return; case DO_SET_INPUT_CONTEXT: { - inputMethod.bindInput((InputBinding)msg.obj); + if (isValid(inputMethod, target, "DO_SET_INPUT_CONTEXT")) { + inputMethod.bindInput((InputBinding) msg.obj); + } return; } case DO_UNSET_INPUT_CONTEXT: - inputMethod.unbindInput(); + if (isValid(inputMethod, target, "DO_UNSET_INPUT_CONTEXT")) { + inputMethod.unbindInput(); + } return; case DO_START_INPUT: { final SomeArgs args = (SomeArgs) msg.obj; - final InputConnection inputConnection = (InputConnection) args.arg1; - final IInputMethod.StartInputParams params = - (IInputMethod.StartInputParams) args.arg2; - inputMethod.dispatchStartInput(inputConnection, params); + if (isValid(inputMethod, target, "DO_START_INPUT")) { + final InputConnection inputConnection = (InputConnection) args.arg1; + final IInputMethod.StartInputParams params = + (IInputMethod.StartInputParams) args.arg2; + inputMethod.dispatchStartInput(inputConnection, params); + } args.recycle(); return; } case DO_ON_NAV_BUTTON_FLAGS_CHANGED: - inputMethod.onNavButtonFlagsChanged(msg.arg1); + if (isValid(inputMethod, target, "DO_ON_NAV_BUTTON_FLAGS_CHANGED")) { + inputMethod.onNavButtonFlagsChanged(msg.arg1); + } return; case DO_CREATE_SESSION: { SomeArgs args = (SomeArgs)msg.obj; - inputMethod.createSession(new InputMethodSessionCallbackWrapper( - mContext, (InputChannel) args.arg1, - (IInputMethodSessionCallback) args.arg2)); + if (isValid(inputMethod, target, "DO_CREATE_SESSION")) { + inputMethod.createSession(new InputMethodSessionCallbackWrapper( + mContext, (InputChannel) args.arg1, + (IInputMethodSessionCallback) args.arg2)); + } args.recycle(); return; } case DO_SET_SESSION_ENABLED: - inputMethod.setSessionEnabled((InputMethodSession)msg.obj, - msg.arg1 != 0); + if (isValid(inputMethod, target, "DO_SET_SESSION_ENABLED")) { + inputMethod.setSessionEnabled((InputMethodSession) msg.obj, msg.arg1 != 0); + } return; case DO_SHOW_SOFT_INPUT: { final SomeArgs args = (SomeArgs)msg.obj; - inputMethod.showSoftInputWithToken( - msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1); + if (isValid(inputMethod, target, "DO_SHOW_SOFT_INPUT")) { + inputMethod.showSoftInputWithToken( + msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1); + } args.recycle(); return; } case DO_HIDE_SOFT_INPUT: { final SomeArgs args = (SomeArgs) msg.obj; - inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2, - (IBinder) args.arg1); + if (isValid(inputMethod, target, "DO_HIDE_SOFT_INPUT")) { + inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2, + (IBinder) args.arg1); + } args.recycle(); return; } case DO_CHANGE_INPUTMETHOD_SUBTYPE: - inputMethod.changeInputMethodSubtype((InputMethodSubtype)msg.obj); + if (isValid(inputMethod, target, "DO_CHANGE_INPUTMETHOD_SUBTYPE")) { + inputMethod.changeInputMethodSubtype((InputMethodSubtype) msg.obj); + } return; case DO_CREATE_INLINE_SUGGESTIONS_REQUEST: { final SomeArgs args = (SomeArgs) msg.obj; - inputMethod.onCreateInlineSuggestionsRequest( - (InlineSuggestionsRequestInfo) args.arg1, - (IInlineSuggestionsRequestCallback) args.arg2); + if (isValid(inputMethod, target, "DO_CREATE_INLINE_SUGGESTIONS_REQUEST")) { + inputMethod.onCreateInlineSuggestionsRequest( + (InlineSuggestionsRequestInfo) args.arg1, + (IInlineSuggestionsRequestCallback) args.arg2); + } args.recycle(); return; } case DO_CAN_START_STYLUS_HANDWRITING: { - inputMethod.canStartStylusHandwriting(msg.arg1); + if (isValid(inputMethod, target, "DO_CAN_START_STYLUS_HANDWRITING")) { + inputMethod.canStartStylusHandwriting(msg.arg1); + } return; } case DO_UPDATE_TOOL_TYPE: { - inputMethod.updateEditorToolType(msg.arg1); + if (isValid(inputMethod, target, "DO_UPDATE_TOOL_TYPE")) { + inputMethod.updateEditorToolType(msg.arg1); + } return; } case DO_START_STYLUS_HANDWRITING: { final SomeArgs args = (SomeArgs) msg.obj; - inputMethod.startStylusHandwriting(msg.arg1, (InputChannel) args.arg1, - (List) args.arg2); + if (isValid(inputMethod, target, "DO_START_STYLUS_HANDWRITING")) { + inputMethod.startStylusHandwriting(msg.arg1, (InputChannel) args.arg1, + (List) args.arg2); + } args.recycle(); return; } case DO_INIT_INK_WINDOW: { - inputMethod.initInkWindow(); + if (isValid(inputMethod, target, "DO_INIT_INK_WINDOW")) { + inputMethod.initInkWindow(); + } return; } case DO_FINISH_STYLUS_HANDWRITING: { - inputMethod.finishStylusHandwriting(); + if (isValid(inputMethod, target, "DO_FINISH_STYLUS_HANDWRITING")) { + inputMethod.finishStylusHandwriting(); + } return; } case DO_REMOVE_STYLUS_HANDWRITING_WINDOW: { - inputMethod.removeStylusHandwritingWindow(); + if (isValid(inputMethod, target, "DO_REMOVE_STYLUS_HANDWRITING_WINDOW")) { + inputMethod.removeStylusHandwritingWindow(); + } return; } - } Log.w(TAG, "Unhandled message code: " + msg.what); } @@ -445,4 +472,15 @@ class IInputMethodWrapper extends IInputMethod.Stub public void removeStylusHandwritingWindow() { mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_REMOVE_STYLUS_HANDWRITING_WINDOW)); } + + private static boolean isValid(InputMethod inputMethod, InputMethodServiceInternal target, + String msg) { + if (inputMethod != null && target != null && !target.isServiceDestroyed()) { + return true; + } else { + Log.w(TAG, "Ignoring " + msg + ", InputMethod:" + inputMethod + + ", InputMethodServiceInternal:" + target); + return false; + } + } } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 7436601f5352f..8b3451e9cdcf5 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -700,11 +700,6 @@ public class InputMethodService extends AbstractInputMethodService { @MainThread @Override public final void initializeInternal(@NonNull IInputMethod.InitParams params) { - if (mDestroyed) { - Log.i(TAG, "The InputMethodService has already onDestroyed()." - + "Ignore the initialization."); - return; - } Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal"); mConfigTracker.onInitialize(params.configChanges); mPrivOps.set(params.privilegedOperations); @@ -3938,6 +3933,14 @@ public class InputMethodService extends AbstractInputMethodService { public void triggerServiceDump(String where, @Nullable byte[] icProto) { ImeTracing.getInstance().triggerServiceDump(where, mDumper, icProto); } + + /** + * {@inheritDoc} + */ + @Override + public boolean isServiceDestroyed() { + return mDestroyed; + } }; } diff --git a/core/java/android/inputmethodservice/InputMethodServiceInternal.java b/core/java/android/inputmethodservice/InputMethodServiceInternal.java index f44f49d7dcaf2..c6612f6e54c5e 100644 --- a/core/java/android/inputmethodservice/InputMethodServiceInternal.java +++ b/core/java/android/inputmethodservice/InputMethodServiceInternal.java @@ -85,4 +85,11 @@ interface InputMethodServiceInternal { */ default void triggerServiceDump(@NonNull String where, @Nullable byte[] icProto) { } + + /** + * @return {@code true} if {@link InputMethodService} is destroyed. + */ + default boolean isServiceDestroyed() { + return false; + }; }