diff options
Diffstat (limited to 'core/java')
5 files changed, 69 insertions, 83 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index ffebf711e43e..7c0657795f51 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3287,6 +3287,7 @@ public final class ViewRootImpl implements ViewParent, private final static int MSG_DISPATCH_APP_VISIBILITY = 8; private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9; private final static int MSG_DISPATCH_KEY_FROM_IME = 11; + private final static int MSG_FINISH_INPUT_CONNECTION = 12; private final static int MSG_CHECK_FOCUS = 13; private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14; private final static int MSG_DISPATCH_DRAG_EVENT = 15; @@ -3326,6 +3327,8 @@ public final class ViewRootImpl implements ViewParent, return "MSG_DISPATCH_GET_NEW_SURFACE"; case MSG_DISPATCH_KEY_FROM_IME: return "MSG_DISPATCH_KEY_FROM_IME"; + case MSG_FINISH_INPUT_CONNECTION: + return "MSG_FINISH_INPUT_CONNECTION"; case MSG_CHECK_FOCUS: return "MSG_CHECK_FOCUS"; case MSG_CLOSE_SYSTEM_DIALOGS: @@ -3546,6 +3549,12 @@ public final class ViewRootImpl implements ViewParent, } enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true); } break; + case MSG_FINISH_INPUT_CONNECTION: { + InputMethodManager imm = InputMethodManager.peekInstance(); + if (imm != null) { + imm.reportFinishInputConnection((InputConnection)msg.obj); + } + } break; case MSG_CHECK_FOCUS: { InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null) { @@ -5856,6 +5865,11 @@ public final class ViewRootImpl implements ViewParent, } } + public void dispatchFinishInputConnection(InputConnection connection) { + Message msg = mHandler.obtainMessage(MSG_FINISH_INPUT_CONNECTION, connection); + mHandler.sendMessage(msg); + } + public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig, Rect backDropFrame, boolean forceLayout, diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index a3c49c5a8457..6a830f87de1f 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -158,8 +158,8 @@ public class BaseInputConnection implements InputConnection { * * @hide */ - public void reportFinish() { - // Intentionally empty + protected void reportFinish() { + // Intentionaly empty } /** diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 4bb0c3cbb5ee..cf5cc3e0510a 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -317,6 +317,7 @@ public final class InputMethodManager { /** * The InputConnection that was last retrieved from the served view. */ + InputConnection mServedInputConnection; ControlledInputConnectionWrapper mServedInputConnectionWrapper; /** * The completions that were last provided by the served view. @@ -497,7 +498,7 @@ public final class InputMethodManager { // from a thread that created mServedView. That could happen // the current activity is running in the system process. // In that case, we really should not call - // mServedInputConnectionWrapper.finishComposingText(). + // mServedInputConnection.finishComposingText. if (checkFocusNoStartInput(mHasBeenInactive, false)) { final int reason = active ? InputMethodClient.START_INPUT_REASON_ACTIVATED_BY_IMMS : @@ -531,25 +532,22 @@ public final class InputMethodManager { private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper { private final InputMethodManager mParentInputMethodManager; + private boolean mActive; public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn, final InputMethodManager inputMethodManager) { super(mainLooper, conn); mParentInputMethodManager = inputMethodManager; + mActive = true; } @Override public boolean isActive() { - return mParentInputMethodManager.mActive && !isFinished(); + return mParentInputMethodManager.mActive && mActive; } void deactivate() { - if (isFinished()) { - // This is a small performance optimization. Still only the 1st call of - // reportFinish() will take effect. - return; - } - reportFinish(); + mActive = false; } @Override @@ -564,9 +562,7 @@ public final class InputMethodManager { @Override public String toString() { - return "ControlledInputConnectionWrapper{" - + "connection=" + getInputConnection() - + " finished=" + isFinished() + return "ControlledInputConnectionWrapper{mActive=" + mActive + " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive + "}"; } @@ -784,8 +780,7 @@ public final class InputMethodManager { */ public boolean isAcceptingText() { checkFocus(); - return mServedInputConnectionWrapper != null && - mServedInputConnectionWrapper.getInputConnection() != null; + return mServedInputConnection != null; } /** @@ -820,6 +815,7 @@ public final class InputMethodManager { */ void clearConnectionLocked() { mCurrentTextBoxAttribute = null; + mServedInputConnection = null; if (mServedInputConnectionWrapper != null) { mServedInputConnectionWrapper.deactivate(); mServedInputConnectionWrapper = null; @@ -840,6 +836,7 @@ public final class InputMethodManager { throw e.rethrowFromSystemServer(); } } + notifyInputConnectionFinished(); mServedView = null; mCompletions = null; mServedConnecting = false; @@ -847,6 +844,37 @@ public final class InputMethodManager { } } + /** + * Notifies the served view that the current InputConnection will no longer be used. + */ + private void notifyInputConnectionFinished() { + if (mServedView != null && mServedInputConnection != null) { + // We need to tell the previously served view that it is no + // longer the input target, so it can reset its state. Schedule + // this call on its window's Handler so it will be on the correct + // thread and outside of our lock. + ViewRootImpl viewRootImpl = mServedView.getViewRootImpl(); + if (viewRootImpl != null) { + // This will result in a call to reportFinishInputConnection() below. + viewRootImpl.dispatchFinishInputConnection(mServedInputConnection); + } + } + } + + /** + * Called from the FINISH_INPUT_CONNECTION message above. + * @hide + */ + public void reportFinishInputConnection(InputConnection ic) { + if (mServedInputConnection != ic) { + ic.finishComposingText(); + // To avoid modifying the public InputConnection interface + if (ic instanceof BaseInputConnection) { + ((BaseInputConnection) ic).reportFinish(); + } + } + } + public void displayCompletions(View view, CompletionInfo[] completions) { checkFocus(); synchronized (mH) { @@ -1212,10 +1240,9 @@ public final class InputMethodManager { // Hook 'em up and let 'er rip. mCurrentTextBoxAttribute = tba; mServedConnecting = false; - if (mServedInputConnectionWrapper != null) { - mServedInputConnectionWrapper.deactivate(); - mServedInputConnectionWrapper = null; - } + // Notify the served view that its previous input connection is finished + notifyInputConnectionFinished(); + mServedInputConnection = ic; ControlledInputConnectionWrapper servedContext; final int missingMethodFlags; if (ic != null) { @@ -1240,6 +1267,9 @@ public final class InputMethodManager { servedContext = null; missingMethodFlags = 0; } + if (mServedInputConnectionWrapper != null) { + mServedInputConnectionWrapper.deactivate(); + } mServedInputConnectionWrapper = servedContext; try { @@ -1383,7 +1413,7 @@ public final class InputMethodManager { return false; } - final ControlledInputConnectionWrapper ic; + InputConnection ic = null; synchronized (mH) { if (mServedView == mNextServedView && !forceNewFocus) { return false; @@ -1403,7 +1433,7 @@ public final class InputMethodManager { return false; } - ic = mServedInputConnectionWrapper; + ic = mServedInputConnection; mServedView = mNextServedView; mCurrentTextBoxAttribute = null; @@ -2252,7 +2282,7 @@ public final class InputMethodManager { } else { p.println(" mCurrentTextBoxAttribute: null"); } - p.println(" mServedInputConnectionWrapper=" + mServedInputConnectionWrapper); + p.println(" mServedInputConnection=" + mServedInputConnection); p.println(" mCompletions=" + Arrays.toString(mCompletions)); p.println(" mCursorRect=" + mCursorRect); p.println(" mCursorSelStart=" + mCursorSelStart diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java index 02b9db347f1a..3be15f3998ec 100644 --- a/core/java/com/android/internal/view/IInputConnectionWrapper.java +++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java @@ -16,10 +16,6 @@ package com.android.internal.view; -import com.android.internal.annotations.GuardedBy; - -import android.annotation.NonNull; -import android.annotation.Nullable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -27,7 +23,6 @@ import android.os.Message; import android.os.RemoteException; import android.util.Log; import android.view.KeyEvent; -import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; import android.view.inputmethod.ExtractedTextRequest; @@ -61,16 +56,11 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { private static final int DO_PERFORM_PRIVATE_COMMAND = 120; private static final int DO_CLEAR_META_KEY_STATES = 130; private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140; - private static final int DO_REPORT_FINISH = 150; - @NonNull - private final WeakReference<InputConnection> mInputConnection; + private WeakReference<InputConnection> mInputConnection; private Looper mMainLooper; private Handler mH; - private Object mLock = new Object(); - @GuardedBy("mLock") - private boolean mFinished = false; static class SomeArgs { Object arg1; @@ -96,17 +86,6 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { mH = new MyHandler(mMainLooper); } - @Nullable - public InputConnection getInputConnection() { - return mInputConnection.get(); - } - - protected boolean isFinished() { - synchronized (mLock) { - return mFinished; - } - } - abstract protected boolean isActive(); /** @@ -219,10 +198,6 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { seq, callback)); } - public void reportFinish() { - dispatchMessage(obtainMessage(DO_REPORT_FINISH)); - } - void dispatchMessage(Message msg) { // If we are calling this from the main thread, then we can call // right through. Otherwise, we need to send the message to the @@ -235,7 +210,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { mH.sendMessage(msg); } - + void executeMessage(Message msg) { switch (msg.what) { case DO_GET_TEXT_AFTER_CURSOR: { @@ -498,36 +473,6 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { } return; } - case DO_REPORT_FINISH: { - // Note that we do not need to worry about race condition here, because 1) mFinished - // is updated only inside this block, and 2) the code here is running on a Handler - // hence we assume multiple DO_REPORT_FINISH messages will not be handled at the - // same time. - if (isFinished()) { - return; - } - try { - InputConnection ic = mInputConnection.get(); - // Note we do NOT check isActive() here, because this is safe - // for an IME to call at any time, and we need to allow it - // through to clean up our state after the IME has switched to - // another client. - if (ic == null) { - return; - } - ic.finishComposingText(); - // TODO: Make reportFinish() public method of InputConnection to remove this - // check. - if (ic instanceof BaseInputConnection) { - ((BaseInputConnection) ic).reportFinish(); - } - } finally { - synchronized (mLock) { - mFinished = true; - } - } - return; - } } Log.w(TAG, "Unhandled message code: " + msg.what); } diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java index a96b5a0d6ab1..f211ff269339 100644 --- a/core/java/com/android/internal/widget/EditableInputConnection.java +++ b/core/java/com/android/internal/widget/EditableInputConnection.java @@ -83,11 +83,8 @@ public class EditableInputConnection extends BaseInputConnection { return false; } - /** - * @hide - */ @Override - public void reportFinish() { + protected void reportFinish() { super.reportFinish(); synchronized(this) { |
