Loading core/java/android/view/ViewRootImpl.java +14 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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: Loading Loading @@ -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) { Loading Loading @@ -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, Loading core/java/android/view/inputmethod/BaseInputConnection.java +2 −2 Original line number Diff line number Diff line Loading @@ -158,8 +158,8 @@ public class BaseInputConnection implements InputConnection { * * @hide */ public void reportFinish() { // Intentionally empty protected void reportFinish() { // Intentionaly empty } /** Loading core/java/android/view/inputmethod/InputMethodManager.java +50 −20 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 : Loading Loading @@ -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 Loading @@ -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 + "}"; } Loading Loading @@ -784,8 +780,7 @@ public final class InputMethodManager { */ public boolean isAcceptingText() { checkFocus(); return mServedInputConnectionWrapper != null && mServedInputConnectionWrapper.getInputConnection() != null; return mServedInputConnection != null; } /** Loading Loading @@ -820,6 +815,7 @@ public final class InputMethodManager { */ void clearConnectionLocked() { mCurrentTextBoxAttribute = null; mServedInputConnection = null; if (mServedInputConnectionWrapper != null) { mServedInputConnectionWrapper.deactivate(); mServedInputConnectionWrapper = null; Loading @@ -840,6 +836,7 @@ public final class InputMethodManager { throw e.rethrowFromSystemServer(); } } notifyInputConnectionFinished(); mServedView = null; mCompletions = null; mServedConnecting = false; Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -1240,6 +1267,9 @@ public final class InputMethodManager { servedContext = null; missingMethodFlags = 0; } if (mServedInputConnectionWrapper != null) { mServedInputConnectionWrapper.deactivate(); } mServedInputConnectionWrapper = servedContext; try { Loading Loading @@ -1383,7 +1413,7 @@ public final class InputMethodManager { return false; } final ControlledInputConnectionWrapper ic; InputConnection ic = null; synchronized (mH) { if (mServedView == mNextServedView && !forceNewFocus) { return false; Loading @@ -1403,7 +1433,7 @@ public final class InputMethodManager { return false; } ic = mServedInputConnectionWrapper; ic = mServedInputConnection; mServedView = mNextServedView; mCurrentTextBoxAttribute = null; Loading Loading @@ -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 Loading core/java/com/android/internal/view/IInputConnectionWrapper.java +2 −57 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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(); /** Loading Loading @@ -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 Loading Loading @@ -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); } Loading core/java/com/android/internal/widget/EditableInputConnection.java +1 −4 Original line number Diff line number Diff line Loading @@ -83,11 +83,8 @@ public class EditableInputConnection extends BaseInputConnection { return false; } /** * @hide */ @Override public void reportFinish() { protected void reportFinish() { super.reportFinish(); synchronized(this) { Loading Loading
core/java/android/view/ViewRootImpl.java +14 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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: Loading Loading @@ -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) { Loading Loading @@ -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, Loading
core/java/android/view/inputmethod/BaseInputConnection.java +2 −2 Original line number Diff line number Diff line Loading @@ -158,8 +158,8 @@ public class BaseInputConnection implements InputConnection { * * @hide */ public void reportFinish() { // Intentionally empty protected void reportFinish() { // Intentionaly empty } /** Loading
core/java/android/view/inputmethod/InputMethodManager.java +50 −20 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 : Loading Loading @@ -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 Loading @@ -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 + "}"; } Loading Loading @@ -784,8 +780,7 @@ public final class InputMethodManager { */ public boolean isAcceptingText() { checkFocus(); return mServedInputConnectionWrapper != null && mServedInputConnectionWrapper.getInputConnection() != null; return mServedInputConnection != null; } /** Loading Loading @@ -820,6 +815,7 @@ public final class InputMethodManager { */ void clearConnectionLocked() { mCurrentTextBoxAttribute = null; mServedInputConnection = null; if (mServedInputConnectionWrapper != null) { mServedInputConnectionWrapper.deactivate(); mServedInputConnectionWrapper = null; Loading @@ -840,6 +836,7 @@ public final class InputMethodManager { throw e.rethrowFromSystemServer(); } } notifyInputConnectionFinished(); mServedView = null; mCompletions = null; mServedConnecting = false; Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -1240,6 +1267,9 @@ public final class InputMethodManager { servedContext = null; missingMethodFlags = 0; } if (mServedInputConnectionWrapper != null) { mServedInputConnectionWrapper.deactivate(); } mServedInputConnectionWrapper = servedContext; try { Loading Loading @@ -1383,7 +1413,7 @@ public final class InputMethodManager { return false; } final ControlledInputConnectionWrapper ic; InputConnection ic = null; synchronized (mH) { if (mServedView == mNextServedView && !forceNewFocus) { return false; Loading @@ -1403,7 +1433,7 @@ public final class InputMethodManager { return false; } ic = mServedInputConnectionWrapper; ic = mServedInputConnection; mServedView = mNextServedView; mCurrentTextBoxAttribute = null; Loading Loading @@ -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 Loading
core/java/com/android/internal/view/IInputConnectionWrapper.java +2 −57 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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(); /** Loading Loading @@ -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 Loading Loading @@ -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); } Loading
core/java/com/android/internal/widget/EditableInputConnection.java +1 −4 Original line number Diff line number Diff line Loading @@ -83,11 +83,8 @@ public class EditableInputConnection extends BaseInputConnection { return false; } /** * @hide */ @Override public void reportFinish() { protected void reportFinish() { super.reportFinish(); synchronized(this) { Loading