From fc6d5e91b7cc87b47d93f79c85fce6242f46d8cc Mon Sep 17 00:00:00 2001 From: Taran Singh Date: Thu, 21 Apr 2022 21:44:02 +0000 Subject: [PATCH] Fix InputConnection creation callback As noted in the linked bug, in certain scenarios IC established callback is not always called. As a fix, we make sure we don't return early when MSG_BIND callback is received from IME Fix: 228105257 Bug: 217971553 Test: atest StylusHandwritingTest#testHandwritingEndToEnd Change-Id: I780327003f7145c4f9b9df4dc5243227d7e67d92 --- .../view/inputmethod/InputMethodManager.java | 33 ++++++++++++++++--- .../RemoteInputConnectionImpl.java | 2 +- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 850256871b157..d9bde5825fde7 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -33,6 +33,7 @@ import static android.view.inputmethod.InputMethodManagerProto.CUR_ID; import static android.view.inputmethod.InputMethodManagerProto.FULLSCREEN_MODE; import static android.view.inputmethod.InputMethodManagerProto.SERVED_CONNECTING; +import static com.android.internal.inputmethod.StartInputReason.BOUND_TO_IMMS; import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION; import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION; @@ -449,6 +450,11 @@ public final class InputMethodManager { int mInitialSelStart; int mInitialSelEnd; + /** + * Handler for {@link RemoteInputConnectionImpl#getInputConnection()}. + */ + private Handler mServedInputConnectionHandler; + /** * The instance that has previously been sent to the input method. */ @@ -1658,6 +1664,7 @@ public final class InputMethodManager { if (mServedInputConnection != null) { mServedInputConnection.deactivate(); mServedInputConnection = null; + mServedInputConnectionHandler = null; } } @@ -2289,6 +2296,13 @@ public final class InputMethodManager { "Starting input: finished by someone else. view=" + dumpViewInfo(view) + " servedView=" + dumpViewInfo(servedView) + " mServedConnecting=" + mServedConnecting); + if (mServedInputConnection != null && startInputReason == BOUND_TO_IMMS) { + // This is not an error. Once IME binds (MSG_BIND), InputConnection is fully + // established. So we report this to interested recipients. + reportInputConnectionOpened( + mServedInputConnection.getInputConnection(), mCurrentTextBoxAttribute, + mServedInputConnectionHandler, view); + } return false; } @@ -2305,6 +2319,7 @@ public final class InputMethodManager { if (mServedInputConnection != null) { mServedInputConnection.deactivate(); mServedInputConnection = null; + mServedInputConnectionHandler = null; } RemoteInputConnectionImpl servedInputConnection; if (ic != null) { @@ -2323,11 +2338,13 @@ public final class InputMethodManager { // TODO(b/199934664): See if we can remove this by providing a default impl. } icHandler = handler; + mServedInputConnectionHandler = icHandler; servedInputConnection = new RemoteInputConnectionImpl( icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this, view); } else { servedInputConnection = null; icHandler = null; + mServedInputConnectionHandler = null; } mServedInputConnection = servedInputConnection; @@ -2397,16 +2414,21 @@ public final class InputMethodManager { Log.v(TAG, "Calling View.onInputConnectionOpened: view= " + view + ", ic=" + ic + ", tba=" + tba + ", handler=" + icHandler); } - view.onInputConnectionOpenedInternal(ic, tba, icHandler); - final ViewRootImpl viewRoot = view.getViewRootImpl(); - if (viewRoot != null) { - viewRoot.getHandwritingInitiator().onInputConnectionCreated(view); - } + reportInputConnectionOpened(ic, tba, icHandler, view); } return true; } + private void reportInputConnectionOpened( + InputConnection ic, EditorInfo tba, Handler icHandler, View view) { + view.onInputConnectionOpenedInternal(ic, tba, icHandler); + final ViewRootImpl viewRoot = view.getViewRootImpl(); + if (viewRoot != null) { + viewRoot.getHandwritingInitiator().onInputConnectionCreated(view); + } + } + /** * An empty method only to avoid crashes of apps that call this method via reflection and do not * handle {@link NoSuchMethodException} in a graceful manner. @@ -3550,6 +3572,7 @@ public final class InputMethodManager { p.println(" mCurrentTextBoxAttribute: null"); } p.println(" mServedInputConnection=" + mServedInputConnection); + p.println(" mServedInputConnectionHandler=" + mServedInputConnectionHandler); p.println(" mCompletions=" + Arrays.toString(mCompletions)); p.println(" mCursorRect=" + mCursorRect); p.println(" mCursorSelStart=" + mCursorSelStart diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java index 12b522bb98f22..f21cee9971638 100644 --- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java +++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java @@ -191,7 +191,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { * @return {@link InputConnection} to which incoming IPCs will be dispatched. */ @Nullable - private InputConnection getInputConnection() { + public InputConnection getInputConnection() { synchronized (mLock) { return mInputConnection; }